Work in progress checkin

This commit is contained in:
Jeff Hartmann 2000-01-06 23:44:30 +00:00
parent 0c9c9a805d
commit 8e20fb13f3
13 changed files with 1209 additions and 82 deletions

View file

@ -13,7 +13,7 @@
L_TARGET := libdrm.a
L_OBJS := init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
lists.o lock.o ioctl.o fops.o vm.o dma.o
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
M_OBJS :=
@ -25,6 +25,10 @@ ifdef CONFIG_DRM_TDFX
M_OBJS += tdfx.o
endif
ifdef CONFIG_DRM_MGA
M_OBJS += mga.o
endif
include $(TOPDIR)/Rules.make
gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
@ -32,3 +36,7 @@ gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
tdfx.o: tdfx_drv.o tdfx_context.o $(L_TARGET)
$(LD) $(LD_RFLAG) -r -o $@ tdfx_drv.o tdfx_context.o -L. -ldrm
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_context.o mga_bufs.o mga_dma.o -L. -ldrm

View file

@ -70,24 +70,27 @@
#define DRM_FLAG_DEBUG 0x01
#define DRM_FLAG_NOCTX 0x02
#define DRM_MEM_DMA 0
#define DRM_MEM_SAREA 1
#define DRM_MEM_DRIVER 2
#define DRM_MEM_MAGIC 3
#define DRM_MEM_IOCTLS 4
#define DRM_MEM_MAPS 5
#define DRM_MEM_VMAS 6
#define DRM_MEM_BUFS 7
#define DRM_MEM_SEGS 8
#define DRM_MEM_PAGES 9
#define DRM_MEM_FILES 10
#define DRM_MEM_QUEUES 11
#define DRM_MEM_CMDS 12
#define DRM_MEM_MAPPINGS 13
#define DRM_MEM_BUFLISTS 14
#define DRM_MEM_AGPLISTS 15
#define DRM_MEM_TOTALAGP 16
#define DRM_MEM_BOUNDAGP 17
#define DRM_MEM_DMA 0
#define DRM_MEM_SAREA 1
#define DRM_MEM_DRIVER 2
#define DRM_MEM_MAGIC 3
#define DRM_MEM_IOCTLS 4
#define DRM_MEM_MAPS 5
#define DRM_MEM_VMAS 6
#define DRM_MEM_BUFS 7
#define DRM_MEM_SEGS 8
#define DRM_MEM_PAGES 9
#define DRM_MEM_FILES 10
#define DRM_MEM_QUEUES 11
#define DRM_MEM_CMDS 12
#define DRM_MEM_MAPPINGS 13
#define DRM_MEM_BUFLISTS 14
#define DRM_MEM_AGPLISTS 15
#define DRM_MEM_TOTALAGP 16
#define DRM_MEM_BOUNDAGP 17
#define DRM_MEM_CTXBITMAP 18
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 4 * 8)
/* Backward compatibility section */
/* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */
@ -504,6 +507,7 @@ typedef struct drm_device {
#ifdef DRM_AGP
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
} drm_device_t;
@ -692,6 +696,12 @@ extern int drm_flush_unblock(drm_device_t *dev, int context,
extern int drm_flush_block_and_flush(drm_device_t *dev, int context,
drm_lock_flags_t flags);
/* Context Bitmap support (ctxbitmap.c) */
extern int drm_ctxbitmap_init(drm_device_t *dev);
extern void drm_ctxbitmap_cleanup(drm_device_t *dev);
extern int drm_ctxbitmap_next(drm_device_t *dev);
extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
#ifdef DRM_AGP
/* AGP/GART support (agpsupport.c) */
extern drm_agp_head_t *drm_agp_init(void);

View file

@ -1,6 +1,5 @@
/* mga_drv.c -- Matrox g200/g400 driver -*- linux-c -*-
* Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
* Revised: Mon Dec 13 02:26:34 1999 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
@ -23,7 +22,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/
@ -70,26 +73,36 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_unbind, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_bind, 1, 1},
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
#ifdef MODULE
@ -269,6 +282,8 @@ static int mga_takedown(drm_device_t *dev)
- PAGE_SHIFT,
DRM_MEM_SAREA);
break;
case _DRM_AGP:
break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
@ -319,6 +334,10 @@ int mga_init(void)
DRM_DEBUG("\n");
memset((void *)dev, 0, sizeof(*dev));
if((retcode = drm_ctxbitmap_init(dev))) {
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
return retcode;
}
dev->count_lock = SPIN_LOCK_UNLOCKED;
sema_init(&dev->struct_sem, 1);
@ -328,6 +347,7 @@ int mga_init(void)
if ((retcode = misc_register(&mga_misc))) {
DRM_ERROR("Cannot register \"%s\"\n", MGA_NAME);
drm_ctxbitmap_cleanup(dev);
return retcode;
}
dev->device = MKDEV(MISC_MAJOR, mga_misc.minor);
@ -343,7 +363,9 @@ int mga_init(void)
MGA_PATCHLEVEL,
MGA_DATE,
mga_misc.minor);
dev->agp = drm_agp_init();
return 0;
}
@ -362,6 +384,7 @@ void mga_cleanup(void)
DRM_INFO("Module unloaded\n");
}
mga_takedown(dev);
drm_ctxbitmap_cleanup(dev);
}
int mga_version(struct inode *inode, struct file *filp, unsigned int cmd,
@ -484,6 +507,151 @@ int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return retcode;
}
int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
DECLARE_WAITQUEUE(entry, current);
int ret = 0;
drm_lock_t lock;
#if DRM_DMA_HISTOGRAM
cycles_t start;
dev->lck_start = start = get_cycles();
#endif
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
current->pid, lock.context);
return -EINVAL;
}
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
lock.context, current->pid, dev->lock.hw_lock->lock,
lock.flags);
#if 0
/* dev->queue_count == 0 right now for
mga. FIXME? */
if (lock.context < 0 || lock.context >= dev->queue_count)
return -EINVAL;
#endif
if (!ret) {
#if 0
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
!= lock.context) {
long j = jiffies - dev->lock.lock_time;
if (lock.context == mga_res_ctx.handle &&
j >= 0 && j < DRM_LOCK_SLICE) {
/* Can't take lock if we just had it and
there is contention. */
DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
lock.context, current->pid, j,
dev->lock.lock_time, jiffies);
current->state = TASK_INTERRUPTIBLE;
current->policy |= SCHED_YIELD;
schedule_timeout(DRM_LOCK_SLICE-j);
DRM_DEBUG("jiffies=%d\n", jiffies);
}
}
#endif
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
break;
}
if (drm_lock_take(&dev->lock.hw_lock->lock,
lock.context)) {
dev->lock.pid = current->pid;
dev->lock.lock_time = jiffies;
atomic_inc(&dev->total_locks);
break; /* Got lock */
}
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
#if 1
current->policy |= SCHED_YIELD;
#endif
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
}
#if 0
if (!ret && dev->last_context != lock.context &&
lock.context != mga_res_ctx.handle &&
dev->last_context != mga_res_ctx.handle) {
add_wait_queue(&dev->context_wait, &entry);
current->state = TASK_INTERRUPTIBLE;
/* PRE: dev->last_context != lock.context */
mga_context_switch(dev, dev->last_context, lock.context);
/* POST: we will wait for the context
switch and will dispatch on a later call
when dev->last_context == lock.context
NOTE WE HOLD THE LOCK THROUGHOUT THIS
TIME! */
current->policy |= SCHED_YIELD;
schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&dev->context_wait, &entry);
if (signal_pending(current)) {
ret = -EINTR;
} else if (dev->last_context != lock.context) {
DRM_ERROR("Context mismatch: %d %d\n",
dev->last_context, lock.context);
}
}
#endif
if (!ret) {
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
if (lock.flags & _DRM_LOCK_QUIESCENT) {
/* Make hardware quiescent */
#if 0
mga_quiescent(dev);
#endif
}
}
#if 0
DRM_ERROR("pid = %5d, old counter = %5ld\n",
current->pid, current->counter);
#endif
if (lock.context != mga_res_ctx.handle) {
current->counter = 5;
current->priority = DEF_PRIORITY/4;
}
#if 0
while (current->counter > 25)
current->counter >>= 1; /* decrease time slice */
DRM_ERROR("pid = %5d, new counter = %5ld\n",
current->pid, current->counter);
#endif
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
#if DRM_DMA_HISTOGRAM
atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
#endif
return ret;
}
int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)

View file

@ -13,7 +13,7 @@
L_TARGET := libdrm.a
L_OBJS := init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
lists.o lock.o ioctl.o fops.o vm.o dma.o
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
M_OBJS :=
@ -25,6 +25,10 @@ ifdef CONFIG_DRM_TDFX
M_OBJS += tdfx.o
endif
ifdef CONFIG_DRM_MGA
M_OBJS += mga.o
endif
include $(TOPDIR)/Rules.make
gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
@ -32,3 +36,7 @@ gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET)
tdfx.o: tdfx_drv.o tdfx_context.o $(L_TARGET)
$(LD) $(LD_RFLAG) -r -o $@ tdfx_drv.o tdfx_context.o -L. -ldrm
mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET)
$(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_context.o mga_bufs.o mga_dma.o -L. -ldrm

View file

@ -56,12 +56,12 @@ MODVERSIONS := $(shell \
# **** End of SMP/MODVERSIONS detection
MODS= gamma.o tdfx.o r128.o
MODS= gamma.o tdfx.o mga.o
LIBS= libdrm.a
PROGS= drmstat
DRMOBJS= init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
lists.o lock.o ioctl.o fops.o vm.o dma.o
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.c
DRMHEADERS= drm.h drmP.h
GAMMAOBJS= gamma_drv.o gamma_dma.o
@ -70,8 +70,8 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
TDFXOBJS= tdfx_drv.o tdfx_context.o
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
R128OBJS= r128_drv.o r128_context.o
R128HEADERS= r128_drv.h $(DRMHEADERS)
MGAOBJS= mga_drv.o mga_context.o mga_dma.o mga_bufs.o
MGAHEADERS= mga_drv.h $(DRMHEADERS)
PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po
PROGHEADERS= xf86drm.h $(DRMHEADERS)
@ -111,7 +111,7 @@ gamma.o: $(GAMMAOBJS) $(LIBS)
tdfx.o: $(TDFXOBJS) $(LIBS)
$(LD) -r $^ -o $@
r128.o: $(R128OBJS) $(LIBS)
mga.o: $(MGAOBJS) $(LIBS)
$(LD) -r $^ -o $@
drmstat: $(PROGOBJS)
@ -135,7 +135,7 @@ ChangeLog:
$(DRMOBJS): $(DRMHEADERS)
$(GAMMAOBJS): $(GAMMAHEADERS)
$(TDFXOBJS): $(TDFXHEADERS)
$(R128OBJS): $(R128HEADERS)
$(MGAOBJS): $(MGAHEADERS)
$(PROGOBJS): $(PROGHEADERS)
clean:

80
linux/ctxbitmap.c Normal file
View file

@ -0,0 +1,80 @@
/* ctxbitmap.c -- Context bitmap management -*- linux-c -*-
* Created: Thu Jan 6 03:56:42 2000 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/
#include "drmP.h"
void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle)
{
if (ctx_handle < 0) goto failed;
if (ctx_handle < DRM_MAX_CTXBITMAP) {
clear_bit(ctx_handle, dev->ctx_bitmap);
return;
}
failed:
DRM_DEBUG("Attempt to free invalid context handle: %d\n",
ctx_handle);
return;
}
int drm_ctxbitmap_next(drm_device_t *dev)
{
int bit;
bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
if (bit < DRM_MAX_CTXBITMAP) {
set_bit(bit, dev->ctx_bitmap);
return bit;
}
return -1;
}
int drm_ctxbitmap_init(drm_device_t *dev)
{
dev->ctx_bitmap = (unsigned long *) drm_alloc(PAGE_SIZE * 4,
DRM_MEM_CTXBITMAP);
if(dev->ctx_bitmap == NULL) {
return -ENOMEM;
}
memset((void *) dev->ctx_bitmap, 0, PAGE_SIZE * 4);
for(i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
drm_ctxbitmap_next(dev);
}
return 0;
}
void drm_ctxbitmap_cleanup(drm_device_t *dev)
{
drm_free((void *)dev->ctx_bitmap, PAGE_SIZE * 4,
DRM_MEM_CTXBITMAP);
}

View file

@ -70,24 +70,27 @@
#define DRM_FLAG_DEBUG 0x01
#define DRM_FLAG_NOCTX 0x02
#define DRM_MEM_DMA 0
#define DRM_MEM_SAREA 1
#define DRM_MEM_DRIVER 2
#define DRM_MEM_MAGIC 3
#define DRM_MEM_IOCTLS 4
#define DRM_MEM_MAPS 5
#define DRM_MEM_VMAS 6
#define DRM_MEM_BUFS 7
#define DRM_MEM_SEGS 8
#define DRM_MEM_PAGES 9
#define DRM_MEM_FILES 10
#define DRM_MEM_QUEUES 11
#define DRM_MEM_CMDS 12
#define DRM_MEM_MAPPINGS 13
#define DRM_MEM_BUFLISTS 14
#define DRM_MEM_AGPLISTS 15
#define DRM_MEM_TOTALAGP 16
#define DRM_MEM_BOUNDAGP 17
#define DRM_MEM_DMA 0
#define DRM_MEM_SAREA 1
#define DRM_MEM_DRIVER 2
#define DRM_MEM_MAGIC 3
#define DRM_MEM_IOCTLS 4
#define DRM_MEM_MAPS 5
#define DRM_MEM_VMAS 6
#define DRM_MEM_BUFS 7
#define DRM_MEM_SEGS 8
#define DRM_MEM_PAGES 9
#define DRM_MEM_FILES 10
#define DRM_MEM_QUEUES 11
#define DRM_MEM_CMDS 12
#define DRM_MEM_MAPPINGS 13
#define DRM_MEM_BUFLISTS 14
#define DRM_MEM_AGPLISTS 15
#define DRM_MEM_TOTALAGP 16
#define DRM_MEM_BOUNDAGP 17
#define DRM_MEM_CTXBITMAP 18
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 4 * 8)
/* Backward compatibility section */
/* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */
@ -504,6 +507,7 @@ typedef struct drm_device {
#ifdef DRM_AGP
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
} drm_device_t;
@ -692,6 +696,12 @@ extern int drm_flush_unblock(drm_device_t *dev, int context,
extern int drm_flush_block_and_flush(drm_device_t *dev, int context,
drm_lock_flags_t flags);
/* Context Bitmap support (ctxbitmap.c) */
extern int drm_ctxbitmap_init(drm_device_t *dev);
extern void drm_ctxbitmap_cleanup(drm_device_t *dev);
extern int drm_ctxbitmap_next(drm_device_t *dev);
extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
#ifdef DRM_AGP
/* AGP/GART support (agpsupport.c) */
extern drm_agp_head_t *drm_agp_init(void);

View file

@ -63,6 +63,7 @@ static drm_mem_stats_t drm_mem_stats[] = {
[DRM_MEM_AGPLISTS] = { "agplist" },
[DRM_MEM_TOTALAGP] = { "totalagp" },
[DRM_MEM_BOUNDAGP] = { "boundagp" },
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
{ NULL, 0, } /* Last entry must be null */
};

427
linux/mga_bufs.c Normal file
View file

@ -0,0 +1,427 @@
/* mga_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
* Created: Thu Jan 6 01:47:26 2000 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/
#define __NO_VERSION__
#include "drmP.h"
#include "linux/un.h"
int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int count;
int order;
int size;
int total;
int page_order;
drm_buf_entry_t *entry;
unsigned long page;
drm_buf_t *buf;
int alignment;
unsigned long offset;
int i;
int byte_count;
int page_count;
if (!dma) return -EINVAL;
copy_from_user_ret(&request,
(drm_buf_desc_t *)arg,
sizeof(request),
-EFAULT);
count = request.count;
order = drm_order(request.size);
size = 1 << order;
DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %d\n",
request.count, request.size, size, order, dev->queue_count);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
alignment = (request.flags & DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
spin_lock(&dev->count_lock);
if (dev->buf_use) {
spin_unlock(&dev->count_lock);
return -EBUSY;
}
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
down(&dev->struct_sem);
entry = &dma->bufs[order];
if (entry->buf_count) {
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
DRM_MEM_SEGS);
if (!entry->seglist) {
drm_free(entry->buflist,
count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
memset(entry->seglist, 0, count * sizeof(*entry->seglist));
dma->pagelist = drm_realloc(dma->pagelist,
dma->page_count * sizeof(*dma->pagelist),
(dma->page_count + (count << page_order))
* sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_DEBUG("pagelist: %d entries\n",
dma->page_count + (count << page_order));
entry->buf_size = size;
entry->page_order = page_order;
byte_count = 0;
page_count = 0;
while (entry->buf_count < count) {
if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break;
entry->seglist[entry->seg_count++] = page;
for (i = 0; i < (1 << page_order); i++) {
DRM_DEBUG("page %d @ 0x%08lx\n",
dma->page_count + page_count,
page + PAGE_SIZE * i);
dma->pagelist[dma->page_count + page_count++]
= page + PAGE_SIZE * i;
}
for (offset = 0;
offset + size <= total && entry->buf_count < count;
offset += alignment, ++entry->buf_count) {
buf = &entry->buflist[entry->buf_count];
buf->idx = dma->buf_count + entry->buf_count;
buf->total = alignment;
buf->order = order;
buf->used = 0;
buf->offset = (dma->byte_count + byte_count + offset);
buf->address = (void *)(page + offset);
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->pid = 0;
#if DRM_DMA_HISTOGRAM
buf->time_queued = 0;
buf->time_dispatched = 0;
buf->time_completed = 0;
buf->time_freed = 0;
#endif
DRM_DEBUG("buffer %d @ %p\n",
entry->buf_count, buf->address);
}
byte_count += PAGE_SIZE << page_order;
}
dma->buflist = drm_realloc(dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS);
for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
dma->buf_count += entry->buf_count;
dma->seg_count += entry->seg_count;
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
drm_freelist_create(&entry->freelist, entry->buf_count);
for (i = 0; i < entry->buf_count; i++) {
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
}
up(&dev->struct_sem);
request.count = entry->buf_count;
request.size = size;
copy_to_user_ret((drm_buf_desc_t *)arg,
&request,
sizeof(request),
-EFAULT);
atomic_dec(&dev->buf_alloc);
return 0;
}
int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_info_t request;
int i;
int count;
if (!dma) return -EINVAL;
spin_lock(&dev->count_lock);
if (atomic_read(&dev->buf_alloc)) {
spin_unlock(&dev->count_lock);
return -EBUSY;
}
++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
copy_from_user_ret(&request,
(drm_buf_info_t *)arg,
sizeof(request),
-EFAULT);
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) ++count;
}
DRM_DEBUG("count = %d\n", count);
if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
copy_to_user_ret(&request.list[count].count,
&dma->bufs[i].buf_count,
sizeof(dma->bufs[0]
.buf_count),
-EFAULT);
copy_to_user_ret(&request.list[count].size,
&dma->bufs[i].buf_size,
sizeof(dma->bufs[0].buf_size),
-EFAULT);
copy_to_user_ret(&request.list[count].low_mark,
&dma->bufs[i]
.freelist.low_mark,
sizeof(dma->bufs[0]
.freelist.low_mark),
-EFAULT);
copy_to_user_ret(&request.list[count]
.high_mark,
&dma->bufs[i]
.freelist.high_mark,
sizeof(dma->bufs[0]
.freelist.high_mark),
-EFAULT);
DRM_DEBUG("%d %d %d %d %d\n",
i,
dma->bufs[i].buf_count,
dma->bufs[i].buf_size,
dma->bufs[i].freelist.low_mark,
dma->bufs[i].freelist.high_mark);
++count;
}
}
}
request.count = count;
copy_to_user_ret((drm_buf_info_t *)arg,
&request,
sizeof(request),
-EFAULT);
return 0;
}
int mga_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int order;
drm_buf_entry_t *entry;
if (!dma) return -EINVAL;
copy_from_user_ret(&request,
(drm_buf_desc_t *)arg,
sizeof(request),
-EFAULT);
DRM_DEBUG("%d, %d, %d\n",
request.size, request.low_mark, request.high_mark);
order = drm_order(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
entry = &dma->bufs[order];
if (request.low_mark < 0 || request.low_mark > entry->buf_count)
return -EINVAL;
if (request.high_mark < 0 || request.high_mark > entry->buf_count)
return -EINVAL;
entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
return 0;
}
int mga_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_free_t request;
int i;
int idx;
drm_buf_t *buf;
if (!dma) return -EINVAL;
copy_from_user_ret(&request,
(drm_buf_free_t *)arg,
sizeof(request),
-EFAULT);
DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
copy_from_user_ret(&idx,
&request.list[i],
sizeof(idx),
-EFAULT);
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
idx, dma->buf_count - 1);
return -EINVAL;
}
buf = dma->buflist[idx];
if (buf->pid != current->pid) {
DRM_ERROR("Process %d freeing buffer owned by %d\n",
current->pid, buf->pid);
return -EINVAL;
}
drm_free_buffer(dev, buf);
}
return 0;
}
int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
int retcode = 0;
const int zero = 0;
unsigned long virtual;
unsigned long address;
drm_buf_map_t request;
int i;
if (!dma) return -EINVAL;
DRM_DEBUG("\n");
spin_lock(&dev->count_lock);
if (atomic_read(&dev->buf_alloc)) {
spin_unlock(&dev->count_lock);
return -EBUSY;
}
++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
copy_from_user_ret(&request,
(drm_buf_map_t *)arg,
sizeof(request),
-EFAULT);
if (request.count >= dma->buf_count) {
virtual = do_mmap(filp, 0, dma->byte_count,
PROT_READ|PROT_WRITE, MAP_SHARED, 0);
if (virtual > -1024UL) {
/* Real error */
retcode = (signed long)virtual;
goto done;
}
request.virtual = (void *)virtual;
for (i = 0; i < dma->buf_count; i++) {
if (copy_to_user(&request.list[i].idx,
&dma->buflist[i]->idx,
sizeof(request.list[0].idx))) {
retcode = -EFAULT;
goto done;
}
if (copy_to_user(&request.list[i].total,
&dma->buflist[i]->total,
sizeof(request.list[0].total))) {
retcode = -EFAULT;
goto done;
}
if (copy_to_user(&request.list[i].used,
&zero,
sizeof(zero))) {
retcode = -EFAULT;
goto done;
}
address = virtual + dma->buflist[i]->offset;
if (copy_to_user(&request.list[i].address,
&address,
sizeof(address))) {
retcode = -EFAULT;
goto done;
}
}
}
done:
request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
copy_to_user_ret((drm_buf_map_t *)arg,
&request,
sizeof(request),
-EFAULT);
return retcode;
}

210
linux/mga_context.c Normal file
View file

@ -0,0 +1,210 @@
/* mga_context.c -- IOCTLs for mga contexts -*- linux-c -*-
* Created: Thu Jan 6 01:42:46 2000 by jhartmann@precisioninsight.com
*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/
#include <linux/sched.h>
#define __NO_VERSION__
#include "drmP.h"
#include "mga_drv.h"
extern drm_ctx_t mga_res_ctx;
static int mga_alloc_queue(drm_device_t *dev)
{
return drm_ctxbitmap_next(dev);
}
int mga_context_switch(drm_device_t *dev, int old, int new)
{
char buf[64];
atomic_inc(&dev->total_ctx);
if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
return -EBUSY;
}
#if DRM_DMA_HISTOGRAM
dev->ctx_start = get_cycles();
#endif
DRM_DEBUG("Context switch from %d to %d\n", old, new);
if (new == dev->last_context) {
clear_bit(0, &dev->context_flag);
return 0;
}
if (drm_flags & DRM_FLAG_NOCTX) {
mga_context_switch_complete(dev, new);
} else {
sprintf(buf, "C %d %d\n", old, new);
drm_write_string(dev, buf);
}
return 0;
}
int mga_context_switch_complete(drm_device_t *dev, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("Lock isn't held after context switch\n");
}
/* If a context switch is ever initiated
when the kernel holds the lock, release
that lock here. */
#if DRM_DMA_HISTOGRAM
atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
- dev->ctx_start)]);
#endif
clear_bit(0, &dev->context_flag);
wake_up(&dev->context_wait);
return 0;
}
int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_ctx_res_t res;
drm_ctx_t ctx;
int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
copy_to_user_ret(&res.contexts[i],
&i,
sizeof(i),
-EFAULT);
}
}
res.count = DRM_RESERVED_CONTEXTS;
copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
return 0;
}
int mga_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
if ((ctx.handle = mga_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = mga_alloc_queue(dev);
}
DRM_DEBUG("%d\n", ctx.handle);
if (ctx.handle == -1) {
DRM_DEBUG("Not enough free contexts.\n");
/* Should this return -EBUSY instead? */
return -ENOMEM;
}
copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
return 0;
}
int mga_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
if (ctx.flags==_DRM_CONTEXT_PRESERVED)
mga_res_ctx.handle=ctx.handle;
return 0;
}
int mga_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
/* This is 0, because we don't hanlde any context flags */
ctx.flags = 0;
copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
return 0;
}
int mga_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
DRM_DEBUG("%d\n", ctx.handle);
return mga_context_switch(dev, dev->last_context, ctx.handle);
}
int mga_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
DRM_DEBUG("%d\n", ctx.handle);
mga_context_switch_complete(dev, ctx.handle);
return 0;
}
int mga_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
DRM_DEBUG("%d\n", ctx.handle);
drm_ctxbitmap_free(dev, ctx.handle);
return 0;
}

View file

@ -1,6 +1,5 @@
/* mga_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
* Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
* Revised: Mon Dec 13 02:19:32 1999 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
@ -23,7 +22,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/

View file

@ -1,6 +1,5 @@
/* mga_drv.c -- Matrox g200/g400 driver -*- linux-c -*-
* Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
* Revised: Mon Dec 13 02:26:34 1999 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
@ -23,7 +22,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*
*/
@ -70,26 +73,36 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { mga_control, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { mga_addbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { mga_markbufs, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { mga_infobufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { mga_mapbufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { mga_freebufs, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { mga_addctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { mga_rmctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { mga_modctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { mga_getctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { mga_switchctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { mga_newctx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { mga_resctx, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { mga_lock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { mga_unlock, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_unbind, 1, 1},
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_bind, 1, 1},
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
#ifdef MODULE
@ -269,6 +282,8 @@ static int mga_takedown(drm_device_t *dev)
- PAGE_SHIFT,
DRM_MEM_SAREA);
break;
case _DRM_AGP:
break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
@ -319,6 +334,10 @@ int mga_init(void)
DRM_DEBUG("\n");
memset((void *)dev, 0, sizeof(*dev));
if((retcode = drm_ctxbitmap_init(dev))) {
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
return retcode;
}
dev->count_lock = SPIN_LOCK_UNLOCKED;
sema_init(&dev->struct_sem, 1);
@ -328,6 +347,7 @@ int mga_init(void)
if ((retcode = misc_register(&mga_misc))) {
DRM_ERROR("Cannot register \"%s\"\n", MGA_NAME);
drm_ctxbitmap_cleanup(dev);
return retcode;
}
dev->device = MKDEV(MISC_MAJOR, mga_misc.minor);
@ -343,7 +363,9 @@ int mga_init(void)
MGA_PATCHLEVEL,
MGA_DATE,
mga_misc.minor);
dev->agp = drm_agp_init();
return 0;
}
@ -362,6 +384,7 @@ void mga_cleanup(void)
DRM_INFO("Module unloaded\n");
}
mga_takedown(dev);
drm_ctxbitmap_cleanup(dev);
}
int mga_version(struct inode *inode, struct file *filp, unsigned int cmd,
@ -484,6 +507,151 @@ int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return retcode;
}
int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
DECLARE_WAITQUEUE(entry, current);
int ret = 0;
drm_lock_t lock;
#if DRM_DMA_HISTOGRAM
cycles_t start;
dev->lck_start = start = get_cycles();
#endif
copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
current->pid, lock.context);
return -EINVAL;
}
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
lock.context, current->pid, dev->lock.hw_lock->lock,
lock.flags);
#if 0
/* dev->queue_count == 0 right now for
mga. FIXME? */
if (lock.context < 0 || lock.context >= dev->queue_count)
return -EINVAL;
#endif
if (!ret) {
#if 0
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
!= lock.context) {
long j = jiffies - dev->lock.lock_time;
if (lock.context == mga_res_ctx.handle &&
j >= 0 && j < DRM_LOCK_SLICE) {
/* Can't take lock if we just had it and
there is contention. */
DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
lock.context, current->pid, j,
dev->lock.lock_time, jiffies);
current->state = TASK_INTERRUPTIBLE;
current->policy |= SCHED_YIELD;
schedule_timeout(DRM_LOCK_SLICE-j);
DRM_DEBUG("jiffies=%d\n", jiffies);
}
}
#endif
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
break;
}
if (drm_lock_take(&dev->lock.hw_lock->lock,
lock.context)) {
dev->lock.pid = current->pid;
dev->lock.lock_time = jiffies;
atomic_inc(&dev->total_locks);
break; /* Got lock */
}
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
#if 1
current->policy |= SCHED_YIELD;
#endif
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
current->state = TASK_RUNNING;
remove_wait_queue(&dev->lock.lock_queue, &entry);
}
#if 0
if (!ret && dev->last_context != lock.context &&
lock.context != mga_res_ctx.handle &&
dev->last_context != mga_res_ctx.handle) {
add_wait_queue(&dev->context_wait, &entry);
current->state = TASK_INTERRUPTIBLE;
/* PRE: dev->last_context != lock.context */
mga_context_switch(dev, dev->last_context, lock.context);
/* POST: we will wait for the context
switch and will dispatch on a later call
when dev->last_context == lock.context
NOTE WE HOLD THE LOCK THROUGHOUT THIS
TIME! */
current->policy |= SCHED_YIELD;
schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&dev->context_wait, &entry);
if (signal_pending(current)) {
ret = -EINTR;
} else if (dev->last_context != lock.context) {
DRM_ERROR("Context mismatch: %d %d\n",
dev->last_context, lock.context);
}
}
#endif
if (!ret) {
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
if (lock.flags & _DRM_LOCK_QUIESCENT) {
/* Make hardware quiescent */
#if 0
mga_quiescent(dev);
#endif
}
}
#if 0
DRM_ERROR("pid = %5d, old counter = %5ld\n",
current->pid, current->counter);
#endif
if (lock.context != mga_res_ctx.handle) {
current->counter = 5;
current->priority = DEF_PRIORITY/4;
}
#if 0
while (current->counter > 25)
current->counter >>= 1; /* decrease time slice */
DRM_ERROR("pid = %5d, new counter = %5ld\n",
current->pid, current->counter);
#endif
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
#if DRM_DMA_HISTOGRAM
atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
#endif
return ret;
}
int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)

View file

@ -1,6 +1,5 @@
/* mga_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*-
* Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
* Revised: Mon Dec 13 02:27:49 1999 by jhartmann@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* All rights reserved.
@ -23,8 +22,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*
*
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
* Jeff Hartmann <jhartmann@precisioninsight.com>
*
* $XFree86$
*/
#ifndef _MGA_DRV_H_
@ -53,6 +55,38 @@ extern int mga_irq_uninstall(drm_device_t *dev);
extern int mga_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* mga_bufs.c */
extern int mga_addbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_infobufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_markbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* mga_context.c */
extern int mga_resctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_addctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_modctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_getctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_switchctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_newctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_rmctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_context_switch(drm_device_t *dev, int old, int new);
extern int mga_context_switch_complete(drm_device_t *dev, int new);
#define MGAREG_MGA_EXEC 0x0100
#define MGAREG_AGP_PLL 0x1e4c
#define MGAREG_ALPHACTRL 0x2c7c