Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / linux / lnx_video.c
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 static Bool ExtendedEnabled = FALSE;
50
51 #ifdef __ia64__
52
53 #include "compiler.h"
54 #include <sys/io.h>
55
56 #elif !defined(__powerpc__) && \
57 !defined(__mc68000__) && \
58 !defined(__sparc__) && \
59 !defined(__mips__) && \
60 !defined(__nds32__) && \
61 !defined(__arm__) && \
62 !defined(__aarch64__)
63
64 /*
65 * Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare
66 * these.
67 */
68 extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on);
69 extern int iopl(int __level);
70
71 #endif
72
73 #ifdef __alpha__
74 #define BUS_BASE bus_base
75 #else
76 #define BUS_BASE (0)
77 #endif /* __alpha__ */
78
79 /***************************************************************************/
80 /* Video Memory Mapping section */
81 /***************************************************************************/
82
83 static pointer mapVidMem(int, unsigned long, unsigned long, int);
84 static void unmapVidMem(int, pointer, unsigned long);
85
86 #if defined (__alpha__)
87 extern void sethae(unsigned long hae);
88 extern unsigned long _bus_base __P((void)) __attribute__ ((const));
89 extern unsigned long _bus_base_sparse __P((void)) __attribute__ ((const));
90
91 static pointer mapVidMemSparse(int, unsigned long, unsigned long, int);
92 extern axpDevice lnxGetAXP(void);
93 static void unmapVidMemSparse(int, pointer, unsigned long);
94 static axpDevice axpSystem = -1;
95 static Bool needSparse;
96 static unsigned long hae_thresh;
97 static unsigned long hae_mask;
98 static unsigned long bus_base;
99 #endif
100
101 #ifdef HAS_MTRR_SUPPORT
102
103 #define SPLIT_WC_REGIONS 1
104
105 static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType);
106 static void undoWC(int, pointer);
107
108 /* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr
109 driver will clean up when we exit. */
110 #define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */
111 #define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had
112 a problem. */
113 static int mtrr_fd = MTRR_FD_UNOPENED;
114
115 /* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0,
116 and will fail on Linux 2.2 with MTRR support configured out,
117 so verbosity should be chosen appropriately. */
118 static Bool
119 mtrr_open(int verbosity)
120 {
121 /* Only report absence of /proc/mtrr once. */
122 static Bool warned = FALSE;
123
124 if (mtrr_fd == MTRR_FD_UNOPENED) {
125 mtrr_fd = open("/proc/mtrr", O_WRONLY);
126
127 if (mtrr_fd < 0)
128 mtrr_fd = MTRR_FD_PROBLEM;
129 }
130
131 if (mtrr_fd == MTRR_FD_PROBLEM) {
132 /* To make sure we only ever warn once, need to check
133 verbosity outside xf86MsgVerb */
134 if (!warned && verbosity <= xf86GetVerbosity()) {
135 xf86MsgVerb(X_WARNING, verbosity,
136 "System lacks support for changing MTRRs\n");
137 warned = TRUE;
138 }
139
140 return FALSE;
141 }
142 else
143 return TRUE;
144 }
145
146 /*
147 * We maintain a list of WC regions for each physical mapping so they can
148 * be undone when unmapping.
149 */
150
151 struct mtrr_wc_region {
152 struct mtrr_sentry sentry;
153 Bool added; /* added WC or removed it */
154 struct mtrr_wc_region *next;
155 };
156
157 static struct mtrr_wc_region *
158 mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size,
159 MessageType from)
160 {
161 /* Some BIOS writers thought that setting wc over the mmio
162 region of a graphics devices was a good idea. Try to fix
163 it. */
164
165 struct mtrr_gentry gent;
166 struct mtrr_wc_region *wcreturn = NULL, *wcr;
167 int count, ret = 0;
168
169 /* Linux 2.0 users should not get a warning without -verbose */
170 if (!mtrr_open(2))
171 return NULL;
172
173 for (gent.regnum = 0;
174 ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) {
175 if (gent.type != MTRR_TYPE_WRCOMB
176 || gent.base + gent.size <= base || base + size <= gent.base)
177 continue;
178
179 /* Found an overlapping region. Delete it. */
180
181 wcr = malloc(sizeof(*wcr));
182 if (!wcr)
183 return NULL;
184 wcr->sentry.base = gent.base;
185 wcr->sentry.size = gent.size;
186 wcr->sentry.type = MTRR_TYPE_WRCOMB;
187 wcr->added = FALSE;
188
189 count = 3;
190 while (count-- &&
191 (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0);
192
193 if (ret >= 0) {
194 xf86DrvMsg(screenNum, from,
195 "Removed MMIO write-combining range "
196 "(0x%lx,0x%lx)\n",
197 (unsigned long) gent.base, (unsigned long) gent.size);
198 wcr->next = wcreturn;
199 wcreturn = wcr;
200 gent.regnum--;
201 }
202 else {
203 free(wcr);
204 xf86DrvMsgVerb(screenNum, X_WARNING, 0,
205 "Failed to remove MMIO "
206 "write-combining range (0x%lx,0x%lx)\n",
207 gent.base, (unsigned long) gent.size);
208 }
209 }
210 return wcreturn;
211 }
212
213 static struct mtrr_wc_region *
214 mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size,
215 MessageType from)
216 {
217 struct mtrr_gentry gent;
218 struct mtrr_wc_region *wcreturn = NULL, **wcr;
219
220 if (!mtrr_open(2))
221 return NULL;
222
223 wcr = &wcreturn;
224 for (gent.regnum = 0;
225 ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) {
226 if (gent.type == MTRR_TYPE_WRCOMB
227 && ((gent.base >= base && gent.base + gent.size < base + size) ||
228 (gent.base > base && gent.base + gent.size <= base + size))) {
229 *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from);
230 if (*wcr)
231 gent.regnum--;
232 while (*wcr) {
233 wcr = &((*wcr)->next);
234 }
235 }
236 }
237 return wcreturn;
238 }
239
240 static struct mtrr_wc_region *
241 mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size,
242 MessageType from)
243 {
244 struct mtrr_wc_region **wcr, *wcreturn, *curwcr;
245
246 /*
247 * There can be only one....
248 */
249
250 wcreturn = mtrr_remove_offending(screenNum, base, size, from);
251 wcr = &wcreturn;
252 while (*wcr) {
253 wcr = &((*wcr)->next);
254 }
255
256 /* Linux 2.0 should not warn, unless the user explicitly asks for
257 WC. */
258
259 if (!mtrr_open(from == X_CONFIG ? 0 : 2))
260 return wcreturn;
261
262 *wcr = curwcr = malloc(sizeof(**wcr));
263 if (!curwcr)
264 return wcreturn;
265
266 curwcr->sentry.base = base;
267 curwcr->sentry.size = size;
268 curwcr->sentry.type = MTRR_TYPE_WRCOMB;
269 curwcr->added = TRUE;
270 curwcr->next = NULL;
271
272 #if SPLIT_WC_REGIONS
273 /*
274 * Splits up the write-combining region if it is not aligned on a
275 * size boundary.
276 */
277
278 {
279 unsigned long lbase, d_size = 1;
280 unsigned long n_size = size;
281 unsigned long n_base = base;
282
283 for (lbase = n_base, d_size = 1; !(lbase & 1);
284 lbase = lbase >> 1, d_size <<= 1);
285 while (d_size > n_size)
286 d_size = d_size >> 1;
287 DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n", base, base + d_size - 1);
288 n_base += d_size;
289 n_size -= d_size;
290 if (n_size) {
291 xf86DrvMsgVerb(screenNum, X_INFO, 3, "Splitting WC range: "
292 "base: 0x%lx, size: 0x%lx\n", base, size);
293 curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size, from);
294 }
295 curwcr->sentry.size = d_size;
296 }
297
298 /*****************************************************************/
299 #endif /* SPLIT_WC_REGIONS */
300
301 if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) {
302 /* Avoid printing on every VT switch */
303 if (xf86ServerIsInitialising()) {
304 xf86DrvMsg(screenNum, from,
305 "Write-combining range (0x%lx,0x%lx)\n", base, size);
306 }
307 return wcreturn;
308 }
309 else {
310 *wcr = curwcr->next;
311 free(curwcr);
312
313 /* Don't complain about the VGA region: MTRR fixed
314 regions aren't currently supported, but might be in
315 the future. */
316 if ((unsigned long) base >= 0x100000) {
317 xf86DrvMsgVerb(screenNum, X_WARNING, 0,
318 "Failed to set up write-combining range "
319 "(0x%lx,0x%lx)\n", base, size);
320 }
321 return wcreturn;
322 }
323 }
324
325 static void
326 mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr)
327 {
328 struct mtrr_wc_region *p, *prev;
329
330 if (mtrr_fd >= 0) {
331 p = wcr;
332 while (p) {
333 if (p->added)
334 ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry);
335 prev = p;
336 p = p->next;
337 free(prev);
338 }
339 }
340 }
341
342 static pointer
343 setWC(int screenNum, unsigned long base, unsigned long size, Bool enable,
344 MessageType from)
345 {
346 if (enable)
347 return mtrr_add_wc_region(screenNum, base, size, from);
348 else
349 return mtrr_cull_wc_region(screenNum, base, size, from);
350 }
351
352 static void
353 undoWC(int screenNum, pointer regioninfo)
354 {
355 mtrr_undo_wc_region(screenNum, regioninfo);
356 }
357
358 #endif /* HAS_MTRR_SUPPORT */
359
360 void
361 xf86OSInitVidMem(VidMemInfoPtr pVidMem)
362 {
363 pVidMem->linearSupported = TRUE;
364 #ifdef __alpha__
365 if (axpSystem == -1) {
366 axpSystem = lnxGetAXP();
367 if ((needSparse = (_bus_base_sparse() > 0))) {
368 hae_thresh = xf86AXPParams[axpSystem].hae_thresh;
369 hae_mask = xf86AXPParams[axpSystem].hae_mask;
370 }
371 bus_base = _bus_base();
372 }
373 if (needSparse) {
374 xf86Msg(X_INFO, "Machine needs sparse mapping\n");
375 pVidMem->mapMem = mapVidMemSparse;
376 pVidMem->unmapMem = unmapVidMemSparse;
377 }
378 else {
379 xf86Msg(X_INFO, "Machine type has 8/16 bit access\n");
380 pVidMem->mapMem = mapVidMem;
381 pVidMem->unmapMem = unmapVidMem;
382 }
383 #else
384 pVidMem->mapMem = mapVidMem;
385 pVidMem->unmapMem = unmapVidMem;
386 #endif /* __alpha__ */
387
388 #ifdef HAS_MTRR_SUPPORT
389 pVidMem->setWC = setWC;
390 pVidMem->undoWC = undoWC;
391 #endif
392 pVidMem->initialised = TRUE;
393 }
394
395 #ifdef __sparc__
396 /* Basically, you simply cannot do this on Sparc. You have to do something portable
397 * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM
398 */
399 static pointer
400 mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
401 {
402 return NULL;
403 }
404 #else
405 static pointer
406 mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
407 {
408 pointer base;
409 int fd;
410 int mapflags = MAP_SHARED;
411 int prot;
412 memType realBase, alignOff;
413
414 realBase = Base & ~(getpagesize() - 1);
415 alignOff = Base - realBase;
416 DebugF("base: %lx, realBase: %lx, alignOff: %lx \n",
417 Base, realBase, alignOff);
418
419 #if defined(__ia64__) || defined(__arm__) || defined(__s390__)
420 #ifndef MAP_WRITECOMBINED
421 #define MAP_WRITECOMBINED 0x00010000
422 #endif
423 #ifndef MAP_NONCACHED
424 #define MAP_NONCACHED 0x00020000
425 #endif
426 if (flags & VIDMEM_FRAMEBUFFER)
427 mapflags |= MAP_WRITECOMBINED;
428 else
429 mapflags |= MAP_NONCACHED;
430 #endif
431
432 #if 0
433 /* this will disappear when people upgrade their kernels */
434 fd = open(DEV_MEM,
435 ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC);
436 #else
437 fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
438 #endif
439 if (fd < 0) {
440 FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n",
441 strerror(errno));
442 }
443
444 if (flags & VIDMEM_READONLY)
445 prot = PROT_READ;
446 else
447 prot = PROT_READ | PROT_WRITE;
448
449 /* This requires linux-0.99.pl10 or above */
450 base = mmap((caddr_t) 0, Size + alignOff, prot, mapflags, fd,
451 (off_t) realBase + BUS_BASE);
452 close(fd);
453 if (base == MAP_FAILED) {
454 FatalError("xf86MapVidMem: Could not mmap framebuffer"
455 " (0x%08lx,0x%lx) (%s)\n", Base, Size, strerror(errno));
456 }
457 DebugF("base: %lx aligned base: %lx\n", base, (char *) base + alignOff);
458 return (char *) base + alignOff;
459 }
460 #endif /* !(__sparc__) */
461
462 static void
463 unmapVidMem(int ScreenNum, pointer Base, unsigned long Size)
464 {
465 uintptr_t alignOff = (uintptr_t) Base
466 - ((uintptr_t) Base & ~(getpagesize() - 1));
467
468 DebugF("alignment offset: %lx\n", (unsigned long) alignOff);
469 munmap((void *) ((uintptr_t) Base - alignOff), (Size + alignOff));
470 }
471
472 /***************************************************************************/
473 /* I/O Permissions section */
474 /***************************************************************************/
475
476 #if defined(__powerpc__)
477 volatile unsigned char *ioBase = NULL;
478
479 #ifndef __NR_pciconfig_iobase
480 #define __NR_pciconfig_iobase 200
481 #endif
482
483 static Bool
484 hwEnableIO(void)
485 {
486 int fd;
487 unsigned int ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0);
488
489 fd = open("/dev/mem", O_RDWR);
490 if (ioBase == NULL) {
491 ioBase = (volatile unsigned char *) mmap(0, 0x20000,
492 PROT_READ | PROT_WRITE,
493 MAP_SHARED, fd, ioBase_phys);
494 }
495 close(fd);
496
497 return ioBase != MAP_FAILED;
498 }
499
500 static void
501 hwDisableIO(void)
502 {
503 munmap(ioBase, 0x20000);
504 ioBase = NULL;
505 }
506
507 #elif defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || \
508 defined(__alpha__)
509
510 static Bool
511 hwEnableIO(void)
512 {
513 if (ioperm(0, 1024, 1) || iopl(3)) {
514 ErrorF("xf86EnableIOPorts: failed to set IOPL for I/O (%s)\n",
515 strerror(errno));
516 return FALSE;
517 }
518 #if !defined(__alpha__)
519 /* XXX: this is actually not trapping anything because of iopl(3)
520 * above */
521 ioperm(0x40, 4, 0); /* trap access to the timer chip */
522 ioperm(0x60, 4, 0); /* trap access to the keyboard controller */
523 #endif
524
525 return TRUE;
526 }
527
528 static void
529 hwDisableIO(void)
530 {
531 iopl(0);
532 ioperm(0, 1024, 0);
533 }
534
535 #else /* non-IO architectures */
536
537 #define hwEnableIO() TRUE
538 #define hwDisableIO() do {} while (0)
539
540 #endif
541
542 Bool
543 xf86EnableIO(void)
544 {
545 if (ExtendedEnabled)
546 return TRUE;
547
548 ExtendedEnabled = hwEnableIO();
549
550 return ExtendedEnabled;
551 }
552
553 void
554 xf86DisableIO(void)
555 {
556 if (!ExtendedEnabled)
557 return;
558
559 hwDisableIO();
560
561 ExtendedEnabled = FALSE;
562 }
563
564 #if defined (__alpha__)
565
566 #define vuip volatile unsigned int *
567
568 extern int readDense8(pointer Base, register unsigned long Offset);
569 extern int readDense16(pointer Base, register unsigned long Offset);
570 extern int readDense32(pointer Base, register unsigned long Offset);
571 extern void
572 writeDenseNB8(int Value, pointer Base, register unsigned long Offset);
573 extern void
574 writeDenseNB16(int Value, pointer Base, register unsigned long Offset);
575 extern void
576 writeDenseNB32(int Value, pointer Base, register unsigned long Offset);
577 extern void
578 writeDense8(int Value, pointer Base, register unsigned long Offset);
579 extern void
580 writeDense16(int Value, pointer Base, register unsigned long Offset);
581 extern void
582 writeDense32(int Value, pointer Base, register unsigned long Offset);
583
584 static int readSparse8(pointer Base, register unsigned long Offset);
585 static int readSparse16(pointer Base, register unsigned long Offset);
586 static int readSparse32(pointer Base, register unsigned long Offset);
587 static void
588 writeSparseNB8(int Value, pointer Base, register unsigned long Offset);
589 static void
590 writeSparseNB16(int Value, pointer Base, register unsigned long Offset);
591 static void
592 writeSparseNB32(int Value, pointer Base, register unsigned long Offset);
593 static void
594 writeSparse8(int Value, pointer Base, register unsigned long Offset);
595 static void
596 writeSparse16(int Value, pointer Base, register unsigned long Offset);
597 static void
598 writeSparse32(int Value, pointer Base, register unsigned long Offset);
599
600 #define DENSE_BASE 0x2ff00000000UL
601 #define SPARSE_BASE 0x30000000000UL
602
603 static unsigned long msb_set = 0;
604
605 static pointer
606 mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size,
607 int flags)
608 {
609 int fd, prot;
610 unsigned long ret, rets = 0;
611
612 static Bool was_here = FALSE;
613
614 if (!was_here) {
615 was_here = TRUE;
616
617 xf86WriteMmio8 = writeSparse8;
618 xf86WriteMmio16 = writeSparse16;
619 xf86WriteMmio32 = writeSparse32;
620 xf86WriteMmioNB8 = writeSparseNB8;
621 xf86WriteMmioNB16 = writeSparseNB16;
622 xf86WriteMmioNB32 = writeSparseNB32;
623 xf86ReadMmio8 = readSparse8;
624 xf86ReadMmio16 = readSparse16;
625 xf86ReadMmio32 = readSparse32;
626 }
627
628 fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
629 if (fd < 0) {
630 FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n",
631 strerror(errno));
632 }
633
634 #if 0
635 xf86Msg(X_INFO, "mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n",
636 Base, Size, flags);
637 #endif
638
639 if (flags & VIDMEM_READONLY)
640 prot = PROT_READ;
641 else
642 prot = PROT_READ | PROT_WRITE;
643
644 /* This requirers linux-0.99.pl10 or above */
645
646 /*
647 * Always do DENSE mmap, since read32/write32 currently require it.
648 */
649 ret = (unsigned long) mmap((caddr_t) (DENSE_BASE + Base), Size,
650 prot, MAP_SHARED, fd, (off_t) (bus_base + Base));
651
652 /*
653 * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER
654 * and SPARSE (which should require the use of read/write macros).
655 *
656 * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K
657 * bytes worth of pagetable (32 pages).
658 */
659 if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) ||
660 ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) {
661 rets = (unsigned long) mmap((caddr_t) (SPARSE_BASE + (Base << 5)),
662 Size << 5, prot, MAP_SHARED, fd,
663 (off_t) _bus_base_sparse() + (Base << 5));
664 }
665
666 close(fd);
667
668 if (ret == (unsigned long) MAP_FAILED) {
669 FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n",
670 strerror(errno));
671 }
672
673 if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) ||
674 ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) {
675 if (rets == (unsigned long) MAP_FAILED ||
676 rets != (SPARSE_BASE + (Base << 5))) {
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", Base, Size, ret);
690
691 #endif
692 return (pointer) ret;
693 }
694
695 static void
696 unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size)
697 {
698 unsigned long Offset = (unsigned long) Base - DENSE_BASE;
699
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
711 static int
712 readSparse8(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
735 static int
736 readSparse16(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
759 static int
760 readSparse32(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
767 static void
768 writeSparse8(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
788 static void
789 writeSparse16(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
809 static void
810 writeSparse32(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
818 static void
819 writeSparseNB8(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
836 static void
837 writeSparseNB16(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
854 static void
855 writeSparseNB32(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
862 void (*xf86WriteMmio8) (int Value, pointer Base, unsigned long Offset)
863 = writeDense8;
864 void (*xf86WriteMmio16) (int Value, pointer Base, unsigned long Offset)
865 = writeDense16;
866 void (*xf86WriteMmio32) (int Value, pointer Base, unsigned long Offset)
867 = writeDense32;
868 void (*xf86WriteMmioNB8) (int Value, pointer Base, unsigned long Offset)
869 = writeDenseNB8;
870 void (*xf86WriteMmioNB16) (int Value, pointer Base, unsigned long Offset)
871 = writeDenseNB16;
872 void (*xf86WriteMmioNB32) (int Value, pointer Base, unsigned long Offset)
873 = writeDenseNB32;
874 int (*xf86ReadMmio8) (pointer Base, unsigned long Offset)
875 = readDense8;
876 int (*xf86ReadMmio16) (pointer Base, unsigned long Offset)
877 = readDense16;
878 int (*xf86ReadMmio32) (pointer Base, unsigned long Offset)
879 = readDense32;
880
881 #endif /* __alpha__ */