1/* 2 * Copyright 1992 by Orest Zborowski <obz@Kodak.com> 3 * Copyright 1993 by David Wexelblat <dwex@goblin.org> 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the names of Orest Zborowski and David Wexelblat 10 * not be used in advertising or publicity pertaining to distribution of 11 * the software without specific, written prior permission. Orest Zborowski 12 * and David Wexelblat make no representations about the suitability of this 13 * software for any purpose. It is provided "as is" without express or 14 * implied warranty. 15 * 16 * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD 17 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE 19 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 * 24 */ 25 26#ifdef HAVE_XORG_CONFIG_H 27#include <xorg-config.h> 28#endif 29 30#include <errno.h> 31#include <string.h> 32 33#include <X11/X.h> 34#include "input.h" 35#include "scrnintstr.h" 36 37#include "xf86.h" 38#include "xf86Priv.h" 39#include "xf86_OSlib.h" 40#include "xf86OSpriv.h" 41#ifdef __alpha__ 42#include "shared/xf86Axp.h" 43#endif 44 45#ifdef HAS_MTRR_SUPPORT 46#include <asm/mtrr.h> 47#endif 48 49#ifndef MAP_FAILED 50#define MAP_FAILED ((void *)-1) 51#endif 52 53static Bool ExtendedEnabled = FALSE; 54 55#ifdef __ia64__ 56 57#include "compiler.h" 58#include <sys/io.h> 59 60#elif !defined(__powerpc__) && \ 61 !defined(__mc68000__) && \ 62 !defined(__sparc__) && \ 63 !defined(__mips__) && \ 64 !defined(__nds32__) && \ 65 !defined(__arm__) 66 67/* 68 * Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare 69 * these. 70 */ 71extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); 72extern int iopl(int __level); 73 74#endif 75 76#ifdef __alpha__ 77# define BUS_BASE bus_base 78#else 79#define BUS_BASE (0) 80#endif /* __alpha__ */ 81 82/***************************************************************************/ 83/* Video Memory Mapping section */ 84/***************************************************************************/ 85 86static pointer mapVidMem(int, unsigned long, unsigned long, int); 87static void unmapVidMem(int, pointer, unsigned long); 88#if defined (__alpha__) 89extern void sethae(unsigned long hae); 90extern unsigned long _bus_base __P ((void)) __attribute__ ((const)); 91extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const)); 92 93static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); 94extern axpDevice lnxGetAXP(void); 95static void unmapVidMemSparse(int, pointer, unsigned long); 96static axpDevice axpSystem = -1; 97static Bool needSparse; 98static unsigned long hae_thresh; 99static unsigned long hae_mask; 100static unsigned long bus_base; 101#endif 102 103#ifdef HAS_MTRR_SUPPORT 104 105#define SPLIT_WC_REGIONS 1 106 107static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); 108static void undoWC(int, pointer); 109 110/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr 111 driver will clean up when we exit. */ 112#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ 113#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had 114 a problem. */ 115static int mtrr_fd = MTRR_FD_UNOPENED; 116 117/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, 118 and will fail on Linux 2.2 with MTRR support configured out, 119 so verbosity should be chosen appropriately. */ 120static Bool 121mtrr_open(int verbosity) 122{ 123 /* Only report absence of /proc/mtrr once. */ 124 static Bool warned = FALSE; 125 126 if (mtrr_fd == MTRR_FD_UNOPENED) { 127 mtrr_fd = open("/proc/mtrr", O_WRONLY); 128 129 if (mtrr_fd < 0) 130 mtrr_fd = MTRR_FD_PROBLEM; 131 } 132 133 if (mtrr_fd == MTRR_FD_PROBLEM) { 134 /* To make sure we only ever warn once, need to check 135 verbosity outside xf86MsgVerb */ 136 if (!warned && verbosity <= xf86GetVerbosity()) { 137 xf86MsgVerb(X_WARNING, verbosity, 138 "System lacks support for changing MTRRs\n"); 139 warned = TRUE; 140 } 141 142 return FALSE; 143 } 144 else 145 return TRUE; 146} 147 148/* 149 * We maintain a list of WC regions for each physical mapping so they can 150 * be undone when unmapping. 151 */ 152 153struct mtrr_wc_region { 154 struct mtrr_sentry sentry; 155 Bool added; /* added WC or removed it */ 156 struct mtrr_wc_region * next; 157}; 158 159 160static struct mtrr_wc_region * 161mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, 162 MessageType from) 163{ 164 /* Some BIOS writers thought that setting wc over the mmio 165 region of a graphics devices was a good idea. Try to fix 166 it. */ 167 168 struct mtrr_gentry gent; 169 struct mtrr_wc_region *wcreturn = NULL, *wcr; 170 int count, ret=0; 171 172 /* Linux 2.0 users should not get a warning without -verbose */ 173 if (!mtrr_open(2)) 174 return NULL; 175 176 for (gent.regnum = 0; 177 ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; 178 gent.regnum++) { 179 if (gent.type != MTRR_TYPE_WRCOMB 180 || gent.base + gent.size <= base 181 || base + size <= gent.base) 182 continue; 183 184 /* Found an overlapping region. Delete it. */ 185 186 wcr = malloc(sizeof(*wcr)); 187 if (!wcr) 188 return NULL; 189 wcr->sentry.base = gent.base; 190 wcr->sentry.size = gent.size; 191 wcr->sentry.type = MTRR_TYPE_WRCOMB; 192 wcr->added = FALSE; 193 194 count = 3; 195 while (count-- && 196 (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); 197 198 if (ret >= 0) { 199 xf86DrvMsg(screenNum, from, 200 "Removed MMIO write-combining range " 201 "(0x%lx,0x%lx)\n", 202 (unsigned long) gent.base, (unsigned long) gent.size); 203 wcr->next = wcreturn; 204 wcreturn = wcr; 205 gent.regnum--; 206 } else { 207 free(wcr); 208 xf86DrvMsgVerb(screenNum, X_WARNING, 0, 209 "Failed to remove MMIO " 210 "write-combining range (0x%lx,0x%lx)\n", 211 gent.base, (unsigned long) gent.size); 212 } 213 } 214 return wcreturn; 215} 216 217 218static struct mtrr_wc_region * 219mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, 220 MessageType from) 221{ 222 struct mtrr_gentry gent; 223 struct mtrr_wc_region *wcreturn = NULL, **wcr; 224 225 if (!mtrr_open(2)) 226 return NULL; 227 228 wcr = &wcreturn; 229 for (gent.regnum = 0; 230 ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) { 231 if (gent.type == MTRR_TYPE_WRCOMB 232 && ((gent.base >= base && gent.base + gent.size < base + size) || 233 (gent.base > base && gent.base + gent.size <= base + size))) { 234 *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); 235 if (*wcr) gent.regnum--; 236 while(*wcr) { 237 wcr = &((*wcr)->next); 238 } 239 } 240 } 241 return wcreturn; 242} 243 244 245static struct mtrr_wc_region * 246mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, 247 MessageType from) 248{ 249 struct mtrr_wc_region **wcr, *wcreturn, *curwcr; 250 251 /* 252 * There can be only one.... 253 */ 254 255 wcreturn = mtrr_remove_offending(screenNum, base, size, from); 256 wcr = &wcreturn; 257 while (*wcr) { 258 wcr = &((*wcr)->next); 259 } 260 261 /* Linux 2.0 should not warn, unless the user explicitly asks for 262 WC. */ 263 264 if (!mtrr_open(from == X_CONFIG ? 0 : 2)) 265 return wcreturn; 266 267 *wcr = curwcr = malloc(sizeof(**wcr)); 268 if (!curwcr) 269 return wcreturn; 270 271 curwcr->sentry.base = base; 272 curwcr->sentry.size = size; 273 curwcr->sentry.type = MTRR_TYPE_WRCOMB; 274 curwcr->added = TRUE; 275 curwcr->next = NULL; 276 277#if SPLIT_WC_REGIONS 278 /* 279 * Splits up the write-combining region if it is not aligned on a 280 * size boundary. 281 */ 282 283 { 284 unsigned long lbase, d_size = 1; 285 unsigned long n_size = size; 286 unsigned long n_base = base; 287 288 for (lbase = n_base, d_size = 1; !(lbase & 1); 289 lbase = lbase >> 1, d_size <<= 1); 290 while (d_size > n_size) 291 d_size = d_size >> 1; 292 DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); 293 n_base += d_size; 294 n_size -= d_size; 295 if (n_size) { 296 xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " 297 "base: 0x%lx, size: 0x%lx\n",base,size); 298 curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); 299 } 300 curwcr->sentry.size = d_size; 301 } 302 303 /*****************************************************************/ 304#endif /* SPLIT_WC_REGIONS */ 305 306 if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { 307 /* Avoid printing on every VT switch */ 308 if (xf86ServerIsInitialising()) { 309 xf86DrvMsg(screenNum, from, 310 "Write-combining range (0x%lx,0x%lx)\n", 311 base, size); 312 } 313 return wcreturn; 314 } 315 else { 316 *wcr = curwcr->next; 317 free(curwcr); 318 319 /* Don't complain about the VGA region: MTRR fixed 320 regions aren't currently supported, but might be in 321 the future. */ 322 if ((unsigned long)base >= 0x100000) { 323 xf86DrvMsgVerb(screenNum, X_WARNING, 0, 324 "Failed to set up write-combining range " 325 "(0x%lx,0x%lx)\n", base, size); 326 } 327 return wcreturn; 328 } 329} 330 331static void 332mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) 333{ 334 struct mtrr_wc_region *p, *prev; 335 336 if (mtrr_fd >= 0) { 337 p = wcr; 338 while (p) { 339 if (p->added) 340 ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); 341 prev = p; 342 p = p->next; 343 free(prev); 344 } 345 } 346} 347 348static pointer 349setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, 350 MessageType from) 351{ 352 if (enable) 353 return mtrr_add_wc_region(screenNum, base, size, from); 354 else 355 return mtrr_cull_wc_region(screenNum, base, size, from); 356} 357 358static void 359undoWC(int screenNum, pointer regioninfo) 360{ 361 mtrr_undo_wc_region(screenNum, regioninfo); 362} 363 364#endif /* HAS_MTRR_SUPPORT */ 365 366void 367xf86OSInitVidMem(VidMemInfoPtr pVidMem) 368{ 369 pVidMem->linearSupported = TRUE; 370#ifdef __alpha__ 371 if (axpSystem == -1) { 372 axpSystem = lnxGetAXP(); 373 if ((needSparse = (_bus_base_sparse() > 0))) { 374 hae_thresh = xf86AXPParams[axpSystem].hae_thresh; 375 hae_mask = xf86AXPParams[axpSystem].hae_mask; 376 } 377 bus_base = _bus_base(); 378 } 379 if (needSparse) { 380 xf86Msg(X_INFO,"Machine needs sparse mapping\n"); 381 pVidMem->mapMem = mapVidMemSparse; 382 pVidMem->unmapMem = unmapVidMemSparse; 383 } else { 384 xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); 385 pVidMem->mapMem = mapVidMem; 386 pVidMem->unmapMem = unmapVidMem; 387 } 388#else 389 pVidMem->mapMem = mapVidMem; 390 pVidMem->unmapMem = unmapVidMem; 391#endif /* __alpha__ */ 392 393 394#ifdef HAS_MTRR_SUPPORT 395 pVidMem->setWC = setWC; 396 pVidMem->undoWC = undoWC; 397#endif 398 pVidMem->initialised = TRUE; 399} 400 401#ifdef __sparc__ 402/* Basically, you simply cannot do this on Sparc. You have to do something portable 403 * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM 404 */ 405static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) 406{ 407 return NULL; 408} 409#else 410static pointer 411mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) 412{ 413 pointer base; 414 int fd; 415 int mapflags = MAP_SHARED; 416 int prot; 417 memType realBase, alignOff; 418 419 realBase = Base & ~(getpagesize() - 1); 420 alignOff = Base - realBase; 421 DebugF("base: %lx, realBase: %lx, alignOff: %lx \n", 422 Base,realBase,alignOff); 423 424#if defined(__ia64__) || defined(__arm__) || defined(__s390__) 425#ifndef MAP_WRITECOMBINED 426#define MAP_WRITECOMBINED 0x00010000 427#endif 428#ifndef MAP_NONCACHED 429#define MAP_NONCACHED 0x00020000 430#endif 431 if(flags & VIDMEM_FRAMEBUFFER) 432 mapflags |= MAP_WRITECOMBINED; 433 else 434 mapflags |= MAP_NONCACHED; 435#endif 436 437#if 0 438 /* this will disappear when people upgrade their kernels */ 439 fd = open(DEV_MEM, 440 ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC); 441#else 442 fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); 443#endif 444 if (fd < 0) 445 { 446 FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", 447 strerror(errno)); 448 } 449 450 if (flags & VIDMEM_READONLY) 451 prot = PROT_READ; 452 else 453 prot = PROT_READ | PROT_WRITE; 454 455 /* This requires linux-0.99.pl10 or above */ 456 base = mmap((caddr_t)0, Size + alignOff, prot, mapflags, fd, 457 (off_t)realBase + BUS_BASE); 458 close(fd); 459 if (base == MAP_FAILED) { 460 FatalError("xf86MapVidMem: Could not mmap framebuffer" 461 " (0x%08lx,0x%lx) (%s)\n", Base, Size, 462 strerror(errno)); 463 } 464 DebugF("base: %lx aligned base: %lx\n",base, (char *)base + alignOff); 465 return (char *)base + alignOff; 466} 467#endif /* !(__sparc__) */ 468 469static void 470unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) 471{ 472 uintptr_t alignOff = (uintptr_t)Base 473 - ((uintptr_t)Base & ~(getpagesize() - 1)); 474 475 DebugF("alignment offset: %lx\n", (unsigned long)alignOff); 476 munmap((void *)((uintptr_t)Base - alignOff), (Size + alignOff)); 477} 478 479 480/***************************************************************************/ 481/* I/O Permissions section */ 482/***************************************************************************/ 483 484#if defined(__powerpc__) 485volatile unsigned char *ioBase = NULL; 486 487#ifndef __NR_pciconfig_iobase 488#define __NR_pciconfig_iobase 200 489#endif 490 491#endif 492 493Bool 494xf86EnableIO(void) 495{ 496#if defined(__powerpc__) 497 int fd; 498 unsigned int ioBase_phys; 499#endif 500 501 if (ExtendedEnabled) 502 return TRUE; 503 504#if defined(__powerpc__) 505 ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); 506 507 fd = open("/dev/mem", O_RDWR); 508 if (ioBase == NULL) { 509 ioBase = (volatile unsigned char *)mmap(0, 0x20000, 510 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 511 ioBase_phys); 512/* Should this be fatal or just a warning? */ 513#if 0 514 if (ioBase == MAP_FAILED) { 515 xf86Msg(X_WARNING, 516 "xf86EnableIOPorts: Failed to map iobase (%s)\n", 517 strerror(errno)); 518 return FALSE; 519 } 520#endif 521 } 522 close(fd); 523#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) && !defined(__nds32__) 524 if (ioperm(0, 1024, 1) || iopl(3)) { 525 if (errno == ENODEV) 526 ErrorF("xf86EnableIOPorts: no I/O ports found\n"); 527 else 528 FatalError("xf86EnableIOPorts: failed to set IOPL" 529 " for I/O (%s)\n", strerror(errno)); 530 return FALSE; 531 } 532# if !defined(__alpha__) 533 /* XXX: this is actually not trapping anything because of iopl(3) 534 * above */ 535 ioperm(0x40,4,0); /* trap access to the timer chip */ 536 ioperm(0x60,4,0); /* trap access to the keyboard controller */ 537# endif 538#endif 539 ExtendedEnabled = TRUE; 540 541 return TRUE; 542} 543 544void 545xf86DisableIO(void) 546{ 547 if (!ExtendedEnabled) 548 return; 549#if defined(__powerpc__) 550 munmap(ioBase, 0x20000); 551 ioBase = NULL; 552#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) && !defined(__nds32__) 553 iopl(0); 554 ioperm(0, 1024, 0); 555#endif 556 ExtendedEnabled = FALSE; 557 558 return; 559} 560 561#if defined (__alpha__) 562 563#define vuip volatile unsigned int * 564 565extern int readDense8(pointer Base, register unsigned long Offset); 566extern int readDense16(pointer Base, register unsigned long Offset); 567extern int readDense32(pointer Base, register unsigned long Offset); 568extern void 569writeDenseNB8(int Value, pointer Base, register unsigned long Offset); 570extern void 571writeDenseNB16(int Value, pointer Base, register unsigned long Offset); 572extern void 573writeDenseNB32(int Value, pointer Base, register unsigned long Offset); 574extern void 575writeDense8(int Value, pointer Base, register unsigned long Offset); 576extern void 577writeDense16(int Value, pointer Base, register unsigned long Offset); 578extern void 579writeDense32(int Value, pointer Base, register unsigned long Offset); 580 581static int readSparse8(pointer Base, register unsigned long Offset); 582static int readSparse16(pointer Base, register unsigned long Offset); 583static int readSparse32(pointer Base, register unsigned long Offset); 584static void 585writeSparseNB8(int Value, pointer Base, register unsigned long Offset); 586static void 587writeSparseNB16(int Value, pointer Base, register unsigned long Offset); 588static void 589writeSparseNB32(int Value, pointer Base, register unsigned long Offset); 590static void 591writeSparse8(int Value, pointer Base, register unsigned long Offset); 592static void 593writeSparse16(int Value, pointer Base, register unsigned long Offset); 594static void 595writeSparse32(int Value, pointer Base, register unsigned long Offset); 596 597#define DENSE_BASE 0x2ff00000000UL 598#define SPARSE_BASE 0x30000000000UL 599 600static unsigned long msb_set = 0; 601 602static pointer 603mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) 604{ 605 int fd, prot; 606 unsigned long ret, rets = 0; 607 608 static Bool was_here = FALSE; 609 610 if (!was_here) { 611 was_here = TRUE; 612 613 xf86WriteMmio8 = writeSparse8; 614 xf86WriteMmio16 = writeSparse16; 615 xf86WriteMmio32 = writeSparse32; 616 xf86WriteMmioNB8 = writeSparseNB8; 617 xf86WriteMmioNB16 = writeSparseNB16; 618 xf86WriteMmioNB32 = writeSparseNB32; 619 xf86ReadMmio8 = readSparse8; 620 xf86ReadMmio16 = readSparse16; 621 xf86ReadMmio32 = readSparse32; 622 } 623 624 fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); 625 if (fd < 0) { 626 FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", 627 strerror(errno)); 628 } 629 630#if 0 631 xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", 632 Base, Size, flags); 633#endif 634 635 if (flags & VIDMEM_READONLY) 636 prot = PROT_READ; 637 else 638 prot = PROT_READ | PROT_WRITE; 639 640 /* This requirers linux-0.99.pl10 or above */ 641 642 /* 643 * Always do DENSE mmap, since read32/write32 currently require it. 644 */ 645 ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, 646 prot, MAP_SHARED, fd, 647 (off_t) (bus_base + Base)); 648 649 /* 650 * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER 651 * and SPARSE (which should require the use of read/write macros). 652 * 653 * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K 654 * bytes worth of pagetable (32 pages). 655 */ 656 if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || 657 ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) 658 { 659 rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), 660 Size << 5, prot, MAP_SHARED, fd, 661 (off_t) _bus_base_sparse() + (Base << 5)); 662 } 663 664 close(fd); 665 666 if (ret == (unsigned long)MAP_FAILED) { 667 FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", 668 strerror(errno)); 669 } 670 671 if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || 672 ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) 673 { 674 if (rets == (unsigned long)MAP_FAILED || 675 rets != (SPARSE_BASE + (Base << 5))) 676 { 677 FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", 678 strerror(errno)); 679 } 680 } 681 682#if 1 683 if (rets) 684 xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" 685 " to DENSE at 0x%lx and SPARSE at 0x%lx\n", 686 Base, Size, ret, rets); 687 else 688 xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" 689 " to DENSE only at 0x%lx\n", 690 Base, Size, ret); 691 692#endif 693 return (pointer) ret; 694} 695 696static void 697unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) 698{ 699 unsigned long Offset = (unsigned long)Base - DENSE_BASE; 700#if 1 701 xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", 702 Base, Size); 703#endif 704 /* Unmap DENSE always. */ 705 munmap((caddr_t)Base, Size); 706 707 /* Unmap SPARSE always, and ignore error in case we did not map it. */ 708 munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); 709} 710 711static int 712readSparse8(pointer Base, register unsigned long Offset) 713{ 714 register unsigned long result, shift; 715 register unsigned long msb; 716 717 mem_barrier(); 718 Offset += (unsigned long)Base - DENSE_BASE; 719 shift = (Offset & 0x3) << 3; 720 if (Offset >= (hae_thresh)) { 721 msb = Offset & hae_mask; 722 Offset -= msb; 723 if (msb_set != msb) { 724 sethae(msb); 725 msb_set = msb; 726 } 727 } 728 729 mem_barrier(); 730 result = *(vuip) (SPARSE_BASE + (Offset << 5)); 731 result >>= shift; 732 return 0xffUL & result; 733} 734 735static int 736readSparse16(pointer Base, register unsigned long Offset) 737{ 738 register unsigned long result, shift; 739 register unsigned long msb; 740 741 mem_barrier(); 742 Offset += (unsigned long)Base - DENSE_BASE; 743 shift = (Offset & 0x2) << 3; 744 if (Offset >= hae_thresh) { 745 msb = Offset & hae_mask; 746 Offset -= msb; 747 if (msb_set != msb) { 748 sethae(msb); 749 msb_set = msb; 750 } 751 } 752 753 mem_barrier(); 754 result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); 755 result >>= shift; 756 return 0xffffUL & result; 757} 758 759static int 760readSparse32(pointer Base, register unsigned long Offset) 761{ 762 /* NOTE: this is really using DENSE. */ 763 mem_barrier(); 764 return *(vuip)((unsigned long)Base+(Offset)); 765} 766 767static void 768writeSparse8(int Value, pointer Base, register unsigned long Offset) 769{ 770 register unsigned long msb; 771 register unsigned int b = Value & 0xffU; 772 773 write_mem_barrier(); 774 Offset += (unsigned long)Base - DENSE_BASE; 775 if (Offset >= hae_thresh) { 776 msb = Offset & hae_mask; 777 Offset -= msb; 778 if (msb_set != msb) { 779 sethae(msb); 780 msb_set = msb; 781 } 782 } 783 784 write_mem_barrier(); 785 *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; 786} 787 788static void 789writeSparse16(int Value, pointer Base, register unsigned long Offset) 790{ 791 register unsigned long msb; 792 register unsigned int w = Value & 0xffffU; 793 794 write_mem_barrier(); 795 Offset += (unsigned long)Base - DENSE_BASE; 796 if (Offset >= hae_thresh) { 797 msb = Offset & hae_mask; 798 Offset -= msb; 799 if (msb_set != msb) { 800 sethae(msb); 801 msb_set = msb; 802 } 803 } 804 805 write_mem_barrier(); 806 *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; 807} 808 809static void 810writeSparse32(int Value, pointer Base, register unsigned long Offset) 811{ 812 /* NOTE: this is really using DENSE. */ 813 write_mem_barrier(); 814 *(vuip)((unsigned long)Base + (Offset)) = Value; 815 return; 816} 817 818static void 819writeSparseNB8(int Value, pointer Base, register unsigned long Offset) 820{ 821 register unsigned long msb; 822 register unsigned int b = Value & 0xffU; 823 824 Offset += (unsigned long)Base - DENSE_BASE; 825 if (Offset >= hae_thresh) { 826 msb = Offset & hae_mask; 827 Offset -= msb; 828 if (msb_set != msb) { 829 sethae(msb); 830 msb_set = msb; 831 } 832 } 833 *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; 834} 835 836static void 837writeSparseNB16(int Value, pointer Base, register unsigned long Offset) 838{ 839 register unsigned long msb; 840 register unsigned int w = Value & 0xffffU; 841 842 Offset += (unsigned long)Base - DENSE_BASE; 843 if (Offset >= hae_thresh) { 844 msb = Offset & hae_mask; 845 Offset -= msb; 846 if (msb_set != msb) { 847 sethae(msb); 848 msb_set = msb; 849 } 850 } 851 *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; 852} 853 854static void 855writeSparseNB32(int Value, pointer Base, register unsigned long Offset) 856{ 857 /* NOTE: this is really using DENSE. */ 858 *(vuip)((unsigned long)Base + (Offset)) = Value; 859 return; 860} 861 862void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) 863 = writeDense8; 864void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) 865 = writeDense16; 866void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) 867 = writeDense32; 868void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) 869 = writeDenseNB8; 870void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) 871 = writeDenseNB16; 872void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) 873 = writeDenseNB32; 874int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) 875 = readDense8; 876int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) 877 = readDense16; 878int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) 879 = readDense32; 880 881#endif /* __alpha__ */ 882