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