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