view src/video/Xext/Xxf86dga/XF86DGA2.c @ 1721:1cc762cafff8 SDL-1.3

Fixed indenting in MSVC inline assembly
author Sam Lantinga <slouken@libsdl.org>
date Fri, 30 Jun 2006 05:50:35 +0000
parents 4da1ee79c9af
children
line wrap: on
line source

/* $XFree86: xc/lib/Xxf86dga/XF86DGA2.c,v 1.18 2001/08/17 13:27:51 dawes Exp $ */
/*

Copyright (c) 1995  Jon Tombs
Copyright (c) 1995,1996  The XFree86 Project, Inc

*/

/* THIS IS NOT AN X CONSORTIUM STANDARD */

#ifdef __EMX__                  /* needed here to override certain constants in X headers */
#define INCL_DOS
#define INCL_DOSIOCTL
#include <os2.h>
#endif

#define NEED_EVENTS
#define NEED_REPLIES

#include <X11/Xlibint.h>
#include "../extensions/xf86dga.h"
#include "../extensions/xf86dgastr.h"
#include "../extensions/Xext.h"
#include "../extensions/extutil.h"
#include <stdio.h>

#if defined(ENABLE_FBCON)       /* Needed for framebuffer console support */
#include <sys/ioctl.h>
#include <linux/fb.h>
#endif

/* If you change this, change the Bases[] array below as well */
#define MAX_HEADS 16

char *SDL_NAME(xdga_extension_name) = XF86DGANAME;

static XExtensionInfo _xdga_info_data;
static XExtensionInfo *xdga_info = &_xdga_info_data;


Bool SDL_NAME(XDGAMapFramebuffer) (int, char *, unsigned char *, CARD32,
                                   CARD32, CARD32);
void SDL_NAME(XDGAUnmapFramebuffer) (int);
unsigned char *SDL_NAME(XDGAGetMappedMemory) (int);

#define XDGACheckExtension(dpy,i,val) \
  XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val)

/*****************************************************************************
 *                                                                           *
 *			   private utility routines                          *
 *                                                                           *
 *****************************************************************************/

static int xdga_close_display(Display * dpy, XExtCodes * codes);
static Bool xdga_wire_to_event(Display * dpy, XEvent * event,
                               xEvent * wire_ev);
static Status xdga_event_to_wire(Display * dpy, XEvent * event,
                                 xEvent * wire_ev);

static XExtensionHooks xdga_extension_hooks = {
    NULL,                       /* create_gc */
    NULL,                       /* copy_gc */
    NULL,                       /* flush_gc */
    NULL,                       /* free_gc */
    NULL,                       /* create_font */
    NULL,                       /* free_font */
    xdga_close_display,         /* close_display */
    xdga_wire_to_event,         /* wire_to_event */
    xdga_event_to_wire,         /* event_to_wire */
    NULL,                       /* error */
    NULL,                       /* error_string */
};

static
XEXT_GENERATE_CLOSE_DISPLAY(xdga_close_display, xdga_info)
XEXT_GENERATE_FIND_DISPLAY(SDL_NAME(xdga_find_display), xdga_info,
                           "XFree86-DGA", &xdga_extension_hooks, 0, NULL)
     static Status
         xdga_event_to_wire(Display * dpy, XEvent * event, xEvent * wire_ev)
{
    return True;
}

static Bool
xdga_wire_to_event(Display * dpy, XEvent * event, xEvent * wire_ev)
{
    dgaEvent *wire = (dgaEvent *) wire_ev;
    SDL_NAME(XDGAButtonEvent) * bevent;
    SDL_NAME(XDGAKeyEvent) * kevent;
    SDL_NAME(XDGAMotionEvent) * mevent;
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);

    XDGACheckExtension(dpy, info, False);

    switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
    case MotionNotify:
        mevent = (SDL_NAME(XDGAMotionEvent) *) event;
        mevent->type = wire->u.u.type & 0x7F;
        mevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
        mevent->display = dpy;
        mevent->screen = wire->u.event.screen;
        mevent->time = wire->u.event.time;
        mevent->state = wire->u.event.state;
        mevent->dx = wire->u.event.dx;
        mevent->dy = wire->u.event.dy;
        return True;
    case ButtonPress:
    case ButtonRelease:
        bevent = (SDL_NAME(XDGAButtonEvent) *) event;
        bevent->type = wire->u.u.type & 0x7F;
        bevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
        bevent->display = dpy;
        bevent->screen = wire->u.event.screen;
        bevent->time = wire->u.event.time;
        bevent->state = wire->u.event.state;
        bevent->button = wire->u.u.detail;
        return True;
    case KeyPress:
    case KeyRelease:
        kevent = (SDL_NAME(XDGAKeyEvent) *) event;
        kevent->type = wire->u.u.type & 0x7F;
        kevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
        kevent->display = dpy;
        kevent->screen = wire->u.event.screen;
        kevent->time = wire->u.event.time;
        kevent->state = wire->u.event.state;
        kevent->keycode = wire->u.u.detail;
        return True;
    }

    return False;
}


Bool SDL_NAME(XDGAQueryExtension) (Display * dpy,
                                   int *event_basep, int *error_basep)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);

    if (XextHasExtension(info)) {
        *event_basep = info->codes->first_event;
        *error_basep = info->codes->first_error;
        return True;
    } else {
        return False;
    }
}


Bool SDL_NAME(XDGAQueryVersion) (Display * dpy,
                                 int *majorVersion, int *minorVersion)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAQueryVersionReply rep;
    xXDGAQueryVersionReq *req;

    XDGACheckExtension(dpy, info, False);

    LockDisplay(dpy);
    GetReq(XDGAQueryVersion, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAQueryVersion;
    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }
    *majorVersion = rep.majorVersion;
    *minorVersion = rep.minorVersion;
    UnlockDisplay(dpy);
    SyncHandle();
    if (*majorVersion >= 2) {
        int i, j;

        for (i = 0, j = info->codes->first_event;
             i < XF86DGANumberEvents; i++, j++) {
            XESetWireToEvent(dpy, j, xdga_wire_to_event);
            XESetEventToWire(dpy, j, xdga_event_to_wire);
        }
        SDL_NAME(XDGASetClientVersion) (dpy);
    }
    return True;
}

Bool SDL_NAME(XDGASetClientVersion) (Display * dpy)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGASetClientVersionReq *req;

    XDGACheckExtension(dpy, info, False);

    LockDisplay(dpy);
    GetReq(XDGASetClientVersion, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGASetClientVersion;
    req->major = XDGA_MAJOR_VERSION;
    req->minor = XDGA_MINOR_VERSION;
    UnlockDisplay(dpy);
    SyncHandle();
    return True;
}

Bool SDL_NAME(XDGAOpenFramebuffer) (Display * dpy, int screen)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAOpenFramebufferReply rep;
    xXDGAOpenFramebufferReq *req;
    char *deviceName = NULL;
    Bool ret;

    XDGACheckExtension(dpy, info, False);

    LockDisplay(dpy);
    GetReq(XDGAOpenFramebuffer, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAOpenFramebuffer;
    req->screen = screen;
    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return False;
    }

    if (rep.length) {
        deviceName = Xmalloc(rep.length << 2);
        _XRead(dpy, deviceName, rep.length << 2);
    }

    ret = SDL_NAME(XDGAMapFramebuffer) (screen, deviceName,
                                        (unsigned char *) (long) rep.mem1,
                                        rep.size, rep.offset, rep.extra);

    if (deviceName)
        Xfree(deviceName);

    UnlockDisplay(dpy);
    SyncHandle();
    return ret;
}

void SDL_NAME(XDGACloseFramebuffer) (Display * dpy, int screen)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGACloseFramebufferReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    SDL_NAME(XDGAUnmapFramebuffer) (screen);

    LockDisplay(dpy);
    GetReq(XDGACloseFramebuffer, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGACloseFramebuffer;
    req->screen = screen;
    UnlockDisplay(dpy);
    SyncHandle();
}



SDL_NAME(XDGAMode) * SDL_NAME(XDGAQueryModes) (Display * dpy,
                                               int screen, int *num)
{
    XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy);
    xXDGAQueryModesReply rep;
    xXDGAQueryModesReq *req;
    SDL_NAME(XDGAMode) * modes = NULL;

    *num = 0;

    XDGACheckExtension(dpy, dinfo, NULL);

    LockDisplay(dpy);
    GetReq(XDGAQueryModes, req);
    req->reqType = dinfo->codes->major_opcode;
    req->dgaReqType = X_XDGAQueryModes;
    req->screen = screen;

    if (_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
        if (rep.length) {
            xXDGAModeInfo info;
            int i, size;
            char *offset;

            size = rep.length << 2;
            size -= rep.number * sz_xXDGAModeInfo;      /* find text size */
            modes = (SDL_NAME(XDGAMode) *)
                Xmalloc((rep.number * sizeof(SDL_NAME(XDGAMode))) + size);
            offset = (char *) (&modes[rep.number]);     /* start of text */


            if (modes) {
                for (i = 0; i < rep.number; i++) {
                    _XRead(dpy, (char *) (&info), sz_xXDGAModeInfo);

                    modes[i].num = info.num;
                    modes[i].verticalRefresh =
                        (float) info.vsync_num / (float) info.vsync_den;
                    modes[i].flags = info.flags;
                    modes[i].imageWidth = info.image_width;
                    modes[i].imageHeight = info.image_height;
                    modes[i].pixmapWidth = info.pixmap_width;
                    modes[i].pixmapHeight = info.pixmap_height;
                    modes[i].bytesPerScanline = info.bytes_per_scanline;
                    modes[i].byteOrder = info.byte_order;
                    modes[i].depth = info.depth;
                    modes[i].bitsPerPixel = info.bpp;
                    modes[i].redMask = info.red_mask;
                    modes[i].greenMask = info.green_mask;
                    modes[i].blueMask = info.blue_mask;
                    modes[i].visualClass = info.visual_class;
                    modes[i].viewportWidth = info.viewport_width;
                    modes[i].viewportHeight = info.viewport_height;
                    modes[i].xViewportStep = info.viewport_xstep;
                    modes[i].yViewportStep = info.viewport_ystep;
                    modes[i].maxViewportX = info.viewport_xmax;
                    modes[i].maxViewportY = info.viewport_ymax;
                    modes[i].viewportFlags = info.viewport_flags;
                    modes[i].reserved1 = info.reserved1;
                    modes[i].reserved2 = info.reserved2;

                    _XRead(dpy, offset, info.name_size);
                    modes[i].name = offset;
                    offset += info.name_size;
                }
                *num = rep.number;
            } else
                _XEatData(dpy, rep.length << 2);
        }
    }

    UnlockDisplay(dpy);
    SyncHandle();

    return modes;
}


SDL_NAME(XDGADevice) *
SDL_NAME(XDGASetMode) (Display * dpy, int screen, int mode)
{
    XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy);
    xXDGASetModeReply rep;
    xXDGASetModeReq *req;
    SDL_NAME(XDGADevice) * dev = NULL;
    Pixmap pid;

    XDGACheckExtension(dpy, dinfo, NULL);

    LockDisplay(dpy);
    GetReq(XDGASetMode, req);
    req->reqType = dinfo->codes->major_opcode;
    req->dgaReqType = X_XDGASetMode;
    req->screen = screen;
    req->mode = mode;
    req->pid = pid = XAllocID(dpy);

    if (_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
        if (rep.length) {
            xXDGAModeInfo info;
            int size;

            size = rep.length << 2;
            size -= sz_xXDGAModeInfo;   /* get text size */

            dev = (SDL_NAME(XDGADevice) *)
                Xmalloc(sizeof(SDL_NAME(XDGADevice)) + size);

            if (dev) {
                _XRead(dpy, (char *) (&info), sz_xXDGAModeInfo);

                dev->mode.num = info.num;
                dev->mode.verticalRefresh =
                    (float) info.vsync_num / (float) info.vsync_den;
                dev->mode.flags = info.flags;
                dev->mode.imageWidth = info.image_width;
                dev->mode.imageHeight = info.image_height;
                dev->mode.pixmapWidth = info.pixmap_width;
                dev->mode.pixmapHeight = info.pixmap_height;
                dev->mode.bytesPerScanline = info.bytes_per_scanline;
                dev->mode.byteOrder = info.byte_order;
                dev->mode.depth = info.depth;
                dev->mode.bitsPerPixel = info.bpp;
                dev->mode.redMask = info.red_mask;
                dev->mode.greenMask = info.green_mask;
                dev->mode.blueMask = info.blue_mask;
                dev->mode.visualClass = info.visual_class;
                dev->mode.viewportWidth = info.viewport_width;
                dev->mode.viewportHeight = info.viewport_height;
                dev->mode.xViewportStep = info.viewport_xstep;
                dev->mode.yViewportStep = info.viewport_ystep;
                dev->mode.maxViewportX = info.viewport_xmax;
                dev->mode.maxViewportY = info.viewport_ymax;
                dev->mode.viewportFlags = info.viewport_flags;
                dev->mode.reserved1 = info.reserved1;
                dev->mode.reserved2 = info.reserved2;

                dev->mode.name = (char *) (&dev[1]);
                _XRead(dpy, dev->mode.name, info.name_size);

                dev->pixmap = (rep.flags & XDGAPixmap) ? pid : 0;
                dev->data = SDL_NAME(XDGAGetMappedMemory) (screen);

                if (dev->data)
                    dev->data += rep.offset;
            }
            /* not sure what to do if the allocation fails */
        }
    }

    UnlockDisplay(dpy);
    SyncHandle();

    return dev;
}


void SDL_NAME(XDGASetViewport) (Display * dpy,
                                int screen, int x, int y, int flags)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGASetViewportReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGASetViewport, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGASetViewport;
    req->screen = screen;
    req->x = x;
    req->y = y;
    req->flags = flags;
    UnlockDisplay(dpy);
    SyncHandle();
}


void SDL_NAME(XDGAInstallColormap) (Display * dpy, int screen, Colormap cmap)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAInstallColormapReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGAInstallColormap, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAInstallColormap;
    req->screen = screen;
    req->cmap = cmap;
    UnlockDisplay(dpy);
    SyncHandle();
}

void SDL_NAME(XDGASelectInput) (Display * dpy, int screen, long mask)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGASelectInputReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGASelectInput, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGASelectInput;
    req->screen = screen;
    req->mask = mask;
    UnlockDisplay(dpy);
    SyncHandle();
}

void SDL_NAME(XDGAFillRectangle) (Display * dpy,
                                  int screen,
                                  int x,
                                  int y,
                                  unsigned int width,
                                  unsigned int height, unsigned long color)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAFillRectangleReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGAFillRectangle, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAFillRectangle;
    req->screen = screen;
    req->x = x;
    req->y = y;
    req->width = width;
    req->height = height;
    req->color = color;
    UnlockDisplay(dpy);
    SyncHandle();
}

void SDL_NAME(XDGACopyArea) (Display * dpy,
                             int screen,
                             int srcx,
                             int srcy,
                             unsigned int width,
                             unsigned int height, int dstx, int dsty)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGACopyAreaReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGACopyArea, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGACopyArea;
    req->screen = screen;
    req->srcx = srcx;
    req->srcy = srcy;
    req->width = width;
    req->height = height;
    req->dstx = dstx;
    req->dsty = dsty;
    UnlockDisplay(dpy);
    SyncHandle();
}

void SDL_NAME(XDGACopyTransparentArea) (Display * dpy,
                                        int screen,
                                        int srcx,
                                        int srcy,
                                        unsigned int width,
                                        unsigned int height,
                                        int dstx, int dsty, unsigned long key)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGACopyTransparentAreaReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGACopyTransparentArea, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGACopyTransparentArea;
    req->screen = screen;
    req->srcx = srcx;
    req->srcy = srcy;
    req->width = width;
    req->height = height;
    req->dstx = dstx;
    req->dsty = dsty;
    req->key = key;
    UnlockDisplay(dpy);
    SyncHandle();
}


int SDL_NAME(XDGAGetViewportStatus) (Display * dpy, int screen)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAGetViewportStatusReply rep;
    xXDGAGetViewportStatusReq *req;
    int status = 0;

    XDGACheckExtension(dpy, info, 0);

    LockDisplay(dpy);
    GetReq(XDGAGetViewportStatus, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAGetViewportStatus;
    req->screen = screen;
    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse))
        status = rep.status;
    UnlockDisplay(dpy);
    SyncHandle();
    return status;
}

void SDL_NAME(XDGASync) (Display * dpy, int screen)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGASyncReply rep;
    xXDGASyncReq *req;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGASync, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGASync;
    req->screen = screen;
    _XReply(dpy, (xReply *) & rep, 0, xFalse);
    UnlockDisplay(dpy);
    SyncHandle();
}


void SDL_NAME(XDGAChangePixmapMode) (Display * dpy,
                                     int screen, int *x, int *y, int mode)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGAChangePixmapModeReq *req;
    xXDGAChangePixmapModeReply rep;

    XextSimpleCheckExtension(dpy, info, SDL_NAME(xdga_extension_name));

    LockDisplay(dpy);
    GetReq(XDGAChangePixmapMode, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGAChangePixmapMode;
    req->screen = screen;
    req->x = *x;
    req->y = *y;
    req->flags = mode;
    _XReply(dpy, (xReply *) & rep, 0, xFalse);
    *x = rep.x;
    *y = rep.y;
    UnlockDisplay(dpy);
    SyncHandle();
}

Colormap SDL_NAME(XDGACreateColormap) (Display * dpy,
                                       int screen,
                                       SDL_NAME(XDGADevice) * dev, int alloc)
{
    XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
    xXDGACreateColormapReq *req;
    Colormap cid;

    XDGACheckExtension(dpy, info, -1);

    LockDisplay(dpy);
    GetReq(XDGACreateColormap, req);
    req->reqType = info->codes->major_opcode;
    req->dgaReqType = X_XDGACreateColormap;
    req->screen = screen;
    req->mode = dev->mode.num;
    req->alloc = alloc;
    cid = req->id = XAllocID(dpy);
    UnlockDisplay(dpy);
    SyncHandle();

    return cid;
}


void SDL_NAME(XDGAKeyEventToXKeyEvent) (SDL_NAME(XDGAKeyEvent) * dk,
                                        XKeyEvent * xk)
{
    xk->type = dk->type;
    xk->serial = dk->serial;
    xk->send_event = False;
    xk->display = dk->display;
    xk->window = RootWindow(dk->display, dk->screen);
    xk->root = xk->window;
    xk->subwindow = None;
    xk->time = dk->time;
    xk->x = xk->y = xk->x_root = xk->y_root = 0;
    xk->state = dk->state;
    xk->keycode = dk->keycode;
    xk->same_screen = True;
}

#include <X11/Xmd.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)
#  if !defined(__EMX__)
#   include <sys/mman.h>
#  endif
# else
#  include <sys/types.h>
#  include <errno.h>
#  include <smem.h>
# 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 _DGAMapRec
{
    unsigned char *physical;
    unsigned char *virtual;
    CARD32 size;
    int fd;
    int screen;
    struct _DGAMapRec *next;
} DGAMapRec, *DGAMapPtr;

static Bool
DGAMapPhysical(int, char *, unsigned char *, CARD32, CARD32, CARD32,
               DGAMapPtr);
static void DGAUnmapPhysical(DGAMapPtr);

static DGAMapPtr _Maps = NULL;


unsigned char *SDL_NAME(XDGAGetMappedMemory) (int screen)
{
    DGAMapPtr pMap = _Maps;
    unsigned char *pntr = NULL;

    while (pMap != NULL) {
        if (pMap->screen == screen) {
            pntr = pMap->virtual;
            break;
        }
        pMap = pMap->next;
    }

    return pntr;
}

Bool SDL_NAME(XDGAMapFramebuffer) (int screen, char *name,      /* optional device name */
                                   unsigned char *base, /* physical memory */
                                   CARD32 size, /* size */
                                   CARD32 offset,       /* optional offset */
                                   CARD32 extra /* optional extra data */
    )
{
    DGAMapPtr pMap = _Maps;
    Bool result;

    /* is it already mapped ? */
    while (pMap != NULL) {
        if (pMap->screen == screen)
            return True;
        pMap = pMap->next;
    }

    if (extra & XDGANeedRoot) {
        /* we should probably check if we have root permissions and
           return False here */

    }

    pMap = (DGAMapPtr) Xmalloc(sizeof(DGAMapRec));

    result = DGAMapPhysical(screen, name, base, size, offset, extra, pMap);

    if (result) {
        pMap->next = _Maps;
        _Maps = pMap;
    } else
        Xfree(pMap);

    return result;
}

void SDL_NAME(XDGAUnmapFramebuffer) (int screen)
{
    DGAMapPtr pMap = _Maps;
    DGAMapPtr pPrev = NULL;

    /* is it already mapped */
    while (pMap != NULL) {
        if (pMap->screen == screen)
            break;
        pPrev = pMap;
        pMap = pMap->next;
    }

    if (!pMap)
        return;

    DGAUnmapPhysical(pMap);

    if (!pPrev)
        _Maps = pMap->next;
    else
        pPrev->next = pMap->next;

    Xfree(pMap);
}


static Bool
DGAMapPhysical(int screen, char *name,  /* optional device name */
               unsigned char *base,     /* physical memory */
               CARD32 size,     /* size */
               CARD32 offset,   /* optional offset */
               CARD32 extra,    /* optional extra data */
               DGAMapPtr pMap)
{
#if defined(ISC) && defined(HAS_SVR3_MMAP)
    struct kd_memloc mloc;
#elif defined(__EMX__)
    APIRET rc;
    ULONG action;
    HFILE hfd;
#endif

    base += offset;

    pMap->screen = screen;
    pMap->physical = base;
    pMap->size = size;

#if defined(ISC) && defined(HAS_SVR3_MMAP)
    if ((pMap->fd = open("/dev/mmap", O_RDWR)) < 0)
        return False;
    mloc.vaddr = (char *) 0;
    mloc.physaddr = (char *) base;
    mloc.length = size;
    mloc.ioflg = 1;

    if ((pMap->virtual = (void *) ioctl(pMap->fd, MAP, &mloc)) == (void *) -1)
        return False;
#elif defined (__EMX__)
    /*
     * 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 False;
    {
        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 = base;
        pmap.size = size;
        rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP,
                         (PULONG) & pmap, sizeof(pmap), &plen,
                         (PULONG) & dmap, sizeof(dmap), &dlen);
        if (rc == 0) {
            pMap->virtual = dmap.a.user;
        }
    }
    if (rc != 0)
        return False;
#elif defined (Lynx)
    pMap->virtual =
        smem_create("XF86DGA", (char *) base, size, SM_READ | SM_WRITE);
#else
#ifndef MAP_FILE
#define MAP_FILE 0
#endif
    if (!name)
        name = DEV_MEM;
    if ((pMap->fd = open(name, O_RDWR)) < 0)
#if defined(ENABLE_FBCON)
    {                           /* /dev/fb0 fallback added by Sam Lantinga <hercules@lokigames.com> */
        /* Try to fall back to /dev/fb on Linux - FIXME: verify the device */
        struct fb_fix_screeninfo finfo;

        if ((pMap->fd = open("/dev/fb0", O_RDWR)) < 0) {
            return False;
        }
        /* The useable framebuffer console memory may not be the whole
           framebuffer that X has access to. :-(
         */
        if (ioctl(pMap->fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
            close(pMap->fd);
            return False;
        }
        /* Warning: On PPC, the size and virtual need to be offset by:
           (((long)finfo.smem_start) -
           (((long)finfo.smem_start)&~(PAGE_SIZE-1)))
         */
        base = 0;
        size = pMap->size = finfo.smem_len;
    }
#else
        return False;
#endif
    pMap->virtual = mmap(NULL, size, PROT_READ | PROT_WRITE,
                         MAP_FILE | MAP_SHARED, pMap->fd, (off_t) base);
    if (pMap->virtual == (void *) -1)
        return False;
#endif

#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \
	&& !defined(__EMX__)
    mprotect(pMap->virtual, size, PROT_READ | PROT_WRITE);
#endif

    return True;
}



static void
DGAUnmapPhysical(DGAMapPtr pMap)
{
#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \
	&& !defined(__EMX__)
    mprotect(pMap->virtual, pMap->size, PROT_READ);
#elif defined(Lynx)
    /* XXX this doesn't allow enable after disable */
    smem_create(NULL, pMap->virtual, pMap->size, SM_DETACH);
    smem_remove("XF86DGA");
#endif


    /* We need to unmap and close too !!!!!!!!!! */
}

/* vi: set ts=4 sw=4 expandtab: */