18dd3e0eeSmrg/* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.23tsi Exp $ */
28dd3e0eeSmrg/*
38dd3e0eeSmrg
48dd3e0eeSmrgCopyright (c) 1995  Jon Tombs
58dd3e0eeSmrgCopyright (c) 1995,1996  The XFree86 Project, Inc
68dd3e0eeSmrg
78dd3e0eeSmrg*/
88dd3e0eeSmrg
98dd3e0eeSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD */
108dd3e0eeSmrg
118dd3e0eeSmrg
128dd3e0eeSmrg#if defined(linux)
138dd3e0eeSmrg#define HAS_MMAP_ANON
148dd3e0eeSmrg#include <sys/types.h>
158dd3e0eeSmrg#include <sys/mman.h>
168dd3e0eeSmrg/* kernel header doesn't work with -ansi */
178dd3e0eeSmrg/* #include <asm/page.h> */   /* PAGE_SIZE */
188dd3e0eeSmrg#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */
198dd3e0eeSmrg#define HAS_GETPAGESIZE
208dd3e0eeSmrg#endif /* linux */
218dd3e0eeSmrg
228dd3e0eeSmrg#if defined(CSRG_BASED)
238dd3e0eeSmrg#define HAS_MMAP_ANON
248dd3e0eeSmrg#define HAS_GETPAGESIZE
258dd3e0eeSmrg#include <sys/types.h>
268dd3e0eeSmrg#include <sys/mman.h>
278dd3e0eeSmrg#endif /* CSRG_BASED */
288dd3e0eeSmrg
29565394e5Smrg#if defined(SVR4)
308dd3e0eeSmrg#define MMAP_DEV_ZERO
318dd3e0eeSmrg#include <sys/types.h>
328dd3e0eeSmrg#include <sys/mman.h>
338dd3e0eeSmrg#include <unistd.h>
34565394e5Smrg#endif /* SVR4 */
358dd3e0eeSmrg
368dd3e0eeSmrg#ifdef XNO_SYSCONF
378dd3e0eeSmrg#undef _SC_PAGESIZE
388dd3e0eeSmrg#endif
398dd3e0eeSmrg
408dd3e0eeSmrg#include <X11/Xlibint.h>
41329fdfe9Smrg#include <X11/extensions/Xxf86dga.h>
42329fdfe9Smrg#include <X11/extensions/xf86dgaproto.h>
438dd3e0eeSmrg#include <X11/extensions/Xext.h>
448dd3e0eeSmrg#include <X11/extensions/extutil.h>
458dd3e0eeSmrg
468dd3e0eeSmrgextern XExtDisplayInfo* xdga_find_display(Display*);
47d5a688bcSmrgextern const char *xdga_extension_name;
488dd3e0eeSmrg
498dd3e0eeSmrg#define XF86DGACheckExtension(dpy,i,val) \
508dd3e0eeSmrg  XextCheckExtension (dpy, i, xdga_extension_name, val)
518dd3e0eeSmrg
528dd3e0eeSmrg/*****************************************************************************
538dd3e0eeSmrg *                                                                           *
548dd3e0eeSmrg *		    public XFree86-DGA Extension routines                    *
558dd3e0eeSmrg *                                                                           *
568dd3e0eeSmrg *****************************************************************************/
578dd3e0eeSmrg
588dd3e0eeSmrgBool XF86DGAQueryExtension (
598dd3e0eeSmrg    Display *dpy,
608dd3e0eeSmrg    int *event_basep,
618dd3e0eeSmrg    int *error_basep
628dd3e0eeSmrg){
638dd3e0eeSmrg    return XDGAQueryExtension(dpy, event_basep, error_basep);
648dd3e0eeSmrg}
658dd3e0eeSmrg
668dd3e0eeSmrgBool XF86DGAQueryVersion(
678dd3e0eeSmrg    Display* dpy,
68d5a688bcSmrg    int* majorVersion,
698dd3e0eeSmrg    int* minorVersion
708dd3e0eeSmrg){
718dd3e0eeSmrg    return XDGAQueryVersion(dpy, majorVersion, minorVersion);
728dd3e0eeSmrg}
738dd3e0eeSmrg
748dd3e0eeSmrgBool XF86DGAGetVideoLL(
758dd3e0eeSmrg    Display* dpy,
768dd3e0eeSmrg    int screen,
778dd3e0eeSmrg    unsigned int *offset,
78d5a688bcSmrg    int *width,
79d5a688bcSmrg    int *bank_size,
808dd3e0eeSmrg    int *ram_size
818dd3e0eeSmrg){
828dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
838dd3e0eeSmrg    xXF86DGAGetVideoLLReply rep;
848dd3e0eeSmrg    xXF86DGAGetVideoLLReq *req;
858dd3e0eeSmrg
868dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
878dd3e0eeSmrg
888dd3e0eeSmrg    LockDisplay(dpy);
898dd3e0eeSmrg    GetReq(XF86DGAGetVideoLL, req);
908dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
918dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetVideoLL;
928dd3e0eeSmrg    req->screen = screen;
938dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
948dd3e0eeSmrg	UnlockDisplay(dpy);
958dd3e0eeSmrg	SyncHandle();
968dd3e0eeSmrg	return False;
978dd3e0eeSmrg    }
988dd3e0eeSmrg
998dd3e0eeSmrg    *offset = rep.offset;
1008dd3e0eeSmrg    *width = rep.width;
1018dd3e0eeSmrg    *bank_size = rep.bank_size;
1028dd3e0eeSmrg    *ram_size = rep.ram_size;
103d5a688bcSmrg
1048dd3e0eeSmrg    UnlockDisplay(dpy);
1058dd3e0eeSmrg    SyncHandle();
1068dd3e0eeSmrg    return True;
1078dd3e0eeSmrg}
1088dd3e0eeSmrg
109d5a688bcSmrg
1108dd3e0eeSmrgBool XF86DGADirectVideoLL(
1118dd3e0eeSmrg    Display* dpy,
1128dd3e0eeSmrg    int screen,
1138dd3e0eeSmrg    int enable
1148dd3e0eeSmrg){
1158dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1168dd3e0eeSmrg    xXF86DGADirectVideoReq *req;
1178dd3e0eeSmrg
1188dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1198dd3e0eeSmrg
1208dd3e0eeSmrg    LockDisplay(dpy);
1218dd3e0eeSmrg    GetReq(XF86DGADirectVideo, req);
1228dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1238dd3e0eeSmrg    req->dgaReqType = X_XF86DGADirectVideo;
1248dd3e0eeSmrg    req->screen = screen;
1258dd3e0eeSmrg    req->enable = enable;
1268dd3e0eeSmrg    UnlockDisplay(dpy);
1278dd3e0eeSmrg    SyncHandle();
1288dd3e0eeSmrg    XSync(dpy,False);
1298dd3e0eeSmrg    return True;
1308dd3e0eeSmrg}
1318dd3e0eeSmrg
1328dd3e0eeSmrgBool XF86DGAGetViewPortSize(
1338dd3e0eeSmrg    Display* dpy,
1348dd3e0eeSmrg    int screen,
135d5a688bcSmrg    int *width,
1368dd3e0eeSmrg    int *height
1378dd3e0eeSmrg){
1388dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1398dd3e0eeSmrg    xXF86DGAGetViewPortSizeReply rep;
1408dd3e0eeSmrg    xXF86DGAGetViewPortSizeReq *req;
1418dd3e0eeSmrg
1428dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1438dd3e0eeSmrg
1448dd3e0eeSmrg    LockDisplay(dpy);
1458dd3e0eeSmrg    GetReq(XF86DGAGetViewPortSize, req);
1468dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1478dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetViewPortSize;
1488dd3e0eeSmrg    req->screen = screen;
1498dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
1508dd3e0eeSmrg	UnlockDisplay(dpy);
1518dd3e0eeSmrg	SyncHandle();
1528dd3e0eeSmrg	return False;
1538dd3e0eeSmrg    }
1548dd3e0eeSmrg
1558dd3e0eeSmrg    *width = rep.width;
1568dd3e0eeSmrg    *height = rep.height;
157d5a688bcSmrg
1588dd3e0eeSmrg    UnlockDisplay(dpy);
1598dd3e0eeSmrg    SyncHandle();
1608dd3e0eeSmrg    return True;
1618dd3e0eeSmrg}
162d5a688bcSmrg
163d5a688bcSmrg
1648dd3e0eeSmrgBool XF86DGASetViewPort(
1658dd3e0eeSmrg    Display* dpy,
1668dd3e0eeSmrg    int screen,
167d5a688bcSmrg    int x,
1688dd3e0eeSmrg    int y
1698dd3e0eeSmrg){
1708dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1718dd3e0eeSmrg    xXF86DGASetViewPortReq *req;
1728dd3e0eeSmrg
1738dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1748dd3e0eeSmrg
1758dd3e0eeSmrg    LockDisplay(dpy);
1768dd3e0eeSmrg    GetReq(XF86DGASetViewPort, req);
1778dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1788dd3e0eeSmrg    req->dgaReqType = X_XF86DGASetViewPort;
1798dd3e0eeSmrg    req->screen = screen;
1808dd3e0eeSmrg    req->x = x;
1818dd3e0eeSmrg    req->y = y;
1828dd3e0eeSmrg    UnlockDisplay(dpy);
1838dd3e0eeSmrg    SyncHandle();
1848dd3e0eeSmrg    XSync(dpy,False);
1858dd3e0eeSmrg    return True;
1868dd3e0eeSmrg}
1878dd3e0eeSmrg
188d5a688bcSmrg
1898dd3e0eeSmrgBool XF86DGAGetVidPage(
1908dd3e0eeSmrg    Display* dpy,
1918dd3e0eeSmrg    int screen,
1928dd3e0eeSmrg    int *vpage
1938dd3e0eeSmrg){
1948dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1958dd3e0eeSmrg    xXF86DGAGetVidPageReply rep;
1968dd3e0eeSmrg    xXF86DGAGetVidPageReq *req;
1978dd3e0eeSmrg
1988dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1998dd3e0eeSmrg
2008dd3e0eeSmrg    LockDisplay(dpy);
2018dd3e0eeSmrg    GetReq(XF86DGAGetVidPage, req);
2028dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2038dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetVidPage;
2048dd3e0eeSmrg    req->screen = screen;
2058dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
2068dd3e0eeSmrg	UnlockDisplay(dpy);
2078dd3e0eeSmrg	SyncHandle();
2088dd3e0eeSmrg	return False;
2098dd3e0eeSmrg    }
2108dd3e0eeSmrg
2118dd3e0eeSmrg    *vpage = rep.vpage;
2128dd3e0eeSmrg    UnlockDisplay(dpy);
2138dd3e0eeSmrg    SyncHandle();
2148dd3e0eeSmrg    return True;
2158dd3e0eeSmrg}
2168dd3e0eeSmrg
217d5a688bcSmrg
2188dd3e0eeSmrgBool XF86DGASetVidPage(
2198dd3e0eeSmrg    Display* dpy,
2208dd3e0eeSmrg    int screen,
2218dd3e0eeSmrg    int vpage
2228dd3e0eeSmrg){
2238dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2248dd3e0eeSmrg    xXF86DGASetVidPageReq *req;
2258dd3e0eeSmrg
2268dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2278dd3e0eeSmrg
2288dd3e0eeSmrg    LockDisplay(dpy);
2298dd3e0eeSmrg    GetReq(XF86DGASetVidPage, req);
2308dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2318dd3e0eeSmrg    req->dgaReqType = X_XF86DGASetVidPage;
2328dd3e0eeSmrg    req->screen = screen;
2338dd3e0eeSmrg    req->vpage = vpage;
2348dd3e0eeSmrg    UnlockDisplay(dpy);
2358dd3e0eeSmrg    SyncHandle();
2368dd3e0eeSmrg    XSync(dpy,False);
2378dd3e0eeSmrg    return True;
2388dd3e0eeSmrg}
2398dd3e0eeSmrg
2408dd3e0eeSmrgBool XF86DGAInstallColormap(
2418dd3e0eeSmrg    Display* dpy,
2428dd3e0eeSmrg    int screen,
2438dd3e0eeSmrg    Colormap cmap
2448dd3e0eeSmrg){
2458dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2468dd3e0eeSmrg    xXF86DGAInstallColormapReq *req;
2478dd3e0eeSmrg
2488dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2498dd3e0eeSmrg
2508dd3e0eeSmrg    LockDisplay(dpy);
2518dd3e0eeSmrg    GetReq(XF86DGAInstallColormap, req);
2528dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2538dd3e0eeSmrg    req->dgaReqType = X_XF86DGAInstallColormap;
2548dd3e0eeSmrg    req->screen = screen;
2558dd3e0eeSmrg    req->id = cmap;
2568dd3e0eeSmrg    UnlockDisplay(dpy);
2578dd3e0eeSmrg    SyncHandle();
2588dd3e0eeSmrg    XSync(dpy,False);
2598dd3e0eeSmrg    return True;
2608dd3e0eeSmrg}
2618dd3e0eeSmrg
2628dd3e0eeSmrgBool XF86DGAQueryDirectVideo(
2638dd3e0eeSmrg    Display *dpy,
2648dd3e0eeSmrg    int screen,
2658dd3e0eeSmrg    int *flags
2668dd3e0eeSmrg){
2678dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2688dd3e0eeSmrg    xXF86DGAQueryDirectVideoReply rep;
2698dd3e0eeSmrg    xXF86DGAQueryDirectVideoReq *req;
2708dd3e0eeSmrg
2718dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2728dd3e0eeSmrg
2738dd3e0eeSmrg    LockDisplay(dpy);
2748dd3e0eeSmrg    GetReq(XF86DGAQueryDirectVideo, req);
2758dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2768dd3e0eeSmrg    req->dgaReqType = X_XF86DGAQueryDirectVideo;
2778dd3e0eeSmrg    req->screen = screen;
2788dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
2798dd3e0eeSmrg	UnlockDisplay(dpy);
2808dd3e0eeSmrg	SyncHandle();
2818dd3e0eeSmrg	return False;
2828dd3e0eeSmrg    }
2838dd3e0eeSmrg    *flags = rep.flags;
2848dd3e0eeSmrg    UnlockDisplay(dpy);
2858dd3e0eeSmrg    SyncHandle();
2868dd3e0eeSmrg    return True;
2878dd3e0eeSmrg}
2888dd3e0eeSmrg
2898dd3e0eeSmrgBool XF86DGAViewPortChanged(
2908dd3e0eeSmrg    Display *dpy,
2918dd3e0eeSmrg    int screen,
2928dd3e0eeSmrg    int n
2938dd3e0eeSmrg){
2948dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2958dd3e0eeSmrg    xXF86DGAViewPortChangedReply rep;
2968dd3e0eeSmrg    xXF86DGAViewPortChangedReq *req;
2978dd3e0eeSmrg
2988dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2998dd3e0eeSmrg
3008dd3e0eeSmrg    LockDisplay(dpy);
3018dd3e0eeSmrg    GetReq(XF86DGAViewPortChanged, req);
3028dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
3038dd3e0eeSmrg    req->dgaReqType = X_XF86DGAViewPortChanged;
3048dd3e0eeSmrg    req->screen = screen;
3058dd3e0eeSmrg    req->n = n;
3068dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
3078dd3e0eeSmrg	UnlockDisplay(dpy);
3088dd3e0eeSmrg	SyncHandle();
3098dd3e0eeSmrg	return False;
3108dd3e0eeSmrg    }
3118dd3e0eeSmrg    UnlockDisplay(dpy);
3128dd3e0eeSmrg    SyncHandle();
3138dd3e0eeSmrg    return rep.result;
3148dd3e0eeSmrg}
3158dd3e0eeSmrg
3168dd3e0eeSmrg
3178dd3e0eeSmrg
3188dd3e0eeSmrg/* Helper functions */
3198dd3e0eeSmrg
3208dd3e0eeSmrg#include <X11/Xmd.h>
3218dd3e0eeSmrg#include <stdlib.h>
3228dd3e0eeSmrg#include <stdio.h>
3238dd3e0eeSmrg#include <fcntl.h>
324565394e5Smrg#include <sys/mman.h>
3258dd3e0eeSmrg#include <sys/wait.h>
3268dd3e0eeSmrg#include <signal.h>
3278dd3e0eeSmrg#include <unistd.h>
3288dd3e0eeSmrg
3298dd3e0eeSmrg#if defined(SVR4) && !defined(sun)
3308dd3e0eeSmrg#define DEV_MEM "/dev/pmem"
3318dd3e0eeSmrg#elif defined(SVR4) && defined(sun)
3328dd3e0eeSmrg#define DEV_MEM "/dev/xsvc"
3338dd3e0eeSmrg#elif defined(HAS_APERTURE_DRV)
3348dd3e0eeSmrg#define DEV_MEM "/dev/xf86"
3358dd3e0eeSmrg#else
3368dd3e0eeSmrg#define DEV_MEM "/dev/mem"
3378dd3e0eeSmrg#endif
3388dd3e0eeSmrg
3398dd3e0eeSmrgtypedef struct {
3408dd3e0eeSmrg    unsigned long physaddr;	/* actual requested physical address */
3418dd3e0eeSmrg    unsigned long size;		/* actual requested map size */
3428dd3e0eeSmrg    unsigned long delta;	/* delta to account for page alignment */
3438dd3e0eeSmrg    void *	  vaddr;	/* mapped address, without the delta */
3448dd3e0eeSmrg    int		  refcount;	/* reference count */
3458dd3e0eeSmrg} MapRec, *MapPtr;
3468dd3e0eeSmrg
3478dd3e0eeSmrgtypedef struct {
3488dd3e0eeSmrg    Display *	display;
3498dd3e0eeSmrg    int		screen;
3508dd3e0eeSmrg    MapPtr	map;
3518dd3e0eeSmrg} ScrRec, *ScrPtr;
3528dd3e0eeSmrg
3538dd3e0eeSmrgstatic int mapFd = -1;
3548dd3e0eeSmrgstatic int numMaps = 0;
3558dd3e0eeSmrgstatic int numScrs = 0;
3568dd3e0eeSmrgstatic MapPtr *mapList = NULL;
3578dd3e0eeSmrgstatic ScrPtr *scrList = NULL;
3588dd3e0eeSmrg
3598dd3e0eeSmrgstatic MapPtr
3608dd3e0eeSmrgAddMap(void)
3618dd3e0eeSmrg{
3628dd3e0eeSmrg    MapPtr *old;
3638dd3e0eeSmrg
3648dd3e0eeSmrg    old = mapList;
3658dd3e0eeSmrg    mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1));
3668dd3e0eeSmrg    if (!mapList) {
3678dd3e0eeSmrg	mapList = old;
3688dd3e0eeSmrg	return NULL;
3698dd3e0eeSmrg    }
3708dd3e0eeSmrg    mapList[numMaps] = malloc(sizeof(MapRec));
3718dd3e0eeSmrg    if (!mapList[numMaps])
3728dd3e0eeSmrg	return NULL;
3738dd3e0eeSmrg    return mapList[numMaps++];
3748dd3e0eeSmrg}
3758dd3e0eeSmrg
3768dd3e0eeSmrgstatic ScrPtr
3778dd3e0eeSmrgAddScr(void)
3788dd3e0eeSmrg{
3798dd3e0eeSmrg    ScrPtr *old;
3808dd3e0eeSmrg
3818dd3e0eeSmrg    old = scrList;
3828dd3e0eeSmrg    scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1));
3838dd3e0eeSmrg    if (!scrList) {
3848dd3e0eeSmrg	scrList = old;
3858dd3e0eeSmrg	return NULL;
3868dd3e0eeSmrg    }
3878dd3e0eeSmrg    scrList[numScrs] = malloc(sizeof(ScrRec));
3888dd3e0eeSmrg    if (!scrList[numScrs])
3898dd3e0eeSmrg	return NULL;
3908dd3e0eeSmrg    return scrList[numScrs++];
3918dd3e0eeSmrg}
3928dd3e0eeSmrg
3938dd3e0eeSmrgstatic MapPtr
3948dd3e0eeSmrgFindMap(unsigned long address, unsigned long size)
3958dd3e0eeSmrg{
3968dd3e0eeSmrg    int i;
3978dd3e0eeSmrg
3988dd3e0eeSmrg    for (i = 0; i < numMaps; i++) {
3998dd3e0eeSmrg	if (mapList[i]->physaddr == address &&
4008dd3e0eeSmrg	    mapList[i]->size == size)
4018dd3e0eeSmrg	    return mapList[i];
4028dd3e0eeSmrg    }
4038dd3e0eeSmrg    return NULL;
4048dd3e0eeSmrg}
4058dd3e0eeSmrg
4068dd3e0eeSmrgstatic ScrPtr
4078dd3e0eeSmrgFindScr(Display *display, int screen)
4088dd3e0eeSmrg{
4098dd3e0eeSmrg    int i;
4108dd3e0eeSmrg
4118dd3e0eeSmrg    for (i = 0; i < numScrs; i++) {
4128dd3e0eeSmrg	if (scrList[i]->display == display &&
4138dd3e0eeSmrg	    scrList[i]->screen == screen)
4148dd3e0eeSmrg	    return scrList[i];
4158dd3e0eeSmrg    }
4168dd3e0eeSmrg    return NULL;
4178dd3e0eeSmrg}
4188dd3e0eeSmrg
4198dd3e0eeSmrgstatic void *
4208dd3e0eeSmrgMapPhysAddress(unsigned long address, unsigned long size)
4218dd3e0eeSmrg{
4228dd3e0eeSmrg    unsigned long offset, delta;
4238dd3e0eeSmrg    int pagesize = -1;
4248dd3e0eeSmrg    void *vaddr;
4258dd3e0eeSmrg    MapPtr mp;
4268dd3e0eeSmrg
4278dd3e0eeSmrg    if ((mp = FindMap(address, size))) {
4288dd3e0eeSmrg	mp->refcount++;
4298dd3e0eeSmrg	return (void *)((unsigned long)mp->vaddr + mp->delta);
4308dd3e0eeSmrg    }
4318dd3e0eeSmrg
4328dd3e0eeSmrg#if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE)
4338dd3e0eeSmrg    pagesize = sysconf(_SC_PAGESIZE);
4348dd3e0eeSmrg#endif
4358dd3e0eeSmrg#ifdef _SC_PAGE_SIZE
4368dd3e0eeSmrg    if (pagesize == -1)
4378dd3e0eeSmrg	pagesize = sysconf(_SC_PAGE_SIZE);
4388dd3e0eeSmrg#endif
4398dd3e0eeSmrg#ifdef HAS_GETPAGESIZE
4408dd3e0eeSmrg    if (pagesize == -1)
4418dd3e0eeSmrg	pagesize = getpagesize();
4428dd3e0eeSmrg#endif
4438dd3e0eeSmrg#ifdef PAGE_SIZE
4448dd3e0eeSmrg    if (pagesize == -1)
4458dd3e0eeSmrg	pagesize = PAGE_SIZE;
4468dd3e0eeSmrg#endif
4478dd3e0eeSmrg    if (pagesize == -1)
4488dd3e0eeSmrg	pagesize = 4096;
4498dd3e0eeSmrg
4508dd3e0eeSmrg   delta = address % pagesize;
4518dd3e0eeSmrg   offset = address - delta;
4528dd3e0eeSmrg#ifndef MAP_FILE
4538dd3e0eeSmrg#define MAP_FILE 0
4548dd3e0eeSmrg#endif
4558dd3e0eeSmrg    if (mapFd < 0) {
4568dd3e0eeSmrg	if ((mapFd = open(DEV_MEM, O_RDWR)) < 0)
4578dd3e0eeSmrg	    return NULL;
4588dd3e0eeSmrg    }
4598dd3e0eeSmrg    vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE,
460565394e5Smrg			 MAP_FILE | MAP_SHARED, mapFd, (off_t)offset);
4618dd3e0eeSmrg    if (vaddr == (void *)-1)
4628dd3e0eeSmrg	return NULL;
4638dd3e0eeSmrg
4648dd3e0eeSmrg    if (!vaddr) {
4658dd3e0eeSmrg	if (!(mp = AddMap()))
4668dd3e0eeSmrg	    return NULL;
4678dd3e0eeSmrg	mp->physaddr = address;
4688dd3e0eeSmrg	mp->size = size;
4698dd3e0eeSmrg	mp->delta = delta;
4708dd3e0eeSmrg	mp->vaddr = vaddr;
4718dd3e0eeSmrg	mp->refcount = 1;
4728dd3e0eeSmrg    }
4738dd3e0eeSmrg    return (void *)((unsigned long)vaddr + delta);
4748dd3e0eeSmrg}
4758dd3e0eeSmrg
4768dd3e0eeSmrg/*
4778dd3e0eeSmrg * Still need to find a clean way of detecting the death of a DGA app
4788dd3e0eeSmrg * and returning things to normal - Jon
4798dd3e0eeSmrg * This is here to help debugging without rebooting... Also C-A-BS
4808dd3e0eeSmrg * should restore text mode.
4818dd3e0eeSmrg */
4828dd3e0eeSmrg
4838dd3e0eeSmrgint
4848dd3e0eeSmrgXF86DGAForkApp(int screen)
4858dd3e0eeSmrg{
4868dd3e0eeSmrg    pid_t pid;
4878dd3e0eeSmrg    int status;
4888dd3e0eeSmrg    int i;
4898dd3e0eeSmrg
4908dd3e0eeSmrg     /* fork the app, parent hangs around to clean up */
4918dd3e0eeSmrg    if ((pid = fork()) > 0) {
4928dd3e0eeSmrg	ScrPtr sp;
4938dd3e0eeSmrg
4948dd3e0eeSmrg	waitpid(pid, &status, 0);
4958dd3e0eeSmrg	for (i = 0; i < numScrs; i++) {
4968dd3e0eeSmrg	    sp = scrList[i];
4978dd3e0eeSmrg	    XF86DGADirectVideoLL(sp->display, sp->screen, 0);
4988dd3e0eeSmrg	    XSync(sp->display, False);
4998dd3e0eeSmrg	}
5008dd3e0eeSmrg        if (WIFEXITED(status))
5018dd3e0eeSmrg	    _exit(0);
5028dd3e0eeSmrg	else
5038dd3e0eeSmrg	    _exit(-1);
5048dd3e0eeSmrg    }
5058dd3e0eeSmrg    return pid;
5068dd3e0eeSmrg}
5078dd3e0eeSmrg
5088dd3e0eeSmrg
5098dd3e0eeSmrgBool
5108dd3e0eeSmrgXF86DGADirectVideo(
5118dd3e0eeSmrg    Display *dis,
5128dd3e0eeSmrg    int screen,
5138dd3e0eeSmrg    int enable
5148dd3e0eeSmrg){
5158dd3e0eeSmrg    ScrPtr sp;
5168dd3e0eeSmrg    MapPtr mp = NULL;
5178dd3e0eeSmrg
5188dd3e0eeSmrg    if ((sp = FindScr(dis, screen)))
5198dd3e0eeSmrg	mp = sp->map;
5208dd3e0eeSmrg
5218dd3e0eeSmrg    if (enable & XF86DGADirectGraphics) {
5228dd3e0eeSmrg	if (mp && mp->vaddr)
5238dd3e0eeSmrg	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE);
5248dd3e0eeSmrg    } else {
5258dd3e0eeSmrg	if (mp && mp->vaddr)
5268dd3e0eeSmrg	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ);
5278dd3e0eeSmrg    }
5288dd3e0eeSmrg
5298dd3e0eeSmrg    XF86DGADirectVideoLL(dis, screen, enable);
5308dd3e0eeSmrg    return 1;
5318dd3e0eeSmrg}
5328dd3e0eeSmrg
5338dd3e0eeSmrg
5348dd3e0eeSmrgstatic void
535da01b833Schristos#ifdef __NetBSD__
536da01b833Schristos__attribute__ ((__destructor__))
537da01b833Schristos#endif
538188cbdcfStsutsuiXF86cleanup_atexit(void)
5398dd3e0eeSmrg{
5408dd3e0eeSmrg    ScrPtr sp;
5418dd3e0eeSmrg    int i;
5428dd3e0eeSmrg    static char beenhere = 0;
5438dd3e0eeSmrg
5448dd3e0eeSmrg    if (beenhere)
545188cbdcfStsutsui	return;
5468dd3e0eeSmrg    beenhere = 1;
5478dd3e0eeSmrg
5488dd3e0eeSmrg    for (i = 0; i < numScrs; i++) {
5498dd3e0eeSmrg	sp = scrList[i];
5508dd3e0eeSmrg	XF86DGADirectVideo(sp->display, sp->screen, 0);
5518dd3e0eeSmrg	XSync(sp->display, False);
5528dd3e0eeSmrg    }
553188cbdcfStsutsui}
554188cbdcfStsutsui
555188cbdcfStsutsuistatic void
556188cbdcfStsutsuiXF86cleanup(int sig)
557188cbdcfStsutsui{
558188cbdcfStsutsui    /* XXX FIXME XF86cleanup_atexit() is not async-signal-safe */
559188cbdcfStsutsui    XF86cleanup_atexit();
560188cbdcfStsutsui
5618dd3e0eeSmrg    _exit(3);
5628dd3e0eeSmrg}
5638dd3e0eeSmrg
5648dd3e0eeSmrgBool
5658dd3e0eeSmrgXF86DGAGetVideo(
5668dd3e0eeSmrg    Display *dis,
5678dd3e0eeSmrg    int screen,
5688dd3e0eeSmrg    char **addr,
569d5a688bcSmrg    int *width,
570d5a688bcSmrg    int *bank,
5718dd3e0eeSmrg    int *ram
5728dd3e0eeSmrg){
5738dd3e0eeSmrg    unsigned int offset;
5748dd3e0eeSmrg    static int beenHere = 0;
5758dd3e0eeSmrg    ScrPtr sp;
5768dd3e0eeSmrg    MapPtr mp;
5778dd3e0eeSmrg
5788dd3e0eeSmrg    if (!(sp = FindScr(dis, screen))) {
5798dd3e0eeSmrg	if (!(sp = AddScr())) {
5808dd3e0eeSmrg	    fprintf(stderr, "XF86DGAGetVideo: malloc failure\n");
5818dd3e0eeSmrg	    exit(-2);
5828dd3e0eeSmrg	}
5838dd3e0eeSmrg	sp->display = dis;
5848dd3e0eeSmrg	sp->screen = screen;
5858dd3e0eeSmrg	sp->map = NULL;
5868dd3e0eeSmrg    }
5878dd3e0eeSmrg
5888dd3e0eeSmrg    XF86DGAGetVideoLL(dis, screen , &offset, width, bank, ram);
5898dd3e0eeSmrg
5908dd3e0eeSmrg    *addr = MapPhysAddress(offset, *bank);
5918dd3e0eeSmrg    if (*addr == NULL) {
5928dd3e0eeSmrg	fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n",
5938dd3e0eeSmrg		strerror(errno));
5948dd3e0eeSmrg	exit(-2);
5958dd3e0eeSmrg    }
5968dd3e0eeSmrg
5978dd3e0eeSmrg    if ((mp = FindMap(offset, *bank)))
5988dd3e0eeSmrg	sp->map = mp;
5998dd3e0eeSmrg
6008dd3e0eeSmrg    if (!beenHere) {
6018dd3e0eeSmrg	beenHere = 1;
602da01b833Schristos#ifndef __NetBSD__
603188cbdcfStsutsui	atexit((void(*)(void))XF86cleanup_atexit);
604da01b833Schristos#endif
6058dd3e0eeSmrg	/* one shot XF86cleanup attempts */
6068dd3e0eeSmrg	signal(SIGSEGV, XF86cleanup);
6078dd3e0eeSmrg#ifdef SIGBUS
6088dd3e0eeSmrg	signal(SIGBUS, XF86cleanup);
6098dd3e0eeSmrg#endif
6108dd3e0eeSmrg	signal(SIGHUP, XF86cleanup);
611d5a688bcSmrg	signal(SIGFPE, XF86cleanup);
6128dd3e0eeSmrg    }
6138dd3e0eeSmrg
6148dd3e0eeSmrg    return 1;
6158dd3e0eeSmrg}
616