summaryrefslogtreecommitdiff
path: root/linux-core/i810_drv.c
AgeCommit message (Expand)Author
2006-10-14remove config.h from build no longer exists kbuild does itDave Airlie
2006-01-26add missing name, desc, date, major, minor and patchlevel entriesAlan Hourihane
2005-11-11i810 should be fine with i810.. no idea what this crack is ..Dave Airlie
2005-11-11cleanup ioctl/max_ioctl to use header file for extern symbolsDave Airlie
2005-08-05Rename the driver hooks in the DRM to something a little moreEric Anholt
2005-07-03Add sysfs attribute dri_library_name on Linux. code in share-core/via_drv.cJon Smirl
2005-06-29these don't need reclaim buffers their release functions handle itDave Airlie
2005-06-16Force AGP always for Intel chipsets.Alan Hourihane
2005-02-01make more functions static in i810 and fix pageflip cleanupDave Airlie
2005-01-01i810/i830 bug with Jon's file operations changesDave Airlie
2004-10-13Add a poll function that alternates between zero and normal poll return toJon Smirl
2004-10-12Breakout heads into their own data structures.Jon Smirl
2004-10-10Rename fn_tbl to driver. Core driver now uses pci_driver name whichJon Smirl
2004-09-30Lindent of core build. Drivers checked for no binary diffs. A few filesJon Smirl
2004-09-30Make fops per driver instead of global, remove default flush, poll, readJon Smirl
2004-09-27First check in for DRM that splits core from personality modulesJon Smirl
2004-09-231) switches from class_sysfs to drm sysfs implementation to allowJon Smirl
2004-08-24Merged drmfntbl-0-0-2Dave Airlie
2003-06-19Revert the janitorial - that works is now on the new branchJose Fonseca
2003-06-03Split declarations/definitions in drm_scatter.h into drm_sg.h/drm_sg_tmp.hJose Fonseca
2003-04-22Rename drm_lists.h to gamma_lists.hKeith Whitwell
2002-07-05merged bsd-3-0-0-branchAlan Hourihane
2002-04-09Merged drmcommand-0-0-1Jens Owen
2002-02-14First pass of mesa-4-0 branch merge into trunk.David Dawes
2002-01-27First pass merge of XFree86 4.2.0 import.David Dawes
2001-11-27Put back i810 major version number (same reasons as for r128)Keith Whitwell
2001-09-17bumped the DRM versions (already done in ddx and client side drivers).Alan Hourihane
2001-08-07Lots of DRM fixes: added new pieces of template code so the ffb driver canJeff Hartmann
2001-07-23Fixes that allow the modules to be built into the kernelJeff Hartmann
2001-07-18Add module version name at a lower layer of the code, allows things to beJeff Hartmann
2001-07-17Someone forgot to bump the r128 and i810 drivers properly before the 4.1.0Jeff Hartmann
2001-07-16Added version string to the end of the kernel module name. This allowsJeff Hartmann
2001-06-18Forgot to bump date stamp.Gareth Hughes
2001-02-16- Clean up the way customization of the templates is done.Gareth Hughes
2001-02-15Added missing include "drm_lists.h".Keith Whitwell
2001-02-15Merge mga-1-0-0-branch into trunk.Gareth Hughes
2000-11-15Sync with Linux 2.4.0-test11-pre5 Provide backward compatibility testedRik Faith
2000-09-29Audit calls to schedule() Remove tags from files shared with Linux kernelRik Faith
2000-09-27Merged the mga-lock-debug-0-2-0-branch with the trunk. This includesJeff Hartmann
2000-09-24commit xfree86 4.0.1d-pre updateAlan Hourihane
2000-09-10Sync with 2.4.0-test8 kernel.Gareth Hughes
2000-09-06Sync with 2.4.0-test8-pre5 kernel.Gareth Hughes
2000-08-28Add compatibility header file to make Linux 2.4.0 kernel patches cleaner.Rik Faith
2000-08-26Sync with Linux 2.4.0-test7 Add signal blocking support to all driversRik Faith
2000-08-08Sync with Linux 2.4.0-test6-pre8Rik Faith
2000-08-04Sync with Linux 2.4.0-test6-pre2Rik Faith
2000-07-20More fixups for kernel build: EXPORT_SYMTAB warning removalRik Faith
2000-07-20Fix signature for *_options functionRik Faith
2000-07-20Added support for building as modules or as part of monolithic kernelRik Faith
2000-07-19Bump driver dates and add descriptionsRik Faith
a id='n429' href='#n429'>429 430
/**************************************************************************
 * 
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
 * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS 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.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 * 
 * 
 **************************************************************************/
/*
 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdint.h>
#include <drm/drm.h>
#include "xf86dri.h"
#include "xf86drm.h"
#include "stdio.h"
#include "sys/types.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "sys/mman.h"

typedef struct
{
    enum
    {
	haveNothing,
	haveDisplay,
	haveConnection,
	haveDriverName,
	haveDeviceInfo,
	haveDRM,
	haveContext
    }
    state;

    Display *display;
    int screen;
    drm_handle_t sAreaOffset;
    char *curBusID;
    char *driverName;
    int drmFD;
    XVisualInfo visualInfo;
    XID id;
    drm_context_t hwContext;
    void *driPriv;
    int driPrivSize;
    int fbSize;
    int fbOrigin;
    int fbStride;
    drm_handle_t fbHandle;
    int ddxDriverMajor;
    int ddxDriverMinor;
    int ddxDriverPatch;
} TinyDRIContext;

#ifndef __x86_64__
static unsigned
fastrdtsc(void)
{
    unsigned eax;
    __asm__ volatile ("\t"
	"pushl  %%ebx\n\t"
	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
	:"0"(0)
	:"ecx", "edx", "cc");

    return eax;
}
#else
static unsigned
fastrdtsc(void)
{
    unsigned eax;
    __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax)
	:"0"(0)
	:"ecx", "edx", "ebx", "cc");

    return eax;
}
#endif

void
bmError(int val, const char *file, const char *function, int line)
{
    fprintf(stderr, "Fatal video memory manager error \"%s\".\n"
	"Check kernel logs or set the LIBGL_DEBUG\n"
	"environment variable to \"verbose\" for more info.\n"
	"Detected in file %s, line %d, function %s.\n",
	strerror(-val), file, line, function);
    abort();
}

#define BM_CKFATAL(val)					       \
  do{							       \
    int tstVal = (val);					       \
    if (tstVal) 					       \
      bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \
  } while(0);

static unsigned
time_diff(unsigned t, unsigned t2)
{
    return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
}

static int
releaseContext(TinyDRIContext * ctx)
{
    switch (ctx->state) {
    case haveContext:
	uniDRIDestroyContext(ctx->display, ctx->screen, ctx->id);
    case haveDRM:
	drmClose(ctx->drmFD);
    case haveDeviceInfo:
	XFree(ctx->driPriv);
    case haveDriverName:
	XFree(ctx->driverName);
    case haveConnection:
	XFree(ctx->curBusID);
	uniDRICloseConnection(ctx->display, ctx->screen);
    case haveDisplay:
	XCloseDisplay(ctx->display);
    default:
	break;
    }
    return -1;
}

static void
readBuf(void *buf, unsigned long size)
{
    volatile unsigned *buf32 = (unsigned *)buf;
    unsigned *end = (unsigned *)buf32 + size / sizeof(*buf32);

    while (buf32 < end) {
	(void)*buf32++;
    }
}

static int
benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
    unsigned long *ticks)
{
    unsigned long curTime, oldTime;
    int ret;
    drmBO buf;
    void *virtual;

    /*
     * Test system memory objects.
     */
    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOCreate(ctx->drmFD, size, 0, NULL,
			   DRM_BO_FLAG_READ |
			   DRM_BO_FLAG_WRITE |
			   DRM_BO_FLAG_MEM_LOCAL, 0, &buf));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    /*
     * Test TT bound buffer objects.
     */

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
			     DRM_BO_FLAG_MEM_TT, 
			     DRM_BO_MASK_MEM, 
			      0,0,0));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
			     DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 0, 0,0));
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    /*
     * Test cached buffers objects.
     */

    oldTime = fastrdtsc();
    ret = drmBOSetStatus(ctx->drmFD, &buf,
			 DRM_BO_FLAG_MEM_TT | 
			 DRM_BO_FLAG_CACHED | 
			 DRM_BO_FLAG_FORCE_CACHING,
			 DRM_BO_MASK_MEMTYPE | 
			 DRM_BO_FLAG_FORCE_CACHING,
			 0, 0, 0);
    curTime = fastrdtsc();

    if (ret) {
	printf("Couldn't bind cached. Probably no support\n");
	BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
	return 1;
    }
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    BM_CKFATAL(drmBOMap(ctx->drmFD, &buf,
	    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual));

    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0xF0, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    memset(virtual, 0x0F, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    oldTime = fastrdtsc();
    readBuf(virtual, buf.size);
    curTime = fastrdtsc();
    *ticks++ = time_diff(oldTime, curTime);

    BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
    BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));

    return 0;
}

static void
testAGP(TinyDRIContext * ctx)
{
    unsigned long ticks[128], *pTicks;
    unsigned long size = 8 * 1024;
    int ret;

    ret = benchmarkBuffer(ctx, size, ticks);
    if (ret < 0) {
	fprintf(stderr, "Buffer error %s\n", strerror(-ret));
	return;
    }
    pTicks = ticks;

    printf("Buffer size %d bytes\n", size);
    printf("System memory timings ********************************\n");
    printf("Creation took            %12lu ticks\n", *pTicks++);
    printf("Mapping took             %12lu ticks\n", *pTicks++);
    printf("Writing took             %12lu ticks\n", *pTicks++);
    printf("Writing Again took       %12lu ticks\n", *pTicks++);
    printf("Reading took             %12lu ticks\n", *pTicks++);
    printf("Unmapping took           %12lu ticks\n", *pTicks++);

    printf("\nTT Memory timings ************************************\n");
    printf("Moving to TT took        %12lu ticks\n", *pTicks++);
    printf("Mapping in TT took       %12lu ticks\n", *pTicks++);
    printf("Writing to TT took       %12lu ticks\n", *pTicks++);
    printf("Writing again to TT took %12lu ticks\n", *pTicks++);
    printf("Reading from TT took     %12lu ticks\n", *pTicks++);
    printf("Moving to system took    %12lu ticks\n", *pTicks++);

    if (ret == 1)
	return;

    printf("\nCached TT Memory timings *****************************\n");
    printf("Moving to CTT took       %12lu ticks\n", *pTicks++);
    printf("Mapping in CTT took      %12lu ticks\n", *pTicks++);
    printf("Writing to CTT took      %12lu ticks\n", *pTicks++);
    printf("Re-writing to CTT took   %12lu ticks\n", *pTicks++);
    printf("Reading from CTT took    %12lu ticks\n", *pTicks++);
    printf("\n\n");
}

int
main()
{
    int ret, screen, isCapable;
    char *displayName = ":0";
    TinyDRIContext ctx;
    unsigned magic;

    ctx.screen = 0;
    ctx.state = haveNothing;
    ctx.display = XOpenDisplay(displayName);
    if (!ctx.display) {
	fprintf(stderr, "Could not open display\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDisplay;

    ret =
	uniDRIQueryDirectRenderingCapable(ctx.display, ctx.screen,
	&isCapable);
    if (!ret || !isCapable) {
	fprintf(stderr, "No DRI on this display:sceen\n");
	return releaseContext(&ctx);
    }

    if (!uniDRIOpenConnection(ctx.display, ctx.screen, &ctx.sAreaOffset,
	    &ctx.curBusID)) {
	fprintf(stderr, "Could not open DRI connection.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveConnection;

    if (!uniDRIGetClientDriverName(ctx.display, ctx.screen,
	    &ctx.ddxDriverMajor, &ctx.ddxDriverMinor,
	    &ctx.ddxDriverPatch, &ctx.driverName)) {
	fprintf(stderr, "Could not get DRI driver name.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDriverName;

    if (!uniDRIGetDeviceInfo(ctx.display, ctx.screen,
	    &ctx.fbHandle, &ctx.fbOrigin, &ctx.fbSize,
	    &ctx.fbStride, &ctx.driPrivSize, &ctx.driPriv)) {
	fprintf(stderr, "Could not get DRI device info.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveDriverName;

    if ((ctx.drmFD = drmOpen(NULL, ctx.curBusID)) < 0) {
	perror("DRM Device could not be opened");
	return releaseContext(&ctx);
    }
    ctx.state = haveDRM;

    drmGetMagic(ctx.drmFD, &magic);
    if (!uniDRIAuthConnection(ctx.display, ctx.screen, magic)) {
	fprintf(stderr, "Could not get X server to authenticate us.\n");
	return releaseContext(&ctx);
    }

    ret = XMatchVisualInfo(ctx.display, ctx.screen, 24, TrueColor,
	&ctx.visualInfo);
    if (!ret) {
	ret = XMatchVisualInfo(ctx.display, ctx.screen, 16, TrueColor,
	    &ctx.visualInfo);
	if (!ret) {
	    fprintf(stderr, "Could not find a matching visual.\n");
	    return releaseContext(&ctx);
	}
    }

    if (!uniDRICreateContext(ctx.display, ctx.screen, ctx.visualInfo.visual,
	    &ctx.id, &ctx.hwContext)) {
	fprintf(stderr, "Could not create DRI context.\n");
	return releaseContext(&ctx);
    }
    ctx.state = haveContext;

    testAGP(&ctx);

    releaseContext(&ctx);
    printf("Terminating normally\n");
    return 0;
}