summaryrefslogtreecommitdiff
path: root/src/XF86DGA.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:49 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:49 +0000
commitca572cb2f331b374c246b4435f5aeb036392e16f (patch)
tree674ffa9b790828cb9951585a75881df6ea6dfbe3 /src/XF86DGA.c
Initial revisionXORG-STABLE
Diffstat (limited to 'src/XF86DGA.c')
-rw-r--r--src/XF86DGA.c718
1 files changed, 718 insertions, 0 deletions
diff --git a/src/XF86DGA.c b/src/XF86DGA.c
new file mode 100644
index 0000000..ceff6b3
--- /dev/null
+++ b/src/XF86DGA.c
@@ -0,0 +1,718 @@
+/* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.22 2002/12/14 04:41:12 dawes 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
+#include <os2.h>
+#endif
+
+#if defined(linux)
+#define HAS_MMAP_ANON
+#include <sys/types.h>
+#include <sys/mman.h>
+#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,
+ 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 = /*(char *)*/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) && !defined(SCO325)
+#define DEV_MEM "/dev/pmem"
+#elif defined(SVR4) && defined(sun)
+#define DEV_MEM "/dev/xsvc"
+#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 long*/ 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;
+}
+