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