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