XF86DGA.c revision 8dd3e0ee
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#ifdef __UNIXOS2__ /* needed here to override certain constants in X headers */
128dd3e0eeSmrg#define INCL_DOS
138dd3e0eeSmrg#define INCL_DOSIOCTL
148dd3e0eeSmrg#define I_NEED_OS2_H
158dd3e0eeSmrg#include <os2.h>
168dd3e0eeSmrg#endif
178dd3e0eeSmrg
188dd3e0eeSmrg#if defined(linux)
198dd3e0eeSmrg#define HAS_MMAP_ANON
208dd3e0eeSmrg#include <sys/types.h>
218dd3e0eeSmrg#include <sys/mman.h>
228dd3e0eeSmrg/* kernel header doesn't work with -ansi */
238dd3e0eeSmrg/* #include <asm/page.h> */   /* PAGE_SIZE */
248dd3e0eeSmrg#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */
258dd3e0eeSmrg#define HAS_GETPAGESIZE
268dd3e0eeSmrg#endif /* linux */
278dd3e0eeSmrg
288dd3e0eeSmrg#if defined(CSRG_BASED)
298dd3e0eeSmrg#define HAS_MMAP_ANON
308dd3e0eeSmrg#define HAS_GETPAGESIZE
318dd3e0eeSmrg#include <sys/types.h>
328dd3e0eeSmrg#include <sys/mman.h>
338dd3e0eeSmrg#endif /* CSRG_BASED */
348dd3e0eeSmrg
358dd3e0eeSmrg#if defined(DGUX)
368dd3e0eeSmrg#define HAS_GETPAGESIZE
378dd3e0eeSmrg#define MMAP_DEV_ZERO
388dd3e0eeSmrg#include <sys/types.h>
398dd3e0eeSmrg#include <sys/mman.h>
408dd3e0eeSmrg#include <unistd.h>
418dd3e0eeSmrg#endif /* DGUX */
428dd3e0eeSmrg
438dd3e0eeSmrg#if defined(SVR4) && !defined(DGUX)
448dd3e0eeSmrg#define MMAP_DEV_ZERO
458dd3e0eeSmrg#include <sys/types.h>
468dd3e0eeSmrg#include <sys/mman.h>
478dd3e0eeSmrg#include <unistd.h>
488dd3e0eeSmrg#endif /* SVR4 && !DGUX */
498dd3e0eeSmrg
508dd3e0eeSmrg#if defined(sun) && !defined(SVR4) /* SunOS */
518dd3e0eeSmrg#define MMAP_DEV_ZERO   /* doesn't SunOS have MAP_ANON ?? */
528dd3e0eeSmrg#define HAS_GETPAGESIZE
538dd3e0eeSmrg#include <sys/types.h>
548dd3e0eeSmrg#include <sys/mman.h>
558dd3e0eeSmrg#endif /* sun && !SVR4 */
568dd3e0eeSmrg
578dd3e0eeSmrg#ifdef XNO_SYSCONF
588dd3e0eeSmrg#undef _SC_PAGESIZE
598dd3e0eeSmrg#endif
608dd3e0eeSmrg
618dd3e0eeSmrg
628dd3e0eeSmrg#define NEED_EVENTS
638dd3e0eeSmrg#define NEED_REPLIES
648dd3e0eeSmrg#include <X11/Xlibint.h>
658dd3e0eeSmrg#include <X11/extensions/xf86dga.h>
668dd3e0eeSmrg#include <X11/extensions/xf86dgastr.h>
678dd3e0eeSmrg#include <X11/extensions/Xext.h>
688dd3e0eeSmrg#include <X11/extensions/extutil.h>
698dd3e0eeSmrg
708dd3e0eeSmrgextern XExtDisplayInfo* xdga_find_display(Display*);
718dd3e0eeSmrgextern char *xdga_extension_name;
728dd3e0eeSmrg
738dd3e0eeSmrg#define XF86DGACheckExtension(dpy,i,val) \
748dd3e0eeSmrg  XextCheckExtension (dpy, i, xdga_extension_name, val)
758dd3e0eeSmrg
768dd3e0eeSmrg/*****************************************************************************
778dd3e0eeSmrg *                                                                           *
788dd3e0eeSmrg *		    public XFree86-DGA Extension routines                    *
798dd3e0eeSmrg *                                                                           *
808dd3e0eeSmrg *****************************************************************************/
818dd3e0eeSmrg
828dd3e0eeSmrgBool XF86DGAQueryExtension (
838dd3e0eeSmrg    Display *dpy,
848dd3e0eeSmrg    int *event_basep,
858dd3e0eeSmrg    int *error_basep
868dd3e0eeSmrg){
878dd3e0eeSmrg    return XDGAQueryExtension(dpy, event_basep, error_basep);
888dd3e0eeSmrg}
898dd3e0eeSmrg
908dd3e0eeSmrgBool XF86DGAQueryVersion(
918dd3e0eeSmrg    Display* dpy,
928dd3e0eeSmrg    int* majorVersion,
938dd3e0eeSmrg    int* minorVersion
948dd3e0eeSmrg){
958dd3e0eeSmrg    return XDGAQueryVersion(dpy, majorVersion, minorVersion);
968dd3e0eeSmrg}
978dd3e0eeSmrg
988dd3e0eeSmrgBool XF86DGAGetVideoLL(
998dd3e0eeSmrg    Display* dpy,
1008dd3e0eeSmrg    int screen,
1018dd3e0eeSmrg    unsigned int *offset,
1028dd3e0eeSmrg    int *width,
1038dd3e0eeSmrg    int *bank_size,
1048dd3e0eeSmrg    int *ram_size
1058dd3e0eeSmrg){
1068dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1078dd3e0eeSmrg    xXF86DGAGetVideoLLReply rep;
1088dd3e0eeSmrg    xXF86DGAGetVideoLLReq *req;
1098dd3e0eeSmrg
1108dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1118dd3e0eeSmrg
1128dd3e0eeSmrg    LockDisplay(dpy);
1138dd3e0eeSmrg    GetReq(XF86DGAGetVideoLL, req);
1148dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1158dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetVideoLL;
1168dd3e0eeSmrg    req->screen = screen;
1178dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
1188dd3e0eeSmrg	UnlockDisplay(dpy);
1198dd3e0eeSmrg	SyncHandle();
1208dd3e0eeSmrg	return False;
1218dd3e0eeSmrg    }
1228dd3e0eeSmrg
1238dd3e0eeSmrg    *offset = rep.offset;
1248dd3e0eeSmrg    *width = rep.width;
1258dd3e0eeSmrg    *bank_size = rep.bank_size;
1268dd3e0eeSmrg    *ram_size = rep.ram_size;
1278dd3e0eeSmrg
1288dd3e0eeSmrg    UnlockDisplay(dpy);
1298dd3e0eeSmrg    SyncHandle();
1308dd3e0eeSmrg    return True;
1318dd3e0eeSmrg}
1328dd3e0eeSmrg
1338dd3e0eeSmrg
1348dd3e0eeSmrgBool XF86DGADirectVideoLL(
1358dd3e0eeSmrg    Display* dpy,
1368dd3e0eeSmrg    int screen,
1378dd3e0eeSmrg    int enable
1388dd3e0eeSmrg){
1398dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1408dd3e0eeSmrg    xXF86DGADirectVideoReq *req;
1418dd3e0eeSmrg
1428dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1438dd3e0eeSmrg
1448dd3e0eeSmrg    LockDisplay(dpy);
1458dd3e0eeSmrg    GetReq(XF86DGADirectVideo, req);
1468dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1478dd3e0eeSmrg    req->dgaReqType = X_XF86DGADirectVideo;
1488dd3e0eeSmrg    req->screen = screen;
1498dd3e0eeSmrg    req->enable = enable;
1508dd3e0eeSmrg    UnlockDisplay(dpy);
1518dd3e0eeSmrg    SyncHandle();
1528dd3e0eeSmrg    XSync(dpy,False);
1538dd3e0eeSmrg    return True;
1548dd3e0eeSmrg}
1558dd3e0eeSmrg
1568dd3e0eeSmrgBool XF86DGAGetViewPortSize(
1578dd3e0eeSmrg    Display* dpy,
1588dd3e0eeSmrg    int screen,
1598dd3e0eeSmrg    int *width,
1608dd3e0eeSmrg    int *height
1618dd3e0eeSmrg){
1628dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1638dd3e0eeSmrg    xXF86DGAGetViewPortSizeReply rep;
1648dd3e0eeSmrg    xXF86DGAGetViewPortSizeReq *req;
1658dd3e0eeSmrg
1668dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1678dd3e0eeSmrg
1688dd3e0eeSmrg    LockDisplay(dpy);
1698dd3e0eeSmrg    GetReq(XF86DGAGetViewPortSize, req);
1708dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
1718dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetViewPortSize;
1728dd3e0eeSmrg    req->screen = screen;
1738dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
1748dd3e0eeSmrg	UnlockDisplay(dpy);
1758dd3e0eeSmrg	SyncHandle();
1768dd3e0eeSmrg	return False;
1778dd3e0eeSmrg    }
1788dd3e0eeSmrg
1798dd3e0eeSmrg    *width = rep.width;
1808dd3e0eeSmrg    *height = rep.height;
1818dd3e0eeSmrg
1828dd3e0eeSmrg    UnlockDisplay(dpy);
1838dd3e0eeSmrg    SyncHandle();
1848dd3e0eeSmrg    return True;
1858dd3e0eeSmrg}
1868dd3e0eeSmrg
1878dd3e0eeSmrg
1888dd3e0eeSmrgBool XF86DGASetViewPort(
1898dd3e0eeSmrg    Display* dpy,
1908dd3e0eeSmrg    int screen,
1918dd3e0eeSmrg    int x,
1928dd3e0eeSmrg    int y
1938dd3e0eeSmrg){
1948dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
1958dd3e0eeSmrg    xXF86DGASetViewPortReq *req;
1968dd3e0eeSmrg
1978dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
1988dd3e0eeSmrg
1998dd3e0eeSmrg    LockDisplay(dpy);
2008dd3e0eeSmrg    GetReq(XF86DGASetViewPort, req);
2018dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2028dd3e0eeSmrg    req->dgaReqType = X_XF86DGASetViewPort;
2038dd3e0eeSmrg    req->screen = screen;
2048dd3e0eeSmrg    req->x = x;
2058dd3e0eeSmrg    req->y = y;
2068dd3e0eeSmrg    UnlockDisplay(dpy);
2078dd3e0eeSmrg    SyncHandle();
2088dd3e0eeSmrg    XSync(dpy,False);
2098dd3e0eeSmrg    return True;
2108dd3e0eeSmrg}
2118dd3e0eeSmrg
2128dd3e0eeSmrg
2138dd3e0eeSmrgBool XF86DGAGetVidPage(
2148dd3e0eeSmrg    Display* dpy,
2158dd3e0eeSmrg    int screen,
2168dd3e0eeSmrg    int *vpage
2178dd3e0eeSmrg){
2188dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2198dd3e0eeSmrg    xXF86DGAGetVidPageReply rep;
2208dd3e0eeSmrg    xXF86DGAGetVidPageReq *req;
2218dd3e0eeSmrg
2228dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2238dd3e0eeSmrg
2248dd3e0eeSmrg    LockDisplay(dpy);
2258dd3e0eeSmrg    GetReq(XF86DGAGetVidPage, req);
2268dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2278dd3e0eeSmrg    req->dgaReqType = X_XF86DGAGetVidPage;
2288dd3e0eeSmrg    req->screen = screen;
2298dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
2308dd3e0eeSmrg	UnlockDisplay(dpy);
2318dd3e0eeSmrg	SyncHandle();
2328dd3e0eeSmrg	return False;
2338dd3e0eeSmrg    }
2348dd3e0eeSmrg
2358dd3e0eeSmrg    *vpage = rep.vpage;
2368dd3e0eeSmrg    UnlockDisplay(dpy);
2378dd3e0eeSmrg    SyncHandle();
2388dd3e0eeSmrg    return True;
2398dd3e0eeSmrg}
2408dd3e0eeSmrg
2418dd3e0eeSmrg
2428dd3e0eeSmrgBool XF86DGASetVidPage(
2438dd3e0eeSmrg    Display* dpy,
2448dd3e0eeSmrg    int screen,
2458dd3e0eeSmrg    int vpage
2468dd3e0eeSmrg){
2478dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2488dd3e0eeSmrg    xXF86DGASetVidPageReq *req;
2498dd3e0eeSmrg
2508dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2518dd3e0eeSmrg
2528dd3e0eeSmrg    LockDisplay(dpy);
2538dd3e0eeSmrg    GetReq(XF86DGASetVidPage, req);
2548dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2558dd3e0eeSmrg    req->dgaReqType = X_XF86DGASetVidPage;
2568dd3e0eeSmrg    req->screen = screen;
2578dd3e0eeSmrg    req->vpage = vpage;
2588dd3e0eeSmrg    UnlockDisplay(dpy);
2598dd3e0eeSmrg    SyncHandle();
2608dd3e0eeSmrg    XSync(dpy,False);
2618dd3e0eeSmrg    return True;
2628dd3e0eeSmrg}
2638dd3e0eeSmrg
2648dd3e0eeSmrgBool XF86DGAInstallColormap(
2658dd3e0eeSmrg    Display* dpy,
2668dd3e0eeSmrg    int screen,
2678dd3e0eeSmrg    Colormap cmap
2688dd3e0eeSmrg){
2698dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2708dd3e0eeSmrg    xXF86DGAInstallColormapReq *req;
2718dd3e0eeSmrg
2728dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2738dd3e0eeSmrg
2748dd3e0eeSmrg    LockDisplay(dpy);
2758dd3e0eeSmrg    GetReq(XF86DGAInstallColormap, req);
2768dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
2778dd3e0eeSmrg    req->dgaReqType = X_XF86DGAInstallColormap;
2788dd3e0eeSmrg    req->screen = screen;
2798dd3e0eeSmrg    req->id = cmap;
2808dd3e0eeSmrg    UnlockDisplay(dpy);
2818dd3e0eeSmrg    SyncHandle();
2828dd3e0eeSmrg    XSync(dpy,False);
2838dd3e0eeSmrg    return True;
2848dd3e0eeSmrg}
2858dd3e0eeSmrg
2868dd3e0eeSmrgBool XF86DGAQueryDirectVideo(
2878dd3e0eeSmrg    Display *dpy,
2888dd3e0eeSmrg    int screen,
2898dd3e0eeSmrg    int *flags
2908dd3e0eeSmrg){
2918dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
2928dd3e0eeSmrg    xXF86DGAQueryDirectVideoReply rep;
2938dd3e0eeSmrg    xXF86DGAQueryDirectVideoReq *req;
2948dd3e0eeSmrg
2958dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
2968dd3e0eeSmrg
2978dd3e0eeSmrg    LockDisplay(dpy);
2988dd3e0eeSmrg    GetReq(XF86DGAQueryDirectVideo, req);
2998dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
3008dd3e0eeSmrg    req->dgaReqType = X_XF86DGAQueryDirectVideo;
3018dd3e0eeSmrg    req->screen = screen;
3028dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
3038dd3e0eeSmrg	UnlockDisplay(dpy);
3048dd3e0eeSmrg	SyncHandle();
3058dd3e0eeSmrg	return False;
3068dd3e0eeSmrg    }
3078dd3e0eeSmrg    *flags = rep.flags;
3088dd3e0eeSmrg    UnlockDisplay(dpy);
3098dd3e0eeSmrg    SyncHandle();
3108dd3e0eeSmrg    return True;
3118dd3e0eeSmrg}
3128dd3e0eeSmrg
3138dd3e0eeSmrgBool XF86DGAViewPortChanged(
3148dd3e0eeSmrg    Display *dpy,
3158dd3e0eeSmrg    int screen,
3168dd3e0eeSmrg    int n
3178dd3e0eeSmrg){
3188dd3e0eeSmrg    XExtDisplayInfo *info = xdga_find_display (dpy);
3198dd3e0eeSmrg    xXF86DGAViewPortChangedReply rep;
3208dd3e0eeSmrg    xXF86DGAViewPortChangedReq *req;
3218dd3e0eeSmrg
3228dd3e0eeSmrg    XF86DGACheckExtension (dpy, info, False);
3238dd3e0eeSmrg
3248dd3e0eeSmrg    LockDisplay(dpy);
3258dd3e0eeSmrg    GetReq(XF86DGAViewPortChanged, req);
3268dd3e0eeSmrg    req->reqType = info->codes->major_opcode;
3278dd3e0eeSmrg    req->dgaReqType = X_XF86DGAViewPortChanged;
3288dd3e0eeSmrg    req->screen = screen;
3298dd3e0eeSmrg    req->n = n;
3308dd3e0eeSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
3318dd3e0eeSmrg	UnlockDisplay(dpy);
3328dd3e0eeSmrg	SyncHandle();
3338dd3e0eeSmrg	return False;
3348dd3e0eeSmrg    }
3358dd3e0eeSmrg    UnlockDisplay(dpy);
3368dd3e0eeSmrg    SyncHandle();
3378dd3e0eeSmrg    return rep.result;
3388dd3e0eeSmrg}
3398dd3e0eeSmrg
3408dd3e0eeSmrg
3418dd3e0eeSmrg
3428dd3e0eeSmrg/* Helper functions */
3438dd3e0eeSmrg
3448dd3e0eeSmrg#include <X11/Xmd.h>
3458dd3e0eeSmrg#include <X11/extensions/xf86dga.h>
3468dd3e0eeSmrg#include <stdlib.h>
3478dd3e0eeSmrg#include <stdio.h>
3488dd3e0eeSmrg#include <fcntl.h>
3498dd3e0eeSmrg#if defined(ISC)
3508dd3e0eeSmrg# define HAS_SVR3_MMAP
3518dd3e0eeSmrg# include <sys/types.h>
3528dd3e0eeSmrg# include <errno.h>
3538dd3e0eeSmrg
3548dd3e0eeSmrg# include <sys/at_ansi.h>
3558dd3e0eeSmrg# include <sys/kd.h>
3568dd3e0eeSmrg
3578dd3e0eeSmrg# include <sys/sysmacros.h>
3588dd3e0eeSmrg# include <sys/immu.h>
3598dd3e0eeSmrg# include <sys/region.h>
3608dd3e0eeSmrg
3618dd3e0eeSmrg# include <sys/mmap.h>
3628dd3e0eeSmrg#else
3638dd3e0eeSmrg# if defined(Lynx) && defined(NO_MMAP)
3648dd3e0eeSmrg#  include <sys/types.h>
3658dd3e0eeSmrg#  include <errno.h>
3668dd3e0eeSmrg#  include <smem.h>
3678dd3e0eeSmrg# else
3688dd3e0eeSmrg#  if !defined(__UNIXOS2__)
3698dd3e0eeSmrg#   include <sys/mman.h>
3708dd3e0eeSmrg#  endif
3718dd3e0eeSmrg# endif
3728dd3e0eeSmrg#endif
3738dd3e0eeSmrg#include <sys/wait.h>
3748dd3e0eeSmrg#include <signal.h>
3758dd3e0eeSmrg#include <unistd.h>
3768dd3e0eeSmrg
3778dd3e0eeSmrg#if defined(SVR4) && !defined(sun)
3788dd3e0eeSmrg#define DEV_MEM "/dev/pmem"
3798dd3e0eeSmrg#elif defined(SVR4) && defined(sun)
3808dd3e0eeSmrg#define DEV_MEM "/dev/xsvc"
3818dd3e0eeSmrg#elif defined(HAS_APERTURE_DRV)
3828dd3e0eeSmrg#define DEV_MEM "/dev/xf86"
3838dd3e0eeSmrg#else
3848dd3e0eeSmrg#define DEV_MEM "/dev/mem"
3858dd3e0eeSmrg#endif
3868dd3e0eeSmrg
3878dd3e0eeSmrgtypedef struct {
3888dd3e0eeSmrg    unsigned long physaddr;	/* actual requested physical address */
3898dd3e0eeSmrg    unsigned long size;		/* actual requested map size */
3908dd3e0eeSmrg    unsigned long delta;	/* delta to account for page alignment */
3918dd3e0eeSmrg    void *	  vaddr;	/* mapped address, without the delta */
3928dd3e0eeSmrg    int		  refcount;	/* reference count */
3938dd3e0eeSmrg} MapRec, *MapPtr;
3948dd3e0eeSmrg
3958dd3e0eeSmrgtypedef struct {
3968dd3e0eeSmrg    Display *	display;
3978dd3e0eeSmrg    int		screen;
3988dd3e0eeSmrg    MapPtr	map;
3998dd3e0eeSmrg} ScrRec, *ScrPtr;
4008dd3e0eeSmrg
4018dd3e0eeSmrgstatic int mapFd = -1;
4028dd3e0eeSmrgstatic int numMaps = 0;
4038dd3e0eeSmrgstatic int numScrs = 0;
4048dd3e0eeSmrgstatic MapPtr *mapList = NULL;
4058dd3e0eeSmrgstatic ScrPtr *scrList = NULL;
4068dd3e0eeSmrg
4078dd3e0eeSmrgstatic MapPtr
4088dd3e0eeSmrgAddMap(void)
4098dd3e0eeSmrg{
4108dd3e0eeSmrg    MapPtr *old;
4118dd3e0eeSmrg
4128dd3e0eeSmrg    old = mapList;
4138dd3e0eeSmrg    mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1));
4148dd3e0eeSmrg    if (!mapList) {
4158dd3e0eeSmrg	mapList = old;
4168dd3e0eeSmrg	return NULL;
4178dd3e0eeSmrg    }
4188dd3e0eeSmrg    mapList[numMaps] = malloc(sizeof(MapRec));
4198dd3e0eeSmrg    if (!mapList[numMaps])
4208dd3e0eeSmrg	return NULL;
4218dd3e0eeSmrg    return mapList[numMaps++];
4228dd3e0eeSmrg}
4238dd3e0eeSmrg
4248dd3e0eeSmrgstatic ScrPtr
4258dd3e0eeSmrgAddScr(void)
4268dd3e0eeSmrg{
4278dd3e0eeSmrg    ScrPtr *old;
4288dd3e0eeSmrg
4298dd3e0eeSmrg    old = scrList;
4308dd3e0eeSmrg    scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1));
4318dd3e0eeSmrg    if (!scrList) {
4328dd3e0eeSmrg	scrList = old;
4338dd3e0eeSmrg	return NULL;
4348dd3e0eeSmrg    }
4358dd3e0eeSmrg    scrList[numScrs] = malloc(sizeof(ScrRec));
4368dd3e0eeSmrg    if (!scrList[numScrs])
4378dd3e0eeSmrg	return NULL;
4388dd3e0eeSmrg    return scrList[numScrs++];
4398dd3e0eeSmrg}
4408dd3e0eeSmrg
4418dd3e0eeSmrgstatic MapPtr
4428dd3e0eeSmrgFindMap(unsigned long address, unsigned long size)
4438dd3e0eeSmrg{
4448dd3e0eeSmrg    int i;
4458dd3e0eeSmrg
4468dd3e0eeSmrg    for (i = 0; i < numMaps; i++) {
4478dd3e0eeSmrg	if (mapList[i]->physaddr == address &&
4488dd3e0eeSmrg	    mapList[i]->size == size)
4498dd3e0eeSmrg	    return mapList[i];
4508dd3e0eeSmrg    }
4518dd3e0eeSmrg    return NULL;
4528dd3e0eeSmrg}
4538dd3e0eeSmrg
4548dd3e0eeSmrgstatic ScrPtr
4558dd3e0eeSmrgFindScr(Display *display, int screen)
4568dd3e0eeSmrg{
4578dd3e0eeSmrg    int i;
4588dd3e0eeSmrg
4598dd3e0eeSmrg    for (i = 0; i < numScrs; i++) {
4608dd3e0eeSmrg	if (scrList[i]->display == display &&
4618dd3e0eeSmrg	    scrList[i]->screen == screen)
4628dd3e0eeSmrg	    return scrList[i];
4638dd3e0eeSmrg    }
4648dd3e0eeSmrg    return NULL;
4658dd3e0eeSmrg}
4668dd3e0eeSmrg
4678dd3e0eeSmrgstatic void *
4688dd3e0eeSmrgMapPhysAddress(unsigned long address, unsigned long size)
4698dd3e0eeSmrg{
4708dd3e0eeSmrg    unsigned long offset, delta;
4718dd3e0eeSmrg    int pagesize = -1;
4728dd3e0eeSmrg    void *vaddr;
4738dd3e0eeSmrg    MapPtr mp;
4748dd3e0eeSmrg#if defined(ISC) && defined(HAS_SVR3_MMAP)
4758dd3e0eeSmrg    struct kd_memloc mloc;
4768dd3e0eeSmrg#elif defined(__UNIXOS2__)
4778dd3e0eeSmrg    APIRET rc;
4788dd3e0eeSmrg    ULONG action;
4798dd3e0eeSmrg    HFILE hfd;
4808dd3e0eeSmrg#endif
4818dd3e0eeSmrg
4828dd3e0eeSmrg    if ((mp = FindMap(address, size))) {
4838dd3e0eeSmrg	mp->refcount++;
4848dd3e0eeSmrg	return (void *)((unsigned long)mp->vaddr + mp->delta);
4858dd3e0eeSmrg    }
4868dd3e0eeSmrg
4878dd3e0eeSmrg#if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE)
4888dd3e0eeSmrg    pagesize = sysconf(_SC_PAGESIZE);
4898dd3e0eeSmrg#endif
4908dd3e0eeSmrg#ifdef _SC_PAGE_SIZE
4918dd3e0eeSmrg    if (pagesize == -1)
4928dd3e0eeSmrg	pagesize = sysconf(_SC_PAGE_SIZE);
4938dd3e0eeSmrg#endif
4948dd3e0eeSmrg#ifdef HAS_GETPAGESIZE
4958dd3e0eeSmrg    if (pagesize == -1)
4968dd3e0eeSmrg	pagesize = getpagesize();
4978dd3e0eeSmrg#endif
4988dd3e0eeSmrg#ifdef PAGE_SIZE
4998dd3e0eeSmrg    if (pagesize == -1)
5008dd3e0eeSmrg	pagesize = PAGE_SIZE;
5018dd3e0eeSmrg#endif
5028dd3e0eeSmrg    if (pagesize == -1)
5038dd3e0eeSmrg	pagesize = 4096;
5048dd3e0eeSmrg
5058dd3e0eeSmrg   delta = address % pagesize;
5068dd3e0eeSmrg   offset = address - delta;
5078dd3e0eeSmrg
5088dd3e0eeSmrg#if defined(ISC) && defined(HAS_SVR3_MMAP)
5098dd3e0eeSmrg    if (mapFd < 0) {
5108dd3e0eeSmrg	if ((mapFd = open("/dev/mmap", O_RDWR)) < 0)
5118dd3e0eeSmrg	    return NULL;
5128dd3e0eeSmrg    }
5138dd3e0eeSmrg    mloc.vaddr = (char *)0;
5148dd3e0eeSmrg    mloc.physaddr = (char *)offset;
5158dd3e0eeSmrg    mloc.length = size + delta;
5168dd3e0eeSmrg    mloc.ioflg=1;
5178dd3e0eeSmrg
5188dd3e0eeSmrg    if ((vaddr = (void *)ioctl(mapFd, MAP, &mloc)) == (void *)-1)
5198dd3e0eeSmrg	return NULL;
5208dd3e0eeSmrg#elif defined (__UNIXOS2__)
5218dd3e0eeSmrg    /*
5228dd3e0eeSmrg     * Dragon warning here! /dev/pmap$ is never closed, except on progam exit.
5238dd3e0eeSmrg     * Consecutive calling of this routine will make PMAP$ driver run out
5248dd3e0eeSmrg     * of memory handles. Some umap/close mechanism should be provided
5258dd3e0eeSmrg     */
5268dd3e0eeSmrg
5278dd3e0eeSmrg    rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN,
5288dd3e0eeSmrg		 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL);
5298dd3e0eeSmrg    if (rc != 0)
5308dd3e0eeSmrg	return NULL;
5318dd3e0eeSmrg    {
5328dd3e0eeSmrg	struct map_ioctl {
5338dd3e0eeSmrg		union {
5348dd3e0eeSmrg			ULONG phys;
5358dd3e0eeSmrg			void* user;
5368dd3e0eeSmrg		} a;
5378dd3e0eeSmrg		ULONG size;
5388dd3e0eeSmrg	} pmap,dmap;
5398dd3e0eeSmrg	ULONG plen,dlen;
5408dd3e0eeSmrg#define XFREE86_PMAP	0x76
5418dd3e0eeSmrg#define PMAP_MAP	0x44
5428dd3e0eeSmrg
5438dd3e0eeSmrg	pmap.a.phys = offset;
5448dd3e0eeSmrg	pmap.size = size + delta;
5458dd3e0eeSmrg	rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP,
5468dd3e0eeSmrg			 (PULONG)&pmap, sizeof(pmap), &plen,
5478dd3e0eeSmrg			 (PULONG)&dmap, sizeof(dmap), &dlen);
5488dd3e0eeSmrg	if (rc == 0) {
5498dd3e0eeSmrg		vaddr = dmap.a.user;
5508dd3e0eeSmrg	}
5518dd3e0eeSmrg   }
5528dd3e0eeSmrg   if (rc != 0)
5538dd3e0eeSmrg	return NULL;
5548dd3e0eeSmrg#elif defined(Lynx) && defined(NO_MMAP)
5558dd3e0eeSmrg    vaddr = (void *)smem_create("XF86DGA", (char *)offset,
5568dd3e0eeSmrg				size + delta, SM_READ|SM_WRITE);
5578dd3e0eeSmrg#else
5588dd3e0eeSmrg#ifndef MAP_FILE
5598dd3e0eeSmrg#define MAP_FILE 0
5608dd3e0eeSmrg#endif
5618dd3e0eeSmrg    if (mapFd < 0) {
5628dd3e0eeSmrg	if ((mapFd = open(DEV_MEM, O_RDWR)) < 0)
5638dd3e0eeSmrg	    return NULL;
5648dd3e0eeSmrg    }
5658dd3e0eeSmrg    vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE,
5668dd3e0eeSmrg                        MAP_FILE | MAP_SHARED, mapFd, (off_t)offset);
5678dd3e0eeSmrg    if (vaddr == (void *)-1)
5688dd3e0eeSmrg	return NULL;
5698dd3e0eeSmrg#endif
5708dd3e0eeSmrg
5718dd3e0eeSmrg    if (!vaddr) {
5728dd3e0eeSmrg	if (!(mp = AddMap()))
5738dd3e0eeSmrg	    return NULL;
5748dd3e0eeSmrg	mp->physaddr = address;
5758dd3e0eeSmrg	mp->size = size;
5768dd3e0eeSmrg	mp->delta = delta;
5778dd3e0eeSmrg	mp->vaddr = vaddr;
5788dd3e0eeSmrg	mp->refcount = 1;
5798dd3e0eeSmrg    }
5808dd3e0eeSmrg    return (void *)((unsigned long)vaddr + delta);
5818dd3e0eeSmrg}
5828dd3e0eeSmrg
5838dd3e0eeSmrg/*
5848dd3e0eeSmrg * Still need to find a clean way of detecting the death of a DGA app
5858dd3e0eeSmrg * and returning things to normal - Jon
5868dd3e0eeSmrg * This is here to help debugging without rebooting... Also C-A-BS
5878dd3e0eeSmrg * should restore text mode.
5888dd3e0eeSmrg */
5898dd3e0eeSmrg
5908dd3e0eeSmrgint
5918dd3e0eeSmrgXF86DGAForkApp(int screen)
5928dd3e0eeSmrg{
5938dd3e0eeSmrg    pid_t pid;
5948dd3e0eeSmrg    int status;
5958dd3e0eeSmrg    int i;
5968dd3e0eeSmrg
5978dd3e0eeSmrg     /* fork the app, parent hangs around to clean up */
5988dd3e0eeSmrg    if ((pid = fork()) > 0) {
5998dd3e0eeSmrg	ScrPtr sp;
6008dd3e0eeSmrg
6018dd3e0eeSmrg	waitpid(pid, &status, 0);
6028dd3e0eeSmrg	for (i = 0; i < numScrs; i++) {
6038dd3e0eeSmrg	    sp = scrList[i];
6048dd3e0eeSmrg	    XF86DGADirectVideoLL(sp->display, sp->screen, 0);
6058dd3e0eeSmrg	    XSync(sp->display, False);
6068dd3e0eeSmrg	}
6078dd3e0eeSmrg        if (WIFEXITED(status))
6088dd3e0eeSmrg	    _exit(0);
6098dd3e0eeSmrg	else
6108dd3e0eeSmrg	    _exit(-1);
6118dd3e0eeSmrg    }
6128dd3e0eeSmrg    return pid;
6138dd3e0eeSmrg}
6148dd3e0eeSmrg
6158dd3e0eeSmrg
6168dd3e0eeSmrgBool
6178dd3e0eeSmrgXF86DGADirectVideo(
6188dd3e0eeSmrg    Display *dis,
6198dd3e0eeSmrg    int screen,
6208dd3e0eeSmrg    int enable
6218dd3e0eeSmrg){
6228dd3e0eeSmrg    ScrPtr sp;
6238dd3e0eeSmrg    MapPtr mp = NULL;
6248dd3e0eeSmrg
6258dd3e0eeSmrg    if ((sp = FindScr(dis, screen)))
6268dd3e0eeSmrg	mp = sp->map;
6278dd3e0eeSmrg
6288dd3e0eeSmrg    if (enable & XF86DGADirectGraphics) {
6298dd3e0eeSmrg#if !defined(ISC) && !defined(HAS_SVR3_MMAP) \
6308dd3e0eeSmrg	&& !(defined(Lynx) && defined(NO_MMAP)) \
6318dd3e0eeSmrg	&& !defined(__UNIXOS2__)
6328dd3e0eeSmrg	if (mp && mp->vaddr)
6338dd3e0eeSmrg	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE);
6348dd3e0eeSmrg#endif
6358dd3e0eeSmrg    } else {
6368dd3e0eeSmrg#if !defined(ISC) && !defined(HAS_SVR3_MMAP) \
6378dd3e0eeSmrg	&& !(defined(Lynx) && defined(NO_MMAP)) \
6388dd3e0eeSmrg	&& !defined(__UNIXOS2__)
6398dd3e0eeSmrg	if (mp && mp->vaddr)
6408dd3e0eeSmrg	    mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ);
6418dd3e0eeSmrg#elif defined(Lynx) && defined(NO_MMAP)
6428dd3e0eeSmrg	/* XXX this doesn't allow enable after disable */
6438dd3e0eeSmrg	smem_create(NULL, mp->vaddr, mp->size + mp->delta, SM_DETACH);
6448dd3e0eeSmrg	smem_remove("XF86DGA");
6458dd3e0eeSmrg#endif
6468dd3e0eeSmrg    }
6478dd3e0eeSmrg
6488dd3e0eeSmrg    XF86DGADirectVideoLL(dis, screen, enable);
6498dd3e0eeSmrg    return 1;
6508dd3e0eeSmrg}
6518dd3e0eeSmrg
6528dd3e0eeSmrg
6538dd3e0eeSmrgstatic void
6548dd3e0eeSmrgXF86cleanup(int sig)
6558dd3e0eeSmrg{
6568dd3e0eeSmrg    ScrPtr sp;
6578dd3e0eeSmrg    int i;
6588dd3e0eeSmrg    static char beenhere = 0;
6598dd3e0eeSmrg
6608dd3e0eeSmrg    if (beenhere)
6618dd3e0eeSmrg	_exit(3);
6628dd3e0eeSmrg    beenhere = 1;
6638dd3e0eeSmrg
6648dd3e0eeSmrg    for (i = 0; i < numScrs; i++) {
6658dd3e0eeSmrg	sp = scrList[i];
6668dd3e0eeSmrg	XF86DGADirectVideo(sp->display, sp->screen, 0);
6678dd3e0eeSmrg	XSync(sp->display, False);
6688dd3e0eeSmrg    }
6698dd3e0eeSmrg    _exit(3);
6708dd3e0eeSmrg}
6718dd3e0eeSmrg
6728dd3e0eeSmrgBool
6738dd3e0eeSmrgXF86DGAGetVideo(
6748dd3e0eeSmrg    Display *dis,
6758dd3e0eeSmrg    int screen,
6768dd3e0eeSmrg    char **addr,
6778dd3e0eeSmrg    int *width,
6788dd3e0eeSmrg    int *bank,
6798dd3e0eeSmrg    int *ram
6808dd3e0eeSmrg){
6818dd3e0eeSmrg    unsigned int offset;
6828dd3e0eeSmrg    static int beenHere = 0;
6838dd3e0eeSmrg    ScrPtr sp;
6848dd3e0eeSmrg    MapPtr mp;
6858dd3e0eeSmrg
6868dd3e0eeSmrg    if (!(sp = FindScr(dis, screen))) {
6878dd3e0eeSmrg	if (!(sp = AddScr())) {
6888dd3e0eeSmrg	    fprintf(stderr, "XF86DGAGetVideo: malloc failure\n");
6898dd3e0eeSmrg	    exit(-2);
6908dd3e0eeSmrg	}
6918dd3e0eeSmrg	sp->display = dis;
6928dd3e0eeSmrg	sp->screen = screen;
6938dd3e0eeSmrg	sp->map = NULL;
6948dd3e0eeSmrg    }
6958dd3e0eeSmrg
6968dd3e0eeSmrg    XF86DGAGetVideoLL(dis, screen , &offset, width, bank, ram);
6978dd3e0eeSmrg
6988dd3e0eeSmrg    *addr = MapPhysAddress(offset, *bank);
6998dd3e0eeSmrg    if (*addr == NULL) {
7008dd3e0eeSmrg	fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n",
7018dd3e0eeSmrg		strerror(errno));
7028dd3e0eeSmrg	exit(-2);
7038dd3e0eeSmrg    }
7048dd3e0eeSmrg
7058dd3e0eeSmrg    if ((mp = FindMap(offset, *bank)))
7068dd3e0eeSmrg	sp->map = mp;
7078dd3e0eeSmrg
7088dd3e0eeSmrg    if (!beenHere) {
7098dd3e0eeSmrg	beenHere = 1;
7108dd3e0eeSmrg	atexit((void(*)(void))XF86cleanup);
7118dd3e0eeSmrg	/* one shot XF86cleanup attempts */
7128dd3e0eeSmrg	signal(SIGSEGV, XF86cleanup);
7138dd3e0eeSmrg#ifdef SIGBUS
7148dd3e0eeSmrg	signal(SIGBUS, XF86cleanup);
7158dd3e0eeSmrg#endif
7168dd3e0eeSmrg	signal(SIGHUP, XF86cleanup);
7178dd3e0eeSmrg	signal(SIGFPE, XF86cleanup);
7188dd3e0eeSmrg    }
7198dd3e0eeSmrg
7208dd3e0eeSmrg    return 1;
7218dd3e0eeSmrg}
7228dd3e0eeSmrg
723