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