Edit

IABSD.fr/xenocara/lib/libXxf86dga/src/XF86DGA.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2007-09-29 20:10:34
    Hash : 8fcba43e
    Message : libXxf86dga 1.0.2

  • lib/libXxf86dga/src/XF86DGA.c
  • /* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.23tsi Exp $ */
    /*
    
    Copyright (c) 1995  Jon Tombs
    Copyright (c) 1995,1996  The XFree86 Project, Inc
    
    */
    
    /* THIS IS NOT AN X CONSORTIUM STANDARD */
    
    #ifdef __UNIXOS2__ /* needed here to override certain constants in X headers */
    #define INCL_DOS
    #define INCL_DOSIOCTL
    #define I_NEED_OS2_H
    #include <os2.h>
    #endif
    
    #if defined(linux)
    #define HAS_MMAP_ANON
    #include <sys/types.h>
    #include <sys/mman.h>
    /* kernel header doesn't work with -ansi */
    /* #include <asm/page.h> */   /* PAGE_SIZE */
    #define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */
    #define HAS_GETPAGESIZE
    #endif /* linux */
    
    #if defined(CSRG_BASED)
    #define HAS_MMAP_ANON
    #define HAS_GETPAGESIZE
    #include <sys/types.h>
    #include <sys/mman.h>
    #endif /* CSRG_BASED */
    
    #if defined(DGUX)
    #define HAS_GETPAGESIZE
    #define MMAP_DEV_ZERO
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <unistd.h>
    #endif /* DGUX */
    
    #if defined(SVR4) && !defined(DGUX)
    #define MMAP_DEV_ZERO
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <unistd.h>
    #endif /* SVR4 && !DGUX */
    
    #if defined(sun) && !defined(SVR4) /* SunOS */
    #define MMAP_DEV_ZERO   /* doesn't SunOS have MAP_ANON ?? */
    #define HAS_GETPAGESIZE
    #include <sys/types.h>
    #include <sys/mman.h>
    #endif /* sun && !SVR4 */
    
    #ifdef XNO_SYSCONF
    #undef _SC_PAGESIZE
    #endif
    
    
    #define NEED_EVENTS
    #define NEED_REPLIES
    #include <X11/Xlibint.h>
    #include <X11/extensions/xf86dga.h>
    #include <X11/extensions/xf86dgastr.h>
    #include <X11/extensions/Xext.h>
    #include <X11/extensions/extutil.h>
    
    extern XExtDisplayInfo* xdga_find_display(Display*);
    extern char *xdga_extension_name;
    
    #define XF86DGACheckExtension(dpy,i,val) \
      XextCheckExtension (dpy, i, xdga_extension_name, val)
    
    /*****************************************************************************
     *                                                                           *
     *		    public XFree86-DGA Extension routines                    *
     *                                                                           *
     *****************************************************************************/
    
    Bool XF86DGAQueryExtension (
        Display *dpy,
        int *event_basep,
        int *error_basep
    ){
        return XDGAQueryExtension(dpy, event_basep, error_basep);
    }
    
    Bool XF86DGAQueryVersion(
        Display* dpy,
        int* majorVersion, 
        int* minorVersion
    ){
        return XDGAQueryVersion(dpy, majorVersion, minorVersion);
    }
    
    Bool XF86DGAGetVideoLL(
        Display* dpy,
        int screen,
        unsigned int *offset,
        int *width, 
        int *bank_size, 
        int *ram_size
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAGetVideoLLReply rep;
        xXF86DGAGetVideoLLReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAGetVideoLL, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAGetVideoLL;
        req->screen = screen;
        if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    	UnlockDisplay(dpy);
    	SyncHandle();
    	return False;
        }
    
        *offset = rep.offset;
        *width = rep.width;
        *bank_size = rep.bank_size;
        *ram_size = rep.ram_size;
    	
        UnlockDisplay(dpy);
        SyncHandle();
        return True;
    }
    
        
    Bool XF86DGADirectVideoLL(
        Display* dpy,
        int screen,
        int enable
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGADirectVideoReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGADirectVideo, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGADirectVideo;
        req->screen = screen;
        req->enable = enable;
        UnlockDisplay(dpy);
        SyncHandle();
        XSync(dpy,False);
        return True;
    }
    
    Bool XF86DGAGetViewPortSize(
        Display* dpy,
        int screen,
        int *width, 
        int *height
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAGetViewPortSizeReply rep;
        xXF86DGAGetViewPortSizeReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAGetViewPortSize, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAGetViewPortSize;
        req->screen = screen;
        if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    	UnlockDisplay(dpy);
    	SyncHandle();
    	return False;
        }
    
        *width = rep.width;
        *height = rep.height;
    	
        UnlockDisplay(dpy);
        SyncHandle();
        return True;
    }
        
        
    Bool XF86DGASetViewPort(
        Display* dpy,
        int screen,
        int x, 
        int y
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGASetViewPortReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGASetViewPort, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGASetViewPort;
        req->screen = screen;
        req->x = x;
        req->y = y;
        UnlockDisplay(dpy);
        SyncHandle();
        XSync(dpy,False);
        return True;
    }
    
        
    Bool XF86DGAGetVidPage(
        Display* dpy,
        int screen,
        int *vpage
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAGetVidPageReply rep;
        xXF86DGAGetVidPageReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAGetVidPage, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAGetVidPage;
        req->screen = screen;
        if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    	UnlockDisplay(dpy);
    	SyncHandle();
    	return False;
        }
    
        *vpage = rep.vpage;
        UnlockDisplay(dpy);
        SyncHandle();
        return True;
    }
    
        
    Bool XF86DGASetVidPage(
        Display* dpy,
        int screen,
        int vpage
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGASetVidPageReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGASetVidPage, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGASetVidPage;
        req->screen = screen;
        req->vpage = vpage;
        UnlockDisplay(dpy);
        SyncHandle();
        XSync(dpy,False);
        return True;
    }
    
    Bool XF86DGAInstallColormap(
        Display* dpy,
        int screen,
        Colormap cmap
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAInstallColormapReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAInstallColormap, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAInstallColormap;
        req->screen = screen;
        req->id = cmap;
        UnlockDisplay(dpy);
        SyncHandle();
        XSync(dpy,False);
        return True;
    }
    
    Bool XF86DGAQueryDirectVideo(
        Display *dpy,
        int screen,
        int *flags
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAQueryDirectVideoReply rep;
        xXF86DGAQueryDirectVideoReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAQueryDirectVideo, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAQueryDirectVideo;
        req->screen = screen;
        if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    	UnlockDisplay(dpy);
    	SyncHandle();
    	return False;
        }
        *flags = rep.flags;
        UnlockDisplay(dpy);
        SyncHandle();
        return True;
    }
    
    Bool XF86DGAViewPortChanged(
        Display *dpy,
        int screen,
        int n
    ){
        XExtDisplayInfo *info = xdga_find_display (dpy);
        xXF86DGAViewPortChangedReply rep;
        xXF86DGAViewPortChangedReq *req;
    
        XF86DGACheckExtension (dpy, info, False);
    
        LockDisplay(dpy);
        GetReq(XF86DGAViewPortChanged, req);
        req->reqType = info->codes->major_opcode;
        req->dgaReqType = X_XF86DGAViewPortChanged;
        req->screen = screen;
        req->n = n;
        if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    	UnlockDisplay(dpy);
    	SyncHandle();
    	return False;
        }
        UnlockDisplay(dpy);
        SyncHandle();
        return rep.result;
    }
    
    
    
    /* Helper functions */
    
    #include <X11/Xmd.h>
    #include <X11/extensions/xf86dga.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    #if defined(ISC) 
    # define HAS_SVR3_MMAP
    # include <sys/types.h>
    # include <errno.h>
    
    # include <sys/at_ansi.h>
    # include <sys/kd.h>
    
    # include <sys/sysmacros.h>
    # include <sys/immu.h>
    # include <sys/region.h>
    
    # include <sys/mmap.h>
    #else
    # if defined(Lynx) && defined(NO_MMAP)
    #  include <sys/types.h>
    #  include <errno.h>
    #  include <smem.h>
    # else
    #  if !defined(__UNIXOS2__)
    #   include <sys/mman.h>
    #  endif
    # endif
    #endif
    #include <sys/wait.h>
    #include <signal.h>
    #include <unistd.h>
    
    #if defined(SVR4) && !defined(sun)
    #define DEV_MEM "/dev/pmem"
    #elif defined(SVR4) && defined(sun)
    #define DEV_MEM "/dev/xsvc"
    #elif defined(HAS_APERTURE_DRV)
    #define DEV_MEM "/dev/xf86"
    #else
    #define DEV_MEM "/dev/mem"
    #endif
    
    typedef struct {
        unsigned long physaddr;	/* actual requested physical address */
        unsigned long size;		/* actual requested map size */
        unsigned long delta;	/* delta to account for page alignment */
        void *	  vaddr;	/* mapped address, without the delta */
        int		  refcount;	/* reference count */
    } MapRec, *MapPtr;
    
    typedef struct {
        Display *	display;
        int		screen;
        MapPtr	map;
    } ScrRec, *ScrPtr;
    
    static int mapFd = -1;
    static int numMaps = 0;
    static int numScrs = 0;
    static MapPtr *mapList = NULL;
    static ScrPtr *scrList = NULL;
    
    static MapPtr
    AddMap(void)
    {
        MapPtr *old;
    
        old = mapList;
        mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1));
        if (!mapList) {
    	mapList = old;
    	return NULL;
        }
        mapList[numMaps] = malloc(sizeof(MapRec));
        if (!mapList[numMaps])
    	return NULL;
        return mapList[numMaps++];
    }
    
    static ScrPtr
    AddScr(void)
    {
        ScrPtr *old;
    
        old = scrList;
        scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1));
        if (!scrList) {
    	scrList = old;
    	return NULL;
        }
        scrList[numScrs] = malloc(sizeof(ScrRec));
        if (!scrList[numScrs])
    	return NULL;
        return scrList[numScrs++];
    }
    
    static MapPtr
    FindMap(unsigned long address, unsigned long size)
    {
        int i;
    
        for (i = 0; i < numMaps; i++) {
    	if (mapList[i]->physaddr == address &&
    	    mapList[i]->size == size)
    	    return mapList[i];
        }
        return NULL;
    }
    
    static ScrPtr
    FindScr(Display *display, int screen)
    {
        int i;
    
        for (i = 0; i < numScrs; i++) {
    	if (scrList[i]->display == display &&
    	    scrList[i]->screen == screen)
    	    return scrList[i];
        }
        return NULL;
    }
    
    static void *
    MapPhysAddress(unsigned long address, unsigned long size)
    {
        unsigned long offset, delta;
        int pagesize = -1;
        void *vaddr;
        MapPtr mp;
    #if defined(ISC) && defined(HAS_SVR3_MMAP)
        struct kd_memloc mloc;
    #elif defined(__UNIXOS2__)
        APIRET rc;
        ULONG action;
        HFILE hfd;
    #endif
    
        if ((mp = FindMap(address, size))) {
    	mp->refcount++;
    	return (void *)((unsigned long)mp->vaddr + mp->delta);
        }
    
    #if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE)
        pagesize = sysconf(_SC_PAGESIZE);
    #endif
    #ifdef _SC_PAGE_SIZE
        if (pagesize == -1)
    	pagesize = sysconf(_SC_PAGE_SIZE);
    #endif
    #ifdef HAS_GETPAGESIZE
        if (pagesize == -1)
    	pagesize = getpagesize();
    #endif
    #ifdef PAGE_SIZE
        if (pagesize == -1)
    	pagesize = PAGE_SIZE;
    #endif
        if (pagesize == -1)
    	pagesize = 4096;
    
       delta = address % pagesize;
       offset = address - delta;
    
    #if defined(ISC) && defined(HAS_SVR3_MMAP)
        if (mapFd < 0) {
    	if ((mapFd = open("/dev/mmap", O_RDWR)) < 0)
    	    return NULL;
        }
        mloc.vaddr = (char *)0;
        mloc.physaddr = (char *)offset;
        mloc.length = size + delta;
        mloc.ioflg=1;
    
        if ((vaddr = (void *)ioctl(mapFd, MAP, &mloc)) == (void *)-1)
    	return NULL;
    #elif defined (__UNIXOS2__)
        /*
         * Dragon warning here! /dev/pmap$ is never closed, except on progam exit.
         * Consecutive calling of this routine will make PMAP$ driver run out
         * of memory handles. Some umap/close mechanism should be provided
         */
    
        rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN,
    		 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL);
        if (rc != 0)
    	return NULL;
        {
    	struct map_ioctl {
    		union {
    			ULONG phys;
    			void* user;
    		} a;
    		ULONG size;
    	} pmap,dmap;
    	ULONG plen,dlen;
    #define XFREE86_PMAP	0x76
    #define PMAP_MAP	0x44
    
    	pmap.a.phys = offset;
    	pmap.size = size + delta;
    	rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP,
    			 (PULONG)&pmap, sizeof(pmap), &plen,
    			 (PULONG)&dmap, sizeof(dmap), &dlen);
    	if (rc == 0) {
    		vaddr = dmap.a.user;
    	}
       }
       if (rc != 0)
    	return NULL;
    #elif defined(Lynx) && defined(NO_MMAP)
        vaddr = (void *)smem_create("XF86DGA", (char *)offset, 
    				size + delta, SM_READ|SM_WRITE);
    #else
    #ifndef MAP_FILE
    #define MAP_FILE 0
    #endif
        if (mapFd < 0) {
    	if ((mapFd = open(DEV_MEM, O_RDWR)) < 0)
    	    return NULL;
        }
        vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE,
                            MAP_FILE | MAP_SHARED, mapFd, (off_t)offset);
        if (vaddr == (void *)-1)
    	return NULL;
    #endif
    
        if (!vaddr) {
    	if (!(mp = AddMap()))
    	    return NULL;
    	mp->physaddr = address;
    	mp->size = size;
    	mp->delta = delta;
    	mp->vaddr = vaddr;
    	mp->refcount = 1;
        }
        return (void *)((unsigned long)vaddr + delta);
    }
    
    /*
     * Still need to find a clean way of detecting the death of a DGA app
     * and returning things to normal - Jon
     * This is here to help debugging without rebooting... Also C-A-BS
     * should restore text mode.
     */
    
    int
    XF86DGAForkApp(int screen)
    {
        pid_t pid;
        int status;
        int i;
    
         /* fork the app, parent hangs around to clean up */
        if ((pid = fork()) > 0) {
    	ScrPtr sp;
    
    	waitpid(pid, &status, 0);
    	for (i = 0; i < numScrs; i++) {
    	    sp = scrList[i];
    	    XF86DGADirectVideoLL(sp->display, sp->screen, 0);
    	    XSync(sp->display, False);
    	}
            if (WIFEXITED(status))
    	    _exit(0);
    	else
    	    _exit(-1);
        }
        return pid;
    }
    
    
    Bool
    XF86DGADirectVideo(
        Display *dis,
        int screen,
        int enable
    ){
        ScrPtr sp;
        MapPtr mp = NULL;
    
        if ((sp = FindScr(dis, screen)))
    	mp = sp->map;
    
        if (enable & XF86DGADirectGraphics) {
    #if !defined(ISC) && !defined(HAS_SVR3_MMAP) \
    	&& !(defined(Lynx) && defined(NO_MMAP)) \
    	&& !defined(__UNIXOS2__)
    	if (mp && mp->vaddr)
    	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE);
    #endif
        } else {
    #if !defined(ISC) && !defined(HAS_SVR3_MMAP) \
    	&& !(defined(Lynx) && defined(NO_MMAP)) \
    	&& !defined(__UNIXOS2__)
    	if (mp && mp->vaddr)
    	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ);
    #elif defined(Lynx) && defined(NO_MMAP)
    	/* XXX this doesn't allow enable after disable */
    	smem_create(NULL, mp->vaddr, mp->size + mp->delta, SM_DETACH);
    	smem_remove("XF86DGA");
    #endif
        }
    
        XF86DGADirectVideoLL(dis, screen, enable);
        return 1;
    }
    
    
    static void
    XF86cleanup(int sig)
    {
        ScrPtr sp;
        int i;
        static char beenhere = 0;
    
        if (beenhere)
    	_exit(3);
        beenhere = 1;
    
        for (i = 0; i < numScrs; i++) {
    	sp = scrList[i];
    	XF86DGADirectVideo(sp->display, sp->screen, 0);
    	XSync(sp->display, False);
        }
        _exit(3);
    }
    
    Bool
    XF86DGAGetVideo(
        Display *dis,
        int screen,
        char **addr,
        int *width, 
        int *bank, 
        int *ram
    ){
        unsigned int offset;
        static int beenHere = 0;
        ScrPtr sp;
        MapPtr mp;
    
        if (!(sp = FindScr(dis, screen))) {
    	if (!(sp = AddScr())) {
    	    fprintf(stderr, "XF86DGAGetVideo: malloc failure\n");
    	    exit(-2);
    	}
    	sp->display = dis;
    	sp->screen = screen;
    	sp->map = NULL;
        }
    
        XF86DGAGetVideoLL(dis, screen , &offset, width, bank, ram);
    
        *addr = MapPhysAddress(offset, *bank);
        if (*addr == NULL) {
    	fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n",
    		strerror(errno));
    	exit(-2);
        }
    
        if ((mp = FindMap(offset, *bank)))
    	sp->map = mp;
    
        if (!beenHere) {
    	beenHere = 1;
    	atexit((void(*)(void))XF86cleanup);
    	/* one shot XF86cleanup attempts */
    	signal(SIGSEGV, XF86cleanup);
    #ifdef SIGBUS
    	signal(SIGBUS, XF86cleanup);
    #endif
    	signal(SIGHUP, XF86cleanup);
    	signal(SIGFPE, XF86cleanup);  
        }
    
        return 1;
    }