Add new ioctls and example drmstat.c program More ioctls are needed, but

this shows preliminary examples Try, for example: ./drmstat -cmv
This commit is contained in:
Rik Faith 2001-02-02 11:44:22 +00:00
parent 95bb76c7de
commit 0af4b005af
11 changed files with 429 additions and 18 deletions

View file

@ -728,7 +728,10 @@ extern int DRM(getunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(setunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getmap)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getclient)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* Context IOCTL support (context.c) */
extern int DRM(resctx)( struct inode *inode, struct file *filp,

View file

@ -97,3 +97,65 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
return 0;
}
int DRM(getmap)( 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_map_t map;
int idx;
if (copy_from_user(&map, (drm_map_t *)arg, sizeof(map)))
return -EFAULT;
idx = map.offset;
down(&dev->struct_sem);
if (idx < 0 || idx >= dev->map_count) {
up(&dev->struct_sem);
return -EINVAL;
}
map.offset = dev->maplist[idx]->offset;
map.size = dev->maplist[idx]->size;
map.type = dev->maplist[idx]->type;
map.flags = dev->maplist[idx]->flags;
map.handle = dev->maplist[idx]->handle;
map.mtrr = dev->maplist[idx]->mtrr;
up(&dev->struct_sem);
if (copy_to_user((drm_map_t *)arg, &map, sizeof(map))) return -EFAULT;
return 0;
}
int DRM(getclient)( 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_client_t client;
drm_file_t *pt;
int idx;
int i;
if (copy_from_user(&client, (drm_client_t *)arg, sizeof(client)))
return -EFAULT;
idx = client.idx;
down(&dev->struct_sem);
for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
;
if (!pt) {
up(&dev->struct_sem);
return -EINVAL;
}
client.auth = pt->authenticated;
client.pid = pt->pid;
client.uid = pt->uid;
client.magic = pt->magic;
client.iocs = pt->ioctl_count;
up(&dev->struct_sem);
if (copy_to_user((drm_client_t *)arg, &client, sizeof(client)))
return -EFAULT;
return 0;
}

View file

@ -52,6 +52,8 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { mga_getunique, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { mga_getmagic, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { mga_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { mga_getmap, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { mga_getclient, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { mga_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { mga_block, 1, 1 },

View file

@ -77,7 +77,8 @@ MODCFLAGS= $(CFLAGS) -D__KERNEL__ -DMODULE -fomit-frame-pointer
PRGCFLAGS= $(CFLAGS) -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
-D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
-I../../../../../../include -I../../../../../../../../include \
-I../../../../../../../../programs/Xserver/hw/xfree86/common
-I../../../../../../../../programs/Xserver/hw/xfree86/common \
-I. -I../../.. -I../../../../../../../../lib/X11
PRGLIBS=
# **** Start of SMP/MODVERSIONS detection
@ -206,6 +207,9 @@ libdrm.a: $(DRMOBJS)
-$(RM) -f $@
$(AR) rcs $@ $(DRMOBJS)
dristat: dristat.c
$(CC) $(PRGCFLAGS) $< -o $@
gamma_drv.o: gamma_drv.c
$(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
gamma.o: $(GAMMAOBJS) $(LIBS)

View file

@ -35,6 +35,7 @@
#ifndef _DRM_H_
#define _DRM_H_
#include <linux/config.h>
#if defined(__linux__)
#include <asm/ioctl.h> /* For _IO* macros */
#define DRM_IOCTL_NR(n) _IOC_NR(n)
@ -43,15 +44,10 @@
#define DRM_IOCTL_NR(n) ((n) & 0xff)
#endif
#define DRM_PROC_DEVICES "/proc/devices"
#define DRM_PROC_MISC "/proc/misc"
#define DRM_PROC_DRM "/proc/drm"
#define DRM_DEV_DRM "/dev/drm"
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define DRM_DEV_UID 0
#define DRM_DEV_GID 0
#define DRM_MAJOR 226
#define DRM_NAME "drm" /* Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */
@ -159,6 +155,15 @@ typedef struct drm_map {
/* Private data */
} drm_map_t;
typedef struct drm_client {
int idx; /* Which client desired? */
int auth; /* Is client authenticated? */
unsigned long pid; /* Process id */
unsigned long uid; /* User id */
unsigned long magic; /* Magic */
unsigned long iocs; /* Ioctl count */
} drm_client_t;
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@ -318,6 +323,8 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)

View file

@ -728,7 +728,10 @@ extern int DRM(getunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(setunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getmap)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getclient)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* Context IOCTL support (context.c) */
extern int DRM(resctx)( struct inode *inode, struct file *filp,

View file

@ -97,3 +97,65 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
return 0;
}
int DRM(getmap)( 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_map_t map;
int idx;
if (copy_from_user(&map, (drm_map_t *)arg, sizeof(map)))
return -EFAULT;
idx = map.offset;
down(&dev->struct_sem);
if (idx < 0 || idx >= dev->map_count) {
up(&dev->struct_sem);
return -EINVAL;
}
map.offset = dev->maplist[idx]->offset;
map.size = dev->maplist[idx]->size;
map.type = dev->maplist[idx]->type;
map.flags = dev->maplist[idx]->flags;
map.handle = dev->maplist[idx]->handle;
map.mtrr = dev->maplist[idx]->mtrr;
up(&dev->struct_sem);
if (copy_to_user((drm_map_t *)arg, &map, sizeof(map))) return -EFAULT;
return 0;
}
int DRM(getclient)( 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_client_t client;
drm_file_t *pt;
int idx;
int i;
if (copy_from_user(&client, (drm_client_t *)arg, sizeof(client)))
return -EFAULT;
idx = client.idx;
down(&dev->struct_sem);
for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
;
if (!pt) {
up(&dev->struct_sem);
return -EINVAL;
}
client.auth = pt->authenticated;
client.pid = pt->pid;
client.uid = pt->uid;
client.magic = pt->magic;
client.iocs = pt->ioctl_count;
up(&dev->struct_sem);
if (copy_to_user((drm_client_t *)arg, &client, sizeof(client)))
return -EFAULT;
return 0;
}

View file

@ -52,6 +52,8 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { mga_getunique, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { mga_getmagic, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { mga_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { mga_getmap, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { mga_getclient, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { mga_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { mga_block, 1, 1 },

View file

@ -35,6 +35,7 @@
#ifndef _DRM_H_
#define _DRM_H_
#include <linux/config.h>
#if defined(__linux__)
#include <asm/ioctl.h> /* For _IO* macros */
#define DRM_IOCTL_NR(n) _IOC_NR(n)
@ -43,15 +44,10 @@
#define DRM_IOCTL_NR(n) ((n) & 0xff)
#endif
#define DRM_PROC_DEVICES "/proc/devices"
#define DRM_PROC_MISC "/proc/misc"
#define DRM_PROC_DRM "/proc/drm"
#define DRM_DEV_DRM "/dev/drm"
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define DRM_DEV_UID 0
#define DRM_DEV_GID 0
#define DRM_MAJOR 226
#define DRM_NAME "drm" /* Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */
@ -159,6 +155,15 @@ typedef struct drm_map {
/* Private data */
} drm_map_t;
typedef struct drm_client {
int idx; /* Which client desired? */
int auth; /* Is client authenticated? */
unsigned long pid; /* Process id */
unsigned long uid; /* User id */
unsigned long magic; /* Magic */
unsigned long iocs; /* Ioctl count */
} drm_client_t;
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@ -318,6 +323,8 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)

View file

@ -35,6 +35,7 @@
#ifndef _DRM_H_
#define _DRM_H_
#include <linux/config.h>
#if defined(__linux__)
#include <asm/ioctl.h> /* For _IO* macros */
#define DRM_IOCTL_NR(n) _IOC_NR(n)
@ -43,15 +44,10 @@
#define DRM_IOCTL_NR(n) ((n) & 0xff)
#endif
#define DRM_PROC_DEVICES "/proc/devices"
#define DRM_PROC_MISC "/proc/misc"
#define DRM_PROC_DRM "/proc/drm"
#define DRM_DEV_DRM "/dev/drm"
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define DRM_DEV_UID 0
#define DRM_DEV_GID 0
#define DRM_MAJOR 226
#define DRM_NAME "drm" /* Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */
@ -159,6 +155,15 @@ typedef struct drm_map {
/* Private data */
} drm_map_t;
typedef struct drm_client {
int idx; /* Which client desired? */
int auth; /* Is client authenticated? */
unsigned long pid; /* Process id */
unsigned long uid; /* User id */
unsigned long magic; /* Magic */
unsigned long iocs; /* Ioctl count */
} drm_client_t;
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@ -318,6 +323,8 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)

252
tests/dristat.c Normal file
View file

@ -0,0 +1,252 @@
/* 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_DIR_NAME "/dev/dri"
#define DRM_DEV_NAME "%s/card%d"
#define DRM_VERSION 0x00000001
#define DRM_MEMORY 0x00000002
#define DRM_CLIENTS 0x00000004
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");
}
}
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;
int drmGetMap(int fd, int idx, drmHandle *offset, drmSize *size,
drmMapType *type, drmMapFlags *flags, drmHandle *handle,
int *mtrr)
{
drm_map_t map;
map.offset = idx;
if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
*offset = map.offset;
*size = map.size;
*type = map.type;
*flags = map.flags;
*handle = (unsigned long)map.handle;
*mtrr = map.mtrr;
return 0;
}
int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
unsigned long *magic, unsigned long *iocs)
{
drm_client_t client;
client.idx = idx;
if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
*auth = client.auth;
*pid = client.pid;
*uid = client.uid;
*magic = client.magic;
*iocs = client.iocs;
return 0;
}
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:\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)
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 int drmOpenMinor(int minor, uid_t user, gid_t group,
mode_t dirmode, mode_t devmode, int force)
{
struct stat st;
char buf[64];
long dev = makedev(DRM_MAJOR, minor);
int setdir = 0;
int setdev = 0;
int fd;
if (stat(DRM_DIR_NAME, &st) || !S_ISDIR(st.st_mode)) {
remove(DRM_DIR_NAME);
mkdir(DRM_DIR_NAME, dirmode);
++setdir;
}
if (force || setdir) {
chown(DRM_DIR_NAME, user, group);
chmod(DRM_DIR_NAME, dirmode);
}
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
if (stat(buf, &st) || st.st_rdev != dev) {
remove(buf);
mknod(buf, S_IFCHR, dev);
++setdev;
}
if (force || setdev) {
chown(buf, user, group);
chmod(buf, devmode);
}
if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
if (setdev) remove(buf);
return -errno;
}
int main(int argc, char **argv)
{
int c;
int mask = 0;
int minor = 0;
int fd;
char buf[64];
int i;
while ((c = getopt(argc, argv, "vmcM:")) != EOF)
switch (c) {
case 'v': mask |= DRM_VERSION; break;
case 'm': mask |= DRM_MEMORY; break;
case 'c': mask |= DRM_CLIENTS; 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, 0, 0, 0700, 0600, 0);
if (fd >= 0) {
printf("%s\n", buf);
if (mask & DRM_VERSION) getversion(fd);
if (mask & DRM_MEMORY) getvm(fd);
if (mask & DRM_CLIENTS) getclients(fd);
close(fd);
}
}
return 0;
}