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