2 * Created: Mon Jan 15 05:05:07 2001 by faith@acm.org
4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
33 #include "../../../xf86drm.h"
34 #include "../xf86drmRandom.c"
35 #include "../xf86drmHash.c"
36 #include "../xf86drm.c"
38 #define DRM_DIR_NAME "/dev/dri"
39 #define DRM_DEV_NAME "%s/card%d"
41 #define DRM_VERSION 0x00000001
42 #define DRM_MEMORY 0x00000002
43 #define DRM_CLIENTS 0x00000004
44 #define DRM_STATS 0x00000008
46 typedef struct drmStatsS {
50 const char *long_format;
51 const char *long_name;
52 const char *rate_format;
53 const char *rate_name;
55 const char *mult_names;
61 static void getversion(int fd)
63 drmVersionPtr version;
65 version = drmGetVersion(fd);
67 printf(" Version information:\n");
68 printf(" Name: %s\n", version->name ? version->name : "?");
69 printf(" Version: %d.%d.%d\n",
70 version->version_major,
71 version->version_minor,
72 version->version_patchlevel);
73 printf(" Date: %s\n", version->date ? version->date : "?");
74 printf(" Desc: %s\n", version->desc ? version->desc : "?");
75 drmFreeVersion(version);
77 printf(" No version information available\n");
82 unsigned long offset; /* Requested physical address (0 for SAREA)*/
83 unsigned long size; /* Requested physical size (bytes) */
84 drm_map_type_t type; /* Type of memory to map */
85 drm_map_flags_t flags; /* Flags */
86 void *handle; /* User-space: "Handle" to pass to mmap */
87 /* Kernel-space: kernel-virtual address */
88 int mtrr; /* MTRR slot used */
90 } drmVmRec, *drmVmPtr;
92 int drmGetMap(int fd, int idx, drmHandle *offset, drmSize *size,
93 drmMapType *type, drmMapFlags *flags, drmHandle *handle,
99 if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
100 *offset = map.offset;
104 *handle = (unsigned long)map.handle;
109 int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
110 unsigned long *magic, unsigned long *iocs)
115 if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
119 *magic = client.magic;
124 int drmGetStats(int fd, drmStatsT *stats)
129 if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
132 memset(stats, 0, sizeof(*stats));
133 if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
137 stats->data[i].long_format = "%-20.20s"; \
138 stats->data[i].rate_format = "%8.8s"; \
139 stats->data[i].isvalue = 1; \
140 stats->data[i].verbose = 0
143 stats->data[i].long_format = "%-20.20s"; \
144 stats->data[i].rate_format = "%5.5s"; \
145 stats->data[i].isvalue = 0; \
146 stats->data[i].mult_names = "kgm"; \
147 stats->data[i].mult = 1000; \
148 stats->data[i].verbose = 0
151 stats->data[i].long_format = "%-9.9s"; \
152 stats->data[i].rate_format = "%5.5s"; \
153 stats->data[i].isvalue = 0; \
154 stats->data[i].mult_names = "KGM"; \
155 stats->data[i].mult = 1024; \
156 stats->data[i].verbose = 0
159 stats->count = s.count;
160 for (i = 0; i < s.count; i++) {
161 stats->data[i].value = s.data[i].value;
162 switch (s.data[i].type) {
164 stats->data[i].long_name = "Lock";
165 stats->data[i].rate_name = "Lock";
168 case _DRM_STAT_OPENS:
169 stats->data[i].long_name = "Opens";
170 stats->data[i].rate_name = "O";
172 stats->data[i].verbose = 1;
174 case _DRM_STAT_CLOSES:
175 stats->data[i].long_name = "Closes";
176 stats->data[i].rate_name = "Lock";
178 stats->data[i].verbose = 1;
180 case _DRM_STAT_IOCTLS:
181 stats->data[i].long_name = "Ioctls";
182 stats->data[i].rate_name = "Ioc/s";
185 case _DRM_STAT_LOCKS:
186 stats->data[i].long_name = "Locks";
187 stats->data[i].rate_name = "Lck/s";
190 case _DRM_STAT_UNLOCKS:
191 stats->data[i].long_name = "Unlocks";
192 stats->data[i].rate_name = "Unl/s";
196 stats->data[i].long_name = "IRQs";
197 stats->data[i].rate_name = "IRQ/s";
200 case _DRM_STAT_PRIMARY:
201 stats->data[i].long_name = "Primary Bytes";
202 stats->data[i].rate_name = "PB/s";
205 case _DRM_STAT_SECONDARY:
206 stats->data[i].long_name = "Secondary Bytes";
207 stats->data[i].rate_name = "SB/s";
211 stats->data[i].long_name = "DMA";
212 stats->data[i].rate_name = "DMA/s";
215 case _DRM_STAT_SPECIAL:
216 stats->data[i].long_name = "Special DMA";
217 stats->data[i].rate_name = "dma/s";
220 case _DRM_STAT_MISSED:
221 stats->data[i].long_name = "Miss";
222 stats->data[i].rate_name = "Ms/s";
225 case _DRM_STAT_VALUE:
226 stats->data[i].long_name = "Value";
227 stats->data[i].rate_name = "Value";
231 stats->data[i].long_name = "Bytes";
232 stats->data[i].rate_name = "B/s";
235 case _DRM_STAT_COUNT:
237 stats->data[i].long_name = "Count";
238 stats->data[i].rate_name = "Cnt/s";
246 static void getvm(int fd)
249 const char *typename;
258 printf(" VM map information:\n");
259 printf(" slot offset size type flags address mtrr\n");
262 !drmGetMap(fd, i, &offset, &size, &type, &flags, &handle, &mtrr);
266 case DRM_FRAME_BUFFER: typename = "FB"; break;
267 case DRM_REGISTERS: typename = "REG"; break;
268 case DRM_SHM: typename = "SHM"; break;
269 case DRM_AGP: typename = "AGP"; break;
270 default: typename = "???"; break;
273 flagname[0] = (flags & DRM_RESTRICTED) ? 'R' : ' ';
274 flagname[1] = (flags & DRM_READ_ONLY) ? 'r' : 'w';
275 flagname[2] = (flags & DRM_LOCKED) ? 'l' : ' ';
276 flagname[3] = (flags & DRM_KERNEL) ? 'k' : ' ';
277 flagname[4] = (flags & DRM_WRITE_COMBINING) ? 'W' : ' ';
278 flagname[5] = (flags & DRM_CONTAINS_LOCK) ? 'L' : ' ';
281 printf(" %4d 0x%08lx 0x%08lx %3.3s %6.6s 0x%08lx ",
282 i, offset, (unsigned long)size, typename, flagname, handle);
283 if (mtrr < 0) printf("none\n");
284 else printf("%4d\n", mtrr);
288 static void getclients(int fd)
300 printf(" DRI client information:\n");
301 printf(" a pid uid magic ioctls prog\n");
303 for (i = 0; !drmGetClient(fd, i, &auth, &pid, &uid, &magic, &iocs); i++) {
304 sprintf(buf, "/proc/%d/cmdline", pid);
305 memset(cmd, sizeof(cmd), 0);
306 if ((procfd = open(buf, O_RDONLY, 0)) >= 0) {
307 read(procfd, cmd, sizeof(cmd)-1);
311 printf(" %c %5d %5d %10lu %10lu %s\n",
312 auth ? 'y' : 'n', pid, uid, magic, iocs, cmd);
314 printf(" %c %5d %5d %10lu %10lu\n",
315 auth ? 'y' : 'n', pid, uid, magic, iocs);
319 static void printhuman(unsigned long value, const char *name, int mult)
323 /* Print width 5 number in width 6 space */
324 if (value < 100000) {
325 printf(" %5lu", value);
330 f = (double)value / (double)mult;
332 printf(" %4.2f%c", f, *p);
337 f = (double)value / (double)mult;
339 printf(" %4.2f%c", f, *p);
344 f = (double)value / (double)mult;
346 printf(" %4.2f%c", f, *p);
351 static void getstats(int fd, int i)
353 drmStatsT prev, curr;
357 printf(" System statistics:\n");
359 if (drmGetStats(fd, &prev)) return;
361 for (j = 0; j < prev.count; j++) {
363 printf(prev.data[j].long_format, prev.data[j].long_name);
364 if (prev.data[j].isvalue) printf(" 0x%08lx\n", prev.data[j].value);
365 else printf(" %10lu\n", prev.data[j].value);
371 for (j = 0; j < prev.count; j++)
372 if (!prev.data[j].verbose) {
374 printf(prev.data[j].rate_format, prev.data[j].rate_name);
380 if (drmGetStats(fd, &curr)) return;
382 for (j = 0; j < curr.count; j++) {
383 if (curr.data[j].verbose) continue;
384 if (curr.data[j].isvalue) {
385 printf(" %08lx", curr.data[j].value);
387 rate = (curr.data[j].value - prev.data[j].value) / (double)i;
388 printhuman(rate, curr.data[j].mult_names, curr.data[j].mult);
392 memcpy(&prev, &curr, sizeof(prev));
397 static int drmOpenMinor(int minor, uid_t user, gid_t group,
398 mode_t dirmode, mode_t devmode, int force)
402 long dev = makedev(DRM_MAJOR, minor);
407 if (stat(DRM_DIR_NAME, &st) || !S_ISDIR(st.st_mode)) {
408 remove(DRM_DIR_NAME);
409 mkdir(DRM_DIR_NAME, dirmode);
413 if (force || setdir) {
414 chown(DRM_DIR_NAME, user, group);
415 chmod(DRM_DIR_NAME, dirmode);
418 sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
419 if (stat(buf, &st) || st.st_rdev != dev) {
421 mknod(buf, S_IFCHR, dev);
425 if (force || setdev) {
426 chown(buf, user, group);
430 if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
431 if (setdev) remove(buf);
435 int main(int argc, char **argv)
445 while ((c = getopt(argc, argv, "avmcsM:i:")) != EOF)
447 case 'a': mask = ~0; break;
448 case 'v': mask |= DRM_VERSION; break;
449 case 'm': mask |= DRM_MEMORY; break;
450 case 'c': mask |= DRM_CLIENTS; break;
451 case 's': mask |= DRM_STATS; break;
452 case 'i': interval = strtol(optarg, NULL, 0); break;
453 case 'M': minor = strtol(optarg, NULL, 0); break;
455 fprintf( stderr, "Usage: dristat [options]\n" );
459 for (i = 0; i < 16; i++) if (!minor || i == minor) {
460 sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i);
461 fd = drmOpenMinor(i, 0, 0, 0700, 0600, 0);
464 if (mask & DRM_VERSION) getversion(fd);
465 if (mask & DRM_MEMORY) getvm(fd);
466 if (mask & DRM_CLIENTS) getclients(fd);
467 if (mask & DRM_STATS) getstats(fd, interval);