XF86DGA2.c revision 329fdfe9
1/* $XFree86: xc/lib/Xxf86dga/XF86DGA2.c,v 1.23 2003/05/05 20:42:30 tsi Exp $ */
2/*
3
4Copyright (c) 1995  Jon Tombs
5Copyright (c) 1995,1996  The XFree86 Project, Inc
6
7*/
8
9/* THIS IS NOT AN X CONSORTIUM STANDARD */
10
11#ifdef __UNIXOS2__ /* needed here to override certain constants in X headers */
12#define INCL_DOS
13#define INCL_DOSIOCTL
14#define I_NEED_OS2_H
15#include <os2.h>
16#endif
17
18#define NEED_EVENTS
19#define NEED_REPLIES
20#include <X11/Xlibint.h>
21#include <X11/extensions/Xxf86dga.h>
22#include <X11/extensions/xf86dgaproto.h>
23#include <X11/extensions/Xext.h>
24#include <X11/extensions/extutil.h>
25#include <stdio.h>
26
27
28/* If you change this, change the Bases[] array below as well */
29#define MAX_HEADS 16
30
31char *xdga_extension_name = XF86DGANAME;
32
33static XExtensionInfo _xdga_info_data;
34static XExtensionInfo *xdga_info = &_xdga_info_data;
35
36
37Bool XDGAMapFramebuffer(int, char *, unsigned char*, CARD32, CARD32, CARD32);
38void XDGAUnmapFramebuffer(int);
39unsigned char* XDGAGetMappedMemory(int);
40
41#define XDGACheckExtension(dpy,i,val) \
42  XextCheckExtension (dpy, i, xdga_extension_name, val)
43
44/*****************************************************************************
45 *                                                                           *
46 *			   private utility routines                          *
47 *                                                                           *
48 *****************************************************************************/
49
50static int xdga_close_display(Display *dpy, XExtCodes *codes);
51static Bool xdga_wire_to_event(Display *dpy, XEvent *event, xEvent *wire_ev);
52static Status xdga_event_to_wire(Display *dpy, XEvent *event, xEvent *wire_ev);
53
54static XExtensionHooks xdga_extension_hooks = {
55    NULL,				/* create_gc */
56    NULL,				/* copy_gc */
57    NULL,				/* flush_gc */
58    NULL,				/* free_gc */
59    NULL,				/* create_font */
60    NULL,				/* free_font */
61    xdga_close_display,			/* close_display */
62    xdga_wire_to_event,			/* wire_to_event */
63    xdga_event_to_wire,			/* event_to_wire */
64    NULL,				/* error */
65    NULL,				/* error_string */
66};
67
68static XEXT_GENERATE_CLOSE_DISPLAY (xdga_close_display, xdga_info)
69
70
71XExtDisplayInfo* xdga_find_display(Display*);
72XEXT_GENERATE_FIND_DISPLAY (xdga_find_display, xdga_info,
73				   "XFree86-DGA",
74				   &xdga_extension_hooks,
75				   0, NULL)
76
77
78static Status
79xdga_event_to_wire(
80  Display *dpy,
81  XEvent *event,
82  xEvent *wire_ev
83){
84    return True;
85}
86
87static Bool
88xdga_wire_to_event(
89  Display *dpy,
90  XEvent *event,
91  xEvent *wire_ev
92){
93  dgaEvent *wire = (dgaEvent *) wire_ev;
94  XDGAButtonEvent *bevent;
95  XDGAKeyEvent *kevent;
96  XDGAMotionEvent *mevent;
97  XExtDisplayInfo *info = xdga_find_display (dpy);
98
99  XDGACheckExtension (dpy, info, False);
100
101  switch((wire->u.u.type & 0x7f) - info->codes->first_event) {
102  case MotionNotify:
103	mevent = (XDGAMotionEvent*)event;
104	mevent->type = wire->u.u.type & 0x7F;
105	mevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire);
106	mevent->display = dpy;
107	mevent->screen = wire->u.event.screen;
108	mevent->time = wire->u.event.time;
109	mevent->state = wire->u.event.state;
110	mevent->dx = wire->u.event.dx;
111	mevent->dy = wire->u.event.dy;
112	return True;
113  case ButtonPress:
114  case ButtonRelease:
115	bevent = (XDGAButtonEvent*)event;
116	bevent->type = wire->u.u.type & 0x7F;
117	bevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire);
118	bevent->display = dpy;
119	bevent->screen = wire->u.event.screen;
120	bevent->time = wire->u.event.time;
121	bevent->state = wire->u.event.state;
122	bevent->button = wire->u.u.detail;
123	return True;
124  case KeyPress:
125  case KeyRelease:
126	kevent = (XDGAKeyEvent*)event;
127	kevent->type = wire->u.u.type & 0x7F;
128	kevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire);
129	kevent->display = dpy;
130	kevent->screen = wire->u.event.screen;
131	kevent->time = wire->u.event.time;
132	kevent->state = wire->u.event.state;
133	kevent->keycode = wire->u.u.detail;
134	return True;
135  }
136
137  return False;
138}
139
140
141Bool XDGAQueryExtension (
142    Display *dpy,
143    int *event_basep,
144    int *error_basep
145){
146    XExtDisplayInfo *info = xdga_find_display (dpy);
147
148    if (XextHasExtension(info)) {
149	*event_basep = info->codes->first_event;
150	*error_basep = info->codes->first_error;
151	return True;
152    } else {
153	return False;
154    }
155}
156
157
158Bool XDGAQueryVersion(
159    Display *dpy,
160    int *majorVersion,
161    int *minorVersion
162){
163    XExtDisplayInfo *info = xdga_find_display (dpy);
164    xXDGAQueryVersionReply rep;
165    xXDGAQueryVersionReq *req;
166
167    XDGACheckExtension (dpy, info, False);
168
169    LockDisplay(dpy);
170    GetReq(XDGAQueryVersion, req);
171    req->reqType = info->codes->major_opcode;
172    req->dgaReqType = X_XDGAQueryVersion;
173    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
174	UnlockDisplay(dpy);
175	SyncHandle();
176	return False;
177    }
178    *majorVersion = rep.majorVersion;
179    *minorVersion = rep.minorVersion;
180    UnlockDisplay(dpy);
181    SyncHandle();
182    if (*majorVersion >= 2)
183    {
184	int i, j;
185
186	for (i = 0, j = info->codes->first_event;
187	     i < XF86DGANumberEvents;
188	     i++, j++)
189	{
190	    XESetWireToEvent (dpy, j, xdga_wire_to_event);
191	    XESetEventToWire (dpy, j, xdga_event_to_wire);
192	}
193	XDGASetClientVersion(dpy);
194    }
195    return True;
196}
197
198Bool XDGASetClientVersion(
199    Display	*dpy
200){
201    XExtDisplayInfo *info = xdga_find_display (dpy);
202    xXDGASetClientVersionReq *req;
203
204    XDGACheckExtension (dpy, info, False);
205
206    LockDisplay(dpy);
207    GetReq(XDGASetClientVersion, req);
208    req->reqType = info->codes->major_opcode;
209    req->dgaReqType = X_XDGASetClientVersion;
210    req->major = XDGA_MAJOR_VERSION;
211    req->minor = XDGA_MINOR_VERSION;
212    UnlockDisplay(dpy);
213    SyncHandle();
214    return True;
215}
216
217Bool XDGAOpenFramebuffer(
218    Display	*dpy,
219    int 	screen
220){
221    XExtDisplayInfo *info = xdga_find_display (dpy);
222    xXDGAOpenFramebufferReply rep;
223    xXDGAOpenFramebufferReq *req;
224    char *deviceName = NULL;
225    Bool ret;
226
227    XDGACheckExtension (dpy, info, False);
228
229    LockDisplay(dpy);
230    GetReq(XDGAOpenFramebuffer, req);
231    req->reqType = info->codes->major_opcode;
232    req->dgaReqType = X_XDGAOpenFramebuffer;
233    req->screen = screen;
234    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
235	UnlockDisplay(dpy);
236	SyncHandle();
237	return False;
238    }
239
240    if(rep.length) {
241	deviceName = Xmalloc(rep.length << 2);
242	_XRead(dpy, deviceName, rep.length << 2);
243    }
244
245    ret = XDGAMapFramebuffer(screen, deviceName,
246				(unsigned char*)(long)rep.mem1,
247				rep.size, rep.offset, rep.extra);
248
249    if(deviceName)
250	Xfree(deviceName);
251
252    UnlockDisplay(dpy);
253    SyncHandle();
254    return ret;
255}
256
257void XDGACloseFramebuffer(
258    Display	*dpy,
259    int		screen
260){
261    XExtDisplayInfo *info = xdga_find_display (dpy);
262    xXDGACloseFramebufferReq *req;
263
264    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
265
266    XDGAUnmapFramebuffer(screen);
267
268    LockDisplay(dpy);
269    GetReq(XDGACloseFramebuffer, req);
270    req->reqType = info->codes->major_opcode;
271    req->dgaReqType = X_XDGACloseFramebuffer;
272    req->screen = screen;
273    UnlockDisplay(dpy);
274    SyncHandle();
275}
276
277
278
279XDGAMode* XDGAQueryModes(
280    Display *dpy,
281    int screen,
282    int *num
283){
284    XExtDisplayInfo *dinfo = xdga_find_display (dpy);
285    xXDGAQueryModesReply rep;
286    xXDGAQueryModesReq *req;
287    XDGAMode *modes = NULL;
288
289    *num = 0;
290
291    XDGACheckExtension (dpy, dinfo, NULL);
292
293    LockDisplay(dpy);
294    GetReq(XDGAQueryModes, req);
295    req->reqType = dinfo->codes->major_opcode;
296    req->dgaReqType = X_XDGAQueryModes;
297    req->screen = screen;
298
299    if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
300	if(rep.length) {
301	   xXDGAModeInfo info;
302	   int i, size;
303	   char *offset;
304
305	   size = rep.length << 2;
306	   size -= rep.number * sz_xXDGAModeInfo; /* find text size */
307	   modes = (XDGAMode*)Xmalloc((rep.number * sizeof(XDGAMode)) + size);
308	   offset = (char*)(&modes[rep.number]); /* start of text */
309
310
311	   if(modes) {
312	      for(i = 0; i < rep.number; i++) {
313		_XRead(dpy, (char*)(&info), sz_xXDGAModeInfo);
314
315		modes[i].num = info.num;
316		modes[i].verticalRefresh =
317			(float)info.vsync_num / (float)info.vsync_den;
318		modes[i].flags = info.flags;
319		modes[i].imageWidth = info.image_width;
320		modes[i].imageHeight = info.image_height;
321		modes[i].pixmapWidth = info.pixmap_width;
322		modes[i].pixmapHeight = info.pixmap_height;
323		modes[i].bytesPerScanline = info.bytes_per_scanline;
324		modes[i].byteOrder = info.byte_order;
325		modes[i].depth = info.depth;
326		modes[i].bitsPerPixel = info.bpp;
327		modes[i].redMask = info.red_mask;
328		modes[i].greenMask = info.green_mask;
329		modes[i].blueMask = info.blue_mask;
330		modes[i].visualClass = info.visual_class;
331		modes[i].viewportWidth = info.viewport_width;
332		modes[i].viewportHeight = info.viewport_height;
333		modes[i].xViewportStep = info.viewport_xstep;
334		modes[i].yViewportStep = info.viewport_ystep;
335		modes[i].maxViewportX = info.viewport_xmax;
336		modes[i].maxViewportY = info.viewport_ymax;
337		modes[i].viewportFlags = info.viewport_flags;
338		modes[i].reserved1 = info.reserved1;
339		modes[i].reserved2 = info.reserved2;
340
341		_XRead(dpy, offset, info.name_size);
342		modes[i].name = offset;
343		offset += info.name_size;
344	      }
345	      *num = rep.number;
346	   } else
347		_XEatData(dpy, rep.length << 2);
348	}
349    }
350
351    UnlockDisplay(dpy);
352    SyncHandle();
353
354    return modes;
355}
356
357
358XDGADevice *
359XDGASetMode(
360    Display	*dpy,
361    int		screen,
362    int		mode
363){
364    XExtDisplayInfo *dinfo = xdga_find_display (dpy);
365    xXDGASetModeReply rep;
366    xXDGASetModeReq *req;
367    XDGADevice *dev = NULL;
368    Pixmap pid;
369
370    XDGACheckExtension (dpy, dinfo, NULL);
371
372    LockDisplay(dpy);
373    GetReq(XDGASetMode, req);
374    req->reqType = dinfo->codes->major_opcode;
375    req->dgaReqType = X_XDGASetMode;
376    req->screen = screen;
377    req->mode = mode;
378    req->pid = pid = XAllocID(dpy);
379
380    if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
381	if(rep.length) {
382	   xXDGAModeInfo info;
383	   int size;
384
385	   size = rep.length << 2;
386	   size -= sz_xXDGAModeInfo; /* get text size */
387
388	   dev = (XDGADevice*)Xmalloc(sizeof(XDGADevice) + size);
389
390	   if(dev) {
391		_XRead(dpy, (char*)(&info), sz_xXDGAModeInfo);
392
393		dev->mode.num = info.num;
394		dev->mode.verticalRefresh =
395				(float)info.vsync_num / (float)info.vsync_den;
396		dev->mode.flags = info.flags;
397		dev->mode.imageWidth = info.image_width;
398		dev->mode.imageHeight = info.image_height;
399		dev->mode.pixmapWidth = info.pixmap_width;
400		dev->mode.pixmapHeight = info.pixmap_height;
401		dev->mode.bytesPerScanline = info.bytes_per_scanline;
402		dev->mode.byteOrder = info.byte_order;
403		dev->mode.depth = info.depth;
404		dev->mode.bitsPerPixel = info.bpp;
405		dev->mode.redMask = info.red_mask;
406		dev->mode.greenMask = info.green_mask;
407		dev->mode.blueMask = info.blue_mask;
408		dev->mode.visualClass = info.visual_class;
409		dev->mode.viewportWidth = info.viewport_width;
410		dev->mode.viewportHeight = info.viewport_height;
411		dev->mode.xViewportStep = info.viewport_xstep;
412		dev->mode.yViewportStep = info.viewport_ystep;
413		dev->mode.maxViewportX = info.viewport_xmax;
414		dev->mode.maxViewportY = info.viewport_ymax;
415		dev->mode.viewportFlags = info.viewport_flags;
416		dev->mode.reserved1 = info.reserved1;
417		dev->mode.reserved2 = info.reserved2;
418
419		dev->mode.name = (char*)(&dev[1]);
420		_XRead(dpy, dev->mode.name, info.name_size);
421
422		dev->pixmap = (rep.flags & XDGAPixmap) ? pid : 0;
423		dev->data = XDGAGetMappedMemory(screen);
424
425		if(dev->data)
426		    dev->data += rep.offset;
427	   }
428	   /* not sure what to do if the allocation fails */
429	}
430    }
431
432    UnlockDisplay(dpy);
433    SyncHandle();
434
435    return dev;
436}
437
438
439void XDGASetViewport(
440    Display	*dpy,
441    int		screen,
442    int		x,
443    int		y,
444    int		flags
445){
446    XExtDisplayInfo *info = xdga_find_display (dpy);
447    xXDGASetViewportReq *req;
448
449    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
450
451    LockDisplay(dpy);
452    GetReq(XDGASetViewport, req);
453    req->reqType = info->codes->major_opcode;
454    req->dgaReqType = X_XDGASetViewport;
455    req->screen = screen;
456    req->x = x;
457    req->y = y;
458    req->flags = flags;
459    UnlockDisplay(dpy);
460    SyncHandle();
461}
462
463
464void XDGAInstallColormap(
465    Display	*dpy,
466    int		screen,
467    Colormap	cmap
468){
469    XExtDisplayInfo *info = xdga_find_display (dpy);
470    xXDGAInstallColormapReq *req;
471
472    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
473
474    LockDisplay(dpy);
475    GetReq(XDGAInstallColormap, req);
476    req->reqType = info->codes->major_opcode;
477    req->dgaReqType = X_XDGAInstallColormap;
478    req->screen = screen;
479    req->cmap = cmap;
480    UnlockDisplay(dpy);
481    SyncHandle();
482}
483
484void XDGASelectInput(
485    Display	*dpy,
486    int		screen,
487    long	mask
488){
489    XExtDisplayInfo *info = xdga_find_display (dpy);
490    xXDGASelectInputReq *req;
491
492    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
493
494    LockDisplay(dpy);
495    GetReq(XDGASelectInput, req);
496    req->reqType = info->codes->major_opcode;
497    req->dgaReqType = X_XDGASelectInput;
498    req->screen = screen;
499    req->mask = mask;
500    UnlockDisplay(dpy);
501    SyncHandle();
502}
503
504void XDGAFillRectangle(
505    Display	*dpy,
506    int		screen,
507    int		x,
508    int		y,
509    unsigned int	width,
510    unsigned int	height,
511    unsigned long	color
512){
513    XExtDisplayInfo *info = xdga_find_display (dpy);
514    xXDGAFillRectangleReq *req;
515
516    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
517
518    LockDisplay(dpy);
519    GetReq(XDGAFillRectangle, req);
520    req->reqType = info->codes->major_opcode;
521    req->dgaReqType = X_XDGAFillRectangle;
522    req->screen = screen;
523    req->x = x;
524    req->y = y;
525    req->width = width;
526    req->height = height;
527    req->color = color;
528    UnlockDisplay(dpy);
529    SyncHandle();
530}
531
532void XDGACopyArea(
533    Display	*dpy,
534    int		screen,
535    int		srcx,
536    int		srcy,
537    unsigned int	width,
538    unsigned int	height,
539    int		dstx,
540    int		dsty
541){
542    XExtDisplayInfo *info = xdga_find_display (dpy);
543    xXDGACopyAreaReq *req;
544
545    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
546
547    LockDisplay(dpy);
548    GetReq(XDGACopyArea, req);
549    req->reqType = info->codes->major_opcode;
550    req->dgaReqType = X_XDGACopyArea;
551    req->screen = screen;
552    req->srcx = srcx;
553    req->srcy = srcy;
554    req->width = width;
555    req->height = height;
556    req->dstx = dstx;
557    req->dsty = dsty;
558    UnlockDisplay(dpy);
559    SyncHandle();
560}
561
562void XDGACopyTransparentArea(
563    Display	*dpy,
564    int		screen,
565    int		srcx,
566    int		srcy,
567    unsigned int	width,
568    unsigned int	height,
569    int		dstx,
570    int		dsty,
571    unsigned long key
572){
573    XExtDisplayInfo *info = xdga_find_display (dpy);
574    xXDGACopyTransparentAreaReq *req;
575
576    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
577
578    LockDisplay(dpy);
579    GetReq(XDGACopyTransparentArea, req);
580    req->reqType = info->codes->major_opcode;
581    req->dgaReqType = X_XDGACopyTransparentArea;
582    req->screen = screen;
583    req->srcx = srcx;
584    req->srcy = srcy;
585    req->width = width;
586    req->height = height;
587    req->dstx = dstx;
588    req->dsty = dsty;
589    req->key = key;
590    UnlockDisplay(dpy);
591    SyncHandle();
592}
593
594
595int XDGAGetViewportStatus(
596    Display *dpy,
597    int screen
598){
599    XExtDisplayInfo *info = xdga_find_display (dpy);
600    xXDGAGetViewportStatusReply rep;
601    xXDGAGetViewportStatusReq *req;
602    int status = 0;
603
604    XDGACheckExtension (dpy, info, 0);
605
606    LockDisplay(dpy);
607    GetReq(XDGAGetViewportStatus, req);
608    req->reqType = info->codes->major_opcode;
609    req->dgaReqType = X_XDGAGetViewportStatus;
610    req->screen = screen;
611    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
612	status = rep.status;
613    UnlockDisplay(dpy);
614    SyncHandle();
615    return status;
616}
617
618void XDGASync(
619    Display *dpy,
620    int screen
621){
622    XExtDisplayInfo *info = xdga_find_display (dpy);
623    xXDGASyncReply rep;
624    xXDGASyncReq *req;
625
626    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
627
628    LockDisplay(dpy);
629    GetReq(XDGASync, req);
630    req->reqType = info->codes->major_opcode;
631    req->dgaReqType = X_XDGASync;
632    req->screen = screen;
633    _XReply(dpy, (xReply *)&rep, 0, xFalse);
634    UnlockDisplay(dpy);
635    SyncHandle();
636}
637
638
639void XDGAChangePixmapMode(
640    Display *dpy,
641    int screen,
642    int *x,
643    int *y,
644    int mode
645){
646    XExtDisplayInfo *info = xdga_find_display (dpy);
647    xXDGAChangePixmapModeReq *req;
648    xXDGAChangePixmapModeReply rep;
649
650    XextSimpleCheckExtension (dpy, info, xdga_extension_name);
651
652    LockDisplay(dpy);
653    GetReq(XDGAChangePixmapMode, req);
654    req->reqType = info->codes->major_opcode;
655    req->dgaReqType = X_XDGAChangePixmapMode;
656    req->screen = screen;
657    req->x = *x;
658    req->y = *y;
659    req->flags = mode;
660    _XReply(dpy, (xReply *)&rep, 0, xFalse);
661    *x = rep.x;
662    *y = rep.y;
663    UnlockDisplay(dpy);
664    SyncHandle();
665}
666
667Colormap XDGACreateColormap(
668    Display *dpy,
669    int screen,
670    XDGADevice *dev,
671    int	alloc
672){
673    XExtDisplayInfo *info = xdga_find_display (dpy);
674    xXDGACreateColormapReq *req;
675    Colormap cid;
676
677    XDGACheckExtension (dpy, info, -1);
678
679    LockDisplay(dpy);
680    GetReq(XDGACreateColormap, req);
681    req->reqType = info->codes->major_opcode;
682    req->dgaReqType = X_XDGACreateColormap;
683    req->screen = screen;
684    req->mode = dev->mode.num;
685    req->alloc = alloc;
686    cid = req->id = XAllocID(dpy);
687    UnlockDisplay(dpy);
688    SyncHandle();
689
690    return cid;
691}
692
693
694void XDGAKeyEventToXKeyEvent(
695    XDGAKeyEvent* dk,
696    XKeyEvent* xk
697){
698    xk->type = dk->type;
699    xk->serial = dk->serial;
700    xk->send_event = False;
701    xk->display = dk->display;
702    xk->window = RootWindow(dk->display, dk->screen);
703    xk->root = xk->window;
704    xk->subwindow = None;
705    xk->time = dk->time;
706    xk->x = xk->y = xk->x_root = xk->y_root = 0;
707    xk->state = dk->state;
708    xk->keycode = dk->keycode;
709    xk->same_screen = True;
710}
711
712#include <X11/Xmd.h>
713#include <stdlib.h>
714#include <stdio.h>
715#include <fcntl.h>
716#if defined(ISC)
717# define HAS_SVR3_MMAP
718# include <sys/types.h>
719# include <errno.h>
720
721# include <sys/at_ansi.h>
722# include <sys/kd.h>
723
724# include <sys/sysmacros.h>
725# include <sys/immu.h>
726# include <sys/region.h>
727
728# include <sys/mmap.h>
729#else
730# if defined(Lynx) && defined(NO_MMAP)
731#  include <sys/types.h>
732#  include <errno.h>
733#  include <smem.h>
734# else
735#  if !defined(__UNIXOS2__)
736#   include <sys/mman.h>
737#  endif
738# endif
739#endif
740#include <sys/wait.h>
741#include <signal.h>
742#include <unistd.h>
743
744#if defined(SVR4) && !defined(sun)
745#define DEV_MEM "/dev/pmem"
746#elif defined(SVR4) && defined(sun)
747#define DEV_MEM "/dev/xsvc"
748#elif defined(HAS_APERTURE_DRV)
749#define DEV_MEM "/dev/xf86"
750#else
751#define DEV_MEM "/dev/mem"
752#endif
753
754
755
756typedef struct _DGAMapRec{
757  unsigned char *physical;
758  unsigned char *virtual;
759  CARD32 size;
760  int fd;
761  int screen;
762  struct _DGAMapRec *next;
763} DGAMapRec, *DGAMapPtr;
764
765static Bool
766DGAMapPhysical(int, char*, unsigned char*, CARD32, CARD32, CARD32, DGAMapPtr);
767static void DGAUnmapPhysical(DGAMapPtr);
768
769static DGAMapPtr _Maps = NULL;
770
771
772unsigned char*
773XDGAGetMappedMemory(int screen)
774{
775    DGAMapPtr pMap = _Maps;
776    unsigned char *pntr = NULL;
777
778    while(pMap != NULL) {
779	if(pMap->screen == screen) {
780	    pntr = pMap->virtual;
781	    break;
782	}
783	pMap = pMap->next;
784    }
785
786    return pntr;
787}
788
789Bool
790XDGAMapFramebuffer(
791   int screen,
792   char *name,			/* optional device name */
793   unsigned char* base,		/* physical memory */
794   CARD32 size,			/* size */
795   CARD32 offset,		/* optional offset */
796   CARD32 extra			/* optional extra data */
797){
798   DGAMapPtr pMap = _Maps;
799   Bool result;
800
801   /* is it already mapped ? */
802   while(pMap != NULL) {
803     if(pMap->screen == screen)
804	return True;
805     pMap = pMap->next;
806   }
807
808   if(extra & XDGANeedRoot) {
809    /* we should probably check if we have root permissions and
810       return False here */
811
812   }
813
814   pMap = (DGAMapPtr)Xmalloc(sizeof(DGAMapRec));
815
816   result = DGAMapPhysical(screen, name, base, size, offset, extra, pMap);
817
818   if(result) {
819      pMap->next = _Maps;
820      _Maps = pMap;
821   } else
822      Xfree(pMap);
823
824   return result;
825}
826
827void
828XDGAUnmapFramebuffer(int screen)
829{
830   DGAMapPtr pMap = _Maps;
831   DGAMapPtr pPrev = NULL;
832
833   /* is it already mapped */
834    while(pMap != NULL) {
835	if(pMap->screen == screen)
836	    break;
837	pPrev = pMap;
838	pMap = pMap->next;
839    }
840
841    if(!pMap)
842	return;
843
844    DGAUnmapPhysical(pMap);
845
846    if(!pPrev)
847	_Maps = pMap->next;
848    else
849	pPrev->next = pMap->next;
850
851    Xfree(pMap);
852}
853
854
855static Bool
856DGAMapPhysical(
857   int screen,
858   char *name,			/* optional device name */
859   unsigned char* base,		/* physical memory */
860   CARD32 size,			/* size */
861   CARD32 offset,		/* optional offset */
862   CARD32 extra,		/* optional extra data */
863   DGAMapPtr pMap
864) {
865#if defined(ISC) && defined(HAS_SVR3_MMAP)
866    struct kd_memloc mloc;
867#elif defined(__UNIXOS2__)
868    APIRET rc;
869    ULONG action;
870    HFILE hfd;
871#endif
872
873    base += offset;
874
875    pMap->screen = screen;
876    pMap->physical = base;
877    pMap->size = size;
878
879#if defined(ISC) && defined(HAS_SVR3_MMAP)
880    if ((pMap->fd = open("/dev/mmap", O_RDWR)) < 0)
881	return False;
882    mloc.vaddr = (char *)0;
883    mloc.physaddr = (char *)base;
884    mloc.length = size;
885    mloc.ioflg=1;
886
887    if ((pMap->virtual = (void *)ioctl(pMap->fd, MAP, &mloc)) == (void *)-1)
888	return False;
889#elif defined (__UNIXOS2__)
890    /*
891     * Dragon warning here! /dev/pmap$ is never closed, except on progam exit.
892     * Consecutive calling of this routine will make PMAP$ driver run out
893     * of memory handles. Some umap/close mechanism should be provided
894     */
895
896    rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN,
897		 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL);
898    if (rc != 0)
899	return False;
900    {
901	struct map_ioctl {
902		union {
903			ULONG phys;
904			void* user;
905		} a;
906		ULONG size;
907	} pmap,dmap;
908	ULONG plen,dlen;
909#define XFREE86_PMAP	0x76
910#define PMAP_MAP	0x44
911
912	pmap.a.phys = base;
913	pmap.size = size;
914	rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP,
915			 (PULONG)&pmap, sizeof(pmap), &plen,
916			 (PULONG)&dmap, sizeof(dmap), &dlen);
917	if (rc == 0) {
918		pMap->virtual = dmap.a.user;
919	}
920   }
921   if (rc != 0)
922	return False;
923#elif defined (Lynx) && defined(NO_MMAP)
924    pMap->virtual = smem_create("XF86DGA", (char*)base, size, SM_READ|SM_WRITE);
925#else
926#ifndef MAP_FILE
927#define MAP_FILE 0
928#endif
929    if (!name)
930	    name = DEV_MEM;
931    if ((pMap->fd = open(name, O_RDWR)) < 0)
932	return False;
933    pMap->virtual = mmap(NULL, size, PROT_READ | PROT_WRITE,
934			MAP_FILE | MAP_SHARED, pMap->fd, (off_t)base);
935    if (pMap->virtual == (void *)-1)
936	return False;
937    mprotect(pMap->virtual, size, PROT_READ | PROT_WRITE);
938#endif
939
940    return True;
941}
942
943
944
945static void
946DGAUnmapPhysical(DGAMapPtr pMap)
947{
948#if defined(ISC) && defined(HAS_SVR3_MMAP)
949    /* XXX Add unmapping code here. */
950#elif defined (__UNIXOS2__)
951    /* XXX Add unmapping code here. */
952#elif defined(Lynx) && defined(NO_MMAP)
953	/* XXX this doesn't allow enable after disable */
954    smem_create(NULL, pMap->virtual, pMap->size, SM_DETACH);
955    smem_remove("XF86DGA");
956#else
957    if (pMap->virtual && pMap->virtual != (void *)-1) {
958	mprotect(pMap->virtual,pMap->size, PROT_READ);
959	munmap(pMap->virtual, pMap->size);
960	pMap->virtual = 0;
961    }
962    if (pMap->fd >= 0) {
963	close(pMap->fd);
964	pMap->fd = -1;
965    }
966#endif
967}
968