Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / bsd / alpha_video.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 1992 by Rich Murphey <Rich@Rice.edu>
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 Rich Murphey and David Wexelblat
10 * not be used in advertising or publicity pertaining to distribution of
11 * the software without specific, written prior permission. Rich Murphey and
12 * 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 * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
17 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
19 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * 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 <X11/X.h>
31#include "xf86.h"
32#include "xf86Priv.h"
33
34#include <sys/param.h>
35#ifndef __NetBSD__
36#include <sys/sysctl.h>
37#endif
38#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
39#include <machine/sysarch.h>
40#endif
41
42#include "xf86Axp.h"
43
44#include "xf86_OSlib.h"
45#include "xf86OSpriv.h"
46
47#if defined(__NetBSD__) && !defined(MAP_FILE)
48#define MAP_FLAGS MAP_SHARED
49#else
50#define MAP_FLAGS (MAP_FILE | MAP_SHARED)
51#endif
52
53axpDevice bsdGetAXP(void);
54
55#ifndef __NetBSD__
56extern unsigned long dense_base(void);
57
58static int axpSystem = -1;
59static unsigned long hae_thresh;
60static unsigned long hae_mask;
61
62static unsigned long
63memory_base(void)
64{
65 static unsigned long base = 0;
66
67 if (base == 0) {
68 size_t len = sizeof(base);
69 int error;
70
71#ifdef __OpenBSD__
72 int mib[3];
73
74 mib[0] = CTL_MACHDEP;
75 mib[1] = CPU_CHIPSET;
76 mib[2] = CPU_CHIPSET_MEM;
77
78 if ((error = sysctl(mib, 3, &base, &len, NULL, 0)) < 0)
79#else
80 if ((error = sysctlbyname("hw.chipset.memory", &base, &len, 0, 0)) < 0)
81#endif
82 FatalError("xf86MapVidMem: can't find memory\n");
83 }
84
85 return base;
86}
87
88static int
89has_bwx(void)
90{
91 static int bwx = 0;
92 size_t len = sizeof(bwx);
93 int error;
94
95#ifdef __OpenBSD__
96 int mib[3];
97
98 mib[0] = CTL_MACHDEP;
99 mib[1] = CPU_CHIPSET;
100 mib[2] = CPU_CHIPSET_BWX;
101
102 if ((error = sysctl(mib, 3, &bwx, &len, NULL, 0)) < 0)
103 return FALSE;
104 else
105 return bwx;
106#else
107 if ((error = sysctlbyname("hw.chipset.bwx", &bwx, &len, 0, 0)) < 0)
108 return FALSE;
109 else
110 return bwx;
111#endif
112}
113#else /* __NetBSD__ */
114static unsigned long hae_thresh = (1UL << 24);
115static unsigned long hae_mask = 0xf8000000UL; /* XXX - should use xf86AXP.c */
116static struct alpha_bus_window *abw;
117static int abw_count = -1;
118
119static void
120init_abw(void)
121{
122 if (abw_count < 0) {
123 abw_count = alpha_bus_getwindows(ALPHA_BUS_TYPE_PCI_MEM, &abw);
124 if (abw_count <= 0)
125 FatalError("init_abw: alpha_bus_getwindows failed\n");
126 }
127}
128
129static int
130has_bwx(void)
131{
132 if (abw_count < 0)
133 init_abw();
134
135 xf86Msg(X_INFO, "has_bwx = %d\n", abw[0].abw_abst.abst_flags & ABST_BWX ? 1 : 0); /* XXXX */
136 return abw[0].abw_abst.abst_flags & ABST_BWX;
137}
138
139static unsigned long
140dense_base(void)
141{
142 if (abw_count < 0)
143 init_abw();
144
145 /* XXX check abst_flags for ABST_DENSE just to be safe? */
146 xf86Msg(X_INFO, "dense base = %#lx\n", abw[0].abw_abst.abst_sys_start); /* XXXX */
147 return abw[0].abw_abst.abst_sys_start;
148}
149
150static unsigned long
151memory_base(void)
152{
153 if (abw_count < 0)
154 init_abw();
155
156 if (abw_count > 1) {
157 xf86Msg(X_INFO, "memory base = %#lx\n", abw[1].abw_abst.abst_sys_start); /* XXXX */
158 return abw[1].abw_abst.abst_sys_start;
159 }
160 else if (abw_count == 1) {
161 /* assume memory_base == dense_base */
162 xf86Msg(X_INFO, "memory base = %#lx\n", abw[0].abw_abst.abst_sys_start); /* XXXX */
163 return abw[0].abw_abst.abst_sys_start;
164 }
165 else {
166 xf86Msg(X_INFO, "no memory base\n"); /* XXXX */
167 return 0;
168 }
169}
170#endif /* __NetBSD__ */
171
172#define BUS_BASE dense_base()
173#define BUS_BASE_BWX memory_base()
174
175/***************************************************************************/
176/* Video Memory Mapping section */
177/***************************************************************************/
178
179#ifdef __OpenBSD__
180#define SYSCTL_MSG "\tCheck that you have set 'machdep.allowaperture=1'\n"\
181 "\tin /etc/sysctl.conf and reboot your machine\n" \
182 "\trefer to xf86(4) for details"
183#endif
184
185static Bool useDevMem = FALSE;
186static int devMemFd = -1;
187
188#ifdef HAS_APERTURE_DRV
189#define DEV_APERTURE "/dev/xf86"
190#endif
191
192static pointer mapVidMem(int, unsigned long, unsigned long, int);
193static void unmapVidMem(int, pointer, unsigned long);
194static pointer mapVidMemSparse(int, unsigned long, unsigned long, int);
195static void unmapVidMemSparse(int, pointer, unsigned long);
196
197/*
198 * Check if /dev/mem can be mmap'd. If it can't print a warning when
199 * "warn" is TRUE.
200 */
201static void
202checkDevMem(Bool warn)
203{
204 static Bool devMemChecked = FALSE;
205 int fd;
206 pointer base;
207
208 if (devMemChecked)
209 return;
210 devMemChecked = TRUE;
211
212#ifdef HAS_APERTURE_DRV
213 /* Try the aperture driver first */
214 if ((fd = open(DEV_APERTURE, O_RDWR)) >= 0) {
215 /* Try to map a page at the VGA address */
216 base = mmap((caddr_t) 0, 4096, PROT_READ | PROT_WRITE,
217 MAP_FLAGS, fd, (off_t) 0xA0000 + BUS_BASE);
218
219 if (base != MAP_FAILED) {
220 munmap((caddr_t) base, 4096);
221 devMemFd = fd;
222 useDevMem = TRUE;
223 xf86Msg(X_INFO, "checkDevMem: using aperture driver %s\n",
224 DEV_APERTURE);
225 return;
226 }
227 else {
228 if (warn) {
229 xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n",
230 DEV_APERTURE, strerror(errno));
231 }
232 }
233 }
234#endif
235 if ((fd = open(DEV_MEM, O_RDWR)) >= 0) {
236 /* Try to map a page at the VGA address */
237 base = mmap((caddr_t) 0, 4096, PROT_READ | PROT_WRITE,
238 MAP_FLAGS, fd, (off_t) 0xA0000 + BUS_BASE);
239
240 if (base != MAP_FAILED) {
241 munmap((caddr_t) base, 4096);
242 devMemFd = fd;
243 useDevMem = TRUE;
244 return;
245 }
246 else {
247 if (warn) {
248 xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n",
249 DEV_MEM, strerror(errno));
250 }
251 }
252 }
253 if (warn) {
254#ifndef HAS_APERTURE_DRV
255 xf86Msg(X_WARNING, "checkDevMem: failed to open/mmap %s (%s)\n",
256 DEV_MEM, strerror(errno));
257#else
258#ifndef __OpenBSD__
259 xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n"
260 "\t(%s)\n", DEV_APERTURE, DEV_MEM, strerror(errno));
261#else /* __OpenBSD__ */
262 xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n"
263 "\t(%s)\n%s", DEV_APERTURE, DEV_MEM, strerror(errno),
264 SYSCTL_MSG);
265#endif /* __OpenBSD__ */
266#endif
267 xf86ErrorF("\tlinear framebuffer access unavailable\n");
268 }
269 useDevMem = FALSE;
270 return;
271}
272
273void
274xf86OSInitVidMem(VidMemInfoPtr pVidMem)
275{
276 checkDevMem(TRUE);
277 pVidMem->linearSupported = useDevMem;
278
279 if (has_bwx()) {
280 xf86Msg(X_PROBED, "Machine type has 8/16 bit access\n");
281 pVidMem->mapMem = mapVidMem;
282 pVidMem->unmapMem = unmapVidMem;
283 }
284 else {
285 xf86Msg(X_PROBED, "Machine needs sparse mapping\n");
286 pVidMem->mapMem = mapVidMemSparse;
287 pVidMem->unmapMem = unmapVidMemSparse;
288#ifndef __NetBSD__
289 if (axpSystem == -1)
290 axpSystem = bsdGetAXP();
291 hae_thresh = xf86AXPParams[axpSystem].hae_thresh;
292 hae_mask = xf86AXPParams[axpSystem].hae_mask;
293#endif /* __NetBSD__ */
294 }
295 pVidMem->initialised = TRUE;
296}
297
298static pointer
299mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
300{
301 pointer base;
302
303 checkDevMem(FALSE);
304 Base = Base & ((1L << 32) - 1);
305
306 if (useDevMem) {
307 if (devMemFd < 0) {
308 FatalError("xf86MapVidMem: failed to open %s (%s)\n",
309 DEV_MEM, strerror(errno));
310 }
311 base = mmap((caddr_t) 0, Size,
312 (flags & VIDMEM_READONLY) ?
313 PROT_READ : (PROT_READ | PROT_WRITE),
314 MAP_FLAGS, devMemFd, (off_t) Base + BUS_BASE_BWX);
315 if (base == MAP_FAILED) {
316 FatalError("%s: could not mmap %s [s=%lx,a=%lx] (%s)\n",
317 "xf86MapVidMem", DEV_MEM, Size, Base, strerror(errno));
318 }
319 return base;
320 }
321
322 /* else, mmap /dev/vga */
323 if ((unsigned long) Base < 0xA0000 || (unsigned long) Base >= 0xC0000) {
324 FatalError("%s: Address 0x%lx outside allowable range\n",
325 "xf86MapVidMem", Base);
326 }
327 base = mmap(0, Size,
328 (flags & VIDMEM_READONLY) ?
329 PROT_READ : (PROT_READ | PROT_WRITE),
330 MAP_FLAGS, xf86Info.consoleFd, (unsigned long) Base + BUS_BASE);
331 if (base == MAP_FAILED) {
332 FatalError("xf86MapVidMem: Could not mmap /dev/vga (%s)\n",
333 strerror(errno));
334 }
335 return base;
336}
337
338static void
339unmapVidMem(int ScreenNum, pointer Base, unsigned long Size)
340{
341 munmap((caddr_t) Base, Size);
342}
343
344/*
345 * Read BIOS via mmap()ing DEV_MEM
346 */
347
348int
349xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf,
350 int Len)
351{
352 unsigned char *ptr;
353 int psize;
354 int mlen;
355
356 checkDevMem(TRUE);
357 if (devMemFd == -1) {
358 return -1;
359 }
360
361 psize = getpagesize();
362 Offset += Base & (psize - 1);
363 Base &= ~(psize - 1);
364 mlen = (Offset + Len + psize - 1) & ~(psize - 1);
365 ptr = (unsigned char *) mmap((caddr_t) 0, mlen, PROT_READ,
366 MAP_SHARED, devMemFd, (off_t) Base + BUS_BASE);
367 if ((long) ptr == -1) {
368 xf86Msg(X_WARNING,
369 "xf86ReadBIOS: %s mmap[s=%x,a=%lx,o=%lx] failed (%s)\n",
370 DEV_MEM, Len, Base, Offset, strerror(errno));
371 return -1;
372 }
373#ifdef DEBUG
374 xf86MsgVerb(X_INFO, 3,
375 "xf86ReadBIOS: BIOS at 0x%08x has signature 0x%04x\n", Base,
376 ptr[0] | (ptr[1] << 8));
377#endif
378 (void) memcpy(Buf, (void *) (ptr + Offset), Len);
379 (void) munmap((caddr_t) ptr, mlen);
380#ifdef DEBUG
381 xf86MsgVerb(X_INFO, 3, "xf86ReadBIOS(%x, %x, Buf, %x)"
382 "-> %02x %02x %02x %02x...\n",
383 Base, Offset, Len, Buf[0], Buf[1], Buf[2], Buf[3]);
384#endif
385 return Len;
386}
387
388#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
389
390extern int ioperm(unsigned long from, unsigned long num, int on);
391
392Bool
393xf86EnableIO()
394{
395 if (!ioperm(0, 65536, TRUE))
396 return TRUE;
397 return FALSE;
398}
399
400void
401xf86DisableIO()
402{
403 return;
404}
405
406#endif /* __FreeBSD_kernel__ || __OpenBSD__ */
407
408#ifdef USE_ALPHA_PIO
409
410Bool
411xf86EnableIO()
412{
413 alpha_pci_io_enable(1);
414 return TRUE;
415}
416
417void
418xf86DisableIO()
419{
420 alpha_pci_io_enable(0);
421}
422
423#endif /* USE_ALPHA_PIO */
424
425#define vuip volatile unsigned int *
426
427static pointer memSBase = 0;
428static pointer memBase = 0;
429
430extern int readDense8(pointer Base, register unsigned long Offset);
431extern int readDense16(pointer Base, register unsigned long Offset);
432extern int readDense32(pointer Base, register unsigned long Offset);
433extern void
434 writeDenseNB8(int Value, pointer Base, register unsigned long Offset);
435extern void
436 writeDenseNB16(int Value, pointer Base, register unsigned long Offset);
437extern void
438 writeDenseNB32(int Value, pointer Base, register unsigned long Offset);
439extern void
440 writeDense8(int Value, pointer Base, register unsigned long Offset);
441extern void
442 writeDense16(int Value, pointer Base, register unsigned long Offset);
443extern void
444 writeDense32(int Value, pointer Base, register unsigned long Offset);
445
446static int readSparse8(pointer Base, register unsigned long Offset);
447static int readSparse16(pointer Base, register unsigned long Offset);
448static int readSparse32(pointer Base, register unsigned long Offset);
449static void
450 writeSparseNB8(int Value, pointer Base, register unsigned long Offset);
451static void
452 writeSparseNB16(int Value, pointer Base, register unsigned long Offset);
453static void
454 writeSparseNB32(int Value, pointer Base, register unsigned long Offset);
455static void
456 writeSparse8(int Value, pointer Base, register unsigned long Offset);
457static void
458 writeSparse16(int Value, pointer Base, register unsigned long Offset);
459static void
460 writeSparse32(int Value, pointer Base, register unsigned long Offset);
461
462#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
463extern int sysarch(int, void *);
464
465struct parms {
466 u_int64_t hae;
467};
468
469static void
470sethae(u_int64_t hae)
471{
472#ifndef ALPHA_SETHAE
473#define ALPHA_SETHAE 0
474#endif
475 static struct parms p;
476
477 if (p.hae != hae) {
478 p.hae = hae;
479 sysarch(ALPHA_SETHAE, (char *) &p);
480 }
481}
482#endif
483
484static pointer
485mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size,
486 int flags)
487{
488 static Bool was_here = FALSE;
489
490 if (!was_here) {
491 was_here = TRUE;
492
493 checkDevMem(FALSE);
494
495 xf86WriteMmio8 = writeSparse8;
496 xf86WriteMmio16 = writeSparse16;
497 xf86WriteMmio32 = writeSparse32;
498 xf86WriteMmioNB8 = writeSparseNB8;
499 xf86WriteMmioNB16 = writeSparseNB16;
500 xf86WriteMmioNB32 = writeSparseNB32;
501 xf86ReadMmio8 = readSparse8;
502 xf86ReadMmio16 = readSparse16;
503 xf86ReadMmio32 = readSparse32;
504
505 memBase = mmap((caddr_t) 0, 0x100000000,
506 PROT_READ | PROT_WRITE,
507 MAP_SHARED, devMemFd, (off_t) BUS_BASE);
508 memSBase = mmap((caddr_t) 0, 0x100000000,
509 PROT_READ | PROT_WRITE,
510 MAP_SHARED, devMemFd, (off_t) BUS_BASE_BWX);
511
512 if (memSBase == MAP_FAILED || memBase == MAP_FAILED) {
513 FatalError("xf86MapVidMem: Could not mmap framebuffer (%s)\n",
514 strerror(errno));
515 }
516 }
517 return (pointer) ((unsigned long) memBase + Base);
518}
519
520static void
521unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size)
522{
523}
524
525static int
526readSparse8(pointer Base, register unsigned long Offset)
527{
528 register unsigned long result, shift;
529 register unsigned long msb;
530
531 mem_barrier();
532 Offset += (unsigned long) Base - (unsigned long) memBase;
533 shift = (Offset & 0x3) << 3;
534 if (Offset >= (hae_thresh)) {
535 msb = Offset & hae_mask;
536 Offset -= msb;
537#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
538 sethae(msb);
539#endif
540 }
541 result = *(vuip) ((unsigned long) memSBase + (Offset << 5));
542 result >>= shift;
543 return 0xffUL & result;
544}
545
546static int
547readSparse16(pointer Base, register unsigned long Offset)
548{
549 register unsigned long result, shift;
550 register unsigned long msb;
551
552 mem_barrier();
553 Offset += (unsigned long) Base - (unsigned long) memBase;
554 shift = (Offset & 0x2) << 3;
555 if (Offset >= (hae_thresh)) {
556 msb = Offset & hae_mask;
557 Offset -= msb;
558#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
559 sethae(msb);
560#endif
561 }
562 result =
563 *(vuip) ((unsigned long) memSBase + (Offset << 5) + (1 << (5 - 2)));
564 result >>= shift;
565 return 0xffffUL & result;
566}
567
568static int
569readSparse32(pointer Base, register unsigned long Offset)
570{
571 mem_barrier();
572 return *(vuip) ((unsigned long) Base + (Offset));
573}
574
575static void
576writeSparse8(int Value, pointer Base, register unsigned long Offset)
577{
578 register unsigned long msb;
579 register unsigned int b = Value & 0xffU;
580
581 write_mem_barrier();
582 Offset += (unsigned long) Base - (unsigned long) memBase;
583 if (Offset >= (hae_thresh)) {
584 msb = Offset & hae_mask;
585 Offset -= msb;
586#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
587 sethae(msb);
588#endif
589 }
590 *(vuip) ((unsigned long) memSBase + (Offset << 5)) = b * 0x01010101;
591}
592
593static void
594writeSparse16(int Value, pointer Base, register unsigned long Offset)
595{
596 register unsigned long msb;
597 register unsigned int w = Value & 0xffffU;
598
599 write_mem_barrier();
600 Offset += (unsigned long) Base - (unsigned long) memBase;
601 if (Offset >= (hae_thresh)) {
602 msb = Offset & hae_mask;
603 Offset -= msb;
604#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
605 sethae(msb);
606#endif
607 }
608 *(vuip) ((unsigned long) memSBase + (Offset << 5) + (1 << (5 - 2))) =
609 w * 0x00010001;
610
611}
612
613static void
614writeSparse32(int Value, pointer Base, register unsigned long Offset)
615{
616 write_mem_barrier();
617 *(vuip) ((unsigned long) Base + (Offset)) = Value;
618 return;
619}
620
621static void
622writeSparseNB8(int Value, pointer Base, register unsigned long Offset)
623{
624 register unsigned long msb;
625 register unsigned int b = Value & 0xffU;
626
627 Offset += (unsigned long) Base - (unsigned long) memBase;
628 if (Offset >= (hae_thresh)) {
629 msb = Offset & hae_mask;
630 Offset -= msb;
631#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
632 sethae(msb);
633#endif
634 }
635 *(vuip) ((unsigned long) memSBase + (Offset << 5)) = b * 0x01010101;
636}
637
638static void
639writeSparseNB16(int Value, pointer Base, register unsigned long Offset)
640{
641 register unsigned long msb;
642 register unsigned int w = Value & 0xffffU;
643
644 Offset += (unsigned long) Base - (unsigned long) memBase;
645 if (Offset >= (hae_thresh)) {
646 msb = Offset & hae_mask;
647 Offset -= msb;
648#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
649 sethae(msb);
650#endif
651 }
652 *(vuip) ((unsigned long) memSBase + (Offset << 5) + (1 << (5 - 2))) =
653 w * 0x00010001;
654}
655
656static void
657writeSparseNB32(int Value, pointer Base, register unsigned long Offset)
658{
659 *(vuip) ((unsigned long) Base + (Offset)) = Value;
660 return;
661}
662
663void (*xf86WriteMmio8) (int Value, pointer Base, unsigned long Offset)
664 = writeDense8;
665void (*xf86WriteMmio16) (int Value, pointer Base, unsigned long Offset)
666 = writeDense16;
667void (*xf86WriteMmio32) (int Value, pointer Base, unsigned long Offset)
668 = writeDense32;
669void (*xf86WriteMmioNB8) (int Value, pointer Base, unsigned long Offset)
670 = writeDenseNB8;
671void (*xf86WriteMmioNB16) (int Value, pointer Base, unsigned long Offset)
672 = writeDenseNB16;
673void (*xf86WriteMmioNB32) (int Value, pointer Base, unsigned long Offset)
674 = writeDenseNB32;
675int (*xf86ReadMmio8) (pointer Base, unsigned long Offset)
676 = readDense8;
677int (*xf86ReadMmio16) (pointer Base, unsigned long Offset)
678 = readDense16;
679int (*xf86ReadMmio32) (pointer Base, unsigned long Offset)
680 = readDense32;