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