SDL-1.2.14
[sdl_omap.git] / src / video / Xext / Xxf86dga / XF86DGA.c
1 /* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.19 2001/08/18 02:41:30 dawes Exp $ */
2 /*
3
4 Copyright (c) 1995  Jon Tombs
5 Copyright (c) 1995,1996  The XFree86 Project, Inc
6
7 */
8
9 /* THIS IS NOT AN X CONSORTIUM STANDARD */
10
11 #ifdef __EMX__ /* needed here to override certain constants in X headers */
12 #define INCL_DOS
13 #define INCL_DOSIOCTL
14 #include <os2.h>
15 #endif
16
17 #if defined(linux)
18 #define HAS_MMAP_ANON
19 #include <sys/types.h>
20 #include <sys/mman.h>
21 /*#include <asm/page.h>*/   /* PAGE_SIZE */
22 #define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */
23 #define HAS_GETPAGESIZE
24 #endif /* linux */
25
26 #if defined(CSRG_BASED)
27 #define HAS_MMAP_ANON
28 #define HAS_GETPAGESIZE
29 #include <sys/types.h>
30 #include <sys/mman.h>
31 #endif /* CSRG_BASED */
32
33 #if defined(DGUX)
34 #define HAS_GETPAGESIZE
35 #define MMAP_DEV_ZERO
36 #include <sys/types.h>
37 #include <sys/mman.h>
38 #include <unistd.h>
39 #endif /* DGUX */
40
41 #if defined(SVR4) && !defined(DGUX)
42 #define MMAP_DEV_ZERO
43 #include <sys/types.h>
44 #include <sys/mman.h>
45 #include <unistd.h>
46 #endif /* SVR4 && !DGUX */
47
48 #if defined(sun) && !defined(SVR4) /* SunOS */
49 #define MMAP_DEV_ZERO   /* doesn't SunOS have MAP_ANON ?? */
50 #define HAS_GETPAGESIZE
51 #include <sys/types.h>
52 #include <sys/mman.h>
53 #endif /* sun && !SVR4 */
54
55 #ifdef XNO_SYSCONF
56 #undef _SC_PAGESIZE
57 #endif
58
59 #define NEED_EVENTS
60 #define NEED_REPLIES
61
62 /* Apparently some X11 systems can't include this multiple times... */
63 #ifndef SDL_INCLUDED_XLIBINT_H
64 #define SDL_INCLUDED_XLIBINT_H 1
65 #include <X11/Xlibint.h>
66 #endif
67
68 #include "../extensions/xf86dga.h"
69 #include "../extensions/xf86dgastr.h"
70 #include "../extensions/Xext.h"
71 #include "../extensions/extutil.h"
72
73 extern XExtDisplayInfo* SDL_NAME(xdga_find_display)(Display*);
74 extern char *SDL_NAME(xdga_extension_name);
75
76 #define XF86DGACheckExtension(dpy,i,val) \
77   XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val)
78
79 /*****************************************************************************
80  *                                                                           *
81  *                  public XFree86-DGA Extension routines                    *
82  *                                                                           *
83  *****************************************************************************/
84
85 Bool SDL_NAME(XF86DGAQueryExtension) (
86     Display *dpy,
87     int *event_basep,
88     int *error_basep
89 ){
90     return SDL_NAME(XDGAQueryExtension)(dpy, event_basep, error_basep);
91 }
92
93 Bool SDL_NAME(XF86DGAQueryVersion)(
94     Display* dpy,
95     int* majorVersion, 
96     int* minorVersion
97 ){
98     return SDL_NAME(XDGAQueryVersion)(dpy, majorVersion, minorVersion);
99 }
100
101 Bool SDL_NAME(XF86DGAGetVideoLL)(
102     Display* dpy,
103     int screen,
104     int *offset,
105     int *width, 
106     int *bank_size, 
107     int *ram_size
108 ){
109     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
110     xXF86DGAGetVideoLLReply rep;
111     xXF86DGAGetVideoLLReq *req;
112
113     XF86DGACheckExtension (dpy, info, False);
114
115     LockDisplay(dpy);
116     GetReq(XF86DGAGetVideoLL, req);
117     req->reqType = info->codes->major_opcode;
118     req->dgaReqType = X_XF86DGAGetVideoLL;
119     req->screen = screen;
120     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
121         UnlockDisplay(dpy);
122         SyncHandle();
123         return False;
124     }
125
126     *offset = /*(char *)*/rep.offset;
127     *width = rep.width;
128     *bank_size = rep.bank_size;
129     *ram_size = rep.ram_size;
130         
131     UnlockDisplay(dpy);
132     SyncHandle();
133     return True;
134 }
135
136     
137 Bool SDL_NAME(XF86DGADirectVideoLL)(
138     Display* dpy,
139     int screen,
140     int enable
141 ){
142     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
143     xXF86DGADirectVideoReq *req;
144
145     XF86DGACheckExtension (dpy, info, False);
146
147     LockDisplay(dpy);
148     GetReq(XF86DGADirectVideo, req);
149     req->reqType = info->codes->major_opcode;
150     req->dgaReqType = X_XF86DGADirectVideo;
151     req->screen = screen;
152     req->enable = enable;
153     UnlockDisplay(dpy);
154     SyncHandle();
155     XSync(dpy,False);
156     return True;
157 }
158
159 Bool SDL_NAME(XF86DGAGetViewPortSize)(
160     Display* dpy,
161     int screen,
162     int *width, 
163     int *height
164 ){
165     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
166     xXF86DGAGetViewPortSizeReply rep;
167     xXF86DGAGetViewPortSizeReq *req;
168
169     XF86DGACheckExtension (dpy, info, False);
170
171     LockDisplay(dpy);
172     GetReq(XF86DGAGetViewPortSize, req);
173     req->reqType = info->codes->major_opcode;
174     req->dgaReqType = X_XF86DGAGetViewPortSize;
175     req->screen = screen;
176     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
177         UnlockDisplay(dpy);
178         SyncHandle();
179         return False;
180     }
181
182     *width = rep.width;
183     *height = rep.height;
184         
185     UnlockDisplay(dpy);
186     SyncHandle();
187     return True;
188 }
189     
190     
191 Bool SDL_NAME(XF86DGASetViewPort)(
192     Display* dpy,
193     int screen,
194     int x, 
195     int y
196 ){
197     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
198     xXF86DGASetViewPortReq *req;
199
200     XF86DGACheckExtension (dpy, info, False);
201
202     LockDisplay(dpy);
203     GetReq(XF86DGASetViewPort, req);
204     req->reqType = info->codes->major_opcode;
205     req->dgaReqType = X_XF86DGASetViewPort;
206     req->screen = screen;
207     req->x = x;
208     req->y = y;
209     UnlockDisplay(dpy);
210     SyncHandle();
211     XSync(dpy,False);
212     return True;
213 }
214
215     
216 Bool SDL_NAME(XF86DGAGetVidPage)(
217     Display* dpy,
218     int screen,
219     int *vpage
220 ){
221     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
222     xXF86DGAGetVidPageReply rep;
223     xXF86DGAGetVidPageReq *req;
224
225     XF86DGACheckExtension (dpy, info, False);
226
227     LockDisplay(dpy);
228     GetReq(XF86DGAGetVidPage, req);
229     req->reqType = info->codes->major_opcode;
230     req->dgaReqType = X_XF86DGAGetVidPage;
231     req->screen = screen;
232     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
233         UnlockDisplay(dpy);
234         SyncHandle();
235         return False;
236     }
237
238     *vpage = rep.vpage;
239     UnlockDisplay(dpy);
240     SyncHandle();
241     return True;
242 }
243
244     
245 Bool SDL_NAME(XF86DGASetVidPage)(
246     Display* dpy,
247     int screen,
248     int vpage
249 ){
250     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
251     xXF86DGASetVidPageReq *req;
252
253     XF86DGACheckExtension (dpy, info, False);
254
255     LockDisplay(dpy);
256     GetReq(XF86DGASetVidPage, req);
257     req->reqType = info->codes->major_opcode;
258     req->dgaReqType = X_XF86DGASetVidPage;
259     req->screen = screen;
260     req->vpage = vpage;
261     UnlockDisplay(dpy);
262     SyncHandle();
263     XSync(dpy,False);
264     return True;
265 }
266
267 Bool SDL_NAME(XF86DGAInstallColormap)(
268     Display* dpy,
269     int screen,
270     Colormap cmap
271 ){
272     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
273     xXF86DGAInstallColormapReq *req;
274
275     XF86DGACheckExtension (dpy, info, False);
276
277     LockDisplay(dpy);
278     GetReq(XF86DGAInstallColormap, req);
279     req->reqType = info->codes->major_opcode;
280     req->dgaReqType = X_XF86DGAInstallColormap;
281     req->screen = screen;
282     req->id = cmap;
283     UnlockDisplay(dpy);
284     SyncHandle();
285     XSync(dpy,False);
286     return True;
287 }
288
289 Bool SDL_NAME(XF86DGAQueryDirectVideo)(
290     Display *dpy,
291     int screen,
292     int *flags
293 ){
294     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
295     xXF86DGAQueryDirectVideoReply rep;
296     xXF86DGAQueryDirectVideoReq *req;
297
298     XF86DGACheckExtension (dpy, info, False);
299
300     LockDisplay(dpy);
301     GetReq(XF86DGAQueryDirectVideo, req);
302     req->reqType = info->codes->major_opcode;
303     req->dgaReqType = X_XF86DGAQueryDirectVideo;
304     req->screen = screen;
305     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
306         UnlockDisplay(dpy);
307         SyncHandle();
308         return False;
309     }
310     *flags = rep.flags;
311     UnlockDisplay(dpy);
312     SyncHandle();
313     return True;
314 }
315
316 Bool SDL_NAME(XF86DGAViewPortChanged)(
317     Display *dpy,
318     int screen,
319     int n
320 ){
321     XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy);
322     xXF86DGAViewPortChangedReply rep;
323     xXF86DGAViewPortChangedReq *req;
324
325     XF86DGACheckExtension (dpy, info, False);
326
327     LockDisplay(dpy);
328     GetReq(XF86DGAViewPortChanged, req);
329     req->reqType = info->codes->major_opcode;
330     req->dgaReqType = X_XF86DGAViewPortChanged;
331     req->screen = screen;
332     req->n = n;
333     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
334         UnlockDisplay(dpy);
335         SyncHandle();
336         return False;
337     }
338     UnlockDisplay(dpy);
339     SyncHandle();
340     return rep.result;
341 }
342
343
344
345 /* Helper functions */
346
347 #include <X11/Xmd.h>
348 #include "../extensions/xf86dga.h"
349 #include <stdlib.h>
350 #include <stdio.h>
351 #include <fcntl.h>
352 #if defined(ISC) 
353 # define HAS_SVR3_MMAP
354 # include <sys/types.h>
355 # include <errno.h>
356
357 # include <sys/at_ansi.h>
358 # include <sys/kd.h>
359
360 # include <sys/sysmacros.h>
361 # include <sys/immu.h>
362 # include <sys/region.h>
363
364 # include <sys/mmap.h>
365 #else
366 # if !defined(Lynx)
367 #  if !defined(__EMX__)
368 #   include <sys/mman.h>
369 #  endif
370 # else
371 #  include <sys/types.h>
372 #  include <errno.h>
373 #  include <smem.h>
374 # endif
375 #endif
376 #include <sys/wait.h>
377 #include <signal.h>
378 #include <unistd.h>
379
380 #if defined(SVR4) && !defined(sun) && !defined(SCO325)
381 #define DEV_MEM "/dev/pmem"
382 #elif defined(SVR4) && defined(sun)
383 #define DEV_MEM "/dev/xsvc"
384 #else
385 #define DEV_MEM "/dev/mem"
386 #endif
387
388 typedef struct {
389     unsigned long physaddr;     /* actual requested physical address */
390     unsigned long size;         /* actual requested map size */
391     unsigned long delta;        /* delta to account for page alignment */
392     void *        vaddr;        /* mapped address, without the delta */
393     int           refcount;     /* reference count */
394 } MapRec, *MapPtr;
395
396 typedef struct {
397     Display *   display;
398     int         screen;
399     MapPtr      map;
400 } ScrRec, *ScrPtr;
401
402 static int mapFd = -1;
403 static int numMaps = 0;
404 static int numScrs = 0;
405 static MapPtr *mapList = NULL;
406 static ScrPtr *scrList = NULL;
407
408 static MapPtr
409 AddMap(void)
410 {
411     MapPtr *old;
412
413     old = mapList;
414     mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1));
415     if (!mapList) {
416         mapList = old;
417         return NULL;
418     }
419     mapList[numMaps] = malloc(sizeof(MapRec));
420     if (!mapList[numMaps])
421         return NULL;
422     return mapList[numMaps++];
423 }
424
425 static ScrPtr
426 AddScr(void)
427 {
428     ScrPtr *old;
429
430     old = scrList;
431     scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1));
432     if (!scrList) {
433         scrList = old;
434         return NULL;
435     }
436     scrList[numScrs] = malloc(sizeof(ScrRec));
437     if (!scrList[numScrs])
438         return NULL;
439     return scrList[numScrs++];
440 }
441
442 static MapPtr
443 FindMap(unsigned long address, unsigned long size)
444 {
445     int i;
446
447     for (i = 0; i < numMaps; i++) {
448         if (mapList[i]->physaddr == address &&
449             mapList[i]->size == size)
450             return mapList[i];
451     }
452     return NULL;
453 }
454
455 static ScrPtr
456 FindScr(Display *display, int screen)
457 {
458     int i;
459
460     for (i = 0; i < numScrs; i++) {
461         if (scrList[i]->display == display &&
462             scrList[i]->screen == screen)
463             return scrList[i];
464     }
465     return NULL;
466 }
467
468 static void *
469 MapPhysAddress(unsigned long address, unsigned long size)
470 {
471     unsigned long offset, delta;
472     int pagesize = -1;
473     void *vaddr;
474     MapPtr mp;
475 #if defined(ISC) && defined(HAS_SVR3_MMAP)
476     struct kd_memloc mloc;
477 #elif defined(__EMX__)
478     APIRET rc;
479     ULONG action;
480     HFILE hfd;
481 #endif
482
483     if ((mp = FindMap(address, size))) {
484         mp->refcount++;
485         return (void *)((unsigned long)mp->vaddr + mp->delta);
486     }
487
488 #if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE)
489     pagesize = sysconf(_SC_PAGESIZE);
490 #endif
491 #ifdef _SC_PAGE_SIZE
492     if (pagesize == -1)
493         pagesize = sysconf(_SC_PAGE_SIZE);
494 #endif
495 #ifdef HAS_GETPAGESIZE
496     if (pagesize == -1)
497         pagesize = getpagesize();
498 #endif
499 #ifdef PAGE_SIZE
500     if (pagesize == -1)
501         pagesize = PAGE_SIZE;
502 #endif
503     if (pagesize == -1)
504         pagesize = 4096;
505
506    delta = address % pagesize;
507    offset = address - delta;
508
509 #if defined(ISC) && defined(HAS_SVR3_MMAP)
510     if (mapFd < 0) {
511         if ((mapFd = open("/dev/mmap", O_RDWR)) < 0)
512             return NULL;
513     }
514     mloc.vaddr = (char *)0;
515     mloc.physaddr = (char *)offset;
516     mloc.length = size + delta;
517     mloc.ioflg=1;
518
519     if ((vaddr = (void *)ioctl(mapFd, MAP, &mloc)) == (void *)-1)
520         return NULL;
521 #elif defined (__EMX__)
522     /*
523      * Dragon warning here! /dev/pmap$ is never closed, except on progam exit.
524      * Consecutive calling of this routine will make PMAP$ driver run out
525      * of memory handles. Some umap/close mechanism should be provided
526      */
527
528     rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN,
529                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL);
530     if (rc != 0)
531         return NULL;
532     {
533         struct map_ioctl {
534                 union {
535                         ULONG phys;
536                         void* user;
537                 } a;
538                 ULONG size;
539         } pmap,dmap;
540         ULONG plen,dlen;
541 #define XFREE86_PMAP    0x76
542 #define PMAP_MAP        0x44
543
544         pmap.a.phys = offset;
545         pmap.size = size + delta;
546         rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP,
547                          (PULONG)&pmap, sizeof(pmap), &plen,
548                          (PULONG)&dmap, sizeof(dmap), &dlen);
549         if (rc == 0) {
550                 vaddr = dmap.a.user;
551         }
552    }
553    if (rc != 0)
554         return NULL;
555 #elif defined (Lynx)
556     vaddr = (void *)smem_create("XF86DGA", (char *)offset, 
557                                 size + delta, SM_READ|SM_WRITE);
558 #else
559 #ifndef MAP_FILE
560 #define MAP_FILE 0
561 #endif
562     if (mapFd < 0) {
563         if ((mapFd = open(DEV_MEM, O_RDWR)) < 0)
564             return NULL;
565     }
566     vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE,
567                         MAP_FILE | MAP_SHARED, mapFd, (off_t)offset);
568     if (vaddr == (void *)-1)
569         return NULL;
570 #endif
571
572     if (!vaddr) {
573         if (!(mp = AddMap()))
574             return NULL;
575         mp->physaddr = address;
576         mp->size = size;
577         mp->delta = delta;
578         mp->vaddr = vaddr;
579         mp->refcount = 1;
580     }
581     return (void *)((unsigned long)vaddr + delta);
582 }
583
584 /*
585  * Still need to find a clean way of detecting the death of a DGA app
586  * and returning things to normal - Jon
587  * This is here to help debugging without rebooting... Also C-A-BS
588  * should restore text mode.
589  */
590
591 int
592 SDL_NAME(XF86DGAForkApp)(int screen)
593 {
594     pid_t pid;
595     int status;
596     int i;
597
598      /* fork the app, parent hangs around to clean up */
599     if ((pid = fork()) > 0) {
600         ScrPtr sp;
601
602         waitpid(pid, &status, 0);
603         for (i = 0; i < numScrs; i++) {
604             sp = scrList[i];
605             SDL_NAME(XF86DGADirectVideoLL)(sp->display, sp->screen, 0);
606             XSync(sp->display, False);
607         }
608         if (WIFEXITED(status))
609             _exit(0);
610         else
611             _exit(-1);
612     }
613     return pid;
614 }
615
616
617 Bool
618 SDL_NAME(XF86DGADirectVideo)(
619     Display *dis,
620     int screen,
621     int enable
622 ){
623     ScrPtr sp;
624     MapPtr mp = NULL;
625
626     if ((sp = FindScr(dis, screen)))
627         mp = sp->map;
628
629     if (enable & XF86DGADirectGraphics) {
630 #if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \
631         && !defined(__EMX__)
632         if (mp && mp->vaddr)
633             mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE);
634 #endif
635     } else {
636 #if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \
637         && !defined(__EMX__)
638         if (mp && mp->vaddr)
639             mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ);
640 #elif defined(Lynx)
641         /* XXX this doesn't allow enable after disable */
642         smem_create(NULL, mp->vaddr, mp->size + mp->delta, SM_DETACH);
643         smem_remove("XF86DGA");
644 #endif
645     }
646
647     SDL_NAME(XF86DGADirectVideoLL)(dis, screen, enable);
648     return 1;
649 }
650
651
652 static void
653 XF86cleanup(int sig)
654 {
655     ScrPtr sp;
656     int i;
657     static char beenhere = 0;
658
659     if (beenhere)
660         _exit(3);
661     beenhere = 1;
662
663     for (i = 0; i < numScrs; i++) {
664         sp = scrList[i];
665         SDL_NAME(XF86DGADirectVideo)(sp->display, sp->screen, 0);
666         XSync(sp->display, False);
667     }
668     _exit(3);
669 }
670
671 Bool
672 SDL_NAME(XF86DGAGetVideo)(
673     Display *dis,
674     int screen,
675     char **addr,
676     int *width, 
677     int *bank, 
678     int *ram
679 ){
680     /*unsigned long*/ int offset;
681     static int beenHere = 0;
682     ScrPtr sp;
683     MapPtr mp;
684
685     if (!(sp = FindScr(dis, screen))) {
686         if (!(sp = AddScr())) {
687             fprintf(stderr, "XF86DGAGetVideo: malloc failure\n");
688             exit(-2);
689         }
690         sp->display = dis;
691         sp->screen = screen;
692         sp->map = NULL;
693     }
694
695     SDL_NAME(XF86DGAGetVideoLL)(dis, screen , &offset, width, bank, ram);
696
697     *addr = MapPhysAddress(offset, *bank);
698     if (*addr == NULL) {
699         fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n",
700                 strerror(errno));
701         exit(-2);
702     }
703
704     if ((mp = FindMap(offset, *bank)))
705         sp->map = mp;
706
707     if (!beenHere) {
708         beenHere = 1;
709         atexit((void(*)(void))XF86cleanup);
710         /* one shot XF86cleanup attempts */
711         signal(SIGSEGV, XF86cleanup);
712 #ifdef SIGBUS
713         signal(SIGBUS, XF86cleanup);
714 #endif
715         signal(SIGHUP, XF86cleanup);
716         signal(SIGFPE, XF86cleanup);  
717     }
718
719     return 1;
720 }
721