mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-05 17:08:03 +02:00
Add support for strips/fans
This commit is contained in:
parent
b3a24766fe
commit
7d2b298294
25 changed files with 15745 additions and 4 deletions
162
linux-core/drm_auth.c
Normal file
162
linux-core/drm_auth.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
static int DRM(hash_magic)(drm_magic_t magic)
|
||||
{
|
||||
return magic & (DRM_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_file_t *retval = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash = DRM(hash_magic)(magic);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
retval = pt->priv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
drm_magic_entry_t *entry;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
hash = DRM(hash_magic)(magic);
|
||||
entry = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
|
||||
if (!entry) return -ENOMEM;
|
||||
entry->magic = magic;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (dev->magiclist[hash].tail) {
|
||||
dev->magiclist[hash].tail->next = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
} else {
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = DRM(hash_magic)(magic);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
if (dev->magiclist[hash].head == pt) {
|
||||
dev->magiclist[hash].head = pt->next;
|
||||
}
|
||||
if (dev->magiclist[hash].tail == pt) {
|
||||
dev->magiclist[hash].tail = prev;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int DRM(getmagic)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_auth_t auth;
|
||||
|
||||
/* Find unique magic */
|
||||
if (priv->magic) {
|
||||
auth.magic = priv->magic;
|
||||
} else {
|
||||
do {
|
||||
spin_lock(&lock);
|
||||
if (!sequence) ++sequence; /* reserve 0 */
|
||||
auth.magic = sequence++;
|
||||
spin_unlock(&lock);
|
||||
} while (DRM(find_file)(dev, auth.magic));
|
||||
priv->magic = auth.magic;
|
||||
DRM(add_magic)(dev, priv, auth.magic);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(authmagic)(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_auth_t auth;
|
||||
drm_file_t *file;
|
||||
|
||||
if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if ((file = DRM(find_file)(dev, auth.magic))) {
|
||||
file->authenticated = 1;
|
||||
DRM(remove_magic)(dev, auth.magic);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
594
linux-core/drm_dma.c
Normal file
594
linux-core/drm_dma.c
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
|
||||
* Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
|
||||
#ifndef __HAVE_DMA_WAITQUEUE
|
||||
#define __HAVE_DMA_WAITQUEUE 0
|
||||
#endif
|
||||
#ifndef __HAVE_DMA_RECLAIM
|
||||
#define __HAVE_DMA_RECLAIM 0
|
||||
#endif
|
||||
|
||||
#if __HAVE_DMA
|
||||
|
||||
int DRM(dma_setup)( drm_device_t *dev )
|
||||
{
|
||||
int i;
|
||||
|
||||
dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
|
||||
if ( !dev->dma )
|
||||
return -ENOMEM;
|
||||
|
||||
memset( dev->dma, 0, sizeof(*dev->dma) );
|
||||
|
||||
for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
|
||||
memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DRM(dma_takedown)(drm_device_t *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
|
||||
if (!dma) return;
|
||||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n",
|
||||
i,
|
||||
dma->bufs[i].buf_count,
|
||||
dma->bufs[i].seg_count);
|
||||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||
DRM(free_pages)(dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].page_order,
|
||||
DRM_MEM_DMA);
|
||||
}
|
||||
DRM(free)(dma->bufs[i].seglist,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist),
|
||||
DRM_MEM_SEGS);
|
||||
}
|
||||
if(dma->bufs[i].buf_count) {
|
||||
for(j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if(dma->bufs[i].buflist[j].dev_private) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
dma->bufs[i].buflist[j].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
DRM(free)(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
sizeof(*dma->bufs[0].buflist),
|
||||
DRM_MEM_BUFS);
|
||||
#if __HAVE_DMA_FREELIST
|
||||
DRM(freelist_destroy)(&dma->bufs[i].freelist);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (dma->buflist) {
|
||||
DRM(free)(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (dma->pagelist) {
|
||||
DRM(free)(dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
/* This is slow, but is useful for debugging. */
|
||||
int DRM(histogram_slot)(unsigned long count)
|
||||
{
|
||||
int value = DRM_DMA_HISTOGRAM_INITIAL;
|
||||
int slot;
|
||||
|
||||
for (slot = 0;
|
||||
slot < DRM_DMA_HISTOGRAM_SLOTS;
|
||||
++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
|
||||
if (count < value) return slot;
|
||||
}
|
||||
return DRM_DMA_HISTOGRAM_SLOTS - 1;
|
||||
}
|
||||
|
||||
void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
cycles_t queued_to_dispatched;
|
||||
cycles_t dispatched_to_completed;
|
||||
cycles_t completed_to_freed;
|
||||
int q2d, d2c, c2f, q2c, q2f;
|
||||
|
||||
if (buf->time_queued) {
|
||||
queued_to_dispatched = (buf->time_dispatched
|
||||
- buf->time_queued);
|
||||
dispatched_to_completed = (buf->time_completed
|
||||
- buf->time_dispatched);
|
||||
completed_to_freed = (buf->time_freed
|
||||
- buf->time_completed);
|
||||
|
||||
q2d = DRM(histogram_slot)(queued_to_dispatched);
|
||||
d2c = DRM(histogram_slot)(dispatched_to_completed);
|
||||
c2f = DRM(histogram_slot)(completed_to_freed);
|
||||
|
||||
q2c = DRM(histogram_slot)(queued_to_dispatched
|
||||
+ dispatched_to_completed);
|
||||
q2f = DRM(histogram_slot)(queued_to_dispatched
|
||||
+ dispatched_to_completed
|
||||
+ completed_to_freed);
|
||||
|
||||
atomic_inc(&dev->histo.total);
|
||||
atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
|
||||
atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
|
||||
atomic_inc(&dev->histo.completed_to_freed[c2f]);
|
||||
|
||||
atomic_inc(&dev->histo.queued_to_completed[q2c]);
|
||||
atomic_inc(&dev->histo.queued_to_freed[q2f]);
|
||||
|
||||
}
|
||||
buf->time_queued = 0;
|
||||
buf->time_dispatched = 0;
|
||||
buf->time_completed = 0;
|
||||
buf->time_freed = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
if (!buf) return;
|
||||
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
buf->pid = 0;
|
||||
buf->used = 0;
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
buf->time_completed = get_cycles();
|
||||
#endif
|
||||
|
||||
if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
|
||||
wake_up_interruptible(&buf->dma_wait);
|
||||
}
|
||||
#if __HAVE_DMA_FREELIST
|
||||
else {
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
/* If processes are waiting, the last one
|
||||
to wake will put the buffer on the free
|
||||
list. If no processes are waiting, we
|
||||
put the buffer on the freelist here. */
|
||||
DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !__HAVE_DMA_RECLAIM
|
||||
void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
|
||||
if (!dma) return;
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (dma->buflist[i]->pid == pid) {
|
||||
switch (dma->buflist[i]->list) {
|
||||
case DRM_LIST_NONE:
|
||||
DRM(free_buffer)(dev, dma->buflist[i]);
|
||||
break;
|
||||
case DRM_LIST_WAIT:
|
||||
dma->buflist[i]->list = DRM_LIST_RECLAIM;
|
||||
break;
|
||||
default:
|
||||
/* Buffer already on hardware. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* GH: This is a big hack for now...
|
||||
*/
|
||||
#if __HAVE_OLD_DMA
|
||||
|
||||
void DRM(clear_next_buffer)(drm_device_t *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
dma->next_buffer = NULL;
|
||||
if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
|
||||
wake_up_interruptible(&dma->next_queue->flush_queue);
|
||||
}
|
||||
dma->next_queue = NULL;
|
||||
}
|
||||
|
||||
int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
|
||||
{
|
||||
int i;
|
||||
int candidate = -1;
|
||||
int j = jiffies;
|
||||
|
||||
if (!dev) {
|
||||
DRM_ERROR("No device\n");
|
||||
return -1;
|
||||
}
|
||||
if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
|
||||
/* This only happens between the time the
|
||||
interrupt is initialized and the time
|
||||
the queues are initialized. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Doing "while locked" DMA? */
|
||||
if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
|
||||
return DRM_KERNEL_CONTEXT;
|
||||
}
|
||||
|
||||
/* If there are buffers on the last_context
|
||||
queue, and we have not been executing
|
||||
this context very long, continue to
|
||||
execute this context. */
|
||||
if (dev->last_switch <= j
|
||||
&& dev->last_switch + DRM_TIME_SLICE > j
|
||||
&& DRM_WAITCOUNT(dev, dev->last_context)) {
|
||||
return dev->last_context;
|
||||
}
|
||||
|
||||
/* Otherwise, find a candidate */
|
||||
for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
|
||||
if (DRM_WAITCOUNT(dev, i)) {
|
||||
candidate = dev->last_checked = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (candidate < 0) {
|
||||
for (i = 0; i < dev->queue_count; i++) {
|
||||
if (DRM_WAITCOUNT(dev, i)) {
|
||||
candidate = dev->last_checked = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wrapper
|
||||
&& candidate >= 0
|
||||
&& candidate != dev->last_context
|
||||
&& dev->last_switch <= j
|
||||
&& dev->last_switch + DRM_TIME_SLICE > j) {
|
||||
if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
|
||||
del_timer(&dev->timer);
|
||||
dev->timer.function = wrapper;
|
||||
dev->timer.data = (unsigned long)dev;
|
||||
dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
|
||||
add_timer(&dev->timer);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
|
||||
int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
int i;
|
||||
drm_queue_t *q;
|
||||
drm_buf_t *buf;
|
||||
int idx;
|
||||
int while_locked = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
|
||||
DRM_DEBUG("%d\n", d->send_count);
|
||||
|
||||
if (d->flags & _DRM_DMA_WHILE_LOCKED) {
|
||||
int context = dev->lock.hw_lock->lock;
|
||||
|
||||
if (!_DRM_LOCK_IS_HELD(context)) {
|
||||
DRM_ERROR("No lock held during \"while locked\""
|
||||
" request\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (d->context != _DRM_LOCKING_CONTEXT(context)
|
||||
&& _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Lock held by %d while %d makes"
|
||||
" \"while locked\" request\n",
|
||||
_DRM_LOCKING_CONTEXT(context),
|
||||
d->context);
|
||||
return -EINVAL;
|
||||
}
|
||||
q = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
while_locked = 1;
|
||||
} else {
|
||||
q = dev->queuelist[d->context];
|
||||
}
|
||||
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->block_write)) {
|
||||
add_wait_queue(&q->write_queue, &entry);
|
||||
atomic_inc(&q->block_count);
|
||||
for (;;) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if (!atomic_read(&q->block_write)) break;
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
atomic_dec(&q->use_count);
|
||||
remove_wait_queue(&q->write_queue, &entry);
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->block_count);
|
||||
current->state = TASK_RUNNING;
|
||||
remove_wait_queue(&q->write_queue, &entry);
|
||||
}
|
||||
|
||||
for (i = 0; i < d->send_count; i++) {
|
||||
idx = d->send_indices[i];
|
||||
if (idx < 0 || idx >= dma->buf_count) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Index %d (of %d max)\n",
|
||||
d->send_indices[i], dma->buf_count - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
buf = dma->buflist[ idx ];
|
||||
if (buf->pid != current->pid) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Process %d using buffer owned by %d\n",
|
||||
current->pid, buf->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (buf->list != DRM_LIST_NONE) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Process %d using buffer %d on list %d\n",
|
||||
current->pid, buf->idx, buf->list);
|
||||
}
|
||||
buf->used = d->send_sizes[i];
|
||||
buf->while_locked = while_locked;
|
||||
buf->context = d->context;
|
||||
if (!buf->used) {
|
||||
DRM_ERROR("Queueing 0 length buffer\n");
|
||||
}
|
||||
if (buf->pending) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Queueing pending buffer:"
|
||||
" buffer %d, offset %d\n",
|
||||
d->send_indices[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (buf->waiting) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Queueing waiting buffer:"
|
||||
" buffer %d, offset %d\n",
|
||||
d->send_indices[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
buf->waiting = 1;
|
||||
if (atomic_read(&q->use_count) == 1
|
||||
|| atomic_read(&q->finalization)) {
|
||||
DRM(free_buffer)(dev, buf);
|
||||
} else {
|
||||
DRM(waitlist_put)(&q->waitlist, buf);
|
||||
atomic_inc(&q->total_queued);
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
|
||||
int order)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = DRM(freelist_get)(&dma->bufs[order].freelist,
|
||||
d->flags & _DRM_DMA_WAIT);
|
||||
if (!buf) break;
|
||||
if (buf->pending || buf->waiting) {
|
||||
DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
|
||||
buf->idx,
|
||||
buf->pid,
|
||||
buf->waiting,
|
||||
buf->pending);
|
||||
}
|
||||
buf->pid = current->pid;
|
||||
if (copy_to_user(&d->request_indices[i],
|
||||
&buf->idx,
|
||||
sizeof(buf->idx)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user(&d->request_sizes[i],
|
||||
&buf->total,
|
||||
sizeof(buf->total)))
|
||||
return -EFAULT;
|
||||
|
||||
++d->granted_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
|
||||
{
|
||||
int order;
|
||||
int retcode = 0;
|
||||
int tmp_order;
|
||||
|
||||
order = DRM(order)(dma->request_size);
|
||||
|
||||
dma->granted_count = 0;
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma, order);
|
||||
|
||||
if (dma->granted_count < dma->request_count
|
||||
&& (dma->flags & _DRM_DMA_SMALLER_OK)) {
|
||||
for (tmp_order = order - 1;
|
||||
!retcode
|
||||
&& dma->granted_count < dma->request_count
|
||||
&& tmp_order >= DRM_MIN_ORDER;
|
||||
--tmp_order) {
|
||||
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma,
|
||||
tmp_order);
|
||||
}
|
||||
}
|
||||
|
||||
if (dma->granted_count < dma->request_count
|
||||
&& (dma->flags & _DRM_DMA_LARGER_OK)) {
|
||||
for (tmp_order = order + 1;
|
||||
!retcode
|
||||
&& dma->granted_count < dma->request_count
|
||||
&& tmp_order <= DRM_MAX_ORDER;
|
||||
++tmp_order) {
|
||||
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma,
|
||||
tmp_order);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __HAVE_OLD_DMA */
|
||||
|
||||
|
||||
#if __HAVE_DMA_IRQ
|
||||
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( !irq )
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
if ( dev->irq ) {
|
||||
up( &dev->struct_sem );
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->irq = irq;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
dev->dma_flag = 0;
|
||||
|
||||
dev->dma->next_buffer = NULL;
|
||||
dev->dma->next_queue = NULL;
|
||||
dev->dma->this_buffer = NULL;
|
||||
|
||||
#if __HAVE_DMA_IRQ_BH
|
||||
INIT_LIST_HEAD( &dev->tq.list );
|
||||
dev->tq.sync = 0;
|
||||
dev->tq.routine = DRM(dma_immediate_bh);
|
||||
dev->tq.data = dev;
|
||||
#endif
|
||||
|
||||
/* Before installing handler */
|
||||
DRIVER_PREINSTALL();
|
||||
|
||||
/* Install handler */
|
||||
ret = request_irq( dev->irq, DRM(dma_service),
|
||||
0, dev->devname, dev );
|
||||
if ( ret < 0 ) {
|
||||
down( &dev->struct_sem );
|
||||
dev->irq = 0;
|
||||
up( &dev->struct_sem );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* After installing handler */
|
||||
DRIVER_POSTINSTALL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
irq = dev->irq;
|
||||
dev->irq = 0;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
if ( !irq )
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
|
||||
DRIVER_UNINSTALL();
|
||||
|
||||
free_irq( irq, dev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(control)( 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_control_t ctl;
|
||||
|
||||
if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __HAVE_DMA_IRQ */
|
||||
|
||||
#endif /* __HAVE_DMA */
|
||||
51
linux-core/drm_drawable.c
Normal file
51
linux-core/drm_drawable.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(adddraw)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_draw_t draw;
|
||||
|
||||
draw.handle = 0; /* NOOP */
|
||||
DRM_DEBUG("%d\n", draw.handle);
|
||||
if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(rmdraw)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0; /* NOOP */
|
||||
}
|
||||
208
linux-core/drm_fops.c
Normal file
208
linux-core/drm_fops.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/* drm_fops.h -- File operations for DRM -*- linux-c -*-
|
||||
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Daryll Strauss <daryll@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
#include <linux/poll.h>
|
||||
|
||||
/* drm_open is called whenever a process opens /dev/drm. */
|
||||
|
||||
int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
|
||||
{
|
||||
kdev_t minor = MINOR(inode->i_rdev);
|
||||
drm_file_t *priv;
|
||||
|
||||
if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
|
||||
if (!DRM(cpu_valid)()) return -EINVAL;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
|
||||
|
||||
priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
filp->private_data = priv;
|
||||
priv->uid = current->euid;
|
||||
priv->pid = current->pid;
|
||||
priv->minor = minor;
|
||||
priv->dev = dev;
|
||||
priv->ioctl_count = 0;
|
||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (!dev->file_last) {
|
||||
priv->next = NULL;
|
||||
priv->prev = NULL;
|
||||
dev->file_first = priv;
|
||||
dev->file_last = priv;
|
||||
} else {
|
||||
priv->next = NULL;
|
||||
priv->prev = dev->file_last;
|
||||
dev->file_last->next = priv;
|
||||
dev->file_last = priv;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(flush)(struct file *filp)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
|
||||
current->pid, dev->device, dev->open_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(fasync)(int fd, struct file *filp, int on)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
|
||||
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
|
||||
if (retcode < 0) return retcode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The drm_read and drm_write_string code (especially that which manages
|
||||
the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
|
||||
DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
|
||||
|
||||
ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
int left;
|
||||
int avail;
|
||||
int send;
|
||||
int cur;
|
||||
|
||||
DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
|
||||
|
||||
while (dev->buf_rp == dev->buf_wp) {
|
||||
DRM_DEBUG(" sleeping\n");
|
||||
if (filp->f_flags & O_NONBLOCK) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
interruptible_sleep_on(&dev->buf_readers);
|
||||
if (signal_pending(current)) {
|
||||
DRM_DEBUG(" interrupted\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
DRM_DEBUG(" awake\n");
|
||||
}
|
||||
|
||||
left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
|
||||
avail = DRM_BSZ - left;
|
||||
send = DRM_MIN(avail, count);
|
||||
|
||||
while (send) {
|
||||
if (dev->buf_wp > dev->buf_rp) {
|
||||
cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
|
||||
} else {
|
||||
cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
|
||||
}
|
||||
if (copy_to_user(buf, dev->buf_rp, cur))
|
||||
return -EFAULT;
|
||||
dev->buf_rp += cur;
|
||||
if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
|
||||
send -= cur;
|
||||
}
|
||||
|
||||
wake_up_interruptible(&dev->buf_writers);
|
||||
return DRM_MIN(avail, count);;
|
||||
}
|
||||
|
||||
int DRM(write_string)(drm_device_t *dev, const char *s)
|
||||
{
|
||||
int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
|
||||
int send = strlen(s);
|
||||
int count;
|
||||
|
||||
DRM_DEBUG("%d left, %d to send (%p, %p)\n",
|
||||
left, send, dev->buf_rp, dev->buf_wp);
|
||||
|
||||
if (left == 1 || dev->buf_wp != dev->buf_rp) {
|
||||
DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
|
||||
left,
|
||||
dev->buf_wp,
|
||||
dev->buf_rp);
|
||||
}
|
||||
|
||||
while (send) {
|
||||
if (dev->buf_wp >= dev->buf_rp) {
|
||||
count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
|
||||
if (count == left) --count; /* Leave a hole */
|
||||
} else {
|
||||
count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
|
||||
}
|
||||
strncpy(dev->buf_wp, s, count);
|
||||
dev->buf_wp += count;
|
||||
if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
|
||||
send -= count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
|
||||
/* The extra parameter to kill_fasync was added in 2.3.21, and is
|
||||
_not_ present in _stock_ 2.2.14 and 2.2.15. However, some
|
||||
distributions patch 2.2.x kernels to add this parameter. The
|
||||
Makefile.linux attempts to detect this addition and defines
|
||||
KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
|
||||
if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
|
||||
#else
|
||||
|
||||
/* Parameter added in 2.3.21. */
|
||||
#if LINUX_VERSION_CODE < 0x020400
|
||||
if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
|
||||
#else
|
||||
/* Type of first parameter changed in
|
||||
Linux 2.4.0-test2... */
|
||||
if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
|
||||
#endif
|
||||
#endif
|
||||
DRM_DEBUG("waking\n");
|
||||
wake_up_interruptible(&dev->buf_readers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
|
||||
poll_wait(filp, &dev->buf_readers, wait);
|
||||
if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
|
||||
return 0;
|
||||
}
|
||||
112
linux-core/drm_init.c
Normal file
112
linux-core/drm_init.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* drm_init.h -- Setup/Cleanup for DRM -*- linux-c -*-
|
||||
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(flags) = 0;
|
||||
|
||||
/* drm_parse_option parses a single option. See description for
|
||||
* drm_parse_options for details.
|
||||
*/
|
||||
static void DRM(parse_option)(char *s)
|
||||
{
|
||||
char *c, *r;
|
||||
|
||||
DRM_DEBUG("\"%s\"\n", s);
|
||||
if (!s || !*s) return;
|
||||
for (c = s; *c && *c != ':'; c++); /* find : or \0 */
|
||||
if (*c) r = c + 1; else r = NULL; /* remember remainder */
|
||||
*c = '\0'; /* terminate */
|
||||
if (!strcmp(s, "noctx")) {
|
||||
DRM(flags) |= DRM_FLAG_NOCTX;
|
||||
DRM_INFO("Server-mediated context switching OFF\n");
|
||||
return;
|
||||
}
|
||||
if (!strcmp(s, "debug")) {
|
||||
DRM(flags) |= DRM_FLAG_DEBUG;
|
||||
DRM_INFO("Debug messages ON\n");
|
||||
return;
|
||||
}
|
||||
DRM_ERROR("\"%s\" is not a valid option\n", s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* drm_parse_options parse the insmod "drm=" options, or the command-line
|
||||
* options passed to the kernel via LILO. The grammar of the format is as
|
||||
* follows:
|
||||
*
|
||||
* drm ::= 'drm=' option_list
|
||||
* option_list ::= option [ ';' option_list ]
|
||||
* option ::= 'device:' major
|
||||
* | 'debug'
|
||||
* | 'noctx'
|
||||
* major ::= INTEGER
|
||||
*
|
||||
* Note that 's' contains option_list without the 'drm=' part.
|
||||
*
|
||||
* device=major,minor specifies the device number used for /dev/drm
|
||||
* if major == 0 then the misc device is used
|
||||
* if major == 0 and minor == 0 then dynamic misc allocation is used
|
||||
* debug=on specifies that debugging messages will be printk'd
|
||||
* debug=trace specifies that each function call will be logged via printk
|
||||
* debug=off turns off all debugging options
|
||||
*
|
||||
*/
|
||||
|
||||
void DRM(parse_options)(char *s)
|
||||
{
|
||||
char *h, *t, *n;
|
||||
|
||||
DRM_DEBUG("\"%s\"\n", s ?: "");
|
||||
if (!s || !*s) return;
|
||||
|
||||
for (h = t = n = s; h && *h; h = n) {
|
||||
for (; *t && *t != ';'; t++); /* find ; or \0 */
|
||||
if (*t) n = t + 1; else n = NULL; /* remember next */
|
||||
*t = '\0'; /* terminate */
|
||||
DRM(parse_option)(h); /* parse */
|
||||
}
|
||||
}
|
||||
|
||||
/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
|
||||
* otherwise.
|
||||
*/
|
||||
int DRM(cpu_valid)(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
|
||||
#endif
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
return 0; /* No cmpxchg before v9 sparc. */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
251
linux-core/drm_lock.c
Normal file
251
linux-core/drm_lock.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* lock.c -- IOCTLs for locking -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(unblock)(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
|
||||
else new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
if (context != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("%d holds heavyweight lock\n",
|
||||
context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (new == (context | _DRM_LOCK_HELD)) {
|
||||
/* Have lock */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||
inside *_unlock to give lock to kernel before calling *_dma_schedule. */
|
||||
int DRM(lock_transfer)(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
|
||||
dev->lock.pid = 0;
|
||||
do {
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DRM(lock_free)(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
pid_t pid = dev->lock.pid;
|
||||
|
||||
dev->lock.pid = 0;
|
||||
do {
|
||||
old = *lock;
|
||||
new = 0;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
|
||||
DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
|
||||
context,
|
||||
_DRM_LOCKING_CONTEXT(old),
|
||||
pid);
|
||||
return 1;
|
||||
}
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DRM(flush_queue)(drm_device_t *dev, int context)
|
||||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
int ret = 0;
|
||||
drm_queue_t *q = dev->queuelist[context];
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->use_count) > 1) {
|
||||
atomic_inc(&q->block_write);
|
||||
add_wait_queue(&q->flush_queue, &entry);
|
||||
atomic_inc(&q->block_count);
|
||||
for (;;) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if (!DRM_BUFCOUNT(&q->waitlist)) break;
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR; /* Can't restart */
|
||||
break;
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->block_count);
|
||||
current->state = TASK_RUNNING;
|
||||
remove_wait_queue(&q->flush_queue, &entry);
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
|
||||
/* NOTE: block_write is still incremented!
|
||||
Use drm_flush_unlock_queue to decrement. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
|
||||
{
|
||||
drm_queue_t *q = dev->queuelist[context];
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->use_count) > 1) {
|
||||
if (atomic_read(&q->block_write)) {
|
||||
atomic_dec(&q->block_write);
|
||||
wake_up_interruptible(&q->write_queue);
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
|
||||
drm_lock_flags_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (flags & _DRM_LOCK_FLUSH) {
|
||||
ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
|
||||
if (!ret) ret = DRM(flush_queue)(dev, context);
|
||||
}
|
||||
if (flags & _DRM_LOCK_FLUSH_ALL) {
|
||||
for (i = 0; !ret && i < dev->queue_count; i++) {
|
||||
ret = DRM(flush_queue)(dev, i);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (flags & _DRM_LOCK_FLUSH) {
|
||||
ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
|
||||
if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
|
||||
}
|
||||
if (flags & _DRM_LOCK_FLUSH_ALL) {
|
||||
for (i = 0; !ret && i < dev->queue_count; i++) {
|
||||
ret = DRM(flush_unblock_queue)(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DRM(finish)(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;
|
||||
int ret = 0;
|
||||
drm_lock_t lock;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
|
||||
return -EFAULT;
|
||||
ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
|
||||
DRM(flush_unblock)(dev, lock.context, lock.flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If we get here, it means that the process has called DRM_IOCTL_LOCK
|
||||
without calling DRM_IOCTL_UNLOCK.
|
||||
|
||||
If the lock is not held, then let the signal proceed as usual.
|
||||
|
||||
If the lock is held, then set the contended flag and keep the signal
|
||||
blocked.
|
||||
|
||||
|
||||
Return 1 if the signal should be delivered normally.
|
||||
Return 0 if the signal should be blocked. */
|
||||
|
||||
int DRM(notifier)(void *priv)
|
||||
{
|
||||
drm_sigdata_t *s = (drm_sigdata_t *)priv;
|
||||
unsigned int old, new, prev;
|
||||
|
||||
|
||||
/* Allow signal delivery if lock isn't held */
|
||||
if (!_DRM_LOCK_IS_HELD(s->lock->lock)
|
||||
|| _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
|
||||
|
||||
/* Otherwise, set flag to force call to
|
||||
drmUnlock */
|
||||
do {
|
||||
old = s->lock->lock;
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
prev = cmpxchg(&s->lock->lock, old, new);
|
||||
} while (prev != old);
|
||||
return 0;
|
||||
}
|
||||
152
linux-core/drm_stub.c
Normal file
152
linux-core/drm_stub.c
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* drm_stub.h -- -*- linux-c -*-
|
||||
* Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
|
||||
*
|
||||
* Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020400
|
||||
#include "stubsupport-pre24.h"
|
||||
#endif
|
||||
|
||||
#define DRM_STUB_MAXCARDS 16 /* Enough for one machine */
|
||||
|
||||
static struct drm_stub_list {
|
||||
const char *name;
|
||||
struct file_operations *fops;
|
||||
struct proc_dir_entry *dev_root;
|
||||
} *DRM(stub_list);
|
||||
|
||||
static struct proc_dir_entry *DRM(stub_root);
|
||||
|
||||
static struct drm_stub_info {
|
||||
int (*info_register)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev);
|
||||
int (*info_unregister)(int minor);
|
||||
} DRM(stub_info);
|
||||
|
||||
static int DRM(stub_open)(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int minor = MINOR(inode->i_rdev);
|
||||
int err = -ENODEV;
|
||||
struct file_operations *old_fops;
|
||||
|
||||
if (!DRM(stub_list) || !DRM(stub_list)[minor].fops) return -ENODEV;
|
||||
old_fops = filp->f_op;
|
||||
filp->f_op = fops_get(DRM(stub_list)[minor].fops);
|
||||
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
|
||||
fops_put(filp->f_op);
|
||||
filp->f_op = fops_get(old_fops);
|
||||
}
|
||||
fops_put(old_fops);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct file_operations DRM(stub_fops) = {
|
||||
#if LINUX_VERSION_CODE >= 0x020400
|
||||
owner: THIS_MODULE,
|
||||
#endif
|
||||
open: DRM(stub_open)
|
||||
};
|
||||
|
||||
static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!DRM(stub_list)) {
|
||||
DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
|
||||
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
|
||||
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
|
||||
DRM(stub_list)[i].name = NULL;
|
||||
DRM(stub_list)[i].fops = NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
|
||||
if (!DRM(stub_list)[i].fops) {
|
||||
DRM(stub_list)[i].name = name;
|
||||
DRM(stub_list)[i].fops = fops;
|
||||
DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
|
||||
&DRM(stub_list)[i]
|
||||
.dev_root);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int DRM(stub_putminor)(int minor)
|
||||
{
|
||||
if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
|
||||
DRM(stub_list)[minor].name = NULL;
|
||||
DRM(stub_list)[minor].fops = NULL;
|
||||
DRM(proc_cleanup)(minor, DRM(stub_root),
|
||||
DRM(stub_list)[minor].dev_root);
|
||||
if (minor) {
|
||||
inter_module_put("drm");
|
||||
} else {
|
||||
inter_module_unregister("drm");
|
||||
DRM(free)(DRM(stub_list),
|
||||
sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
|
||||
DRM_MEM_STUB);
|
||||
unregister_chrdev(DRM_MAJOR, "drm");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev)
|
||||
{
|
||||
struct drm_stub_info *i = NULL;
|
||||
|
||||
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
||||
i = (struct drm_stub_info *)inter_module_get("drm");
|
||||
|
||||
if (i) {
|
||||
/* Already registered */
|
||||
DRM(stub_info).info_register = i->info_register;
|
||||
DRM(stub_info).info_unregister = i->info_unregister;
|
||||
} else {
|
||||
DRM(stub_info).info_register = DRM(stub_getminor);
|
||||
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
||||
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
||||
}
|
||||
if (DRM(stub_info).info_register)
|
||||
return DRM(stub_info).info_register(name, fops, dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DRM(stub_unregister)(int minor)
|
||||
{
|
||||
DRM_DEBUG("%d\n", minor);
|
||||
if (DRM(stub_info).info_unregister)
|
||||
return DRM(stub_info).info_unregister(minor);
|
||||
return -1;
|
||||
}
|
||||
162
linux/drm_auth.h
Normal file
162
linux/drm_auth.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
static int DRM(hash_magic)(drm_magic_t magic)
|
||||
{
|
||||
return magic & (DRM_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_file_t *retval = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash = DRM(hash_magic)(magic);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
retval = pt->priv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
drm_magic_entry_t *entry;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
hash = DRM(hash_magic)(magic);
|
||||
entry = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
|
||||
if (!entry) return -ENOMEM;
|
||||
entry->magic = magic;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (dev->magiclist[hash].tail) {
|
||||
dev->magiclist[hash].tail->next = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
} else {
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = DRM(hash_magic)(magic);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
if (dev->magiclist[hash].head == pt) {
|
||||
dev->magiclist[hash].head = pt->next;
|
||||
}
|
||||
if (dev->magiclist[hash].tail == pt) {
|
||||
dev->magiclist[hash].tail = prev;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int DRM(getmagic)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_auth_t auth;
|
||||
|
||||
/* Find unique magic */
|
||||
if (priv->magic) {
|
||||
auth.magic = priv->magic;
|
||||
} else {
|
||||
do {
|
||||
spin_lock(&lock);
|
||||
if (!sequence) ++sequence; /* reserve 0 */
|
||||
auth.magic = sequence++;
|
||||
spin_unlock(&lock);
|
||||
} while (DRM(find_file)(dev, auth.magic));
|
||||
priv->magic = auth.magic;
|
||||
DRM(add_magic)(dev, priv, auth.magic);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(authmagic)(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_auth_t auth;
|
||||
drm_file_t *file;
|
||||
|
||||
if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if ((file = DRM(find_file)(dev, auth.magic))) {
|
||||
file->authenticated = 1;
|
||||
DRM(remove_magic)(dev, auth.magic);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
594
linux/drm_dma.h
Normal file
594
linux/drm_dma.h
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
|
||||
* Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
|
||||
#ifndef __HAVE_DMA_WAITQUEUE
|
||||
#define __HAVE_DMA_WAITQUEUE 0
|
||||
#endif
|
||||
#ifndef __HAVE_DMA_RECLAIM
|
||||
#define __HAVE_DMA_RECLAIM 0
|
||||
#endif
|
||||
|
||||
#if __HAVE_DMA
|
||||
|
||||
int DRM(dma_setup)( drm_device_t *dev )
|
||||
{
|
||||
int i;
|
||||
|
||||
dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
|
||||
if ( !dev->dma )
|
||||
return -ENOMEM;
|
||||
|
||||
memset( dev->dma, 0, sizeof(*dev->dma) );
|
||||
|
||||
for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
|
||||
memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DRM(dma_takedown)(drm_device_t *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
|
||||
if (!dma) return;
|
||||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n",
|
||||
i,
|
||||
dma->bufs[i].buf_count,
|
||||
dma->bufs[i].seg_count);
|
||||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||
DRM(free_pages)(dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].page_order,
|
||||
DRM_MEM_DMA);
|
||||
}
|
||||
DRM(free)(dma->bufs[i].seglist,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist),
|
||||
DRM_MEM_SEGS);
|
||||
}
|
||||
if(dma->bufs[i].buf_count) {
|
||||
for(j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if(dma->bufs[i].buflist[j].dev_private) {
|
||||
DRM(free)(dma->bufs[i].buflist[j].dev_private,
|
||||
dma->bufs[i].buflist[j].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
DRM(free)(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
sizeof(*dma->bufs[0].buflist),
|
||||
DRM_MEM_BUFS);
|
||||
#if __HAVE_DMA_FREELIST
|
||||
DRM(freelist_destroy)(&dma->bufs[i].freelist);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (dma->buflist) {
|
||||
DRM(free)(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (dma->pagelist) {
|
||||
DRM(free)(dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
/* This is slow, but is useful for debugging. */
|
||||
int DRM(histogram_slot)(unsigned long count)
|
||||
{
|
||||
int value = DRM_DMA_HISTOGRAM_INITIAL;
|
||||
int slot;
|
||||
|
||||
for (slot = 0;
|
||||
slot < DRM_DMA_HISTOGRAM_SLOTS;
|
||||
++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
|
||||
if (count < value) return slot;
|
||||
}
|
||||
return DRM_DMA_HISTOGRAM_SLOTS - 1;
|
||||
}
|
||||
|
||||
void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
cycles_t queued_to_dispatched;
|
||||
cycles_t dispatched_to_completed;
|
||||
cycles_t completed_to_freed;
|
||||
int q2d, d2c, c2f, q2c, q2f;
|
||||
|
||||
if (buf->time_queued) {
|
||||
queued_to_dispatched = (buf->time_dispatched
|
||||
- buf->time_queued);
|
||||
dispatched_to_completed = (buf->time_completed
|
||||
- buf->time_dispatched);
|
||||
completed_to_freed = (buf->time_freed
|
||||
- buf->time_completed);
|
||||
|
||||
q2d = DRM(histogram_slot)(queued_to_dispatched);
|
||||
d2c = DRM(histogram_slot)(dispatched_to_completed);
|
||||
c2f = DRM(histogram_slot)(completed_to_freed);
|
||||
|
||||
q2c = DRM(histogram_slot)(queued_to_dispatched
|
||||
+ dispatched_to_completed);
|
||||
q2f = DRM(histogram_slot)(queued_to_dispatched
|
||||
+ dispatched_to_completed
|
||||
+ completed_to_freed);
|
||||
|
||||
atomic_inc(&dev->histo.total);
|
||||
atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
|
||||
atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
|
||||
atomic_inc(&dev->histo.completed_to_freed[c2f]);
|
||||
|
||||
atomic_inc(&dev->histo.queued_to_completed[q2c]);
|
||||
atomic_inc(&dev->histo.queued_to_freed[q2f]);
|
||||
|
||||
}
|
||||
buf->time_queued = 0;
|
||||
buf->time_dispatched = 0;
|
||||
buf->time_completed = 0;
|
||||
buf->time_freed = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
if (!buf) return;
|
||||
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
buf->pid = 0;
|
||||
buf->used = 0;
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
buf->time_completed = get_cycles();
|
||||
#endif
|
||||
|
||||
if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
|
||||
wake_up_interruptible(&buf->dma_wait);
|
||||
}
|
||||
#if __HAVE_DMA_FREELIST
|
||||
else {
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
/* If processes are waiting, the last one
|
||||
to wake will put the buffer on the free
|
||||
list. If no processes are waiting, we
|
||||
put the buffer on the freelist here. */
|
||||
DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !__HAVE_DMA_RECLAIM
|
||||
void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
|
||||
if (!dma) return;
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (dma->buflist[i]->pid == pid) {
|
||||
switch (dma->buflist[i]->list) {
|
||||
case DRM_LIST_NONE:
|
||||
DRM(free_buffer)(dev, dma->buflist[i]);
|
||||
break;
|
||||
case DRM_LIST_WAIT:
|
||||
dma->buflist[i]->list = DRM_LIST_RECLAIM;
|
||||
break;
|
||||
default:
|
||||
/* Buffer already on hardware. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* GH: This is a big hack for now...
|
||||
*/
|
||||
#if __HAVE_OLD_DMA
|
||||
|
||||
void DRM(clear_next_buffer)(drm_device_t *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
dma->next_buffer = NULL;
|
||||
if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
|
||||
wake_up_interruptible(&dma->next_queue->flush_queue);
|
||||
}
|
||||
dma->next_queue = NULL;
|
||||
}
|
||||
|
||||
int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
|
||||
{
|
||||
int i;
|
||||
int candidate = -1;
|
||||
int j = jiffies;
|
||||
|
||||
if (!dev) {
|
||||
DRM_ERROR("No device\n");
|
||||
return -1;
|
||||
}
|
||||
if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
|
||||
/* This only happens between the time the
|
||||
interrupt is initialized and the time
|
||||
the queues are initialized. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Doing "while locked" DMA? */
|
||||
if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
|
||||
return DRM_KERNEL_CONTEXT;
|
||||
}
|
||||
|
||||
/* If there are buffers on the last_context
|
||||
queue, and we have not been executing
|
||||
this context very long, continue to
|
||||
execute this context. */
|
||||
if (dev->last_switch <= j
|
||||
&& dev->last_switch + DRM_TIME_SLICE > j
|
||||
&& DRM_WAITCOUNT(dev, dev->last_context)) {
|
||||
return dev->last_context;
|
||||
}
|
||||
|
||||
/* Otherwise, find a candidate */
|
||||
for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
|
||||
if (DRM_WAITCOUNT(dev, i)) {
|
||||
candidate = dev->last_checked = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (candidate < 0) {
|
||||
for (i = 0; i < dev->queue_count; i++) {
|
||||
if (DRM_WAITCOUNT(dev, i)) {
|
||||
candidate = dev->last_checked = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wrapper
|
||||
&& candidate >= 0
|
||||
&& candidate != dev->last_context
|
||||
&& dev->last_switch <= j
|
||||
&& dev->last_switch + DRM_TIME_SLICE > j) {
|
||||
if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
|
||||
del_timer(&dev->timer);
|
||||
dev->timer.function = wrapper;
|
||||
dev->timer.data = (unsigned long)dev;
|
||||
dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
|
||||
add_timer(&dev->timer);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
|
||||
int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
int i;
|
||||
drm_queue_t *q;
|
||||
drm_buf_t *buf;
|
||||
int idx;
|
||||
int while_locked = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
|
||||
DRM_DEBUG("%d\n", d->send_count);
|
||||
|
||||
if (d->flags & _DRM_DMA_WHILE_LOCKED) {
|
||||
int context = dev->lock.hw_lock->lock;
|
||||
|
||||
if (!_DRM_LOCK_IS_HELD(context)) {
|
||||
DRM_ERROR("No lock held during \"while locked\""
|
||||
" request\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (d->context != _DRM_LOCKING_CONTEXT(context)
|
||||
&& _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Lock held by %d while %d makes"
|
||||
" \"while locked\" request\n",
|
||||
_DRM_LOCKING_CONTEXT(context),
|
||||
d->context);
|
||||
return -EINVAL;
|
||||
}
|
||||
q = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
while_locked = 1;
|
||||
} else {
|
||||
q = dev->queuelist[d->context];
|
||||
}
|
||||
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->block_write)) {
|
||||
add_wait_queue(&q->write_queue, &entry);
|
||||
atomic_inc(&q->block_count);
|
||||
for (;;) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if (!atomic_read(&q->block_write)) break;
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
atomic_dec(&q->use_count);
|
||||
remove_wait_queue(&q->write_queue, &entry);
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->block_count);
|
||||
current->state = TASK_RUNNING;
|
||||
remove_wait_queue(&q->write_queue, &entry);
|
||||
}
|
||||
|
||||
for (i = 0; i < d->send_count; i++) {
|
||||
idx = d->send_indices[i];
|
||||
if (idx < 0 || idx >= dma->buf_count) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Index %d (of %d max)\n",
|
||||
d->send_indices[i], dma->buf_count - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
buf = dma->buflist[ idx ];
|
||||
if (buf->pid != current->pid) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Process %d using buffer owned by %d\n",
|
||||
current->pid, buf->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (buf->list != DRM_LIST_NONE) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Process %d using buffer %d on list %d\n",
|
||||
current->pid, buf->idx, buf->list);
|
||||
}
|
||||
buf->used = d->send_sizes[i];
|
||||
buf->while_locked = while_locked;
|
||||
buf->context = d->context;
|
||||
if (!buf->used) {
|
||||
DRM_ERROR("Queueing 0 length buffer\n");
|
||||
}
|
||||
if (buf->pending) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Queueing pending buffer:"
|
||||
" buffer %d, offset %d\n",
|
||||
d->send_indices[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (buf->waiting) {
|
||||
atomic_dec(&q->use_count);
|
||||
DRM_ERROR("Queueing waiting buffer:"
|
||||
" buffer %d, offset %d\n",
|
||||
d->send_indices[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
buf->waiting = 1;
|
||||
if (atomic_read(&q->use_count) == 1
|
||||
|| atomic_read(&q->finalization)) {
|
||||
DRM(free_buffer)(dev, buf);
|
||||
} else {
|
||||
DRM(waitlist_put)(&q->waitlist, buf);
|
||||
atomic_inc(&q->total_queued);
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
|
||||
int order)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = DRM(freelist_get)(&dma->bufs[order].freelist,
|
||||
d->flags & _DRM_DMA_WAIT);
|
||||
if (!buf) break;
|
||||
if (buf->pending || buf->waiting) {
|
||||
DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
|
||||
buf->idx,
|
||||
buf->pid,
|
||||
buf->waiting,
|
||||
buf->pending);
|
||||
}
|
||||
buf->pid = current->pid;
|
||||
if (copy_to_user(&d->request_indices[i],
|
||||
&buf->idx,
|
||||
sizeof(buf->idx)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user(&d->request_sizes[i],
|
||||
&buf->total,
|
||||
sizeof(buf->total)))
|
||||
return -EFAULT;
|
||||
|
||||
++d->granted_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
|
||||
{
|
||||
int order;
|
||||
int retcode = 0;
|
||||
int tmp_order;
|
||||
|
||||
order = DRM(order)(dma->request_size);
|
||||
|
||||
dma->granted_count = 0;
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma, order);
|
||||
|
||||
if (dma->granted_count < dma->request_count
|
||||
&& (dma->flags & _DRM_DMA_SMALLER_OK)) {
|
||||
for (tmp_order = order - 1;
|
||||
!retcode
|
||||
&& dma->granted_count < dma->request_count
|
||||
&& tmp_order >= DRM_MIN_ORDER;
|
||||
--tmp_order) {
|
||||
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma,
|
||||
tmp_order);
|
||||
}
|
||||
}
|
||||
|
||||
if (dma->granted_count < dma->request_count
|
||||
&& (dma->flags & _DRM_DMA_LARGER_OK)) {
|
||||
for (tmp_order = order + 1;
|
||||
!retcode
|
||||
&& dma->granted_count < dma->request_count
|
||||
&& tmp_order <= DRM_MAX_ORDER;
|
||||
++tmp_order) {
|
||||
|
||||
retcode = DRM(dma_get_buffers_of_order)(dev, dma,
|
||||
tmp_order);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __HAVE_OLD_DMA */
|
||||
|
||||
|
||||
#if __HAVE_DMA_IRQ
|
||||
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( !irq )
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
if ( dev->irq ) {
|
||||
up( &dev->struct_sem );
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->irq = irq;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
dev->dma_flag = 0;
|
||||
|
||||
dev->dma->next_buffer = NULL;
|
||||
dev->dma->next_queue = NULL;
|
||||
dev->dma->this_buffer = NULL;
|
||||
|
||||
#if __HAVE_DMA_IRQ_BH
|
||||
INIT_LIST_HEAD( &dev->tq.list );
|
||||
dev->tq.sync = 0;
|
||||
dev->tq.routine = DRM(dma_immediate_bh);
|
||||
dev->tq.data = dev;
|
||||
#endif
|
||||
|
||||
/* Before installing handler */
|
||||
DRIVER_PREINSTALL();
|
||||
|
||||
/* Install handler */
|
||||
ret = request_irq( dev->irq, DRM(dma_service),
|
||||
0, dev->devname, dev );
|
||||
if ( ret < 0 ) {
|
||||
down( &dev->struct_sem );
|
||||
dev->irq = 0;
|
||||
up( &dev->struct_sem );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* After installing handler */
|
||||
DRIVER_POSTINSTALL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
irq = dev->irq;
|
||||
dev->irq = 0;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
if ( !irq )
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
|
||||
DRIVER_UNINSTALL();
|
||||
|
||||
free_irq( irq, dev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(control)( 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_control_t ctl;
|
||||
|
||||
if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __HAVE_DMA_IRQ */
|
||||
|
||||
#endif /* __HAVE_DMA */
|
||||
51
linux/drm_drawable.h
Normal file
51
linux/drm_drawable.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(adddraw)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_draw_t draw;
|
||||
|
||||
draw.handle = 0; /* NOOP */
|
||||
DRM_DEBUG("%d\n", draw.handle);
|
||||
if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(rmdraw)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0; /* NOOP */
|
||||
}
|
||||
208
linux/drm_fops.h
Normal file
208
linux/drm_fops.h
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/* drm_fops.h -- File operations for DRM -*- linux-c -*-
|
||||
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Daryll Strauss <daryll@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
#include <linux/poll.h>
|
||||
|
||||
/* drm_open is called whenever a process opens /dev/drm. */
|
||||
|
||||
int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
|
||||
{
|
||||
kdev_t minor = MINOR(inode->i_rdev);
|
||||
drm_file_t *priv;
|
||||
|
||||
if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
|
||||
if (!DRM(cpu_valid)()) return -EINVAL;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
|
||||
|
||||
priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
filp->private_data = priv;
|
||||
priv->uid = current->euid;
|
||||
priv->pid = current->pid;
|
||||
priv->minor = minor;
|
||||
priv->dev = dev;
|
||||
priv->ioctl_count = 0;
|
||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (!dev->file_last) {
|
||||
priv->next = NULL;
|
||||
priv->prev = NULL;
|
||||
dev->file_first = priv;
|
||||
dev->file_last = priv;
|
||||
} else {
|
||||
priv->next = NULL;
|
||||
priv->prev = dev->file_last;
|
||||
dev->file_last->next = priv;
|
||||
dev->file_last = priv;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(flush)(struct file *filp)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
|
||||
current->pid, dev->device, dev->open_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(fasync)(int fd, struct file *filp, int on)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
|
||||
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
|
||||
if (retcode < 0) return retcode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The drm_read and drm_write_string code (especially that which manages
|
||||
the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
|
||||
DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
|
||||
|
||||
ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
int left;
|
||||
int avail;
|
||||
int send;
|
||||
int cur;
|
||||
|
||||
DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
|
||||
|
||||
while (dev->buf_rp == dev->buf_wp) {
|
||||
DRM_DEBUG(" sleeping\n");
|
||||
if (filp->f_flags & O_NONBLOCK) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
interruptible_sleep_on(&dev->buf_readers);
|
||||
if (signal_pending(current)) {
|
||||
DRM_DEBUG(" interrupted\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
DRM_DEBUG(" awake\n");
|
||||
}
|
||||
|
||||
left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
|
||||
avail = DRM_BSZ - left;
|
||||
send = DRM_MIN(avail, count);
|
||||
|
||||
while (send) {
|
||||
if (dev->buf_wp > dev->buf_rp) {
|
||||
cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
|
||||
} else {
|
||||
cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
|
||||
}
|
||||
if (copy_to_user(buf, dev->buf_rp, cur))
|
||||
return -EFAULT;
|
||||
dev->buf_rp += cur;
|
||||
if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
|
||||
send -= cur;
|
||||
}
|
||||
|
||||
wake_up_interruptible(&dev->buf_writers);
|
||||
return DRM_MIN(avail, count);;
|
||||
}
|
||||
|
||||
int DRM(write_string)(drm_device_t *dev, const char *s)
|
||||
{
|
||||
int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
|
||||
int send = strlen(s);
|
||||
int count;
|
||||
|
||||
DRM_DEBUG("%d left, %d to send (%p, %p)\n",
|
||||
left, send, dev->buf_rp, dev->buf_wp);
|
||||
|
||||
if (left == 1 || dev->buf_wp != dev->buf_rp) {
|
||||
DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
|
||||
left,
|
||||
dev->buf_wp,
|
||||
dev->buf_rp);
|
||||
}
|
||||
|
||||
while (send) {
|
||||
if (dev->buf_wp >= dev->buf_rp) {
|
||||
count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
|
||||
if (count == left) --count; /* Leave a hole */
|
||||
} else {
|
||||
count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
|
||||
}
|
||||
strncpy(dev->buf_wp, s, count);
|
||||
dev->buf_wp += count;
|
||||
if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
|
||||
send -= count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
|
||||
/* The extra parameter to kill_fasync was added in 2.3.21, and is
|
||||
_not_ present in _stock_ 2.2.14 and 2.2.15. However, some
|
||||
distributions patch 2.2.x kernels to add this parameter. The
|
||||
Makefile.linux attempts to detect this addition and defines
|
||||
KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
|
||||
if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
|
||||
#else
|
||||
|
||||
/* Parameter added in 2.3.21. */
|
||||
#if LINUX_VERSION_CODE < 0x020400
|
||||
if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
|
||||
#else
|
||||
/* Type of first parameter changed in
|
||||
Linux 2.4.0-test2... */
|
||||
if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
|
||||
#endif
|
||||
#endif
|
||||
DRM_DEBUG("waking\n");
|
||||
wake_up_interruptible(&dev->buf_readers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
|
||||
poll_wait(filp, &dev->buf_readers, wait);
|
||||
if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
|
||||
return 0;
|
||||
}
|
||||
112
linux/drm_init.h
Normal file
112
linux/drm_init.h
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* drm_init.h -- Setup/Cleanup for DRM -*- linux-c -*-
|
||||
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(flags) = 0;
|
||||
|
||||
/* drm_parse_option parses a single option. See description for
|
||||
* drm_parse_options for details.
|
||||
*/
|
||||
static void DRM(parse_option)(char *s)
|
||||
{
|
||||
char *c, *r;
|
||||
|
||||
DRM_DEBUG("\"%s\"\n", s);
|
||||
if (!s || !*s) return;
|
||||
for (c = s; *c && *c != ':'; c++); /* find : or \0 */
|
||||
if (*c) r = c + 1; else r = NULL; /* remember remainder */
|
||||
*c = '\0'; /* terminate */
|
||||
if (!strcmp(s, "noctx")) {
|
||||
DRM(flags) |= DRM_FLAG_NOCTX;
|
||||
DRM_INFO("Server-mediated context switching OFF\n");
|
||||
return;
|
||||
}
|
||||
if (!strcmp(s, "debug")) {
|
||||
DRM(flags) |= DRM_FLAG_DEBUG;
|
||||
DRM_INFO("Debug messages ON\n");
|
||||
return;
|
||||
}
|
||||
DRM_ERROR("\"%s\" is not a valid option\n", s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* drm_parse_options parse the insmod "drm=" options, or the command-line
|
||||
* options passed to the kernel via LILO. The grammar of the format is as
|
||||
* follows:
|
||||
*
|
||||
* drm ::= 'drm=' option_list
|
||||
* option_list ::= option [ ';' option_list ]
|
||||
* option ::= 'device:' major
|
||||
* | 'debug'
|
||||
* | 'noctx'
|
||||
* major ::= INTEGER
|
||||
*
|
||||
* Note that 's' contains option_list without the 'drm=' part.
|
||||
*
|
||||
* device=major,minor specifies the device number used for /dev/drm
|
||||
* if major == 0 then the misc device is used
|
||||
* if major == 0 and minor == 0 then dynamic misc allocation is used
|
||||
* debug=on specifies that debugging messages will be printk'd
|
||||
* debug=trace specifies that each function call will be logged via printk
|
||||
* debug=off turns off all debugging options
|
||||
*
|
||||
*/
|
||||
|
||||
void DRM(parse_options)(char *s)
|
||||
{
|
||||
char *h, *t, *n;
|
||||
|
||||
DRM_DEBUG("\"%s\"\n", s ?: "");
|
||||
if (!s || !*s) return;
|
||||
|
||||
for (h = t = n = s; h && *h; h = n) {
|
||||
for (; *t && *t != ';'; t++); /* find ; or \0 */
|
||||
if (*t) n = t + 1; else n = NULL; /* remember next */
|
||||
*t = '\0'; /* terminate */
|
||||
DRM(parse_option)(h); /* parse */
|
||||
}
|
||||
}
|
||||
|
||||
/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
|
||||
* otherwise.
|
||||
*/
|
||||
int DRM(cpu_valid)(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
|
||||
#endif
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
return 0; /* No cmpxchg before v9 sparc. */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
227
linux/drm_lists.h
Normal file
227
linux/drm_lists.h
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
|
||||
* Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
#if __HAVE_DMA_WAITLIST
|
||||
|
||||
int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
|
||||
{
|
||||
if (bl->count) return -EINVAL;
|
||||
|
||||
bl->count = count;
|
||||
bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
|
||||
DRM_MEM_BUFLISTS);
|
||||
bl->rp = bl->bufs;
|
||||
bl->wp = bl->bufs;
|
||||
bl->end = &bl->bufs[bl->count+1];
|
||||
bl->write_lock = SPIN_LOCK_UNLOCKED;
|
||||
bl->read_lock = SPIN_LOCK_UNLOCKED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(waitlist_destroy)(drm_waitlist_t *bl)
|
||||
{
|
||||
if (bl->rp != bl->wp) return -EINVAL;
|
||||
if (bl->bufs) DRM(free)(bl->bufs,
|
||||
(bl->count + 2) * sizeof(*bl->bufs),
|
||||
DRM_MEM_BUFLISTS);
|
||||
bl->count = 0;
|
||||
bl->bufs = NULL;
|
||||
bl->rp = NULL;
|
||||
bl->wp = NULL;
|
||||
bl->end = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
|
||||
{
|
||||
int left;
|
||||
unsigned long flags;
|
||||
|
||||
left = DRM_LEFTCOUNT(bl);
|
||||
if (!left) {
|
||||
DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
|
||||
buf->idx, buf->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
buf->time_queued = get_cycles();
|
||||
#endif
|
||||
buf->list = DRM_LIST_WAIT;
|
||||
|
||||
spin_lock_irqsave(&bl->write_lock, flags);
|
||||
*bl->wp = buf;
|
||||
if (++bl->wp >= bl->end) bl->wp = bl->bufs;
|
||||
spin_unlock_irqrestore(&bl->write_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
|
||||
{
|
||||
drm_buf_t *buf;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bl->read_lock, flags);
|
||||
buf = *bl->rp;
|
||||
if (bl->rp == bl->wp) {
|
||||
spin_unlock_irqrestore(&bl->read_lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
if (++bl->rp >= bl->end) bl->rp = bl->bufs;
|
||||
spin_unlock_irqrestore(&bl->read_lock, flags);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* __HAVE_DMA_WAITLIST */
|
||||
|
||||
|
||||
#if __HAVE_DMA_FREELIST
|
||||
|
||||
int DRM(freelist_create)(drm_freelist_t *bl, int count)
|
||||
{
|
||||
atomic_set(&bl->count, 0);
|
||||
bl->next = NULL;
|
||||
init_waitqueue_head(&bl->waiting);
|
||||
bl->low_mark = 0;
|
||||
bl->high_mark = 0;
|
||||
atomic_set(&bl->wfh, 0);
|
||||
bl->lock = SPIN_LOCK_UNLOCKED;
|
||||
++bl->initialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(freelist_destroy)(drm_freelist_t *bl)
|
||||
{
|
||||
atomic_set(&bl->count, 0);
|
||||
bl->next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
if (!dma) {
|
||||
DRM_ERROR("No DMA support\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
|
||||
DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
|
||||
buf->idx, buf->waiting, buf->pending, buf->list);
|
||||
}
|
||||
if (!bl) return 1;
|
||||
#if __HAVE_DMA_HISTOGRAM
|
||||
buf->time_freed = get_cycles();
|
||||
DRM(histogram_compute)(dev, buf);
|
||||
#endif
|
||||
buf->list = DRM_LIST_FREE;
|
||||
|
||||
spin_lock(&bl->lock);
|
||||
buf->next = bl->next;
|
||||
bl->next = buf;
|
||||
spin_unlock(&bl->lock);
|
||||
|
||||
atomic_inc(&bl->count);
|
||||
if (atomic_read(&bl->count) > dma->buf_count) {
|
||||
DRM_ERROR("%d of %d buffers free after addition of %d\n",
|
||||
atomic_read(&bl->count), dma->buf_count, buf->idx);
|
||||
return 1;
|
||||
}
|
||||
/* Check for high water mark */
|
||||
if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
|
||||
atomic_set(&bl->wfh, 0);
|
||||
wake_up_interruptible(&bl->waiting);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
|
||||
{
|
||||
drm_buf_t *buf;
|
||||
|
||||
if (!bl) return NULL;
|
||||
|
||||
/* Get buffer */
|
||||
spin_lock(&bl->lock);
|
||||
if (!bl->next) {
|
||||
spin_unlock(&bl->lock);
|
||||
return NULL;
|
||||
}
|
||||
buf = bl->next;
|
||||
bl->next = bl->next->next;
|
||||
spin_unlock(&bl->lock);
|
||||
|
||||
atomic_dec(&bl->count);
|
||||
buf->next = NULL;
|
||||
buf->list = DRM_LIST_NONE;
|
||||
if (buf->waiting || buf->pending) {
|
||||
DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
|
||||
buf->idx, buf->waiting, buf->pending, buf->list);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
|
||||
{
|
||||
drm_buf_t *buf = NULL;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
|
||||
if (!bl || !bl->initialized) return NULL;
|
||||
|
||||
/* Check for low water mark */
|
||||
if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
|
||||
atomic_set(&bl->wfh, 1);
|
||||
if (atomic_read(&bl->wfh)) {
|
||||
if (block) {
|
||||
add_wait_queue(&bl->waiting, &entry);
|
||||
for (;;) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if (!atomic_read(&bl->wfh)
|
||||
&& (buf = DRM(freelist_try)(bl))) break;
|
||||
schedule();
|
||||
if (signal_pending(current)) break;
|
||||
}
|
||||
current->state = TASK_RUNNING;
|
||||
remove_wait_queue(&bl->waiting, &entry);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
return DRM(freelist_try)(bl);
|
||||
}
|
||||
|
||||
#endif /* __HAVE_DMA_FREELIST */
|
||||
251
linux/drm_lock.h
Normal file
251
linux/drm_lock.h
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* lock.c -- IOCTLs for locking -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS 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@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(unblock)(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
|
||||
else new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
if (context != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("%d holds heavyweight lock\n",
|
||||
context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (new == (context | _DRM_LOCK_HELD)) {
|
||||
/* Have lock */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||
inside *_unlock to give lock to kernel before calling *_dma_schedule. */
|
||||
int DRM(lock_transfer)(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
|
||||
dev->lock.pid = 0;
|
||||
do {
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DRM(lock_free)(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
pid_t pid = dev->lock.pid;
|
||||
|
||||
dev->lock.pid = 0;
|
||||
do {
|
||||
old = *lock;
|
||||
new = 0;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
|
||||
DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
|
||||
context,
|
||||
_DRM_LOCKING_CONTEXT(old),
|
||||
pid);
|
||||
return 1;
|
||||
}
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DRM(flush_queue)(drm_device_t *dev, int context)
|
||||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
int ret = 0;
|
||||
drm_queue_t *q = dev->queuelist[context];
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->use_count) > 1) {
|
||||
atomic_inc(&q->block_write);
|
||||
add_wait_queue(&q->flush_queue, &entry);
|
||||
atomic_inc(&q->block_count);
|
||||
for (;;) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if (!DRM_BUFCOUNT(&q->waitlist)) break;
|
||||
schedule();
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR; /* Can't restart */
|
||||
break;
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->block_count);
|
||||
current->state = TASK_RUNNING;
|
||||
remove_wait_queue(&q->flush_queue, &entry);
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
|
||||
/* NOTE: block_write is still incremented!
|
||||
Use drm_flush_unlock_queue to decrement. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
|
||||
{
|
||||
drm_queue_t *q = dev->queuelist[context];
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
atomic_inc(&q->use_count);
|
||||
if (atomic_read(&q->use_count) > 1) {
|
||||
if (atomic_read(&q->block_write)) {
|
||||
atomic_dec(&q->block_write);
|
||||
wake_up_interruptible(&q->write_queue);
|
||||
}
|
||||
}
|
||||
atomic_dec(&q->use_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
|
||||
drm_lock_flags_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (flags & _DRM_LOCK_FLUSH) {
|
||||
ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
|
||||
if (!ret) ret = DRM(flush_queue)(dev, context);
|
||||
}
|
||||
if (flags & _DRM_LOCK_FLUSH_ALL) {
|
||||
for (i = 0; !ret && i < dev->queue_count; i++) {
|
||||
ret = DRM(flush_queue)(dev, i);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (flags & _DRM_LOCK_FLUSH) {
|
||||
ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
|
||||
if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
|
||||
}
|
||||
if (flags & _DRM_LOCK_FLUSH_ALL) {
|
||||
for (i = 0; !ret && i < dev->queue_count; i++) {
|
||||
ret = DRM(flush_unblock_queue)(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DRM(finish)(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;
|
||||
int ret = 0;
|
||||
drm_lock_t lock;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
|
||||
return -EFAULT;
|
||||
ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
|
||||
DRM(flush_unblock)(dev, lock.context, lock.flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If we get here, it means that the process has called DRM_IOCTL_LOCK
|
||||
without calling DRM_IOCTL_UNLOCK.
|
||||
|
||||
If the lock is not held, then let the signal proceed as usual.
|
||||
|
||||
If the lock is held, then set the contended flag and keep the signal
|
||||
blocked.
|
||||
|
||||
|
||||
Return 1 if the signal should be delivered normally.
|
||||
Return 0 if the signal should be blocked. */
|
||||
|
||||
int DRM(notifier)(void *priv)
|
||||
{
|
||||
drm_sigdata_t *s = (drm_sigdata_t *)priv;
|
||||
unsigned int old, new, prev;
|
||||
|
||||
|
||||
/* Allow signal delivery if lock isn't held */
|
||||
if (!_DRM_LOCK_IS_HELD(s->lock->lock)
|
||||
|| _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
|
||||
|
||||
/* Otherwise, set flag to force call to
|
||||
drmUnlock */
|
||||
do {
|
||||
old = s->lock->lock;
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
prev = cmpxchg(&s->lock->lock, old, new);
|
||||
} while (prev != old);
|
||||
return 0;
|
||||
}
|
||||
152
linux/drm_stub.h
Normal file
152
linux/drm_stub.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* drm_stub.h -- -*- linux-c -*-
|
||||
* Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
|
||||
*
|
||||
* Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020400
|
||||
#include "stubsupport-pre24.h"
|
||||
#endif
|
||||
|
||||
#define DRM_STUB_MAXCARDS 16 /* Enough for one machine */
|
||||
|
||||
static struct drm_stub_list {
|
||||
const char *name;
|
||||
struct file_operations *fops;
|
||||
struct proc_dir_entry *dev_root;
|
||||
} *DRM(stub_list);
|
||||
|
||||
static struct proc_dir_entry *DRM(stub_root);
|
||||
|
||||
static struct drm_stub_info {
|
||||
int (*info_register)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev);
|
||||
int (*info_unregister)(int minor);
|
||||
} DRM(stub_info);
|
||||
|
||||
static int DRM(stub_open)(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int minor = MINOR(inode->i_rdev);
|
||||
int err = -ENODEV;
|
||||
struct file_operations *old_fops;
|
||||
|
||||
if (!DRM(stub_list) || !DRM(stub_list)[minor].fops) return -ENODEV;
|
||||
old_fops = filp->f_op;
|
||||
filp->f_op = fops_get(DRM(stub_list)[minor].fops);
|
||||
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
|
||||
fops_put(filp->f_op);
|
||||
filp->f_op = fops_get(old_fops);
|
||||
}
|
||||
fops_put(old_fops);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct file_operations DRM(stub_fops) = {
|
||||
#if LINUX_VERSION_CODE >= 0x020400
|
||||
owner: THIS_MODULE,
|
||||
#endif
|
||||
open: DRM(stub_open)
|
||||
};
|
||||
|
||||
static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!DRM(stub_list)) {
|
||||
DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
|
||||
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
|
||||
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
|
||||
DRM(stub_list)[i].name = NULL;
|
||||
DRM(stub_list)[i].fops = NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
|
||||
if (!DRM(stub_list)[i].fops) {
|
||||
DRM(stub_list)[i].name = name;
|
||||
DRM(stub_list)[i].fops = fops;
|
||||
DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
|
||||
&DRM(stub_list)[i]
|
||||
.dev_root);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int DRM(stub_putminor)(int minor)
|
||||
{
|
||||
if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
|
||||
DRM(stub_list)[minor].name = NULL;
|
||||
DRM(stub_list)[minor].fops = NULL;
|
||||
DRM(proc_cleanup)(minor, DRM(stub_root),
|
||||
DRM(stub_list)[minor].dev_root);
|
||||
if (minor) {
|
||||
inter_module_put("drm");
|
||||
} else {
|
||||
inter_module_unregister("drm");
|
||||
DRM(free)(DRM(stub_list),
|
||||
sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
|
||||
DRM_MEM_STUB);
|
||||
unregister_chrdev(DRM_MAJOR, "drm");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
||||
drm_device_t *dev)
|
||||
{
|
||||
struct drm_stub_info *i = NULL;
|
||||
|
||||
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
||||
i = (struct drm_stub_info *)inter_module_get("drm");
|
||||
|
||||
if (i) {
|
||||
/* Already registered */
|
||||
DRM(stub_info).info_register = i->info_register;
|
||||
DRM(stub_info).info_unregister = i->info_unregister;
|
||||
} else {
|
||||
DRM(stub_info).info_register = DRM(stub_getminor);
|
||||
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
||||
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
||||
}
|
||||
if (DRM(stub_info).info_register)
|
||||
return DRM(stub_info).info_register(name, fops, dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DRM(stub_unregister)(int minor)
|
||||
{
|
||||
DRM_DEBUG("%d\n", minor);
|
||||
if (DRM(stub_info).info_unregister)
|
||||
return DRM(stub_info).info_unregister(minor);
|
||||
return -1;
|
||||
}
|
||||
67
linux/mga.h
Normal file
67
linux/mga.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* mga.h -- Matrox G200/G400 DRM template customization -*- linux-c -*-
|
||||
* Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#ifndef __MGA_H__
|
||||
#define __MGA_H__
|
||||
|
||||
/* This remains constant for all DRM template files.
|
||||
*/
|
||||
#define DRM(x) mga_##x
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
#define __HAVE_AGP 1
|
||||
#define __MUST_HAVE_AGP 1
|
||||
#define __HAVE_MTRR 1
|
||||
#define __HAVE_CTX_BITMAP 1
|
||||
|
||||
/* Driver customization:
|
||||
*/
|
||||
#define DRIVER_PRETAKEDOWN() do { \
|
||||
if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \
|
||||
} while (0)
|
||||
|
||||
/* DMA customization:
|
||||
*/
|
||||
#define __HAVE_DMA 1
|
||||
|
||||
#define __HAVE_DMA_QUIESCENT 1
|
||||
#define DRIVER_DMA_QUIESCENT() do { \
|
||||
drm_mga_private_t *dev_priv = dev->dev_private; \
|
||||
return mga_do_wait_for_idle( dev_priv ); \
|
||||
} while (0)
|
||||
|
||||
/* Buffer customization:
|
||||
*/
|
||||
#define DRIVER_BUF_PRIV_T drm_mga_buf_priv_t
|
||||
|
||||
#define DRIVER_AGP_BUFFERS_MAP( dev ) \
|
||||
((drm_mga_private_t *)((dev)->dev_private))->buffers
|
||||
|
||||
#endif
|
||||
|
|
@ -236,6 +236,8 @@ typedef struct _drm_mga_sarea {
|
|||
*/
|
||||
int ctxOwner;
|
||||
int vertexsize;
|
||||
|
||||
unsigned int wacceptseq;
|
||||
} drm_mga_sarea_t;
|
||||
|
||||
/* Device specific ioctls:
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
|
|||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int pipe = sarea_priv->WarpPipe;
|
||||
unsigned int prim = sarea_priv->wacceptseq;
|
||||
PRIMLOCALS;
|
||||
|
||||
PRIMGETPTR(dev_priv);
|
||||
|
|
@ -271,7 +272,7 @@ static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
|
|||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, prim );
|
||||
} else {
|
||||
if (dev_priv->WarpPipe & MGA_T2) {
|
||||
/* Flush the WARP pipe */
|
||||
|
|
@ -299,7 +300,7 @@ static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
|
|||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
|
||||
PRIMOUTREG(MGAREG_WACCEPTSEQ, prim );
|
||||
}
|
||||
|
||||
PRIMOUTREG(MGAREG_WFLAG, 0);
|
||||
|
|
@ -366,7 +367,7 @@ static void mgaEmitState(drm_mga_private_t * dev_priv)
|
|||
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
|
||||
int multitex = sarea_priv->WarpPipe & MGA_T2;
|
||||
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
if (dirty & MGA_UPLOAD_PIPE) {
|
||||
mgaG400EmitPipe(dev_priv);
|
||||
dev_priv->WarpPipe = sarea_priv->WarpPipe;
|
||||
}
|
||||
|
|
@ -386,7 +387,7 @@ static void mgaEmitState(drm_mga_private_t * dev_priv)
|
|||
sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
|
||||
}
|
||||
} else {
|
||||
if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
|
||||
if (dirty & MGA_UPLOAD_PIPE) {
|
||||
mgaG200EmitPipe(dev_priv);
|
||||
dev_priv->WarpPipe = sarea_priv->WarpPipe;
|
||||
}
|
||||
|
|
|
|||
11645
linux/mga_ucode.h
Normal file
11645
linux/mga_ucode.h
Normal file
File diff suppressed because it is too large
Load diff
215
linux/mga_warp.c
Normal file
215
linux/mga_warp.c
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
|
||||
* Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "mga.h"
|
||||
#include "drmP.h"
|
||||
#include "mga_drv.h"
|
||||
#include "mga_ucode.h"
|
||||
|
||||
|
||||
#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
|
||||
|
||||
#define WARP_UCODE_SIZE( which ) \
|
||||
((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
|
||||
|
||||
#define WARP_UCODE_INSTALL( which, where ) \
|
||||
do { \
|
||||
DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\
|
||||
dev_priv->warp_pipe_phys[where] = pcbase; \
|
||||
memcpy( vcbase, which, sizeof(which) ); \
|
||||
pcbase += WARP_UCODE_SIZE( which ); \
|
||||
vcbase += WARP_UCODE_SIZE( which ); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
size = ( WARP_UCODE_SIZE( warp_g400_tgz ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgza ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzaf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzs ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzsa ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzsaf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_tgzsf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gz ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gza ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzaf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzs ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzsa ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzsaf ) +
|
||||
WARP_UCODE_SIZE( warp_g400_t2gzsf ) );
|
||||
|
||||
size = PAGE_ALIGN( size );
|
||||
|
||||
DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
|
||||
return size;
|
||||
}
|
||||
|
||||
static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
size = ( WARP_UCODE_SIZE( warp_g200_tgz ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgza ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzaf ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzf ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzs ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzsa ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzsaf ) +
|
||||
WARP_UCODE_SIZE( warp_g200_tgzsf ) );
|
||||
|
||||
size = PAGE_ALIGN( size );
|
||||
|
||||
DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
|
||||
return size;
|
||||
}
|
||||
|
||||
static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
unsigned int size;
|
||||
|
||||
size = mga_warp_g400_microcode_size( dev_priv );
|
||||
if ( size > dev_priv->warp->size ) {
|
||||
DRM_ERROR( "microcode too large! (%u > %lu)\n",
|
||||
size, dev_priv->warp->size );
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset( dev_priv->warp_pipe_phys, 0,
|
||||
sizeof(dev_priv->warp_pipe_phys) );
|
||||
|
||||
WARP_UCODE_INSTALL( warp_g400_tgz, MGA_WARP_TGZ );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzf, MGA_WARP_TGZF );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgza, MGA_WARP_TGZA );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzaf, MGA_WARP_TGZAF );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzs, MGA_WARP_TGZS );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzsf, MGA_WARP_TGZSF );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzsa, MGA_WARP_TGZSA );
|
||||
WARP_UCODE_INSTALL( warp_g400_tgzsaf, MGA_WARP_TGZSAF );
|
||||
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gz, MGA_WARP_T2GZ );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzf, MGA_WARP_T2GZF );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gza, MGA_WARP_T2GZA );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzaf, MGA_WARP_T2GZAF );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzs, MGA_WARP_T2GZS );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzsf, MGA_WARP_T2GZSF );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzsa, MGA_WARP_T2GZSA );
|
||||
WARP_UCODE_INSTALL( warp_g400_t2gzsaf, MGA_WARP_T2GZSAF );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
unsigned int size;
|
||||
|
||||
size = mga_warp_g200_microcode_size( dev_priv );
|
||||
if ( size > dev_priv->warp->size ) {
|
||||
DRM_ERROR( "microcode too large! (%u > %lu)\n",
|
||||
size, dev_priv->warp->size );
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset( dev_priv->warp_pipe_phys, 0,
|
||||
sizeof(dev_priv->warp_pipe_phys) );
|
||||
|
||||
WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA );
|
||||
WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mga_warp_install_microcode( drm_device_t *dev )
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
switch ( dev_priv->chipset ) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
return mga_warp_install_g400_microcode( dev_priv );
|
||||
case MGA_CARD_TYPE_G200:
|
||||
return mga_warp_install_g200_microcode( dev_priv );
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
|
||||
|
||||
int mga_warp_init( drm_device_t *dev )
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
u32 wmisc;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
/* FIXME: Get rid of these damned magic numbers...
|
||||
*/
|
||||
switch ( dev_priv->chipset ) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND );
|
||||
MGA_WRITE( MGA_WGETMSB, 0x00000E00 );
|
||||
MGA_WRITE( MGA_WVRTXSZ, 0x00001807 );
|
||||
MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 );
|
||||
break;
|
||||
case MGA_CARD_TYPE_G200:
|
||||
MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
|
||||
MGA_WRITE( MGA_WGETMSB, 0x1606 );
|
||||
MGA_WRITE( MGA_WVRTXSZ, 7 );
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
|
||||
MGA_WMASTER_ENABLE |
|
||||
MGA_WCACHEFLUSH_ENABLE) );
|
||||
wmisc = MGA_READ( MGA_WMISC );
|
||||
if ( wmisc != WMISC_EXPECTED ) {
|
||||
DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
|
||||
wmisc, WMISC_EXPECTED );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
79
linux/r128.h
Normal file
79
linux/r128.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* r128.h -- ATI Rage 128 DRM template customization -*- linux-c -*-
|
||||
* Created: Wed Feb 14 16:07:10 2001 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#ifndef __R128_H__
|
||||
#define __R128_H__
|
||||
|
||||
/* This remains constant for all DRM template files.
|
||||
*/
|
||||
#define DRM(x) r128_##x
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
#define __HAVE_AGP 1
|
||||
#define __MUST_HAVE_AGP 1
|
||||
#define __HAVE_MTRR 1
|
||||
#define __HAVE_CTX_BITMAP 1
|
||||
|
||||
/* Driver customization:
|
||||
*/
|
||||
#define DRIVER_PRERELEASE() do { \
|
||||
if ( dev->dev_private ) { \
|
||||
drm_r128_private_t *dev_priv = dev->dev_private; \
|
||||
if ( dev_priv->page_flipping ) { \
|
||||
r128_do_cleanup_pageflip( dev ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DRIVER_PRETAKEDOWN() do { \
|
||||
if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \
|
||||
} while (0)
|
||||
|
||||
/* DMA customization:
|
||||
*/
|
||||
#define __HAVE_DMA 1
|
||||
|
||||
#if 0
|
||||
/* GH: Remove this for now... */
|
||||
#define __HAVE_DMA_QUIESCENT 1
|
||||
#define DRIVER_DMA_QUIESCENT() do { \
|
||||
drm_r128_private_t *dev_priv = dev->dev_private; \
|
||||
return r128_do_cce_idle( dev_priv ); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Buffer customization:
|
||||
*/
|
||||
#define DRIVER_BUF_PRIV_T drm_r128_buf_priv_t
|
||||
|
||||
#define DRIVER_AGP_BUFFERS_MAP( dev ) \
|
||||
((drm_r128_private_t *)((dev)->dev_private))->buffers
|
||||
|
||||
#endif
|
||||
79
linux/radeon.h
Normal file
79
linux/radeon.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* radeon.h -- ATI Radeon DRM template customization -*- linux-c -*-
|
||||
* Created: Wed Feb 14 17:07:34 2001 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#ifndef __RADEON_H__
|
||||
#define __RADEON_H__
|
||||
|
||||
/* This remains constant for all DRM template files.
|
||||
*/
|
||||
#define DRM(x) radeon_##x
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
#define __HAVE_AGP 1
|
||||
#define __MUST_HAVE_AGP 1
|
||||
#define __HAVE_MTRR 1
|
||||
#define __HAVE_CTX_BITMAP 1
|
||||
|
||||
/* Driver customization:
|
||||
*/
|
||||
#define DRIVER_PRERELEASE() do { \
|
||||
if ( dev->dev_private ) { \
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private; \
|
||||
if ( dev_priv->page_flipping ) { \
|
||||
radeon_do_cleanup_pageflip( dev ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DRIVER_PRETAKEDOWN() do { \
|
||||
if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \
|
||||
} while (0)
|
||||
|
||||
/* DMA customization:
|
||||
*/
|
||||
#define __HAVE_DMA 1
|
||||
|
||||
#if 0
|
||||
/* GH: Remove this for now... */
|
||||
#define __HAVE_DMA_QUIESCENT 1
|
||||
#define DRIVER_DMA_QUIESCENT() do { \
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private; \
|
||||
return radeon_do_cp_idle( dev_priv ); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Buffer customization:
|
||||
*/
|
||||
#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t
|
||||
|
||||
#define DRIVER_AGP_BUFFERS_MAP( dev ) \
|
||||
((drm_radeon_private_t *)((dev)->dev_private))->buffers
|
||||
|
||||
#endif
|
||||
44
linux/stubsupport-pre24.h
Normal file
44
linux/stubsupport-pre24.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* stubsupport.h -- -*- linux-c -*-
|
||||
* Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
|
||||
*
|
||||
* Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _STUBSUPPORT_PRE24_H_
|
||||
#define _STUBSUPPORT_PRE24_H_
|
||||
struct drm_stub_info *DRM(_stub_pointer) = NULL;
|
||||
#define inter_module_put(x)
|
||||
#define inter_module_unregister(x)
|
||||
#define inter_module_get(x) DRM(_stub_pointer)
|
||||
#define inter_module_register(x,y,z) do { DRM(_stub_pointer) = z; } while (0)
|
||||
|
||||
/* This is a kludge for backward compatibility
|
||||
that is only useful in DRM(stub_open) */
|
||||
#define fops_put(fops) MOD_DEC_USE_COUNT
|
||||
#define fops_get(fops) (fops); MOD_INC_USE_COUNT
|
||||
|
||||
#endif
|
||||
42
linux/tdfx.h
Normal file
42
linux/tdfx.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
|
||||
* Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#ifndef __TDFX_H__
|
||||
#define __TDFX_H__
|
||||
|
||||
/* This remains constant for all DRM template files.
|
||||
*/
|
||||
#define DRM(x) tdfx_##x
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
#define __HAVE_MTRR 1
|
||||
#define __HAVE_CTX_BITMAP 1
|
||||
|
||||
#endif
|
||||
280
tests/dristat.c
Normal file
280
tests/dristat.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/* dristat.c --
|
||||
* Created: Mon Jan 15 05:05:07 2001 by faith@acm.org
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "../../../xf86drm.h"
|
||||
#include "../xf86drmRandom.c"
|
||||
#include "../xf86drmHash.c"
|
||||
#include "../xf86drm.c"
|
||||
|
||||
#define DRM_VERSION 0x00000001
|
||||
#define DRM_MEMORY 0x00000002
|
||||
#define DRM_CLIENTS 0x00000004
|
||||
#define DRM_STATS 0x00000008
|
||||
#define DRM_BUSID 0x00000010
|
||||
|
||||
static void getversion(int fd)
|
||||
{
|
||||
drmVersionPtr version;
|
||||
|
||||
version = drmGetVersion(fd);
|
||||
if (version) {
|
||||
printf(" Version information:\n");
|
||||
printf(" Name: %s\n", version->name ? version->name : "?");
|
||||
printf(" Version: %d.%d.%d\n",
|
||||
version->version_major,
|
||||
version->version_minor,
|
||||
version->version_patchlevel);
|
||||
printf(" Date: %s\n", version->date ? version->date : "?");
|
||||
printf(" Desc: %s\n", version->desc ? version->desc : "?");
|
||||
drmFreeVersion(version);
|
||||
} else {
|
||||
printf(" No version information available\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void getbusid(int fd)
|
||||
{
|
||||
const char *busid = drmGetBusid(fd);
|
||||
|
||||
printf(" Busid: %s\n", *busid ? busid : "(not set)");
|
||||
drmFreeBusid(busid);
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
unsigned long offset; /* Requested physical address (0 for SAREA)*/
|
||||
unsigned long size; /* Requested physical size (bytes) */
|
||||
drm_map_type_t type; /* Type of memory to map */
|
||||
drm_map_flags_t flags; /* Flags */
|
||||
void *handle; /* User-space: "Handle" to pass to mmap */
|
||||
/* Kernel-space: kernel-virtual address */
|
||||
int mtrr; /* MTRR slot used */
|
||||
/* Private data */
|
||||
} drmVmRec, *drmVmPtr;
|
||||
#endif
|
||||
|
||||
static void getvm(int fd)
|
||||
{
|
||||
int i;
|
||||
const char *typename;
|
||||
char flagname[33];
|
||||
drmHandle offset;
|
||||
drmSize size;
|
||||
drmMapType type;
|
||||
drmMapFlags flags;
|
||||
drmHandle handle;
|
||||
int mtrr;
|
||||
|
||||
printf(" VM map information (Restricted locked kernel WC Lock):\n");
|
||||
printf(" slot offset size type flags address mtrr\n");
|
||||
|
||||
for (i = 0;
|
||||
!drmGetMap(fd, i, &offset, &size, &type, &flags, &handle, &mtrr);
|
||||
i++) {
|
||||
|
||||
switch (type) {
|
||||
case DRM_FRAME_BUFFER: typename = "FB"; break;
|
||||
case DRM_REGISTERS: typename = "REG"; break;
|
||||
case DRM_SHM: typename = "SHM"; break;
|
||||
case DRM_AGP: typename = "AGP"; break;
|
||||
default: typename = "???"; break;
|
||||
}
|
||||
|
||||
flagname[0] = (flags & DRM_RESTRICTED) ? 'R' : ' ';
|
||||
flagname[1] = (flags & DRM_READ_ONLY) ? 'r' : 'w';
|
||||
flagname[2] = (flags & DRM_LOCKED) ? 'l' : ' ';
|
||||
flagname[3] = (flags & DRM_KERNEL) ? 'k' : ' ';
|
||||
flagname[4] = (flags & DRM_WRITE_COMBINING) ? 'W' : ' ';
|
||||
flagname[5] = (flags & DRM_CONTAINS_LOCK) ? 'L' : ' ';
|
||||
flagname[6] = '\0';
|
||||
|
||||
printf(" %4d 0x%08lx 0x%08lx %3.3s %6.6s 0x%08lx ",
|
||||
i, offset, (unsigned long)size, typename, flagname, handle);
|
||||
if (mtrr < 0) printf("none\n");
|
||||
else printf("%4d\n", mtrr);
|
||||
}
|
||||
}
|
||||
|
||||
static void getclients(int fd)
|
||||
{
|
||||
int i;
|
||||
int auth;
|
||||
int pid;
|
||||
int uid;
|
||||
unsigned long magic;
|
||||
unsigned long iocs;
|
||||
char buf[64];
|
||||
char cmd[40];
|
||||
int procfd;
|
||||
|
||||
printf(" DRI client information:\n");
|
||||
printf(" a pid uid magic ioctls prog\n");
|
||||
|
||||
for (i = 0; !drmGetClient(fd, i, &auth, &pid, &uid, &magic, &iocs); i++) {
|
||||
sprintf(buf, "/proc/%d/cmdline", pid);
|
||||
memset(cmd, sizeof(cmd), 0);
|
||||
if ((procfd = open(buf, O_RDONLY, 0)) >= 0) {
|
||||
read(procfd, cmd, sizeof(cmd)-1);
|
||||
close(procfd);
|
||||
}
|
||||
if (*cmd) {
|
||||
char *pt;
|
||||
|
||||
for (pt = cmd; *pt; pt++) if (!isprint(*pt)) *pt = ' ';
|
||||
printf(" %c %5d %5d %10lu %10lu %s\n",
|
||||
auth ? 'y' : 'n', pid, uid, magic, iocs, cmd);
|
||||
} else {
|
||||
printf(" %c %5d %5d %10lu %10lu\n",
|
||||
auth ? 'y' : 'n', pid, uid, magic, iocs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void printhuman(unsigned long value, const char *name, int mult)
|
||||
{
|
||||
const char *p;
|
||||
double f;
|
||||
/* Print width 5 number in width 6 space */
|
||||
if (value < 100000) {
|
||||
printf(" %5lu", value);
|
||||
return;
|
||||
}
|
||||
|
||||
p = name;
|
||||
f = (double)value / (double)mult;
|
||||
if (f < 10.0) {
|
||||
printf(" %4.2f%c", f, *p);
|
||||
return;
|
||||
}
|
||||
|
||||
p++;
|
||||
f = (double)value / (double)mult;
|
||||
if (f < 10.0) {
|
||||
printf(" %4.2f%c", f, *p);
|
||||
return;
|
||||
}
|
||||
|
||||
p++;
|
||||
f = (double)value / (double)mult;
|
||||
if (f < 10.0) {
|
||||
printf(" %4.2f%c", f, *p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void getstats(int fd, int i)
|
||||
{
|
||||
drmStatsT prev, curr;
|
||||
int j;
|
||||
double rate;
|
||||
|
||||
printf(" System statistics:\n");
|
||||
|
||||
if (drmGetStats(fd, &prev)) return;
|
||||
if (!i) {
|
||||
for (j = 0; j < prev.count; j++) {
|
||||
printf(" ");
|
||||
printf(prev.data[j].long_format, prev.data[j].long_name);
|
||||
if (prev.data[j].isvalue) printf(" 0x%08lx\n", prev.data[j].value);
|
||||
else printf(" %10lu\n", prev.data[j].value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
for (j = 0; j < prev.count; j++)
|
||||
if (!prev.data[j].verbose) {
|
||||
printf(" ");
|
||||
printf(prev.data[j].rate_format, prev.data[j].rate_name);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (;;) {
|
||||
sleep(i);
|
||||
if (drmGetStats(fd, &curr)) return;
|
||||
printf(" ");
|
||||
for (j = 0; j < curr.count; j++) {
|
||||
if (curr.data[j].verbose) continue;
|
||||
if (curr.data[j].isvalue) {
|
||||
printf(" %08lx", curr.data[j].value);
|
||||
} else {
|
||||
rate = (curr.data[j].value - prev.data[j].value) / (double)i;
|
||||
printhuman(rate, curr.data[j].mult_names, curr.data[j].mult);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
memcpy(&prev, &curr, sizeof(prev));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int mask = 0;
|
||||
int minor = 0;
|
||||
int interval = 0;
|
||||
int fd;
|
||||
char buf[64];
|
||||
int i;
|
||||
|
||||
while ((c = getopt(argc, argv, "avmcsbM:i:")) != EOF)
|
||||
switch (c) {
|
||||
case 'a': mask = ~0; break;
|
||||
case 'v': mask |= DRM_VERSION; break;
|
||||
case 'm': mask |= DRM_MEMORY; break;
|
||||
case 'c': mask |= DRM_CLIENTS; break;
|
||||
case 's': mask |= DRM_STATS; break;
|
||||
case 'b': mask |= DRM_BUSID; break;
|
||||
case 'i': interval = strtol(optarg, NULL, 0); break;
|
||||
case 'M': minor = strtol(optarg, NULL, 0); break;
|
||||
default:
|
||||
fprintf( stderr, "Usage: dristat [options]\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) if (!minor || i == minor) {
|
||||
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i);
|
||||
fd = drmOpenMinor(i, 1);
|
||||
if (fd >= 0) {
|
||||
printf("%s\n", buf);
|
||||
if (mask & DRM_BUSID) getbusid(fd);
|
||||
if (mask & DRM_VERSION) getversion(fd);
|
||||
if (mask & DRM_MEMORY) getvm(fd);
|
||||
if (mask & DRM_CLIENTS) getclients(fd);
|
||||
if (mask & DRM_STATS) getstats(fd, interval);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue