Merged ati-4-0-1
parent
e79f86b254
commit
99efe3c247
|
@ -1,8 +1,7 @@
|
||||||
/* xf86drm.c -- User-level interface to DRM device
|
/* xf86drm.c -- User-level interface to DRM device
|
||||||
* Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.com
|
* Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.com
|
||||||
* Revised: Sun Feb 13 23:43:32 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -24,6 +23,8 @@
|
||||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
|
* Author: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
*
|
||||||
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.10 2000/02/23 04:47:23 martin Exp $
|
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.10 2000/02/23 04:47:23 martin Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -143,7 +144,7 @@ static int drm_open(const char *file)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drmAvailable looks for /proc/drm, and returns 1 if it is present. */
|
/* drmAvailable looks for /proc/dri, and returns 1 if it is present. */
|
||||||
|
|
||||||
int drmAvailable(void)
|
int drmAvailable(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,3 +49,5 @@ i810.o: i810_drv.o i810_context.o $(L_TARGET)
|
||||||
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
|
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
|
||||||
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm
|
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm
|
||||||
|
|
||||||
|
r128.o: r128_drv.o r128_context.o $(L_TARGET)
|
||||||
|
$(LD) $(LD_RFLAG) -r -o $@ r128_drv.o r128_context.o -L. -ldrm
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
|
/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
||||||
* Revised: Sun Feb 13 23:34:30 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -228,8 +227,8 @@ typedef struct drm_magic_entry {
|
||||||
} drm_magic_entry_t;
|
} drm_magic_entry_t;
|
||||||
|
|
||||||
typedef struct drm_magic_head {
|
typedef struct drm_magic_head {
|
||||||
struct drm_magic_entry *head;
|
struct drm_magic_entry *head;
|
||||||
struct drm_magic_entry *tail;
|
struct drm_magic_entry *tail;
|
||||||
} drm_magic_head_t;
|
} drm_magic_head_t;
|
||||||
|
|
||||||
typedef struct drm_vma_entry {
|
typedef struct drm_vma_entry {
|
||||||
|
@ -262,16 +261,15 @@ typedef struct drm_buf {
|
||||||
DRM_LIST_RECLAIM = 5
|
DRM_LIST_RECLAIM = 5
|
||||||
} list; /* Which list we're on */
|
} list; /* Which list we're on */
|
||||||
|
|
||||||
|
|
||||||
void *dev_private;
|
|
||||||
int dev_priv_size;
|
|
||||||
|
|
||||||
#if DRM_DMA_HISTOGRAM
|
#if DRM_DMA_HISTOGRAM
|
||||||
cycles_t time_queued; /* Queued to kernel DMA queue */
|
cycles_t time_queued; /* Queued to kernel DMA queue */
|
||||||
cycles_t time_dispatched; /* Dispatched to hardware */
|
cycles_t time_dispatched; /* Dispatched to hardware */
|
||||||
cycles_t time_completed; /* Completed by hardware */
|
cycles_t time_completed; /* Completed by hardware */
|
||||||
cycles_t time_freed; /* Back on freelist */
|
cycles_t time_freed; /* Back on freelist */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int dev_priv_size; /* Size of buffer private stoarge */
|
||||||
|
void *dev_private; /* Per-buffer private storage */
|
||||||
} drm_buf_t;
|
} drm_buf_t;
|
||||||
|
|
||||||
#if DRM_DMA_HISTOGRAM
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
|
|
@ -0,0 +1,737 @@
|
||||||
|
/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXPORT_SYMTAB
|
||||||
|
#include "drmP.h"
|
||||||
|
#include "r128_drv.h"
|
||||||
|
EXPORT_SYMBOL(r128_init);
|
||||||
|
EXPORT_SYMBOL(r128_cleanup);
|
||||||
|
|
||||||
|
#define R128_NAME "r128"
|
||||||
|
#define R128_DESC "r128"
|
||||||
|
#define R128_DATE "20000422"
|
||||||
|
#define R128_MAJOR 0
|
||||||
|
#define R128_MINOR 0
|
||||||
|
#define R128_PATCHLEVEL 5
|
||||||
|
|
||||||
|
static drm_device_t r128_device;
|
||||||
|
drm_ctx_t r128_res_ctx;
|
||||||
|
|
||||||
|
static struct file_operations r128_fops = {
|
||||||
|
open: r128_open,
|
||||||
|
flush: drm_flush,
|
||||||
|
release: r128_release,
|
||||||
|
ioctl: r128_ioctl,
|
||||||
|
mmap: drm_mmap,
|
||||||
|
read: drm_read,
|
||||||
|
fasync: drm_fasync,
|
||||||
|
poll: drm_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct miscdevice r128_misc = {
|
||||||
|
minor: MISC_DYNAMIC_MINOR,
|
||||||
|
name: R128_NAME,
|
||||||
|
fops: &r128_fops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static drm_ioctl_desc_t r128_ioctls[] = {
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_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_CCEIDL)] = { r128_cce_idle, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 },
|
||||||
|
};
|
||||||
|
#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
|
||||||
|
|
||||||
|
#ifdef MODULE
|
||||||
|
int init_module(void);
|
||||||
|
void cleanup_module(void);
|
||||||
|
static char *r128 = NULL;
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas.");
|
||||||
|
MODULE_DESCRIPTION("r128");
|
||||||
|
MODULE_PARM(r128, "s");
|
||||||
|
|
||||||
|
/* init_module is called when insmod is used to load the module */
|
||||||
|
|
||||||
|
int init_module(void)
|
||||||
|
{
|
||||||
|
return r128_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup_module is called when rmmod is used to unload the module */
|
||||||
|
|
||||||
|
void cleanup_module(void)
|
||||||
|
{
|
||||||
|
r128_cleanup();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MODULE
|
||||||
|
/* r128_setup is called by the kernel to parse command-line options passed
|
||||||
|
* via the boot-loader (e.g., LILO). It calls the insmod option routine,
|
||||||
|
* drm_parse_drm.
|
||||||
|
*
|
||||||
|
* This is not currently supported, since it requires changes to
|
||||||
|
* linux/init/main.c. */
|
||||||
|
|
||||||
|
|
||||||
|
void __init r128_setup(char *str, int *ints)
|
||||||
|
{
|
||||||
|
if (ints[0] != 0) {
|
||||||
|
DRM_ERROR("Illegal command line format, ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drm_parse_options(str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int r128_setup(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
atomic_set(&dev->ioctl_count, 0);
|
||||||
|
atomic_set(&dev->vma_count, 0);
|
||||||
|
dev->buf_use = 0;
|
||||||
|
atomic_set(&dev->buf_alloc, 0);
|
||||||
|
|
||||||
|
drm_dma_setup(dev);
|
||||||
|
|
||||||
|
atomic_set(&dev->total_open, 0);
|
||||||
|
atomic_set(&dev->total_close, 0);
|
||||||
|
atomic_set(&dev->total_ioctl, 0);
|
||||||
|
atomic_set(&dev->total_irq, 0);
|
||||||
|
atomic_set(&dev->total_ctx, 0);
|
||||||
|
atomic_set(&dev->total_locks, 0);
|
||||||
|
atomic_set(&dev->total_unlocks, 0);
|
||||||
|
atomic_set(&dev->total_contends, 0);
|
||||||
|
atomic_set(&dev->total_sleeps, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||||
|
dev->magiclist[i].head = NULL;
|
||||||
|
dev->magiclist[i].tail = NULL;
|
||||||
|
}
|
||||||
|
dev->maplist = NULL;
|
||||||
|
dev->map_count = 0;
|
||||||
|
dev->vmalist = NULL;
|
||||||
|
dev->lock.hw_lock = NULL;
|
||||||
|
init_waitqueue_head(&dev->lock.lock_queue);
|
||||||
|
dev->queue_count = 0;
|
||||||
|
dev->queue_reserved = 0;
|
||||||
|
dev->queue_slots = 0;
|
||||||
|
dev->queuelist = NULL;
|
||||||
|
dev->irq = 0;
|
||||||
|
dev->context_flag = 0;
|
||||||
|
dev->interrupt_flag = 0;
|
||||||
|
dev->dma_flag = 0;
|
||||||
|
dev->last_context = 0;
|
||||||
|
dev->last_switch = 0;
|
||||||
|
dev->last_checked = 0;
|
||||||
|
init_timer(&dev->timer);
|
||||||
|
init_waitqueue_head(&dev->context_wait);
|
||||||
|
|
||||||
|
dev->ctx_start = 0;
|
||||||
|
dev->lck_start = 0;
|
||||||
|
|
||||||
|
dev->buf_rp = dev->buf;
|
||||||
|
dev->buf_wp = dev->buf;
|
||||||
|
dev->buf_end = dev->buf + DRM_BSZ;
|
||||||
|
dev->buf_async = NULL;
|
||||||
|
init_waitqueue_head(&dev->buf_readers);
|
||||||
|
init_waitqueue_head(&dev->buf_writers);
|
||||||
|
|
||||||
|
r128_res_ctx.handle=-1;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
/* The kernel's context could be created here, but is now created
|
||||||
|
in drm_dma_enqueue. This is more resource-efficient for
|
||||||
|
hardware that does not do DMA, but may mean that
|
||||||
|
drm_select_queue fails between the time the interrupt is
|
||||||
|
initialized and the time the queues are initialized. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int r128_takedown(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
drm_magic_entry_t *pt, *next;
|
||||||
|
drm_map_t *map;
|
||||||
|
drm_vma_entry_t *vma, *vma_next;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
down(&dev->struct_sem);
|
||||||
|
del_timer(&dev->timer);
|
||||||
|
|
||||||
|
if (dev->devname) {
|
||||||
|
drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
|
||||||
|
dev->devname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->unique) {
|
||||||
|
drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
|
||||||
|
dev->unique = NULL;
|
||||||
|
dev->unique_len = 0;
|
||||||
|
}
|
||||||
|
/* Clear pid list */
|
||||||
|
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||||
|
for (pt = dev->magiclist[i].head; pt; pt = next) {
|
||||||
|
next = pt->next;
|
||||||
|
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||||
|
}
|
||||||
|
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
/* Clear AGP information */
|
||||||
|
if (dev->agp) {
|
||||||
|
drm_agp_mem_t *entry;
|
||||||
|
drm_agp_mem_t *nexte;
|
||||||
|
|
||||||
|
/* Remove AGP resources, but leave dev->agp
|
||||||
|
intact until r128_cleanup is called. */
|
||||||
|
for (entry = dev->agp->memory; entry; entry = nexte) {
|
||||||
|
nexte = entry->next;
|
||||||
|
if (entry->bound) drm_unbind_agp(entry->memory);
|
||||||
|
drm_free_agp(entry->memory, entry->pages);
|
||||||
|
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
|
||||||
|
}
|
||||||
|
dev->agp->memory = NULL;
|
||||||
|
|
||||||
|
if (dev->agp->acquired && drm_agp.release)
|
||||||
|
(*drm_agp.release)();
|
||||||
|
|
||||||
|
dev->agp->acquired = 0;
|
||||||
|
dev->agp->enabled = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Clear vma list (only built for debugging) */
|
||||||
|
if (dev->vmalist) {
|
||||||
|
for (vma = dev->vmalist; vma; vma = vma_next) {
|
||||||
|
vma_next = vma->next;
|
||||||
|
drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
|
||||||
|
}
|
||||||
|
dev->vmalist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear map area and mtrr information */
|
||||||
|
if (dev->maplist) {
|
||||||
|
for (i = 0; i < dev->map_count; i++) {
|
||||||
|
map = dev->maplist[i];
|
||||||
|
switch (map->type) {
|
||||||
|
case _DRM_REGISTERS:
|
||||||
|
case _DRM_FRAME_BUFFER:
|
||||||
|
#ifdef CONFIG_MTRR
|
||||||
|
if (map->mtrr >= 0) {
|
||||||
|
int retcode;
|
||||||
|
retcode = mtrr_del(map->mtrr,
|
||||||
|
map->offset,
|
||||||
|
map->size);
|
||||||
|
DRM_DEBUG("mtrr_del = %d\n", retcode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
drm_ioremapfree(map->handle, map->size);
|
||||||
|
break;
|
||||||
|
case _DRM_SHM:
|
||||||
|
drm_free_pages((unsigned long)map->handle,
|
||||||
|
drm_order(map->size)
|
||||||
|
- PAGE_SHIFT,
|
||||||
|
DRM_MEM_SAREA);
|
||||||
|
break;
|
||||||
|
case _DRM_AGP:
|
||||||
|
/* Do nothing here, because this is all
|
||||||
|
handled in the AGP/GART driver. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
}
|
||||||
|
drm_free(dev->maplist,
|
||||||
|
dev->map_count * sizeof(*dev->maplist),
|
||||||
|
DRM_MEM_MAPS);
|
||||||
|
dev->maplist = NULL;
|
||||||
|
dev->map_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_dma_takedown(dev);
|
||||||
|
|
||||||
|
dev->queue_count = 0;
|
||||||
|
if (dev->lock.hw_lock) {
|
||||||
|
dev->lock.hw_lock = NULL; /* SHM removed */
|
||||||
|
dev->lock.pid = 0;
|
||||||
|
wake_up_interruptible(&dev->lock.lock_queue);
|
||||||
|
}
|
||||||
|
up(&dev->struct_sem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_init is called via init_module at module load time, or via
|
||||||
|
* linux/init/main.c (this is not currently supported). */
|
||||||
|
|
||||||
|
int r128_init(void)
|
||||||
|
{
|
||||||
|
int retcode;
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
memset((void *)dev, 0, sizeof(*dev));
|
||||||
|
dev->count_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
sema_init(&dev->struct_sem, 1);
|
||||||
|
|
||||||
|
#ifdef MODULE
|
||||||
|
drm_parse_options(r128);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((retcode = misc_register(&r128_misc))) {
|
||||||
|
DRM_ERROR("Cannot register \"%s\"\n", R128_NAME);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
dev->device = MKDEV(MISC_MAJOR, r128_misc.minor);
|
||||||
|
dev->name = R128_NAME;
|
||||||
|
|
||||||
|
drm_mem_init();
|
||||||
|
drm_proc_init(dev);
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
dev->agp = drm_agp_init();
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTRR
|
||||||
|
dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
|
||||||
|
dev->agp->agp_info.aper_size*1024*1024,
|
||||||
|
MTRR_TYPE_WRCOMB,
|
||||||
|
1);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((retcode = drm_ctxbitmap_init(dev))) {
|
||||||
|
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||||
|
drm_proc_cleanup();
|
||||||
|
misc_deregister(&r128_misc);
|
||||||
|
r128_takedown(dev);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
|
||||||
|
R128_NAME,
|
||||||
|
R128_MAJOR,
|
||||||
|
R128_MINOR,
|
||||||
|
R128_PATCHLEVEL,
|
||||||
|
R128_DATE,
|
||||||
|
r128_misc.minor);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_cleanup is called via cleanup_module at module unload time. */
|
||||||
|
|
||||||
|
void r128_cleanup(void)
|
||||||
|
{
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
drm_proc_cleanup();
|
||||||
|
if (misc_deregister(&r128_misc)) {
|
||||||
|
DRM_ERROR("Cannot unload module\n");
|
||||||
|
} else {
|
||||||
|
DRM_INFO("Module unloaded\n");
|
||||||
|
}
|
||||||
|
drm_ctxbitmap_cleanup(dev);
|
||||||
|
r128_takedown(dev);
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
if (dev->agp) {
|
||||||
|
/* FIXME -- free other information, too */
|
||||||
|
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||||
|
dev->agp = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_version(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
drm_version_t version;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
copy_from_user_ret(&version,
|
||||||
|
(drm_version_t *)arg,
|
||||||
|
sizeof(version),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
#define DRM_COPY(name,value) \
|
||||||
|
len = strlen(value); \
|
||||||
|
if (len > name##_len) len = name##_len; \
|
||||||
|
name##_len = strlen(value); \
|
||||||
|
if (len && name) { \
|
||||||
|
copy_to_user_ret(name, value, len, -EFAULT); \
|
||||||
|
}
|
||||||
|
|
||||||
|
version.version_major = R128_MAJOR;
|
||||||
|
version.version_minor = R128_MINOR;
|
||||||
|
version.version_patchlevel = R128_PATCHLEVEL;
|
||||||
|
|
||||||
|
DRM_COPY(version.name, R128_NAME);
|
||||||
|
DRM_COPY(version.date, R128_DATE);
|
||||||
|
DRM_COPY(version.desc, R128_DESC);
|
||||||
|
|
||||||
|
copy_to_user_ret((drm_version_t *)arg,
|
||||||
|
&version,
|
||||||
|
sizeof(version),
|
||||||
|
-EFAULT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_open(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
int retcode = 0;
|
||||||
|
|
||||||
|
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||||
|
if (!(retcode = drm_open_helper(inode, filp, dev))) {
|
||||||
|
MOD_INC_USE_COUNT;
|
||||||
|
atomic_inc(&dev->total_open);
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (!dev->open_count++) {
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return r128_setup(dev);
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_release(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
int retcode = 0;
|
||||||
|
|
||||||
|
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||||
|
if (!(retcode = drm_release(inode, filp))) {
|
||||||
|
MOD_DEC_USE_COUNT;
|
||||||
|
atomic_inc(&dev->total_close);
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (!--dev->open_count) {
|
||||||
|
if (atomic_read(&dev->ioctl_count) || dev->blocked) {
|
||||||
|
DRM_ERROR("Device busy: %d %d\n",
|
||||||
|
atomic_read(&dev->ioctl_count),
|
||||||
|
dev->blocked);
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return r128_takedown(dev);
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */
|
||||||
|
|
||||||
|
int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
int nr = DRM_IOCTL_NR(cmd);
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
int retcode = 0;
|
||||||
|
drm_ioctl_desc_t *ioctl;
|
||||||
|
drm_ioctl_t *func;
|
||||||
|
|
||||||
|
atomic_inc(&dev->ioctl_count);
|
||||||
|
atomic_inc(&dev->total_ioctl);
|
||||||
|
++priv->ioctl_count;
|
||||||
|
|
||||||
|
DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
|
||||||
|
current->pid, cmd, nr, dev->device, priv->authenticated);
|
||||||
|
|
||||||
|
if (nr >= R128_IOCTL_COUNT) {
|
||||||
|
retcode = -EINVAL;
|
||||||
|
} else {
|
||||||
|
ioctl = &r128_ioctls[nr];
|
||||||
|
func = ioctl->func;
|
||||||
|
|
||||||
|
if (!func) {
|
||||||
|
DRM_DEBUG("no function\n");
|
||||||
|
retcode = -EINVAL;
|
||||||
|
} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
|
||||||
|
|| (ioctl->auth_needed && !priv->authenticated)) {
|
||||||
|
retcode = -EACCES;
|
||||||
|
} else {
|
||||||
|
retcode = (func)(inode, filp, cmd, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_dec(&dev->ioctl_count);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_lock(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;
|
||||||
|
DECLARE_WAITQUEUE(entry, current);
|
||||||
|
int ret = 0;
|
||||||
|
drm_lock_t lock;
|
||||||
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
cycles_t start;
|
||||||
|
|
||||||
|
dev->lck_start = start = get_cycles();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
|
||||||
|
|
||||||
|
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||||
|
DRM_ERROR("Process %d using kernel context %d\n",
|
||||||
|
current->pid, lock.context);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||||
|
lock.context, current->pid, dev->lock.hw_lock->lock,
|
||||||
|
lock.flags);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* dev->queue_count == 0 right now for
|
||||||
|
r128. FIXME? */
|
||||||
|
if (lock.context < 0 || lock.context >= dev->queue_count)
|
||||||
|
return -EINVAL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
#if 0
|
||||||
|
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
|
||||||
|
!= lock.context) {
|
||||||
|
long j = jiffies - dev->lock.lock_time;
|
||||||
|
|
||||||
|
if (lock.context == r128_res_ctx.handle &&
|
||||||
|
j >= 0 && j < DRM_LOCK_SLICE) {
|
||||||
|
/* Can't take lock if we just had it and
|
||||||
|
there is contention. */
|
||||||
|
DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
|
||||||
|
lock.context, current->pid, j,
|
||||||
|
dev->lock.lock_time, jiffies);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
schedule_timeout(DRM_LOCK_SLICE-j);
|
||||||
|
DRM_DEBUG("jiffies=%d\n", jiffies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
|
for (;;) {
|
||||||
|
if (!dev->lock.hw_lock) {
|
||||||
|
/* Device has been unregistered */
|
||||||
|
ret = -EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (drm_lock_take(&dev->lock.hw_lock->lock,
|
||||||
|
lock.context)) {
|
||||||
|
dev->lock.pid = current->pid;
|
||||||
|
dev->lock.lock_time = jiffies;
|
||||||
|
atomic_inc(&dev->total_locks);
|
||||||
|
break; /* Got lock */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Contention */
|
||||||
|
atomic_inc(&dev->total_sleeps);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
#if 1
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
#endif
|
||||||
|
schedule();
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current->state = TASK_RUNNING;
|
||||||
|
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!ret && dev->last_context != lock.context &&
|
||||||
|
lock.context != r128_res_ctx.handle &&
|
||||||
|
dev->last_context != r128_res_ctx.handle) {
|
||||||
|
add_wait_queue(&dev->context_wait, &entry);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
/* PRE: dev->last_context != lock.context */
|
||||||
|
r128_context_switch(dev, dev->last_context, lock.context);
|
||||||
|
/* POST: we will wait for the context
|
||||||
|
switch and will dispatch on a later call
|
||||||
|
when dev->last_context == lock.context
|
||||||
|
NOTE WE HOLD THE LOCK THROUGHOUT THIS
|
||||||
|
TIME! */
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
schedule();
|
||||||
|
current->state = TASK_RUNNING;
|
||||||
|
remove_wait_queue(&dev->context_wait, &entry);
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
ret = -EINTR;
|
||||||
|
} else if (dev->last_context != lock.context) {
|
||||||
|
DRM_ERROR("Context mismatch: %d %d\n",
|
||||||
|
dev->last_context, lock.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
if (lock.flags & _DRM_LOCK_READY) {
|
||||||
|
/* Wait for space in DMA/FIFO */
|
||||||
|
}
|
||||||
|
if (lock.flags & _DRM_LOCK_QUIESCENT) {
|
||||||
|
/* Make hardware quiescent */
|
||||||
|
#if 0
|
||||||
|
r128_quiescent(dev);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DRM_ERROR("pid = %5d, old counter = %5ld\n",
|
||||||
|
current->pid, current->counter);
|
||||||
|
#endif
|
||||||
|
if (lock.context != r128_res_ctx.handle) {
|
||||||
|
current->counter = 5;
|
||||||
|
current->priority = DEF_PRIORITY/4;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
while (current->counter > 25)
|
||||||
|
current->counter >>= 1; /* decrease time slice */
|
||||||
|
DRM_ERROR("pid = %5d, new counter = %5ld\n",
|
||||||
|
current->pid, current->counter);
|
||||||
|
#endif
|
||||||
|
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
|
||||||
|
|
||||||
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int r128_unlock(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_lock_t lock;
|
||||||
|
|
||||||
|
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
|
||||||
|
|
||||||
|
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||||
|
DRM_ERROR("Process %d using kernel context %d\n",
|
||||||
|
current->pid, lock.context);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG("%d frees lock (%d holds)\n",
|
||||||
|
lock.context,
|
||||||
|
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||||
|
atomic_inc(&dev->total_unlocks);
|
||||||
|
if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
|
||||||
|
atomic_inc(&dev->total_contends);
|
||||||
|
drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
|
||||||
|
/* FIXME: Try to send data to card here */
|
||||||
|
if (!dev->context_flag) {
|
||||||
|
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
|
||||||
|
DRM_KERNEL_CONTEXT)) {
|
||||||
|
DRM_ERROR("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule_timeout(1000);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (lock.context != r128_res_ctx.handle) {
|
||||||
|
current->counter = 5;
|
||||||
|
current->priority = DEF_PRIORITY;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule_timeout(10);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -49,3 +49,5 @@ i810.o: i810_drv.o i810_context.o $(L_TARGET)
|
||||||
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
|
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
|
||||||
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm
|
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm
|
||||||
|
|
||||||
|
r128.o: r128_drv.o r128_context.o $(L_TARGET)
|
||||||
|
$(LD) $(LD_RFLAG) -r -o $@ r128_drv.o r128_context.o -L. -ldrm
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
# Makefile -- For the Direct Rendering Manager module (drm)
|
# Makefile -- For the Direct Rendering Manager module (drm)
|
||||||
# Created: Mon Jan 4 09:26:53 1999 by faith@precisioninsight.com
|
# Created: Mon Jan 4 09:26:53 1999 by faith@precisioninsight.com
|
||||||
# Revised: Sun Feb 13 23:15:59 2000 by kevin@precisioninsight.com
|
|
||||||
#
|
#
|
||||||
# Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
# Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -33,7 +32,7 @@
|
||||||
|
|
||||||
# **** End of SMP/MODVERSIONS detection
|
# **** End of SMP/MODVERSIONS detection
|
||||||
|
|
||||||
MODS= gamma.o tdfx.o
|
MODS= gamma.o tdfx.o r128.o
|
||||||
LIBS= libdrm.a
|
LIBS= libdrm.a
|
||||||
PROGS= drmstat
|
PROGS= drmstat
|
||||||
|
|
||||||
|
@ -47,6 +46,9 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
|
||||||
TDFXOBJS= tdfx_drv.o tdfx_context.o
|
TDFXOBJS= tdfx_drv.o tdfx_context.o
|
||||||
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
|
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
|
||||||
|
|
||||||
|
R128OBJS= r128_drv.o r128_dma.o r128_bufs.o r128_context.o
|
||||||
|
R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS)
|
||||||
|
|
||||||
PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po
|
PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po
|
||||||
PROGHEADERS= xf86drm.h $(DRMHEADERS)
|
PROGHEADERS= xf86drm.h $(DRMHEADERS)
|
||||||
|
|
||||||
|
@ -153,6 +155,9 @@ gamma.o: $(GAMMAOBJS) $(LIBS)
|
||||||
tdfx.o: $(TDFXOBJS) $(LIBS)
|
tdfx.o: $(TDFXOBJS) $(LIBS)
|
||||||
$(LD) -r $^ -o $@
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
|
r128.o: $(R128OBJS) $(LIBS)
|
||||||
|
$(LD) -r $^ -o $@
|
||||||
|
|
||||||
ifeq ($(AGP),1)
|
ifeq ($(AGP),1)
|
||||||
mga.o: $(MGAOBJS) $(LIBS)
|
mga.o: $(MGAOBJS) $(LIBS)
|
||||||
$(LD) -r $^ -o $@
|
$(LD) -r $^ -o $@
|
||||||
|
@ -182,6 +187,7 @@ ChangeLog:
|
||||||
$(DRMOBJS): $(DRMHEADERS)
|
$(DRMOBJS): $(DRMHEADERS)
|
||||||
$(GAMMAOBJS): $(GAMMAHEADERS)
|
$(GAMMAOBJS): $(GAMMAHEADERS)
|
||||||
$(TDFXOBJS): $(TDFXHEADERS)
|
$(TDFXOBJS): $(TDFXHEADERS)
|
||||||
|
$(R128OBJS): $(R128HEADERS)
|
||||||
ifeq ($(AGP),1)
|
ifeq ($(AGP),1)
|
||||||
$(MGAOBJS): $(MGAHEADERS)
|
$(MGAOBJS): $(MGAHEADERS)
|
||||||
$(I810OBJS): $(I810HEADERS)
|
$(I810OBJS): $(I810HEADERS)
|
||||||
|
|
|
@ -239,6 +239,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
if ((retcode = drm_bind_agp(entry->memory, page))) return retcode;
|
if ((retcode = drm_bind_agp(entry->memory, page))) return retcode;
|
||||||
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
|
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
|
||||||
|
DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
|
||||||
|
dev->agp->base, entry->bound);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
linux/drm.h
14
linux/drm.h
|
@ -1,8 +1,7 @@
|
||||||
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
||||||
* Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -71,9 +70,10 @@ typedef struct drm_clip_rect {
|
||||||
unsigned short y2;
|
unsigned short y2;
|
||||||
} drm_clip_rect_t;
|
} drm_clip_rect_t;
|
||||||
|
|
||||||
/* Seperate include files for the i810/mga specific structures */
|
/* Seperate include files for the i810/mga/r128 specific structures */
|
||||||
#include "mga_drm.h"
|
#include "mga_drm.h"
|
||||||
#include "i810_drm.h"
|
#include "i810_drm.h"
|
||||||
|
#include "r128_drm.h"
|
||||||
|
|
||||||
typedef struct drm_version {
|
typedef struct drm_version {
|
||||||
int version_major; /* Major version */
|
int version_major; /* Major version */
|
||||||
|
@ -349,4 +349,12 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||||
|
|
||||||
|
/* Rage 128 specific ioctls */
|
||||||
|
#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
|
||||||
|
#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
|
||||||
|
#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
|
||||||
|
#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
|
||||||
|
#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
|
||||||
|
#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
14
linux/drmP.h
14
linux/drmP.h
|
@ -1,8 +1,7 @@
|
||||||
/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
|
/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
||||||
* Revised: Sun Feb 13 23:34:30 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -228,8 +227,8 @@ typedef struct drm_magic_entry {
|
||||||
} drm_magic_entry_t;
|
} drm_magic_entry_t;
|
||||||
|
|
||||||
typedef struct drm_magic_head {
|
typedef struct drm_magic_head {
|
||||||
struct drm_magic_entry *head;
|
struct drm_magic_entry *head;
|
||||||
struct drm_magic_entry *tail;
|
struct drm_magic_entry *tail;
|
||||||
} drm_magic_head_t;
|
} drm_magic_head_t;
|
||||||
|
|
||||||
typedef struct drm_vma_entry {
|
typedef struct drm_vma_entry {
|
||||||
|
@ -262,16 +261,15 @@ typedef struct drm_buf {
|
||||||
DRM_LIST_RECLAIM = 5
|
DRM_LIST_RECLAIM = 5
|
||||||
} list; /* Which list we're on */
|
} list; /* Which list we're on */
|
||||||
|
|
||||||
|
|
||||||
void *dev_private;
|
|
||||||
int dev_priv_size;
|
|
||||||
|
|
||||||
#if DRM_DMA_HISTOGRAM
|
#if DRM_DMA_HISTOGRAM
|
||||||
cycles_t time_queued; /* Queued to kernel DMA queue */
|
cycles_t time_queued; /* Queued to kernel DMA queue */
|
||||||
cycles_t time_dispatched; /* Dispatched to hardware */
|
cycles_t time_dispatched; /* Dispatched to hardware */
|
||||||
cycles_t time_completed; /* Completed by hardware */
|
cycles_t time_completed; /* Completed by hardware */
|
||||||
cycles_t time_freed; /* Back on freelist */
|
cycles_t time_freed; /* Back on freelist */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int dev_priv_size; /* Size of buffer private stoarge */
|
||||||
|
void *dev_private; /* Per-buffer private storage */
|
||||||
} drm_buf_t;
|
} drm_buf_t;
|
||||||
|
|
||||||
#if DRM_DMA_HISTOGRAM
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* proc.c -- /proc support for DRM -*- linux-c -*-
|
/* proc.c -- /proc support for DRM -*- linux-c -*-
|
||||||
* Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
|
||||||
* Revised: Sun Feb 13 23:41:04 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -400,6 +399,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
|
||||||
pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
|
pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
|
||||||
#endif
|
#endif
|
||||||
DRM_PROC_PRINT("\n");
|
DRM_PROC_PRINT("\n");
|
||||||
|
#if 0
|
||||||
for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
|
for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
|
||||||
pgd = pgd_offset(vma->vm_mm, i);
|
pgd = pgd_offset(vma->vm_mm, i);
|
||||||
pmd = pmd_offset(pgd, i);
|
pmd = pmd_offset(pgd, i);
|
||||||
|
@ -420,6 +420,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
|
||||||
DRM_PROC_PRINT(" 0x%08lx\n", i);
|
DRM_PROC_PRINT(" 0x%08lx\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
|
||||||
|
* Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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 <kevin@precisioninsight.com>
|
||||||
|
* Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
* Jeff Hartmann <jhartmann@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include "drmP.h"
|
||||||
|
#include "r128_drv.h"
|
||||||
|
#include "linux/un.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
int r128_addbufs_agp(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_device_dma_t *dma = dev->dma;
|
||||||
|
drm_buf_desc_t request;
|
||||||
|
drm_buf_entry_t *entry;
|
||||||
|
drm_buf_t *buf;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long agp_offset;
|
||||||
|
int count;
|
||||||
|
int order;
|
||||||
|
int size;
|
||||||
|
int alignment;
|
||||||
|
int page_order;
|
||||||
|
int total;
|
||||||
|
int byte_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!dma) return -EINVAL;
|
||||||
|
|
||||||
|
copy_from_user_ret(&request,
|
||||||
|
(drm_buf_desc_t *)arg,
|
||||||
|
sizeof(request),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
count = request.count;
|
||||||
|
order = drm_order(request.size);
|
||||||
|
size = 1 << order;
|
||||||
|
|
||||||
|
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
|
||||||
|
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
|
||||||
|
total = PAGE_SIZE << page_order;
|
||||||
|
|
||||||
|
byte_count = 0;
|
||||||
|
agp_offset = dev->agp->base + request.agp_start;
|
||||||
|
|
||||||
|
DRM_DEBUG("count: %d\n", count);
|
||||||
|
DRM_DEBUG("order: %d\n", order);
|
||||||
|
DRM_DEBUG("size: %d\n", size);
|
||||||
|
DRM_DEBUG("agp_offset: %ld\n", agp_offset);
|
||||||
|
DRM_DEBUG("alignment: %d\n", alignment);
|
||||||
|
DRM_DEBUG("page_order: %d\n", page_order);
|
||||||
|
DRM_DEBUG("total: %d\n", total);
|
||||||
|
|
||||||
|
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
|
||||||
|
if (dev->queue_count) return -EBUSY; /* Not while in use */
|
||||||
|
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (dev->buf_use) {
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
atomic_inc(&dev->buf_alloc);
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
|
||||||
|
down(&dev->struct_sem);
|
||||||
|
entry = &dma->bufs[order];
|
||||||
|
if (entry->buf_count) {
|
||||||
|
up(&dev->struct_sem);
|
||||||
|
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) {
|
||||||
|
up(&dev->struct_sem);
|
||||||
|
atomic_dec(&dev->buf_alloc);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
|
||||||
|
|
||||||
|
entry->buf_size = size;
|
||||||
|
entry->page_order = page_order;
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
for (offset = 0;
|
||||||
|
entry->buf_count < count;
|
||||||
|
offset += alignment, ++entry->buf_count) {
|
||||||
|
buf = &entry->buflist[entry->buf_count];
|
||||||
|
buf->idx = dma->buf_count + entry->buf_count;
|
||||||
|
buf->total = alignment;
|
||||||
|
buf->order = order;
|
||||||
|
buf->used = 0;
|
||||||
|
buf->offset = (dma->byte_count + offset);
|
||||||
|
buf->address = (void *)(agp_offset + offset);
|
||||||
|
buf->next = NULL;
|
||||||
|
buf->waiting = 0;
|
||||||
|
buf->pending = 0;
|
||||||
|
init_waitqueue_head(&buf->dma_wait);
|
||||||
|
buf->pid = 0;
|
||||||
|
|
||||||
|
buf->dev_priv_size = sizeof(drm_r128_buf_priv_t);
|
||||||
|
buf->dev_private = drm_alloc(sizeof(drm_r128_buf_priv_t),
|
||||||
|
DRM_MEM_BUFS);
|
||||||
|
memset(buf->dev_private, 0, buf->dev_priv_size);
|
||||||
|
|
||||||
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
buf->time_queued = 0;
|
||||||
|
buf->time_dispatched = 0;
|
||||||
|
buf->time_completed = 0;
|
||||||
|
buf->time_freed = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
byte_count += PAGE_SIZE << page_order;
|
||||||
|
|
||||||
|
DRM_DEBUG("buffer %d @ %p\n",
|
||||||
|
entry->buf_count, buf->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG("byte_count: %d\n", byte_count);
|
||||||
|
|
||||||
|
dma->buflist = drm_realloc(dma->buflist,
|
||||||
|
dma->buf_count * sizeof(*dma->buflist),
|
||||||
|
(dma->buf_count + entry->buf_count)
|
||||||
|
* sizeof(*dma->buflist),
|
||||||
|
DRM_MEM_BUFS);
|
||||||
|
for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
|
||||||
|
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
|
||||||
|
|
||||||
|
dma->buf_count += entry->buf_count;
|
||||||
|
dma->byte_count += byte_count;
|
||||||
|
|
||||||
|
drm_freelist_create(&entry->freelist, entry->buf_count);
|
||||||
|
for (i = 0; i < entry->buf_count; i++) {
|
||||||
|
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
up(&dev->struct_sem);
|
||||||
|
|
||||||
|
request.count = entry->buf_count;
|
||||||
|
request.size = size;
|
||||||
|
|
||||||
|
copy_to_user_ret((drm_buf_desc_t *)arg,
|
||||||
|
&request,
|
||||||
|
sizeof(request),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
dma->flags = _DRM_DMA_USE_AGP;
|
||||||
|
|
||||||
|
atomic_dec(&dev->buf_alloc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int r128_addbufs(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_buf_desc_t request;
|
||||||
|
|
||||||
|
if (!dev_priv || dev_priv->is_pci) return -EINVAL;
|
||||||
|
|
||||||
|
copy_from_user_ret(&request,
|
||||||
|
(drm_buf_desc_t *)arg,
|
||||||
|
sizeof(request),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
if (request.flags & _DRM_AGP_BUFFER)
|
||||||
|
return r128_addbufs_agp(inode, filp, cmd, arg);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_mapbufs(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;
|
||||||
|
const int zero = 0;
|
||||||
|
unsigned long virtual;
|
||||||
|
unsigned long address;
|
||||||
|
drm_buf_map_t request;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (atomic_read(&dev->buf_alloc)) {
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
++dev->buf_use; /* Can't allocate more after this call */
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
|
||||||
|
copy_from_user_ret(&request,
|
||||||
|
(drm_buf_map_t *)arg,
|
||||||
|
sizeof(request),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
if (request.count >= dma->buf_count) {
|
||||||
|
if (dma->flags & _DRM_DMA_USE_AGP) {
|
||||||
|
drm_map_t *map;
|
||||||
|
|
||||||
|
map = dev_priv->agp_vertbufs;
|
||||||
|
if (!map) {
|
||||||
|
retcode = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
down(¤t->mm->mmap_sem);
|
||||||
|
virtual = do_mmap(filp, 0, map->size,
|
||||||
|
PROT_READ|PROT_WRITE,
|
||||||
|
MAP_SHARED,
|
||||||
|
(unsigned long)map->offset);
|
||||||
|
up(¤t->mm->mmap_sem);
|
||||||
|
} else {
|
||||||
|
down(¤t->mm->mmap_sem);
|
||||||
|
virtual = do_mmap(filp, 0, dma->byte_count,
|
||||||
|
PROT_READ|PROT_WRITE, MAP_SHARED, 0);
|
||||||
|
up(¤t->mm->mmap_sem);
|
||||||
|
}
|
||||||
|
if (virtual > -1024UL) {
|
||||||
|
/* Real error */
|
||||||
|
retcode = (signed long)virtual;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
request.virtual = (void *)virtual;
|
||||||
|
|
||||||
|
for (i = 0; i < dma->buf_count; i++) {
|
||||||
|
if (copy_to_user(&request.list[i].idx,
|
||||||
|
&dma->buflist[i]->idx,
|
||||||
|
sizeof(request.list[0].idx))) {
|
||||||
|
retcode = -EFAULT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (copy_to_user(&request.list[i].total,
|
||||||
|
&dma->buflist[i]->total,
|
||||||
|
sizeof(request.list[0].total))) {
|
||||||
|
retcode = -EFAULT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (copy_to_user(&request.list[i].used,
|
||||||
|
&zero,
|
||||||
|
sizeof(zero))) {
|
||||||
|
retcode = -EFAULT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
address = virtual + dma->buflist[i]->offset;
|
||||||
|
if (copy_to_user(&request.list[i].address,
|
||||||
|
&address,
|
||||||
|
sizeof(address))) {
|
||||||
|
retcode = -EFAULT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
request.count = dma->buf_count;
|
||||||
|
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
|
||||||
|
|
||||||
|
copy_to_user_ret((drm_buf_map_t *)arg,
|
||||||
|
&request,
|
||||||
|
sizeof(request),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
return retcode;
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/* r128_context.c -- IOCTLs for r128 contexts -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 13 09:51:35 1999 by faith@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Author: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
#define __NO_VERSION__
|
||||||
|
#include "drmP.h"
|
||||||
|
#include "r128_drv.h"
|
||||||
|
|
||||||
|
extern drm_ctx_t r128_res_ctx;
|
||||||
|
|
||||||
|
static int r128_alloc_queue(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
static int context = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return drm_ctxbitmap_next(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_context_switch(drm_device_t *dev, int old, int new)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
atomic_inc(&dev->total_ctx);
|
||||||
|
|
||||||
|
if (test_and_set_bit(0, &dev->context_flag)) {
|
||||||
|
DRM_ERROR("Reentering -- FIXME\n");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a context switch is ever initiated
|
||||||
|
when the kernel holds the lock, release
|
||||||
|
that lock here. */
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
drm_ctx_res_t res;
|
||||||
|
drm_ctx_t ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
|
||||||
|
copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
|
||||||
|
if (res.count >= DRM_RESERVED_CONTEXTS) {
|
||||||
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
|
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||||
|
ctx.handle = i;
|
||||||
|
copy_to_user_ret(&res.contexts[i],
|
||||||
|
&i,
|
||||||
|
sizeof(i),
|
||||||
|
-EFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.count = DRM_RESERVED_CONTEXTS;
|
||||||
|
copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int r128_addctx(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_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
|
||||||
|
if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
|
||||||
|
/* Skip kernel's context and get a new one. */
|
||||||
|
ctx.handle = r128_alloc_queue(dev);
|
||||||
|
}
|
||||||
|
DRM_DEBUG("%d\n", ctx.handle);
|
||||||
|
if (ctx.handle == -1) {
|
||||||
|
DRM_DEBUG("Not enough free contexts.\n");
|
||||||
|
/* Should this return -EBUSY instead? */
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
drm_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
|
||||||
|
if (ctx.flags==_DRM_CONTEXT_PRESERVED)
|
||||||
|
r128_res_ctx.handle=ctx.handle;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
drm_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
|
||||||
|
/* This is 0, because we don't hanlde any context flags */
|
||||||
|
ctx.flags = 0;
|
||||||
|
copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_switchctx(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_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
|
||||||
|
DRM_DEBUG("%d\n", ctx.handle);
|
||||||
|
return r128_context_switch(dev, dev->last_context, ctx.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_newctx(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_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
|
||||||
|
DRM_DEBUG("%d\n", ctx.handle);
|
||||||
|
r128_context_switch_complete(dev, ctx.handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_rmctx(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_ctx_t ctx;
|
||||||
|
|
||||||
|
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
|
||||||
|
DRM_DEBUG("%d\n", ctx.handle);
|
||||||
|
drm_ctxbitmap_free(dev, ctx.handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,908 @@
|
||||||
|
/* 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.
|
||||||
|
* 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 <kevin@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void r128_flush_write_combine(void)
|
||||||
|
{
|
||||||
|
int xchangeDummy;
|
||||||
|
|
||||||
|
__asm__ volatile("push %%eax ;"
|
||||||
|
"xchg %%eax, %0 ;"
|
||||||
|
"pop %%eax" : : "m" (xchangeDummy));
|
||||||
|
__asm__ volatile("push %%eax ;"
|
||||||
|
"push %%ebx ;"
|
||||||
|
"push %%ecx ;"
|
||||||
|
"push %%edx ;"
|
||||||
|
"movl $0,%%eax ;"
|
||||||
|
"cpuid ;"
|
||||||
|
"pop %%edx ;"
|
||||||
|
"pop %%ecx ;"
|
||||||
|
"pop %%ebx ;"
|
||||||
|
"pop %%eax" : /* no outputs */ : /* no inputs */ );
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init),
|
||||||
|
-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_CPP);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet),
|
||||||
|
-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;
|
||||||
|
copy_from_user_ret(buffer, packet.buffer, size, -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;
|
||||||
|
copy_from_user_ret(buffer, packet.buffer, size, -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;
|
||||||
|
copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet),
|
||||||
|
-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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
copy_to_user_ret(&v->request_indices[i],
|
||||||
|
&buf->idx,
|
||||||
|
sizeof(buf->idx),
|
||||||
|
-EFAULT);
|
||||||
|
copy_to_user_ret(&v->request_sizes[i],
|
||||||
|
&buf->total,
|
||||||
|
sizeof(buf->total),
|
||||||
|
-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;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -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);
|
||||||
|
copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT);
|
||||||
|
|
||||||
|
return retcode;
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
|
||||||
|
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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 <kevin@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _R128_DRM_H_
|
||||||
|
#define _R128_DRM_H_
|
||||||
|
|
||||||
|
/* WARNING: If you change any of these defines, make sure to change the
|
||||||
|
* defines in the Xserver file (xf86drmR128.h)
|
||||||
|
*/
|
||||||
|
typedef struct drm_r128_init {
|
||||||
|
enum {
|
||||||
|
R128_INIT_CCE = 0x01,
|
||||||
|
R128_CLEANUP_CCE = 0x02
|
||||||
|
} func;
|
||||||
|
int sarea_priv_offset;
|
||||||
|
int is_pci;
|
||||||
|
int cce_mode;
|
||||||
|
int cce_fifo_size;
|
||||||
|
int cce_secure;
|
||||||
|
int ring_size;
|
||||||
|
int usec_timeout;
|
||||||
|
|
||||||
|
int fb_offset;
|
||||||
|
int agp_ring_offset;
|
||||||
|
int agp_read_ptr_offset;
|
||||||
|
int agp_vertbufs_offset;
|
||||||
|
int agp_indbufs_offset;
|
||||||
|
int agp_textures_offset;
|
||||||
|
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_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 */
|
||||||
|
} 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;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,737 @@
|
||||||
|
/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXPORT_SYMTAB
|
||||||
|
#include "drmP.h"
|
||||||
|
#include "r128_drv.h"
|
||||||
|
EXPORT_SYMBOL(r128_init);
|
||||||
|
EXPORT_SYMBOL(r128_cleanup);
|
||||||
|
|
||||||
|
#define R128_NAME "r128"
|
||||||
|
#define R128_DESC "r128"
|
||||||
|
#define R128_DATE "20000422"
|
||||||
|
#define R128_MAJOR 0
|
||||||
|
#define R128_MINOR 0
|
||||||
|
#define R128_PATCHLEVEL 5
|
||||||
|
|
||||||
|
static drm_device_t r128_device;
|
||||||
|
drm_ctx_t r128_res_ctx;
|
||||||
|
|
||||||
|
static struct file_operations r128_fops = {
|
||||||
|
open: r128_open,
|
||||||
|
flush: drm_flush,
|
||||||
|
release: r128_release,
|
||||||
|
ioctl: r128_ioctl,
|
||||||
|
mmap: drm_mmap,
|
||||||
|
read: drm_read,
|
||||||
|
fasync: drm_fasync,
|
||||||
|
poll: drm_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct miscdevice r128_misc = {
|
||||||
|
minor: MISC_DYNAMIC_MINOR,
|
||||||
|
name: R128_NAME,
|
||||||
|
fops: &r128_fops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static drm_ioctl_desc_t r128_ioctls[] = {
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_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_CCEIDL)] = { r128_cce_idle, 1, 0 },
|
||||||
|
[DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 },
|
||||||
|
};
|
||||||
|
#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
|
||||||
|
|
||||||
|
#ifdef MODULE
|
||||||
|
int init_module(void);
|
||||||
|
void cleanup_module(void);
|
||||||
|
static char *r128 = NULL;
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas.");
|
||||||
|
MODULE_DESCRIPTION("r128");
|
||||||
|
MODULE_PARM(r128, "s");
|
||||||
|
|
||||||
|
/* init_module is called when insmod is used to load the module */
|
||||||
|
|
||||||
|
int init_module(void)
|
||||||
|
{
|
||||||
|
return r128_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup_module is called when rmmod is used to unload the module */
|
||||||
|
|
||||||
|
void cleanup_module(void)
|
||||||
|
{
|
||||||
|
r128_cleanup();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MODULE
|
||||||
|
/* r128_setup is called by the kernel to parse command-line options passed
|
||||||
|
* via the boot-loader (e.g., LILO). It calls the insmod option routine,
|
||||||
|
* drm_parse_drm.
|
||||||
|
*
|
||||||
|
* This is not currently supported, since it requires changes to
|
||||||
|
* linux/init/main.c. */
|
||||||
|
|
||||||
|
|
||||||
|
void __init r128_setup(char *str, int *ints)
|
||||||
|
{
|
||||||
|
if (ints[0] != 0) {
|
||||||
|
DRM_ERROR("Illegal command line format, ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drm_parse_options(str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int r128_setup(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
atomic_set(&dev->ioctl_count, 0);
|
||||||
|
atomic_set(&dev->vma_count, 0);
|
||||||
|
dev->buf_use = 0;
|
||||||
|
atomic_set(&dev->buf_alloc, 0);
|
||||||
|
|
||||||
|
drm_dma_setup(dev);
|
||||||
|
|
||||||
|
atomic_set(&dev->total_open, 0);
|
||||||
|
atomic_set(&dev->total_close, 0);
|
||||||
|
atomic_set(&dev->total_ioctl, 0);
|
||||||
|
atomic_set(&dev->total_irq, 0);
|
||||||
|
atomic_set(&dev->total_ctx, 0);
|
||||||
|
atomic_set(&dev->total_locks, 0);
|
||||||
|
atomic_set(&dev->total_unlocks, 0);
|
||||||
|
atomic_set(&dev->total_contends, 0);
|
||||||
|
atomic_set(&dev->total_sleeps, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||||
|
dev->magiclist[i].head = NULL;
|
||||||
|
dev->magiclist[i].tail = NULL;
|
||||||
|
}
|
||||||
|
dev->maplist = NULL;
|
||||||
|
dev->map_count = 0;
|
||||||
|
dev->vmalist = NULL;
|
||||||
|
dev->lock.hw_lock = NULL;
|
||||||
|
init_waitqueue_head(&dev->lock.lock_queue);
|
||||||
|
dev->queue_count = 0;
|
||||||
|
dev->queue_reserved = 0;
|
||||||
|
dev->queue_slots = 0;
|
||||||
|
dev->queuelist = NULL;
|
||||||
|
dev->irq = 0;
|
||||||
|
dev->context_flag = 0;
|
||||||
|
dev->interrupt_flag = 0;
|
||||||
|
dev->dma_flag = 0;
|
||||||
|
dev->last_context = 0;
|
||||||
|
dev->last_switch = 0;
|
||||||
|
dev->last_checked = 0;
|
||||||
|
init_timer(&dev->timer);
|
||||||
|
init_waitqueue_head(&dev->context_wait);
|
||||||
|
|
||||||
|
dev->ctx_start = 0;
|
||||||
|
dev->lck_start = 0;
|
||||||
|
|
||||||
|
dev->buf_rp = dev->buf;
|
||||||
|
dev->buf_wp = dev->buf;
|
||||||
|
dev->buf_end = dev->buf + DRM_BSZ;
|
||||||
|
dev->buf_async = NULL;
|
||||||
|
init_waitqueue_head(&dev->buf_readers);
|
||||||
|
init_waitqueue_head(&dev->buf_writers);
|
||||||
|
|
||||||
|
r128_res_ctx.handle=-1;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
/* The kernel's context could be created here, but is now created
|
||||||
|
in drm_dma_enqueue. This is more resource-efficient for
|
||||||
|
hardware that does not do DMA, but may mean that
|
||||||
|
drm_select_queue fails between the time the interrupt is
|
||||||
|
initialized and the time the queues are initialized. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int r128_takedown(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
drm_magic_entry_t *pt, *next;
|
||||||
|
drm_map_t *map;
|
||||||
|
drm_vma_entry_t *vma, *vma_next;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
down(&dev->struct_sem);
|
||||||
|
del_timer(&dev->timer);
|
||||||
|
|
||||||
|
if (dev->devname) {
|
||||||
|
drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
|
||||||
|
dev->devname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->unique) {
|
||||||
|
drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
|
||||||
|
dev->unique = NULL;
|
||||||
|
dev->unique_len = 0;
|
||||||
|
}
|
||||||
|
/* Clear pid list */
|
||||||
|
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||||
|
for (pt = dev->magiclist[i].head; pt; pt = next) {
|
||||||
|
next = pt->next;
|
||||||
|
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||||
|
}
|
||||||
|
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
/* Clear AGP information */
|
||||||
|
if (dev->agp) {
|
||||||
|
drm_agp_mem_t *entry;
|
||||||
|
drm_agp_mem_t *nexte;
|
||||||
|
|
||||||
|
/* Remove AGP resources, but leave dev->agp
|
||||||
|
intact until r128_cleanup is called. */
|
||||||
|
for (entry = dev->agp->memory; entry; entry = nexte) {
|
||||||
|
nexte = entry->next;
|
||||||
|
if (entry->bound) drm_unbind_agp(entry->memory);
|
||||||
|
drm_free_agp(entry->memory, entry->pages);
|
||||||
|
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
|
||||||
|
}
|
||||||
|
dev->agp->memory = NULL;
|
||||||
|
|
||||||
|
if (dev->agp->acquired && drm_agp.release)
|
||||||
|
(*drm_agp.release)();
|
||||||
|
|
||||||
|
dev->agp->acquired = 0;
|
||||||
|
dev->agp->enabled = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Clear vma list (only built for debugging) */
|
||||||
|
if (dev->vmalist) {
|
||||||
|
for (vma = dev->vmalist; vma; vma = vma_next) {
|
||||||
|
vma_next = vma->next;
|
||||||
|
drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
|
||||||
|
}
|
||||||
|
dev->vmalist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear map area and mtrr information */
|
||||||
|
if (dev->maplist) {
|
||||||
|
for (i = 0; i < dev->map_count; i++) {
|
||||||
|
map = dev->maplist[i];
|
||||||
|
switch (map->type) {
|
||||||
|
case _DRM_REGISTERS:
|
||||||
|
case _DRM_FRAME_BUFFER:
|
||||||
|
#ifdef CONFIG_MTRR
|
||||||
|
if (map->mtrr >= 0) {
|
||||||
|
int retcode;
|
||||||
|
retcode = mtrr_del(map->mtrr,
|
||||||
|
map->offset,
|
||||||
|
map->size);
|
||||||
|
DRM_DEBUG("mtrr_del = %d\n", retcode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
drm_ioremapfree(map->handle, map->size);
|
||||||
|
break;
|
||||||
|
case _DRM_SHM:
|
||||||
|
drm_free_pages((unsigned long)map->handle,
|
||||||
|
drm_order(map->size)
|
||||||
|
- PAGE_SHIFT,
|
||||||
|
DRM_MEM_SAREA);
|
||||||
|
break;
|
||||||
|
case _DRM_AGP:
|
||||||
|
/* Do nothing here, because this is all
|
||||||
|
handled in the AGP/GART driver. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||||
|
}
|
||||||
|
drm_free(dev->maplist,
|
||||||
|
dev->map_count * sizeof(*dev->maplist),
|
||||||
|
DRM_MEM_MAPS);
|
||||||
|
dev->maplist = NULL;
|
||||||
|
dev->map_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_dma_takedown(dev);
|
||||||
|
|
||||||
|
dev->queue_count = 0;
|
||||||
|
if (dev->lock.hw_lock) {
|
||||||
|
dev->lock.hw_lock = NULL; /* SHM removed */
|
||||||
|
dev->lock.pid = 0;
|
||||||
|
wake_up_interruptible(&dev->lock.lock_queue);
|
||||||
|
}
|
||||||
|
up(&dev->struct_sem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_init is called via init_module at module load time, or via
|
||||||
|
* linux/init/main.c (this is not currently supported). */
|
||||||
|
|
||||||
|
int r128_init(void)
|
||||||
|
{
|
||||||
|
int retcode;
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
memset((void *)dev, 0, sizeof(*dev));
|
||||||
|
dev->count_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
sema_init(&dev->struct_sem, 1);
|
||||||
|
|
||||||
|
#ifdef MODULE
|
||||||
|
drm_parse_options(r128);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((retcode = misc_register(&r128_misc))) {
|
||||||
|
DRM_ERROR("Cannot register \"%s\"\n", R128_NAME);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
dev->device = MKDEV(MISC_MAJOR, r128_misc.minor);
|
||||||
|
dev->name = R128_NAME;
|
||||||
|
|
||||||
|
drm_mem_init();
|
||||||
|
drm_proc_init(dev);
|
||||||
|
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
dev->agp = drm_agp_init();
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTRR
|
||||||
|
dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
|
||||||
|
dev->agp->agp_info.aper_size*1024*1024,
|
||||||
|
MTRR_TYPE_WRCOMB,
|
||||||
|
1);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((retcode = drm_ctxbitmap_init(dev))) {
|
||||||
|
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||||
|
drm_proc_cleanup();
|
||||||
|
misc_deregister(&r128_misc);
|
||||||
|
r128_takedown(dev);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
|
||||||
|
R128_NAME,
|
||||||
|
R128_MAJOR,
|
||||||
|
R128_MINOR,
|
||||||
|
R128_PATCHLEVEL,
|
||||||
|
R128_DATE,
|
||||||
|
r128_misc.minor);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_cleanup is called via cleanup_module at module unload time. */
|
||||||
|
|
||||||
|
void r128_cleanup(void)
|
||||||
|
{
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
|
drm_proc_cleanup();
|
||||||
|
if (misc_deregister(&r128_misc)) {
|
||||||
|
DRM_ERROR("Cannot unload module\n");
|
||||||
|
} else {
|
||||||
|
DRM_INFO("Module unloaded\n");
|
||||||
|
}
|
||||||
|
drm_ctxbitmap_cleanup(dev);
|
||||||
|
r128_takedown(dev);
|
||||||
|
#ifdef DRM_AGP
|
||||||
|
if (dev->agp) {
|
||||||
|
/* FIXME -- free other information, too */
|
||||||
|
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||||
|
dev->agp = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_version(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
drm_version_t version;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
copy_from_user_ret(&version,
|
||||||
|
(drm_version_t *)arg,
|
||||||
|
sizeof(version),
|
||||||
|
-EFAULT);
|
||||||
|
|
||||||
|
#define DRM_COPY(name,value) \
|
||||||
|
len = strlen(value); \
|
||||||
|
if (len > name##_len) len = name##_len; \
|
||||||
|
name##_len = strlen(value); \
|
||||||
|
if (len && name) { \
|
||||||
|
copy_to_user_ret(name, value, len, -EFAULT); \
|
||||||
|
}
|
||||||
|
|
||||||
|
version.version_major = R128_MAJOR;
|
||||||
|
version.version_minor = R128_MINOR;
|
||||||
|
version.version_patchlevel = R128_PATCHLEVEL;
|
||||||
|
|
||||||
|
DRM_COPY(version.name, R128_NAME);
|
||||||
|
DRM_COPY(version.date, R128_DATE);
|
||||||
|
DRM_COPY(version.desc, R128_DESC);
|
||||||
|
|
||||||
|
copy_to_user_ret((drm_version_t *)arg,
|
||||||
|
&version,
|
||||||
|
sizeof(version),
|
||||||
|
-EFAULT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_open(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
drm_device_t *dev = &r128_device;
|
||||||
|
int retcode = 0;
|
||||||
|
|
||||||
|
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||||
|
if (!(retcode = drm_open_helper(inode, filp, dev))) {
|
||||||
|
MOD_INC_USE_COUNT;
|
||||||
|
atomic_inc(&dev->total_open);
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (!dev->open_count++) {
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return r128_setup(dev);
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_release(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
int retcode = 0;
|
||||||
|
|
||||||
|
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||||
|
if (!(retcode = drm_release(inode, filp))) {
|
||||||
|
MOD_DEC_USE_COUNT;
|
||||||
|
atomic_inc(&dev->total_close);
|
||||||
|
spin_lock(&dev->count_lock);
|
||||||
|
if (!--dev->open_count) {
|
||||||
|
if (atomic_read(&dev->ioctl_count) || dev->blocked) {
|
||||||
|
DRM_ERROR("Device busy: %d %d\n",
|
||||||
|
atomic_read(&dev->ioctl_count),
|
||||||
|
dev->blocked);
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
return r128_takedown(dev);
|
||||||
|
}
|
||||||
|
spin_unlock(&dev->count_lock);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */
|
||||||
|
|
||||||
|
int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
int nr = DRM_IOCTL_NR(cmd);
|
||||||
|
drm_file_t *priv = filp->private_data;
|
||||||
|
drm_device_t *dev = priv->dev;
|
||||||
|
int retcode = 0;
|
||||||
|
drm_ioctl_desc_t *ioctl;
|
||||||
|
drm_ioctl_t *func;
|
||||||
|
|
||||||
|
atomic_inc(&dev->ioctl_count);
|
||||||
|
atomic_inc(&dev->total_ioctl);
|
||||||
|
++priv->ioctl_count;
|
||||||
|
|
||||||
|
DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
|
||||||
|
current->pid, cmd, nr, dev->device, priv->authenticated);
|
||||||
|
|
||||||
|
if (nr >= R128_IOCTL_COUNT) {
|
||||||
|
retcode = -EINVAL;
|
||||||
|
} else {
|
||||||
|
ioctl = &r128_ioctls[nr];
|
||||||
|
func = ioctl->func;
|
||||||
|
|
||||||
|
if (!func) {
|
||||||
|
DRM_DEBUG("no function\n");
|
||||||
|
retcode = -EINVAL;
|
||||||
|
} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
|
||||||
|
|| (ioctl->auth_needed && !priv->authenticated)) {
|
||||||
|
retcode = -EACCES;
|
||||||
|
} else {
|
||||||
|
retcode = (func)(inode, filp, cmd, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_dec(&dev->ioctl_count);
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r128_lock(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;
|
||||||
|
DECLARE_WAITQUEUE(entry, current);
|
||||||
|
int ret = 0;
|
||||||
|
drm_lock_t lock;
|
||||||
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
cycles_t start;
|
||||||
|
|
||||||
|
dev->lck_start = start = get_cycles();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
|
||||||
|
|
||||||
|
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||||
|
DRM_ERROR("Process %d using kernel context %d\n",
|
||||||
|
current->pid, lock.context);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||||
|
lock.context, current->pid, dev->lock.hw_lock->lock,
|
||||||
|
lock.flags);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* dev->queue_count == 0 right now for
|
||||||
|
r128. FIXME? */
|
||||||
|
if (lock.context < 0 || lock.context >= dev->queue_count)
|
||||||
|
return -EINVAL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
#if 0
|
||||||
|
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
|
||||||
|
!= lock.context) {
|
||||||
|
long j = jiffies - dev->lock.lock_time;
|
||||||
|
|
||||||
|
if (lock.context == r128_res_ctx.handle &&
|
||||||
|
j >= 0 && j < DRM_LOCK_SLICE) {
|
||||||
|
/* Can't take lock if we just had it and
|
||||||
|
there is contention. */
|
||||||
|
DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
|
||||||
|
lock.context, current->pid, j,
|
||||||
|
dev->lock.lock_time, jiffies);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
schedule_timeout(DRM_LOCK_SLICE-j);
|
||||||
|
DRM_DEBUG("jiffies=%d\n", jiffies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
|
for (;;) {
|
||||||
|
if (!dev->lock.hw_lock) {
|
||||||
|
/* Device has been unregistered */
|
||||||
|
ret = -EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (drm_lock_take(&dev->lock.hw_lock->lock,
|
||||||
|
lock.context)) {
|
||||||
|
dev->lock.pid = current->pid;
|
||||||
|
dev->lock.lock_time = jiffies;
|
||||||
|
atomic_inc(&dev->total_locks);
|
||||||
|
break; /* Got lock */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Contention */
|
||||||
|
atomic_inc(&dev->total_sleeps);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
#if 1
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
#endif
|
||||||
|
schedule();
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current->state = TASK_RUNNING;
|
||||||
|
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!ret && dev->last_context != lock.context &&
|
||||||
|
lock.context != r128_res_ctx.handle &&
|
||||||
|
dev->last_context != r128_res_ctx.handle) {
|
||||||
|
add_wait_queue(&dev->context_wait, &entry);
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
/* PRE: dev->last_context != lock.context */
|
||||||
|
r128_context_switch(dev, dev->last_context, lock.context);
|
||||||
|
/* POST: we will wait for the context
|
||||||
|
switch and will dispatch on a later call
|
||||||
|
when dev->last_context == lock.context
|
||||||
|
NOTE WE HOLD THE LOCK THROUGHOUT THIS
|
||||||
|
TIME! */
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
schedule();
|
||||||
|
current->state = TASK_RUNNING;
|
||||||
|
remove_wait_queue(&dev->context_wait, &entry);
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
ret = -EINTR;
|
||||||
|
} else if (dev->last_context != lock.context) {
|
||||||
|
DRM_ERROR("Context mismatch: %d %d\n",
|
||||||
|
dev->last_context, lock.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
if (lock.flags & _DRM_LOCK_READY) {
|
||||||
|
/* Wait for space in DMA/FIFO */
|
||||||
|
}
|
||||||
|
if (lock.flags & _DRM_LOCK_QUIESCENT) {
|
||||||
|
/* Make hardware quiescent */
|
||||||
|
#if 0
|
||||||
|
r128_quiescent(dev);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DRM_ERROR("pid = %5d, old counter = %5ld\n",
|
||||||
|
current->pid, current->counter);
|
||||||
|
#endif
|
||||||
|
if (lock.context != r128_res_ctx.handle) {
|
||||||
|
current->counter = 5;
|
||||||
|
current->priority = DEF_PRIORITY/4;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
while (current->counter > 25)
|
||||||
|
current->counter >>= 1; /* decrease time slice */
|
||||||
|
DRM_ERROR("pid = %5d, new counter = %5ld\n",
|
||||||
|
current->pid, current->counter);
|
||||||
|
#endif
|
||||||
|
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
|
||||||
|
|
||||||
|
#if DRM_DMA_HISTOGRAM
|
||||||
|
atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int r128_unlock(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_lock_t lock;
|
||||||
|
|
||||||
|
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
|
||||||
|
|
||||||
|
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||||
|
DRM_ERROR("Process %d using kernel context %d\n",
|
||||||
|
current->pid, lock.context);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG("%d frees lock (%d holds)\n",
|
||||||
|
lock.context,
|
||||||
|
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||||
|
atomic_inc(&dev->total_unlocks);
|
||||||
|
if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
|
||||||
|
atomic_inc(&dev->total_contends);
|
||||||
|
drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
|
||||||
|
/* FIXME: Try to send data to card here */
|
||||||
|
if (!dev->context_flag) {
|
||||||
|
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
|
||||||
|
DRM_KERNEL_CONTEXT)) {
|
||||||
|
DRM_ERROR("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
current->policy |= SCHED_YIELD;
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule_timeout(1000);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (lock.context != r128_res_ctx.handle) {
|
||||||
|
current->counter = 5;
|
||||||
|
current->priority = DEF_PRIORITY;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule_timeout(10);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
|
||||||
|
* Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
|
||||||
|
*
|
||||||
|
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
|
* 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: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||||
|
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||||
|
*
|
||||||
|
* $XFree86$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _R128_DRV_H_
|
||||||
|
#define _R128_DRV_H_
|
||||||
|
|
||||||
|
typedef struct drm_r128_private {
|
||||||
|
int is_pci;
|
||||||
|
|
||||||
|
int cce_mode;
|
||||||
|
int cce_fifo_size;
|
||||||
|
int cce_is_bm_mode;
|
||||||
|
int cce_secure;
|
||||||
|
|
||||||
|
drm_r128_sarea_t *sarea_priv;
|
||||||
|
|
||||||
|
__volatile__ u32 *ring_read_ptr;
|
||||||
|
|
||||||
|
u32 *ring_start;
|
||||||
|
u32 *ring_end;
|
||||||
|
int ring_size;
|
||||||
|
int ring_sizel2qw;
|
||||||
|
int ring_entries;
|
||||||
|
|
||||||
|
int submit_age;
|
||||||
|
|
||||||
|
int usec_timeout;
|
||||||
|
|
||||||
|
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;
|
||||||
|
} drm_r128_buf_priv_t;
|
||||||
|
|
||||||
|
/* r128_drv.c */
|
||||||
|
extern int r128_init(void);
|
||||||
|
extern void r128_cleanup(void);
|
||||||
|
extern int r128_version(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_open(struct inode *inode, struct file *filp);
|
||||||
|
extern int r128_release(struct inode *inode, struct file *filp);
|
||||||
|
extern int r128_ioctl(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_lock(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_unlock(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* r128_dma.c */
|
||||||
|
extern int r128_init_cce(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* r128_bufs.c */
|
||||||
|
extern int r128_addbufs(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_mapbufs(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* r128_context.c */
|
||||||
|
extern int r128_resctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_addctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_modctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_getctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_switchctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_newctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
extern int r128_rmctx(struct inode *inode, struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
extern int r128_context_switch(drm_device_t *dev, int old, int new);
|
||||||
|
extern int r128_context_switch_complete(drm_device_t *dev, int new);
|
||||||
|
|
||||||
|
|
||||||
|
/* Register definitions, register access macros and drmAddMap constants
|
||||||
|
* for Rage 128 kernel driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define R128_PC_NGUI_CTLSTAT 0x0184
|
||||||
|
# define R128_PC_FLUSH_ALL 0x00ff
|
||||||
|
# define R128_PC_BUSY (1 << 31)
|
||||||
|
|
||||||
|
#define R128_CLOCK_CNTL_INDEX 0x0008
|
||||||
|
#define R128_CLOCK_CNTL_DATA 0x000c
|
||||||
|
# define R128_PLL_WR_EN (1 << 7)
|
||||||
|
|
||||||
|
#define R128_MCLK_CNTL 0x000f
|
||||||
|
# define R128_FORCE_GCP (1 << 16)
|
||||||
|
# define R128_FORCE_PIPE3D_CPP (1 << 17)
|
||||||
|
|
||||||
|
#define R128_GEN_RESET_CNTL 0x00f0
|
||||||
|
# define R128_SOFT_RESET_GUI (1 << 0)
|
||||||
|
|
||||||
|
#define R128_PM4_BUFFER_CNTL 0x0704
|
||||||
|
# define R128_PM4_NONPM4 (0 << 28)
|
||||||
|
# define R128_PM4_192PIO (1 << 28)
|
||||||
|
# define R128_PM4_192BM (2 << 28)
|
||||||
|
# define R128_PM4_128PIO_64INDBM (3 << 28)
|
||||||
|
# define R128_PM4_128BM_64INDBM (4 << 28)
|
||||||
|
# define R128_PM4_64PIO_128INDBM (5 << 28)
|
||||||
|
# define R128_PM4_64BM_128INDBM (6 << 28)
|
||||||
|
# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
|
||||||
|
# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
|
||||||
|
# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
|
||||||
|
|
||||||
|
|
||||||
|
#define R128_PM4_BUFFER_DL_RPTR 0x0710
|
||||||
|
#define R128_PM4_BUFFER_DL_WPTR 0x0714
|
||||||
|
# define R128_PM4_BUFFER_DL_DONE (1 << 31)
|
||||||
|
|
||||||
|
#define R128_PM4_VC_FPU_SETUP 0x071c
|
||||||
|
|
||||||
|
#define R128_PM4_STAT 0x07b8
|
||||||
|
# define R128_PM4_FIFOCNT_MASK 0x0fff
|
||||||
|
# define R128_PM4_BUSY (1 << 16)
|
||||||
|
# define R128_PM4_GUI_ACTIVE (1 << 31)
|
||||||
|
|
||||||
|
#define R128_PM4_BUFFER_ADDR 0x07f0
|
||||||
|
#define R128_PM4_MICRO_CNTL 0x07fc
|
||||||
|
# define R128_PM4_MICRO_FREERUN (1 << 30)
|
||||||
|
|
||||||
|
#define R128_PM4_FIFO_DATA_EVEN 0x1000
|
||||||
|
#define R128_PM4_FIFO_DATA_ODD 0x1004
|
||||||
|
|
||||||
|
#define R128_GUI_SCRATCH_REG0 0x15e0
|
||||||
|
#define R128_GUI_SCRATCH_REG1 0x15e4
|
||||||
|
#define R128_GUI_SCRATCH_REG2 0x15e8
|
||||||
|
#define R128_GUI_SCRATCH_REG3 0x15ec
|
||||||
|
#define R128_GUI_SCRATCH_REG4 0x15f0
|
||||||
|
#define R128_GUI_SCRATCH_REG5 0x15f4
|
||||||
|
|
||||||
|
#define R128_GUI_STAT 0x1740
|
||||||
|
# define R128_GUI_FIFOCNT_MASK 0x0fff
|
||||||
|
# define R128_GUI_ACTIVE (1 << 31)
|
||||||
|
|
||||||
|
|
||||||
|
/* CCE command packets */
|
||||||
|
#define R128_CCE_PACKET0 0x00000000
|
||||||
|
#define R128_CCE_PACKET1 0x40000000
|
||||||
|
#define R128_CCE_PACKET2 0x80000000
|
||||||
|
# define R128_CCE_PACKET_MASK 0xC0000000
|
||||||
|
# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
|
||||||
|
# define R128_CCE_PACKET0_REG_MASK 0x000007ff
|
||||||
|
# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
|
||||||
|
# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
|
||||||
|
|
||||||
|
|
||||||
|
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
||||||
|
|
||||||
|
|
||||||
|
#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
|
||||||
|
#define R128_ADDR(reg) (R128_BASE(reg) + reg)
|
||||||
|
|
||||||
|
#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg)
|
||||||
|
#define R128_READ(reg) R128_DEREF(reg)
|
||||||
|
#define R128_WRITE(reg,val) do { R128_DEREF(reg) = val; } while (0)
|
||||||
|
|
||||||
|
#define R128_DEREF8(reg) *(__volatile__ char *)R128_ADDR(reg)
|
||||||
|
#define R128_READ8(reg) R128_DEREF8(reg)
|
||||||
|
#define R128_WRITE8(reg,val) do { R128_DEREF8(reg) = val; } while (0)
|
||||||
|
|
||||||
|
#define R128_WRITE_PLL(addr,val) \
|
||||||
|
do { \
|
||||||
|
R128_WRITE8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \
|
||||||
|
R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
extern int R128_READ_PLL(drm_device_t *dev, int addr);
|
||||||
|
|
||||||
|
#define R128CCE0(p,r,n) ((p) | ((n) << 16) | ((r) >> 2))
|
||||||
|
#define R128CCE1(p,r1,r2) ((p) | (((r2) >> 2) << 11) | ((r1) >> 2))
|
||||||
|
#define R128CCE2(p) ((p))
|
||||||
|
#define R128CCE3(p,n) ((p) | ((n) << 16))
|
||||||
|
|
||||||
|
#endif
|
31
linux/vm.c
31
linux/vm.c
|
@ -1,8 +1,7 @@
|
||||||
/* vm.c -- Memory mapping for DRM -*- linux-c -*-
|
/* vm.c -- Memory mapping for DRM -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
|
||||||
* Revised: Mon Feb 14 00:16:45 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -246,6 +245,18 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
/* Check for valid size. */
|
/* Check for valid size. */
|
||||||
if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
|
if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
|
||||||
|
|
||||||
|
if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
|
||||||
|
vma->vm_flags &= VM_MAYWRITE;
|
||||||
|
#if defined(__i386__)
|
||||||
|
pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
|
||||||
|
#else
|
||||||
|
/* Ye gads this is ugly. With more thought
|
||||||
|
we could move this up higher and use
|
||||||
|
`protection_map' instead. */
|
||||||
|
vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
|
||||||
|
__pte(pgprot_val(vma->vm_page_prot)))));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
switch (map->type) {
|
switch (map->type) {
|
||||||
case _DRM_FRAME_BUFFER:
|
case _DRM_FRAME_BUFFER:
|
||||||
|
@ -265,6 +276,10 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
vma->vm_end - vma->vm_start,
|
vma->vm_end - vma->vm_start,
|
||||||
vma->vm_page_prot))
|
vma->vm_page_prot))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
||||||
|
" offset = 0x%lx\n",
|
||||||
|
map->type,
|
||||||
|
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
||||||
vma->vm_ops = &drm_vm_ops;
|
vma->vm_ops = &drm_vm_ops;
|
||||||
break;
|
break;
|
||||||
case _DRM_SHM:
|
case _DRM_SHM:
|
||||||
|
@ -277,19 +292,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
return -EINVAL; /* This should never happen. */
|
return -EINVAL; /* This should never happen. */
|
||||||
}
|
}
|
||||||
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
|
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
|
||||||
if (map->flags & _DRM_READ_ONLY) {
|
|
||||||
#if defined(__i386__)
|
|
||||||
pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
|
|
||||||
#else
|
|
||||||
/* Ye gads this is ugly. With more thought
|
|
||||||
we could move this up higher and use
|
|
||||||
`protection_map' instead. */
|
|
||||||
vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
|
|
||||||
__pte(pgprot_val(vma->vm_page_prot)))));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
|
#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
|
||||||
/* In Linux 2.2.3 and above, this is
|
/* In Linux 2.2.3 and above, this is
|
||||||
handled in do_mmap() in mm/mmap.c. */
|
handled in do_mmap() in mm/mmap.c. */
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
||||||
* Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -71,9 +70,10 @@ typedef struct drm_clip_rect {
|
||||||
unsigned short y2;
|
unsigned short y2;
|
||||||
} drm_clip_rect_t;
|
} drm_clip_rect_t;
|
||||||
|
|
||||||
/* Seperate include files for the i810/mga specific structures */
|
/* Seperate include files for the i810/mga/r128 specific structures */
|
||||||
#include "mga_drm.h"
|
#include "mga_drm.h"
|
||||||
#include "i810_drm.h"
|
#include "i810_drm.h"
|
||||||
|
#include "r128_drm.h"
|
||||||
|
|
||||||
typedef struct drm_version {
|
typedef struct drm_version {
|
||||||
int version_major; /* Major version */
|
int version_major; /* Major version */
|
||||||
|
@ -349,4 +349,12 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||||
|
|
||||||
|
/* Rage 128 specific ioctls */
|
||||||
|
#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
|
||||||
|
#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
|
||||||
|
#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
|
||||||
|
#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
|
||||||
|
#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
|
||||||
|
#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
14
shared/drm.h
14
shared/drm.h
|
@ -1,8 +1,7 @@
|
||||||
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
|
||||||
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
* Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
|
||||||
* Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com
|
|
||||||
*
|
*
|
||||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -71,9 +70,10 @@ typedef struct drm_clip_rect {
|
||||||
unsigned short y2;
|
unsigned short y2;
|
||||||
} drm_clip_rect_t;
|
} drm_clip_rect_t;
|
||||||
|
|
||||||
/* Seperate include files for the i810/mga specific structures */
|
/* Seperate include files for the i810/mga/r128 specific structures */
|
||||||
#include "mga_drm.h"
|
#include "mga_drm.h"
|
||||||
#include "i810_drm.h"
|
#include "i810_drm.h"
|
||||||
|
#include "r128_drm.h"
|
||||||
|
|
||||||
typedef struct drm_version {
|
typedef struct drm_version {
|
||||||
int version_major; /* Major version */
|
int version_major; /* Major version */
|
||||||
|
@ -349,4 +349,12 @@ typedef struct drm_agp_info {
|
||||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||||
|
|
||||||
|
/* Rage 128 specific ioctls */
|
||||||
|
#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
|
||||||
|
#define DRM_IOCTL_R128_RESET DRM_IO( 0x41)
|
||||||
|
#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42)
|
||||||
|
#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43)
|
||||||
|
#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t)
|
||||||
|
#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue