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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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