• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SDL_NAME(XF86DGAQueryExtension)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 
SDL_NAME(XF86DGAQueryVersion)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 
SDL_NAME(XF86DGAGetVideoLL)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 
SDL_NAME(XF86DGADirectVideoLL)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 
SDL_NAME(XF86DGAGetViewPortSize)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 
SDL_NAME(XF86DGASetViewPort)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 
SDL_NAME(XF86DGAGetVidPage)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 
SDL_NAME(XF86DGASetVidPage)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 
SDL_NAME(XF86DGAInstallColormap)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 
SDL_NAME(XF86DGAQueryDirectVideo)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 
SDL_NAME(XF86DGAViewPortChanged)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
AddMap(void)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
AddScr(void)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
FindMap(unsigned long address,unsigned long size)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
FindScr(Display * display,int screen)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 *
MapPhysAddress(unsigned long address,unsigned long size)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
SDL_NAME(XF86DGAForkApp)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
SDL_NAME(XF86DGADirectVideo)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
XF86cleanup(int sig)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
SDL_NAME(XF86DGAGetVideo)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 
722