Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / linux / lnx_video.c
CommitLineData
a09e091a
JB
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
49static 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 */
68extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on);
69extern 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
83static pointer mapVidMem(int, unsigned long, unsigned long, int);
84static void unmapVidMem(int, pointer, unsigned long);
85
86#if defined (__alpha__)
87extern void sethae(unsigned long hae);
88extern unsigned long _bus_base __P((void)) __attribute__ ((const));
89extern unsigned long _bus_base_sparse __P((void)) __attribute__ ((const));
90
91static pointer mapVidMemSparse(int, unsigned long, unsigned long, int);
92extern axpDevice lnxGetAXP(void);
93static void unmapVidMemSparse(int, pointer, unsigned long);
94static axpDevice axpSystem = -1;
95static Bool needSparse;
96static unsigned long hae_thresh;
97static unsigned long hae_mask;
98static unsigned long bus_base;
99#endif
100
101#ifdef HAS_MTRR_SUPPORT
102
103#define SPLIT_WC_REGIONS 1
104
105static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType);
106static 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. */
113static 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. */
118static Bool
119mtrr_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
151struct mtrr_wc_region {
152 struct mtrr_sentry sentry;
153 Bool added; /* added WC or removed it */
154 struct mtrr_wc_region *next;
155};
156
157static struct mtrr_wc_region *
158mtrr_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
213static struct mtrr_wc_region *
214mtrr_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
240static struct mtrr_wc_region *
241mtrr_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
325static void
326mtrr_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
342static pointer
343setWC(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
352static void
353undoWC(int screenNum, pointer regioninfo)
354{
355 mtrr_undo_wc_region(screenNum, regioninfo);
356}
357
358#endif /* HAS_MTRR_SUPPORT */
359
360void
361xf86OSInitVidMem(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 */
399static pointer
400mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
401{
402 return NULL;
403}
404#else
405static pointer
406mapVidMem(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
462static void
463unmapVidMem(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__)
477volatile unsigned char *ioBase = NULL;
478
479#ifndef __NR_pciconfig_iobase
480#define __NR_pciconfig_iobase 200
481#endif
482
483static Bool
484hwEnableIO(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
500static void
501hwDisableIO(void)
502{
503 munmap(ioBase, 0x20000);
504 ioBase = NULL;
505}
506
507#elif defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || \
508 defined(__alpha__)
509
510static Bool
511hwEnableIO(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
528static void
529hwDisableIO(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
542Bool
543xf86EnableIO(void)
544{
545 if (ExtendedEnabled)
546 return TRUE;
547
548 ExtendedEnabled = hwEnableIO();
549
550 return ExtendedEnabled;
551}
552
553void
554xf86DisableIO(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
568extern int readDense8(pointer Base, register unsigned long Offset);
569extern int readDense16(pointer Base, register unsigned long Offset);
570extern int readDense32(pointer Base, register unsigned long Offset);
571extern void
572 writeDenseNB8(int Value, pointer Base, register unsigned long Offset);
573extern void
574 writeDenseNB16(int Value, pointer Base, register unsigned long Offset);
575extern void
576 writeDenseNB32(int Value, pointer Base, register unsigned long Offset);
577extern void
578 writeDense8(int Value, pointer Base, register unsigned long Offset);
579extern void
580 writeDense16(int Value, pointer Base, register unsigned long Offset);
581extern void
582 writeDense32(int Value, pointer Base, register unsigned long Offset);
583
584static int readSparse8(pointer Base, register unsigned long Offset);
585static int readSparse16(pointer Base, register unsigned long Offset);
586static int readSparse32(pointer Base, register unsigned long Offset);
587static void
588 writeSparseNB8(int Value, pointer Base, register unsigned long Offset);
589static void
590 writeSparseNB16(int Value, pointer Base, register unsigned long Offset);
591static void
592 writeSparseNB32(int Value, pointer Base, register unsigned long Offset);
593static void
594 writeSparse8(int Value, pointer Base, register unsigned long Offset);
595static void
596 writeSparse16(int Value, pointer Base, register unsigned long Offset);
597static void
598 writeSparse32(int Value, pointer Base, register unsigned long Offset);
599
600#define DENSE_BASE 0x2ff00000000UL
601#define SPARSE_BASE 0x30000000000UL
602
603static unsigned long msb_set = 0;
604
605static pointer
606mapVidMemSparse(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
695static void
696unmapVidMemSparse(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
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__ */