diff options
Diffstat (limited to 'hw/xfree86/os-support/linux')
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_init.c | 119 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_io.c | 225 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_jstk.c | 77 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_video.c | 1370 |
4 files changed, 1203 insertions, 588 deletions
diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c index 1c0791abb..0ac8c6a8b 100644 --- a/hw/xfree86/os-support/linux/lnx_init.c +++ b/hw/xfree86/os-support/linux/lnx_init.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c,v 3.7.2.3 1998/02/06 22:36:51 hohndel Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c,v 3.14 2001/10/31 22:50:30 tsi Exp $ */ /* * Copyright 1992 by Orest Zborowski <obz@Kodak.com> * Copyright 1993 by David Wexelblat <dwex@goblin.org> @@ -23,18 +23,17 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ -/* $Xorg: lnx_init.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ +/* $XConsortium: lnx_init.c /main/7 1996/10/23 18:46:30 kaleb $ */ #include "X.h" #include "Xmd.h" -#include "input.h" -#include "scrnintstr.h" #include "compiler.h" #include "xf86.h" -#include "xf86Procs.h" +#include "xf86Priv.h" #include "xf86_OSlib.h" +#include "lnx.h" #ifdef USE_DEV_FB extern char *getenv(const char *); @@ -46,52 +45,50 @@ static Bool KeepTty = FALSE; static int VTnum = -1; static int activeVT = -1; -extern void xf86VTRequest( -#if NeedFunctionPrototypes - int -#endif -); - -void xf86OpenConsole() +void +xf86OpenConsole(void) { - int i, fd; + int i, fd = -1; + int result; struct vt_mode VT; char vtname[11]; struct vt_stat vts; + MessageType from = X_PROBED; #ifdef USE_DEV_FB struct fb_var_screeninfo var; int fbfd; #endif + char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; if (serverGeneration == 1) { /* check if we're run with euid==0 */ if (geteuid() != 0) { - FatalError("xf86OpenConsole: Server must be running with root " - "permissions\n" - "You should be using Xwrapper to start the server or xdm.\n" - "We strongly advise against making the server SUID root!\n"); + FatalError("xf86OpenConsole: Server must be suid root\n"); } /* * setup the virtual terminal manager */ - if (VTnum != -1) - { + if (VTnum != -1) { xf86Info.vtno = VTnum; - } - else - { - if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0) + from = X_CMDLINE; + } else { + i=0; + while (tty0[i] != NULL) { + if ((fd = open(tty0[i],O_WRONLY,0)) >= 0) + break; + i++; + } + if (fd < 0) FatalError( "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n", strerror(errno)); - } if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) || - (xf86Info.vtno == -1)) - { + (xf86Info.vtno == -1)) { FatalError("xf86OpenConsole: Cannot find a free VT\n"); } close(fd); @@ -107,21 +104,24 @@ void xf86OpenConsole() if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var)) FatalError("xf86OpenConsole: Unable to get screen info\n"); #endif - ErrorF("(using VT number %d)\n\n", xf86Info.vtno); + xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); - sprintf(vtname,"/dev/tty%d",xf86Info.vtno); /* /dev/tty1-64 */ - - xf86Config(FALSE); /* Read XF86Config */ - - if (!KeepTty) - { + if (!KeepTty) { setpgrp(); } - if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0) - { - FatalError("xf86OpenConsole: Cannot open %s (%s)\n", - vtname, strerror(errno)); + i=0; + while (vcs[i] != NULL) + { + sprintf(vtname, vcs[i], xf86Info.vtno); /* /dev/tty1-64 */ + if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) >= 0) + break; + i++; + } + + if (xf86Info.consoleFd < 0) { + FatalError("xf86OpenConsole: Cannot open virtual console %d (%s)\n", + xf86Info.vtno, strerror(errno)); } /* change ownership of the vt */ @@ -131,7 +131,7 @@ void xf86OpenConsole() * the current VT device we're running on is not "console", we want * to grab all consoles too * - * Why is this needed? + * Why is this needed?? */ chown("/dev/tty0", getuid(), getgid()); @@ -159,17 +159,21 @@ void xf86OpenConsole() /* * now get the VT */ - if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno)); + if (result != 0) { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); } - if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + SYSCALL(result = + ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno)); + if (result != 0) { - ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n"); } - if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) + SYSCALL(result = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT)); + if (result < 0) { - FatalError ("xf86OpenConsole: VT_GETMODE failed\n"); + FatalError("xf86OpenConsole: VT_GETMODE failed\n"); } signal(SIGUSR1, xf86VTRequest); @@ -185,6 +189,10 @@ void xf86OpenConsole() { FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n"); } + + /* we really should have a InitOSInputDevices() function instead + * of Init?$#*&Device(). So I just place it here */ + #ifdef USE_DEV_FB /* copy info to new console */ var.yoffset=0; @@ -200,19 +208,23 @@ void xf86OpenConsole() /* * now get the VT */ - if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno)); + if (result != 0) { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); } - if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + SYSCALL(result = + ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno)); + if (result != 0) { - ErrorF("xf86OpenConsole: VT_WAITACTIVE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n"); } } return; } -void xf86CloseConsole() +void +xf86CloseConsole() { struct vt_mode VT; @@ -238,10 +250,8 @@ void xf86CloseConsole() return; } -int xf86ProcessArgument (argc, argv, i) -int argc; -char *argv[]; -int i; +int +xf86ProcessArgument(int argc, char *argv[], int i) { /* * Keep server from detaching from controlling tty. This is useful @@ -265,7 +275,8 @@ int i; return(0); } -void xf86UseMsg() +void +xf86UseMsg() { ErrorF("vtXX use the specified VT number\n"); ErrorF("-keeptty "); diff --git a/hw/xfree86/os-support/linux/lnx_io.c b/hw/xfree86/os-support/linux/lnx_io.c index 57a2979c5..741b9a279 100644 --- a/hw/xfree86/os-support/linux/lnx_io.c +++ b/hw/xfree86/os-support/linux/lnx_io.c @@ -1,7 +1,7 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c,v 3.3 1996/12/23 06:50:01 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c,v 3.24 2002/10/20 21:45:27 tsi Exp $ */ /* * Copyright 1992 by Orest Zborowski <obz@Kodak.com> - * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> + * Copyright 1993 by David Dawes <dawes@xfree86.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -23,23 +23,21 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ -/* $Xorg: lnx_io.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ +/* $XConsortium: lnx_io.c /main/8 1996/10/19 18:06:28 kaleb $ */ #define NEED_EVENTS #include "X.h" -#include "Xproto.h" -#include "inputstr.h" -#include "scrnintstr.h" #include "compiler.h" -#include "xf86Procs.h" +#include "xf86.h" +#include "xf86Priv.h" #include "xf86_OSlib.h" -void xf86SoundKbdBell(loudness, pitch, duration) -int loudness; -int pitch; -int duration; +#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ + +void +xf86SoundKbdBell(int loudness, int pitch, int duration) { if (loudness && pitch) { @@ -50,20 +48,100 @@ int duration; } } -void xf86SetKbdLeds(leds) -int leds; +void +xf86SetKbdLeds(int leds) { - ioctl(xf86Info.consoleFd, KDSETLED, leds); + ioctl(xf86Info.consoleFd, KDSETLED, leds); } -int xf86GetKbdLeds() +int +xf86GetKbdLeds() { - int leds; + int leds = 0; - ioctl(xf86Info.consoleFd, KDGETLED, &leds); + ioctl(xf86Info.consoleFd, KDGETLED, &leds); return(leds); } +/* kbd rate stuff based on kbdrate.c from Rik Faith <faith@cs.unc.edu> et.al. + * from util-linux-2.9t package */ + +#include <linux/kd.h> +#ifdef __sparc__ +#include <asm/param.h> +#include <asm/kbio.h> +#endif + +/* Deal with spurious kernel header change */ +#if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,42) +# define rate period +# endif +#endif + +static int +KDKBDREP_ioctl_ok(int rate, int delay) { +#if defined(KDKBDREP) && !defined(__sparc__) + /* This ioctl is defined in <linux/kd.h> but is not + implemented anywhere - must be in some m68k patches. */ + struct kbd_repeat kbdrep_s; + + /* don't change, just test */ + kbdrep_s.rate = -1; + kbdrep_s.delay = -1; + if (ioctl( 0, KDKBDREP, &kbdrep_s )) { + return 0; + } + + /* do the change */ + if (rate == 0) /* switch repeat off */ + kbdrep_s.rate = 0; + else + kbdrep_s.rate = 10000 / rate; /* convert cps to msec */ + if (kbdrep_s.rate < 1) + kbdrep_s.rate = 1; + kbdrep_s.delay = delay; + if (kbdrep_s.delay < 1) + kbdrep_s.delay = 1; + + if (ioctl( 0, KDKBDREP, &kbdrep_s )) { + return 0; + } + + return 1; /* success! */ +#else /* no KDKBDREP */ + return 0; +#endif /* KDKBDREP */ +} + +static int +KIOCSRATE_ioctl_ok(int rate, int delay) { +#ifdef KIOCSRATE + struct kbd_rate kbdrate_s; + int fd; + + fd = open("/dev/kbd", O_RDONLY); + if (fd == -1) + return 0; + + kbdrate_s.rate = (rate + 5) / 10; /* must be integer, so round up */ + kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */ + if (kbdrate_s.rate > 50) + kbdrate_s.rate = 50; + + if (ioctl( fd, KIOCSRATE, &kbdrate_s )) + return 0; + + close( fd ); + + return 1; +#else /* no KIOCSRATE */ + return 0; +#endif /* KIOCSRATE */ +} + +#undef rate + #if NeedFunctionPrototypes void xf86SetKbdRepeat(char rad) #else @@ -71,23 +149,101 @@ void xf86SetKbdRepeat(rad) char rad; #endif { - return; +#ifdef __sparc__ + int rate = 500; /* Default rate */ + int delay = 200; /* Default delay */ +#else + int rate = 300; /* Default rate */ + int delay = 250; /* Default delay */ +#endif + +#if defined(__alpha__) || defined (__i386__) || defined(__ia64__) + int i; + int timeout; + int value = 0x7f; /* Maximum delay with slowest rate */ + + static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, + 133, 120, 109, 100, 92, 86, 80, 75, 67, + 60, 55, 50, 46, 43, 40, 37, 33, 30, 27, + 25, 23, 21, 20 }; +#define RATE_COUNT (sizeof( valid_rates ) / sizeof( int )) + + static int valid_delays[] = { 250, 500, 750, 1000 }; +#define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int )) +#endif + + if (xf86Info.kbdRate >= 0) + rate = xf86Info.kbdRate * 10; + if (xf86Info.kbdDelay >= 0) + delay = xf86Info.kbdDelay; + + + if(KDKBDREP_ioctl_ok(rate, delay)) /* m68k? */ + return; + + if(KIOCSRATE_ioctl_ok(rate, delay)) /* sparc? */ + return; + + if (xf86IsPc98()) + return; + +#if defined(__alpha__) || defined (__i386__) || defined(__ia64__) + + /* The ioport way */ + + for (i = 0; i < RATE_COUNT; i++) + if (rate >= valid_rates[i]) { + value &= 0x60; + value |= i; + break; + } + + for (i = 0; i < DELAY_COUNT; i++) + if (delay <= valid_delays[i]) { + value &= 0x1f; + value |= i << 5; + break; + } + + timeout = KBC_TIMEOUT; + while (((inb(0x64) & 2) == 2) && --timeout) + usleep(1000); /* wait */ + + if (timeout == 0) + return; + + outb(0x60, 0xf3); /* set typematic rate */ + while (((inb(0x64) & 2) == 2) && --timeout) + usleep(1000); /* wait */ + + usleep(10000); + outb(0x60, value); + +#endif /* __alpha__ || __i386__ || __ia64__ */ } static int kbdtrans; static struct termios kbdtty; -void xf86KbdInit() +void +xf86KbdInit() { ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans); tcgetattr (xf86Info.consoleFd, &kbdtty); } -int xf86KbdOn() +int +xf86KbdOn() { struct termios nTty; +#ifdef __powerpc__ + if (xf86Info.kbdCustomKeycodes) + ioctl(xf86Info.consoleFd, KDSKBMODE, K_MEDIUMRAW); + else +#endif ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW); + nTty = kbdtty; nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); nTty.c_oflag = 0; @@ -101,36 +257,11 @@ int xf86KbdOn() return(xf86Info.consoleFd); } -int xf86KbdOff() +int +xf86KbdOff() { ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans); tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty); return(xf86Info.consoleFd); } -void xf86MouseInit(mouse) -MouseDevPtr mouse; -{ - return; -} - -int xf86MouseOn(mouse) -MouseDevPtr mouse; -{ - if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) - { - if (xf86AllowMouseOpenFail) { - ErrorF("Cannot open mouse (%s) - Continuing...\n", - strerror(errno)); - return(-2); - } - FatalError("Cannot open mouse (%s)\n", strerror(errno)); - } - - xf86SetupMouse(mouse); - - /* Flush any pending input */ - tcflush(mouse->mseFd, TCIFLUSH); - - return(mouse->mseFd); -} diff --git a/hw/xfree86/os-support/linux/lnx_jstk.c b/hw/xfree86/os-support/linux/lnx_jstk.c index ea308c159..2423bd45e 100644 --- a/hw/xfree86/os-support/linux/lnx_jstk.c +++ b/hw/xfree86/os-support/linux/lnx_jstk.c @@ -1,4 +1,4 @@ -/* $Xorg: lnx_jstk.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ +/* $XConsortium: lnx_jstk.c /main/7 1996/02/21 17:51:36 kaleb $ */ /* Id: lnx_jstk.c,v 1.1 1995/12/20 14:06:09 lepied Exp */ /* * Copyright 1995 by Frederic Lepied, France. <fred@sugix.frmug.fr.net> @@ -23,19 +23,31 @@ * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_jstk.c,v 3.6 1996/12/23 06:50:02 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_jstk.c,v 3.13 1998/07/25 16:56:43 dawes Exp $ */ -static const char rcs_id[] = "$Xorg: lnx_jstk.c,v 1.1 1995/12/20 14:06:09 lepied Exp"; +static const char rcs_id[] = "Id: lnx_jstk.c,v 1.1 1995/12/20 14:06:09 lepied Exp"; #include <sys/types.h> #include <unistd.h> #include <string.h> +#include <errno.h> #define inline __inline__ #include <linux/joystick.h> #include <fcntl.h> #include <sys/ioctl.h> -extern int errno; +#ifdef XFree86LOADER +#include "xf86.h" +#include "xf86_ansic.h" +#endif + +#if !defined(JSIOCGTIMELIMIT) +/* make 2.1.x joystick.h backward compatable */ +#define JSIOCGTIMELIMIT JS_GET_TIMELIMIT +#define JSIOCSTIMELIMIT JS_SET_TIMELIMIT +#define js_status JS_DATA_TYPE +#endif + /*********************************************************************** * @@ -50,33 +62,30 @@ int xf86JoystickOn(char *name, int *timeout, int *centerX, int *centerY) { int fd; - struct JS_DATA_TYPE js; - extern int xf86Verbose; + struct js_status js; #ifdef DEBUG ErrorF("xf86JoystickOn %s\n", name); #endif - if ((fd = open(name, O_RDWR | O_NDELAY)) < 0) + if ((fd = open(name, O_RDWR | O_NDELAY, 0)) < 0) { - ErrorF("Cannot open joystick '%s' (%s)\n", name, - strerror(errno)); + xf86Msg(X_WARNING, "Cannot open joystick '%s' (%s)\n", name, + strerror(errno)); return -1; } if (*timeout == 0) { - if (ioctl (fd, JS_GET_TIMELIMIT, timeout) == -1) { - Error("joystick JS_GET_TIMELIMIT ioctl"); + if (ioctl (fd, JSIOCGTIMELIMIT, timeout) == -1) { + Error("joystick JSIOCGTIMELIMIT ioctl"); } else { - if (xf86Verbose) { - ErrorF("(--) Joystick: timeout value = %d\n", *timeout); - } + xf86Msg(X_CONFIG, "Joystick: timeout value = %d\n", *timeout); } } else { - if (ioctl(fd, JS_SET_TIMELIMIT, timeout) == -1) { - Error("joystick JS_SET_TIMELIMIT ioctl"); + if (ioctl(fd, JSIOCSTIMELIMIT, timeout) == -1) { + Error("joystick JSIOCSTIMELIMIT ioctl"); } } @@ -84,17 +93,13 @@ xf86JoystickOn(char *name, int *timeout, int *centerX, int *centerY) read(fd, &js, JS_RETURN); if (*centerX < 0) { *centerX = js.x; - if (xf86Verbose) { - ErrorF("(--) Joystick: CenterX set to %d\n", *centerX); - } + xf86Msg(X_CONFIG, "Joystick: CenterX set to %d\n", *centerX); } if (*centerY < 0) { *centerY = js.y; - if (xf86Verbose) { - ErrorF("(--) Joystick: CenterY set to %d\n", *centerY); - } + xf86Msg(X_CONFIG, "Joystick: CenterY set to %d\n", *centerY); } - + return fd; } @@ -123,9 +128,7 @@ xf86JoystickInit() */ int -xf86JoystickOff(fd, doclose) -int *fd; -int doclose; +xf86JoystickOff(int *fd, int doclose) { int oldfd; @@ -146,14 +149,10 @@ int doclose; */ int -xf86JoystickGetState(fd, x, y, buttons) -int fd; -int *x; -int *y; -int *buttons; +xf86JoystickGetState(int fd, int *x, int *y, int *buttons) { - struct JS_DATA_TYPE js; - int status; + struct js_status js; + int status; status = read(fd, &js, JS_RETURN); @@ -170,4 +169,16 @@ int *buttons; return 1; } +#ifdef XFree86LOADER +/* + * Entry point for XFree86 Loader + */ +void +linux_jstkModuleInit(pointer *data, INT32 *magic) +{ + *magic = MAGIC_DONE; + *data = NULL; +} +#endif + /* end of lnx_jstk.c */ diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c index a29db8251..107d5595e 100644 --- a/hw/xfree86/os-support/linux/lnx_video.c +++ b/hw/xfree86/os-support/linux/lnx_video.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_video.c,v 3.13.2.1 1997/05/11 05:04:25 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_video.c,v 3.64 2003/02/17 15:29:22 dawes Exp $ */ /* * Copyright 1992 by Orest Zborowski <obz@Kodak.com> * Copyright 1993 by David Wexelblat <dwex@goblin.org> @@ -23,7 +23,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ -/* $Xorg: lnx_video.c,v 1.3 2000/08/17 19:51:23 cpqbld Exp $ */ +/* $XConsortium: lnx_video.c /main/9 1996/10/19 18:06:34 kaleb $ */ #include "X.h" #include "input.h" @@ -32,603 +32,1065 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" - +#include "xf86OSpriv.h" +#include "lnx.h" #ifdef __alpha__ +#include "xf86Axp.h" +#endif -/* - * The Jensen lacks dense memory, thus we have to address the bus via - * the sparse addressing scheme. - * - * Martin Ostermann (ost@comnets.rwth-aachen.de) - Apr.-Sep. 1996 - */ - -#ifdef TEST_JENSEN_CODE /* define to test the Sparse addressing on a non-Jensen */ -#define SPARSE (5) -#define isJensen (1) -#else -#define isJensen (!_bus_base()) -#define SPARSE (7) +#ifdef HAS_MTRR_SUPPORT +#include <asm/mtrr.h> #endif -#define BUS_BASE (isJensen ? _bus_base_sparse() : _bus_base()) -#define JENSEN_SHIFT(x) (isJensen ? ((long)x<<SPARSE) : (long)x) -#else -#define BUS_BASE 0 -#define JENSEN_SHIFT(x) (x) +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) #endif -/***************************************************************************/ -/* Video Memory Mapping section */ -/***************************************************************************/ +static Bool ExtendedEnabled = FALSE; + +#ifdef __ia64__ + +#include "compiler.h" +#include <sys/io.h> + +#elif !defined(__powerpc__) && \ + !defined(__mc68000__) && \ + !defined(__sparc__) && \ + !defined(__mips__) /* - * Unfortunatly mmap without MAP_FIXED only works the first time :-( - * This is now fixed in pl13 ALPHA, but still seems to have problems. + * Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare + * these. */ -#undef ONLY_MMAP_FIXED_WORKS +extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); +extern int iopl(int __level); -#ifdef ONLY_MMAP_FIXED_WORKS -static pointer AllocAddress[MAXSCREENS][NUM_REGIONS]; #endif -#if 0 -static struct xf86memMap { - int offset; - int memSize; -} xf86memMaps[MAXSCREENS]; -#endif +#ifdef __alpha__ -pointer xf86MapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; -{ - pointer base; - int fd; +# ifdef LIBC_IS_FIXED +extern void sethae(unsigned long hae); +# else +# include <unistd.h> +# define sethae(x) syscall(301,x); +# endif -#ifdef ONLY_MMAP_FIXED_WORKS -#ifdef __alpha__ - FatalError("xf86MapVidMem: Unexpected code for Alpha (pagesize=8k!)\n"); -#endif - AllocAddress[ScreenNum][Region] = (pointer)xalloc(Size + 0x1000); - if (AllocAddress[ScreenNum][Region] == NULL) - { - FatalError("xf86MapVidMem: can't alloc framebuffer space\n"); - } - base = (pointer)(((unsigned int)AllocAddress[ScreenNum][Region] - & ~0xFFF) + 0x1000); - if ((fd = open("/dev/mem", O_RDWR)) < 0) - { - FatalError("xf86MapVidMem: failed to open /dev/mem (%s)\n", - strerror(errno)); - } - base = (pointer)mmap((caddr_t)base, Size, PROT_READ|PROT_WRITE, - MAP_FIXED|MAP_SHARED, fd, (off_t)Base); -#else - if ((fd = open("/dev/mem", O_RDWR)) < 0) - { - FatalError("xf86MapVidMem: failed to open /dev/mem (%s)\n", - strerror(errno)); - } - /* This requirers linux-0.99.pl10 or above */ - base = (pointer)mmap((caddr_t)0, JENSEN_SHIFT(Size), - PROT_READ|PROT_WRITE, - MAP_SHARED, fd, - (off_t)(JENSEN_SHIFT((off_t)Base) + BUS_BASE)); -#endif - close(fd); - if ((long)base == -1) - { - FatalError("xf86MapVidMem: Could not mmap framebuffer (%s)\n", - strerror(errno)); - } -#if 0 - xf86memMaps[ScreenNum].offset = (int) Base; - xf86memMaps[ScreenNum].memSize = Size; -#endif - return base; -} +/* define to test the Sparse addressing on a non-Jensen */ +# ifdef TEST_JENSEN_CODE +# define isJensen (1) +# else +# define isJensen (axpSystem == JENSEN) +# endif -#if 0 -void xf86GetVidMemData(ScreenNum, Base, Size) -int ScreenNum; -int *Base; -int *Size; -{ - *Base = xf86memMaps[ScreenNum].offset; - *Size = xf86memMaps[ScreenNum].memSize; -} -#endif +# define BUS_BASE bus_base -void xf86UnMapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; -{ - munmap((caddr_t)JENSEN_SHIFT(Base), JENSEN_SHIFT(Size)); -#ifdef ONLY_MMAP_FIXED_WORKS - xfree(AllocAddress[ScreenNum][Region]); -#endif -} +#else -Bool xf86LinearVidMem() -{ - return(TRUE); -} +#define BUS_BASE (0) + +#endif /* __alpha__ */ /***************************************************************************/ -/* I/O Permissions section */ +/* Video Memory Mapping section */ /***************************************************************************/ -/* - * Linux handles regular (<= 0x3ff) ports with the TSS I/O bitmap, and - * extended ports with the iopl() system call. - * - * For testing, it's useful to enable only the ports we need, but for - * production purposes, it's faster to enable all ports. - */ -#define ALWAYS_USE_EXTENDED +static pointer mapVidMem(int, unsigned long, unsigned long, int); +static void unmapVidMem(int, pointer, unsigned long); +#if defined (__alpha__) +static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); +extern axpDevice lnxGetAXP(void); +static void unmapVidMemSparse(int, pointer, unsigned long); +# if defined(JENSEN_SUPPORT) +static pointer mapVidMemJensen(int, unsigned long, unsigned long, int); +static void unmapVidMemJensen(int, pointer, unsigned long); +# endif +static axpDevice axpSystem = -1; +static Bool needSparse; +static unsigned long hae_thresh; +static unsigned long hae_mask; +static unsigned long bus_base; +static unsigned long sparse_size; +#endif -#ifdef ALWAYS_USE_EXTENDED +#ifdef HAS_MTRR_SUPPORT -static Bool ScreenEnabled[MAXSCREENS]; -static Bool ExtendedEnabled = FALSE; -static Bool InitDone = FALSE; +#define SPLIT_WC_REGIONS 1 -void xf86ClearIOPortList(ScreenNum) -int ScreenNum; -{ - if (!InitDone) - { - int i; +static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); +static void undoWC(int, pointer); + +/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr + driver will clean up when we exit. */ +#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ +#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had + a problem. */ +static int mtrr_fd = MTRR_FD_UNOPENED; - for (i = 0; i < MAXSCREENS; i++) - ScreenEnabled[i] = FALSE; - InitDone = TRUE; +/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, + and will fail on Linux 2.2 with MTRR support configured out, + so verbosity should be chosen appropriately. */ +static Bool +mtrr_open(int verbosity) +{ + /* Only report absence of /proc/mtrr once. */ + static Bool warned = FALSE; + + char **fn; + static char *mtrr_files[] = { + "/dev/cpu/mtrr", /* Possible future name */ + "/proc/mtrr", /* Current name */ + NULL + }; + + if (mtrr_fd == MTRR_FD_UNOPENED) { + /* So open it. */ + for (fn = mtrr_files; mtrr_fd < 0 && *fn; fn++) + mtrr_fd = open(*fn, O_WRONLY); + + if (mtrr_fd < 0) + mtrr_fd = MTRR_FD_PROBLEM; } - return; -} + if (mtrr_fd == MTRR_FD_PROBLEM) { + /* To make sure we only ever warn once, need to check + verbosity outside xf86MsgVerb */ + if (!warned && verbosity <= xf86GetVerbosity()) { + xf86MsgVerb(X_WARNING, verbosity, + "System lacks support for changing MTRRs\n"); + warned = TRUE; + } -void xf86AddIOPorts(ScreenNum, NumPorts, Ports) -int ScreenNum; -int NumPorts; -unsigned *Ports; -{ - return; + return FALSE; + } + else + return TRUE; } -void xf86EnableIOPorts(ScreenNum) -int ScreenNum; -{ - int i; +/* + * We maintain a list of WC regions for each physical mapping so they can + * be undone when unmapping. + */ - ScreenEnabled[ScreenNum] = TRUE; +struct mtrr_wc_region { + struct mtrr_sentry sentry; + Bool added; /* added WC or removed it */ + struct mtrr_wc_region * next; +}; - if (ExtendedEnabled) - return; - -#ifndef __mc68000__ - if (iopl(3)) - FatalError("%s: Failed to set IOPL for I/O\n", - "xf86EnableIOPorts"); -#endif - ExtendedEnabled = TRUE; +static struct mtrr_wc_region * +mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + /* Some BIOS writers thought that setting wc over the mmio + region of a graphics devices was a good idea. Try to fix + it. */ + + struct mtrr_gentry gent; + char buf[20]; + struct mtrr_wc_region *wcreturn = NULL, *wcr; + + /* Linux 2.0 users should not get a warning without -verbose */ + if (!mtrr_open(2)) + return NULL; + + for (gent.regnum = 0; + ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; + gent.regnum++) { + if (gent.type != MTRR_TYPE_WRCOMB + || gent.base + gent.size <= base + || base + size <= gent.base) + continue; - return; + /* Found an overlapping region. Delete it. */ + + wcr = xalloc(sizeof(*wcr)); + if (!wcr) + return NULL; + wcr->sentry.base = gent.base; + wcr->sentry.size = gent.size; + wcr->sentry.type = MTRR_TYPE_WRCOMB; + wcr->added = FALSE; + + /* There is now a nicer ioctl-based way to do this, + but it isn't in current kernels. */ + snprintf(buf, sizeof(buf), "disable=%u\n", gent.regnum); + + if (write(mtrr_fd, buf, strlen(buf)) >= 0) { + xf86DrvMsg(screenNum, from, + "Removed MMIO write-combining range " + "(0x%lx,0x%lx)\n", + gent.base, gent.size); + wcr->next = wcreturn; + wcreturn = wcr; + } else { + xfree(wcr); + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to remove MMIO " + "write-combining range (0x%lx,0x%lx)\n", + gent.base, gent.size); + } + } + return wcreturn; } -void xf86DisableIOPorts(ScreenNum) -int ScreenNum; + +static struct mtrr_wc_region * +mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) { - int i; + struct mtrr_wc_region *wcr; - ScreenEnabled[ScreenNum] = FALSE; + /* Linux 2.0 should not warn, unless the user explicitly asks for + WC. */ + if (!mtrr_open(from == X_CONFIG ? 0 : 2)) + return NULL; - if (!ExtendedEnabled) - return; + wcr = xalloc(sizeof(*wcr)); + if (!wcr) + return NULL; - for (i = 0; i < MAXSCREENS; i++) - if (ScreenEnabled[i]) - return; + wcr->sentry.base = base; + wcr->sentry.size = size; + wcr->sentry.type = MTRR_TYPE_WRCOMB; + wcr->added = TRUE; + wcr->next = NULL; -#ifndef __mc68000__ - iopl(0); -#endif - ExtendedEnabled = FALSE; +#if SPLIT_WC_REGIONS + /* + * Splits up the write-combining region if it is not aligned on a + * size boundary. + */ - return; + { + unsigned long lbase, d_size = 1; + unsigned long n_size = size; + unsigned long n_base = base; + + for (lbase = n_base, d_size = 1; !(lbase & 1); + lbase = lbase >> 1, d_size <<= 1); + while (d_size > n_size) + d_size = d_size >> 1; +#ifdef DEBUG + ErrorF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); +#endif + n_base += d_size; + n_size -= d_size; + if (n_size) { + xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " + "base: 0x%lx, size: 0x%lx\n",base,size); + wcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); + } + wcr->sentry.size = d_size; + } + + /*****************************************************************/ +#endif /* SPLIT_WC_REGIONS */ + + if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &wcr->sentry) >= 0) { + /* Avoid printing on every VT switch */ + if (xf86ServerIsInitialising()) { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx)\n", + base, size); + } + return wcr; + } + else { + xfree(wcr); + + /* Don't complain about the VGA region: MTRR fixed + regions aren't currently supported, but might be in + the future. */ + if ((unsigned long)base >= 0x100000) { + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to set up write-combining range " + "(0x%lx,0x%lx)\n", base, size); + } + return NULL; + } } -#else /* !ALWAYS_USE_EXTENDED */ - -static unsigned *EnabledPorts[MAXSCREENS]; -static int NumEnabledPorts[MAXSCREENS]; -static Bool ScreenEnabled[MAXSCREENS]; -static Bool ExtendedPorts[MAXSCREENS]; -static Bool ExtendedEnabled = FALSE; -static Bool InitDone = FALSE; - -void xf86ClearIOPortList(ScreenNum) -int ScreenNum; +static void +mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) { - if (!InitDone) - { - xf86InitPortLists(EnabledPorts, NumEnabledPorts, - ScreenEnabled, ExtendedPorts, MAXSCREENS); - InitDone = TRUE; - return; + struct mtrr_wc_region *p, *prev; + + if (mtrr_fd > 0) { + p = wcr; + while (p) { + if (p->added) + ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); + prev = p; + p = p->next; + xfree(prev); + } } - ExtendedPorts[ScreenNum] = FALSE; - if (EnabledPorts[ScreenNum] != (unsigned *)NULL) - xfree(EnabledPorts[ScreenNum]); - EnabledPorts[ScreenNum] = (unsigned *)NULL; - NumEnabledPorts[ScreenNum] = 0; } -void xf86AddIOPorts(ScreenNum, NumPorts, Ports) -int ScreenNum; -int NumPorts; -unsigned *Ports; +static pointer +setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, + MessageType from) { - int i; - - if (!InitDone) - { - FatalError("xf86AddIOPorts: I/O control lists not initialised\n"); - } - EnabledPorts[ScreenNum] = (unsigned *)xrealloc(EnabledPorts[ScreenNum], - (NumEnabledPorts[ScreenNum]+NumPorts)*sizeof(unsigned)); - for (i = 0; i < NumPorts; i++) - { - EnabledPorts[ScreenNum][NumEnabledPorts[ScreenNum] + i] = - Ports[i]; - if (Ports[i] > 0x3FF) - ExtendedPorts[ScreenNum] = TRUE; - } - NumEnabledPorts[ScreenNum] += NumPorts; + if (enable) + return mtrr_add_wc_region(screenNum, base, size, from); + else + return mtrr_cull_wc_region(screenNum, base, size, from); } -void xf86EnableIOPorts(ScreenNum) -int ScreenNum; +static void +undoWC(int screenNum, pointer regioninfo) { - int i; + mtrr_undo_wc_region(screenNum, regioninfo); +} - if (ScreenEnabled[ScreenNum]) - return; +#endif /* HAS_MTRR_SUPPORT */ - for (i = 0; i < MAXSCREENS; i++) - { - if (ExtendedPorts[i] && (ScreenEnabled[i] || i == ScreenNum)) - { -#ifndef __mc68000__ - if (iopl(3)) - { - FatalError("%s: Failed to set IOPL for extended I/O\n", - "xf86EnableIOPorts"); - } -#endif - ExtendedEnabled = TRUE; - break; - } - } - /* Extended I/O was used, but not any more */ - if (ExtendedEnabled && i == MAXSCREENS) - { -#ifndef __mc68000__ - iopl(0); -#endif - ExtendedEnabled = FALSE; +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) +{ + pVidMem->linearSupported = TRUE; +#ifdef __alpha__ + if (axpSystem == -1) { + axpSystem = lnxGetAXP(); + if ((needSparse = (_bus_base_sparse() > 0))) { + hae_thresh = xf86AXPParams[axpSystem].hae_thresh; + hae_mask = xf86AXPParams[axpSystem].hae_mask; + sparse_size = xf86AXPParams[axpSystem].size; + } + bus_base = _bus_base(); } - /* - * Turn on non-extended ports even when using extended I/O - * so they are there if extended I/O gets turned off when it's no - * longer needed. - */ - for (i = 0; i < NumEnabledPorts[ScreenNum]; i++) - { - unsigned port = EnabledPorts[ScreenNum][i]; + if (isJensen) { +# ifndef JENSEN_SUPPORT + FatalError("Jensen is not supported any more\n" + "If you are intereseted in fixing Jensen support\n" + "please contact xfree86@xfree86.org\n"); +# else + xf86Msg(X_INFO,"Machine type is Jensen\n"); + pVidMem->mapMem = mapVidMemJensen; + pVidMem->unmapMem = unmapVidMemJensen; +# endif /* JENSEN_SUPPORT */ + } else if (needSparse) { + xf86Msg(X_INFO,"Machine needs sparse mapping\n"); + pVidMem->mapMem = mapVidMemSparse; + pVidMem->unmapMem = unmapVidMemSparse; + } else { + xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; + } +#else + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; +#endif /* __alpha__ */ - if (port > 0x3FF) - continue; - if (xf86CheckPorts(port, EnabledPorts, NumEnabledPorts, - ScreenEnabled, MAXSCREENS)) - { - if (ioperm(port, 1, TRUE) < 0) - { - FatalError("%s: Failed to enable I/O port 0x%x (%s)\n", - "xf86EnableIOPorts", port, strerror(errno)); - } - } - } - ScreenEnabled[ScreenNum] = TRUE; - return; +#ifdef HAS_MTRR_SUPPORT + pVidMem->setWC = setWC; + pVidMem->undoWC = undoWC; +#endif + pVidMem->initialised = TRUE; } -void xf86DisableIOPorts(ScreenNum) -int ScreenNum; +#ifdef __sparc__ +/* Basically, you simply cannot do this on Sparc. You have to do something portable + * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM + */ +static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + return NULL; +} +#else +static pointer +mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) { - int i; + pointer base; + int fd; + int mapflags = MAP_SHARED; + memType realBase, alignOff; + + realBase = Base & ~(getpagesize() - 1); + alignOff = Base - realBase; +#ifdef DEBUG + ErrorF("base: %lx, realBase: %lx, alignOff: %lx \n", + Base,realBase,alignOff); +#endif + +#if defined(__ia64__) +#ifndef MAP_WRITECOMBINED +#define MAP_WRITECOMBINED 0x00010000 +#endif +#ifndef MAP_NONCACHED +#define MAP_NONCACHED 0x00020000 +#endif + if(flags & VIDMEM_FRAMEBUFFER) + mapflags |= MAP_WRITECOMBINED; + else + mapflags |= MAP_NONCACHED; +#endif - if (!ScreenEnabled[ScreenNum]) - return; +#if defined(__ia64__) + /* this will disappear when people upgrade their kernels */ + if ((fd = open(DEV_MEM, O_RDWR|O_SYNC)) < 0) +#else + if ((fd = open(DEV_MEM, O_RDWR)) < 0) +#endif + { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + /* This requires linux-0.99.pl10 or above */ + base = mmap((caddr_t)0, Size + alignOff, + PROT_READ|PROT_WRITE, + mapflags, fd, + (off_t)(off_t)realBase + BUS_BASE); + close(fd); + if (base == MAP_FAILED) { + FatalError("xf86MapVidMem: Could not mmap framebuffer" + " (0x%08x,0x%x) (%s)\n", Base, Size, + strerror(errno)); + } +#ifdef DEBUG + ErrorF("base: %lx aligned base: %lx\n",base, base + alignOff); +#endif + return (char *)base + alignOff; +} +#endif /* !(__sparc__) */ + +static void +unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + memType alignOff = (memType)Base + - ((memType)Base & ~(getpagesize() - 1)); + +#ifdef DEBUG + ErrorF("alignment offset: %lx\n",alignOff); +#endif + munmap((caddr_t)((memType)Base - alignOff), (Size + alignOff)); +} - ScreenEnabled[ScreenNum] = FALSE; - for (i = 0; i < MAXSCREENS; i++) - { - if (ScreenEnabled[i] && ExtendedPorts[i]) - break; - } - if (ExtendedEnabled && i == MAXSCREENS) - { -#ifndef __mc68000__ - iopl(0); + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +#if defined(__powerpc__) +volatile unsigned char *ioBase = NULL; + +#ifndef __NR_pciconfig_iobase +#define __NR_pciconfig_iobase 200 #endif - ExtendedEnabled = FALSE; - } - for (i = 0; i < NumEnabledPorts[ScreenNum]; i++) - { - unsigned port = EnabledPorts[ScreenNum][i]; - if (port > 0x3FF) - continue; +#endif - if (xf86CheckPorts(port, EnabledPorts, NumEnabledPorts, - ScreenEnabled, MAXSCREENS)) - { - ioperm(port, 1, FALSE); +void +xf86EnableIO(void) +{ +#if defined(__powerpc__) + int fd; + unsigned int ioBase_phys; +#endif + + if (ExtendedEnabled) + return; + +#if defined(__powerpc__) + ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); + + fd = open("/dev/mem", O_RDWR); + if (ioBase == NULL) { + ioBase = (volatile unsigned char *)mmap(0, 0x20000, + PROT_READ|PROT_WRITE, MAP_SHARED, fd, + ioBase_phys); +/* Should this be fatal or just a warning? */ +#if 0 + if (ioBase == MAP_FAILED) { + FatalError( + "xf86EnableIOPorts: Failed to map iobase (%s)\n", + strerror(errno)); } +#endif } + close(fd); +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) + if (ioperm(0, 1024, 1) || iopl(3)) + FatalError("xf86EnableIOPorts: Failed to set IOPL for I/O\n"); +# if !defined(__alpha__) + ioperm(0x40,4,0); /* trap access to the timer chip */ + ioperm(0x60,4,0); /* trap access to the keyboard controller */ +# endif +#endif + ExtendedEnabled = TRUE; + return; } -#endif /* ALWAYS_USE_EXTENDED */ - -void xf86DisableIOPrivs() +void +xf86DisableIO(void) { -#ifndef __mc68000__ - if (ExtendedEnabled) - iopl(0); + if (!ExtendedEnabled) + return; +#if defined(__powerpc__) + munmap(ioBase, 0x20000); + ioBase = NULL; +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) + iopl(0); + ioperm(0, 1024, 0); #endif + ExtendedEnabled = FALSE; + return; } + /***************************************************************************/ /* Interrupt Handling section */ /***************************************************************************/ -Bool xf86DisableInterrupts() +/* XXX The #ifdefs should be made simpler. */ + +Bool +xf86DisableInterrupts() { +#if !defined(__mc68000__) && !defined(__powerpc__) && !defined(__sparc__) && !defined(__mips__) && !defined(__ia64__) && !defined(__sh__) && !defined(__hppa__) if (!ExtendedEnabled) -#ifndef __mc68000__ - if (iopl(3)) + if (iopl(3) || ioperm(0, 1024, 1)) return (FALSE); #endif -#if defined(__alpha__) || defined(__mc68000__) -#else -#ifdef __GNUC__ - __asm__ __volatile__("cli"); +#if defined(__alpha__) || defined(__mc68000__) || defined(__powerpc__) || defined(__sparc__) || defined(__mips__) || defined(__arm__) || defined(__sh__) || defined(__ia64__) || defined(__hppa__) #else +# ifdef __GNUC__ +# if defined(__ia64__) +# if 0 + __asm__ __volatile__ (";; rsm psr.i;; srlz.d" ::: "memory"); +# endif +# else + __asm__ __volatile__("cli"); +# endif +# else asm("cli"); +# endif #endif -#endif -#ifndef __mc68000__ - if (!ExtendedEnabled) - iopl(0); +#if !defined(__mc68000__) && !defined(__powerpc__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__ia64__) && !defined(__hppa__) + if (!ExtendedEnabled) { + iopl(0); + ioperm(0, 1024, 0); + } + #endif return (TRUE); } -void xf86EnableInterrupts() +void +xf86EnableInterrupts() { +#if !defined(__mc68000__) && !defined(__powerpc__) && !defined(__sparc__) && !defined(__mips__) && !defined(__ia64__) && !defined(__sh__) && !defined(__hppa__) if (!ExtendedEnabled) -#ifndef __mc68000__ - if (iopl(3)) + if (iopl(3) || ioperm(0, 1024, 1)) return; #endif -#if defined(__alpha__) || defined(__mc68000__) -#else -#ifdef __GNUC__ - __asm__ __volatile__("sti"); +#if defined(__alpha__) || defined(__mc68000__) || defined(__powerpc__) || defined(__sparc__) || defined(__mips__) || defined(__arm__) || defined(__sh__) || defined(__ia64__) || defined(__hppa__) #else +# ifdef __GNUC__ +# if defined(__ia64__) +# if 0 + __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory"); +# endif +# else + __asm__ __volatile__("sti"); +# endif +# else asm("sti"); +# endif #endif -#endif -#ifndef __mc68000__ - if (!ExtendedEnabled) - iopl(0); +#if !defined(__mc68000__) && !defined(__powerpc__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__ia64__) && !defined(__hppa__) + if (!ExtendedEnabled) { + iopl(0); + ioperm(0, 1024, 0); + } #endif return; } -#if defined(__alpha__) +#if defined (__alpha__) -static int xf86SparseShift = 5; /* default to all but JENSEN */ +#define vuip volatile unsigned int * -pointer xf86MapVidMemSparse(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +extern int readDense8(pointer Base, register unsigned long Offset); +extern int readDense16(pointer Base, register unsigned long Offset); +extern int readDense32(pointer Base, register unsigned long Offset); +extern void +writeDenseNB8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB32(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense32(int Value, pointer Base, register unsigned long Offset); + +static int readSparse8(pointer Base, register unsigned long Offset); +static int readSparse16(pointer Base, register unsigned long Offset); +static int readSparse32(pointer Base, register unsigned long Offset); +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset); + +#define DENSE_BASE 0x2ff00000000UL +#define SPARSE_BASE 0x30000000000UL + +static unsigned long msb_set = 0; + +static pointer +mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) { - pointer base; - int fd; + int fd; + unsigned long ret, rets = 0; + + static Bool was_here = FALSE; + + if (!was_here) { + was_here = TRUE; + + xf86WriteMmio8 = writeSparse8; + xf86WriteMmio16 = writeSparse16; + xf86WriteMmio32 = writeSparse32; + xf86WriteMmioNB8 = writeSparseNB8; + xf86WriteMmioNB16 = writeSparseNB16; + xf86WriteMmioNB32 = writeSparseNB32; + xf86ReadMmio8 = readSparse8; + xf86ReadMmio16 = readSparse16; + xf86ReadMmio32 = readSparse32; + } + + if ((fd = open(DEV_MEM, O_RDWR)) < 0) { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + +#if 0 + xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", + Base, Size, flags); +#endif - if (!_bus_base()) xf86SparseShift = 7; /* Uh, oh, JENSEN... */ + /* This requirers linux-0.99.pl10 or above */ + + /* + * Always do DENSE mmap, since read32/write32 currently require it. + */ + ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, + (off_t) (bus_base + Base)); + + /* + * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER + * and SPARSE (which should require the use of read/write macros). + * + * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K + * bytes worth of pagetable (32 pages). + */ + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), + Size << 5, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, + (off_t) _bus_base_sparse() + (Base << 5)); + } - Size <<= xf86SparseShift; - Base = (pointer)((unsigned long)Base << xf86SparseShift); + close(fd); + + if (ret == (unsigned long)MAP_FAILED) { + FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", + strerror(errno)); + } - if ((fd = open("/dev/mem", O_RDWR)) < 0) + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + if (rets == (unsigned long)MAP_FAILED || + rets != (SPARSE_BASE + (Base << 5))) { - FatalError("xf86MapVidMem: failed to open /dev/mem (%s)\n", - strerror(errno)); + FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", + strerror(errno)); } - /* This requirers linux-0.99.pl10 or above */ - base = (pointer)mmap((caddr_t)0, Size, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, - (off_t)Base + _bus_base_sparse()); - close(fd); - if ((long)base == -1) - { - FatalError("xf86MapVidMem: Could not mmap framebuffer (%s)\n", - strerror(errno)); + } + +#if 1 + if (rets) + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE at 0x%lx and SPARSE at 0x%lx\n", + Base, Size, ret, rets); + else + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE only at 0x%lx\n", + Base, Size, ret); + +#endif + return (pointer) ret; +} + +static void +unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) +{ + unsigned long Offset = (unsigned long)Base - DENSE_BASE; +#if 1 + xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", + Base, Size); +#endif + /* Unmap DENSE always. */ + munmap((caddr_t)Base, Size); + + /* Unmap SPARSE always, and ignore error in case we did not map it. */ + munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); +} + +static int +readSparse8(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x3) << 3; + if (Offset >= (hae_thresh)) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; } - return base; + } + + mem_barrier(); + result = *(vuip) (SPARSE_BASE + (Offset << 5)); + result >>= shift; + return 0xffUL & result; } -void xf86UnMapVidMemSparse(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +static int +readSparse16(pointer Base, register unsigned long Offset) { - Size <<= xf86SparseShift; + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x2) << 3; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } - munmap((caddr_t)Base, Size); + mem_barrier(); + result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); + result >>= shift; + return 0xffffUL & result; } -#define vuip volatile unsigned int * +static int +readSparse32(pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + mem_barrier(); + return *(vuip)((unsigned long)Base+(Offset)); +} -extern void sethae(unsigned long hae); +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + write_mem_barrier(); + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} -int xf86ReadSparse8(Base, Offset) -pointer Base; -unsigned long Offset; +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset) { - unsigned long result, shift; - unsigned long msb = 0; + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } - shift = (Offset & 0x3) * 8; - if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000UL; - Offset -= msb; - if (msb) { - sethae(msb); - } - } + write_mem_barrier(); + *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + write_mem_barrier(); + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } } - result = *(vuip) ((unsigned long)Base + (Offset << xf86SparseShift)); - if (msb) - sethae(0); + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} + +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) + = writeDense8; +void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) + = writeDense16; +void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) + = writeDense32; +void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB8; +void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB16; +void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB32; +int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) + = readDense8; +int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) + = readDense16; +int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) + = readDense32; + +#ifdef JENSEN_SUPPORT + +static int +readSparseJensen8(pointer Base, register unsigned long Offset); +static int +readSparseJensen16(pointer Base, register unsigned long Offset); +static int +readSparseJensen32(pointer Base, register unsigned long Offset); +static void +writeSparseJensen8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseJensen16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseJensen32(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseJensenNB8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseJensenNB16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseJensenNB32(int Value, pointer Base, register unsigned long Offset); + +/* + * The Jensen lacks dense memory, thus we have to address the bus via + * the sparse addressing scheme. + * + * Martin Ostermann (ost@comnets.rwth-aachen.de) - Apr.-Sep. 1996 + */ + +#ifdef TEST_JENSEN_CODE +#define SPARSE (5) +#else +#define SPARSE (7) +#endif + +#define JENSEN_SHIFT(x) ((long)x<<SPARSE) + +static pointer +mapVidMemJensen(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + pointer base; + int fd; + + xf86WriteMmio8 = writeSparseJensen8; + xf86WriteMmio16 = writeSparseJensen16; + xf86WriteMmio32 = writeSparseJensen32; + xf86WriteMmioNB8 = writeSparseJensenNB8; + xf86WriteMmioNB16 = writeSparseJensenNB16; + xf86WriteMmioNB32 = writeSparseJensenNB32; + xf86ReadMmio8 = readSparseJensen8; + xf86ReadMmio16 = readSparseJensen16; + xf86ReadMmio32 = readSparseJensen32; + + if ((fd = open(DEV_MEM, O_RDWR)) < 0) { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + /* This requires linux-0.99.pl10 or above */ + base = mmap((caddr_t)0, JENSEN_SHIFT(Size), + PROT_READ|PROT_WRITE, + MAP_SHARED, fd, + (off_t)(JENSEN_SHIFT((off_t)Base) + _bus_base_sparse())); + close(fd); + if (base == MAP_FAILED) { + FatalError("xf86MapVidMem: Could not mmap framebuffer" + " (0x%08x,0x%x) (%s)\n", Base, Size, + strerror(errno)); + } + return base; +} + +static void +unmapVidMemJensen(int ScreenNum, pointer Base, unsigned long Size) +{ + munmap((caddr_t)Base, JENSEN_SHIFT(Size)); +} + +static int +readSparseJensen8(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + + mem_barrier(); + shift = (Offset & 0x3) << 3; + + result = *(vuip) ((unsigned long)Base + (Offset << SPARSE)); + result >>= shift; return 0xffUL & result; } -int xf86ReadSparse16(Base, Offset) -pointer Base; -unsigned long Offset; +static int +readSparseJensen16(pointer Base, register unsigned long Offset) { - unsigned long result, shift; - unsigned long msb = 0; + register unsigned long result, shift; + + mem_barrier(); + shift = (Offset & 0x2) << 3; + + result = *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(1<<(SPARSE-2))); - shift = (Offset & 0x2) * 8; - if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000UL; - Offset -= msb; - if (msb) { - sethae(msb); - } - } - } - result = *(vuip)((unsigned long)Base+(Offset<<xf86SparseShift)+(1<<(xf86SparseShift-2))); - if (msb) - sethae(0); result >>= shift; return 0xffffUL & result; } -int xf86ReadSparse32(Base, Offset) -pointer Base; -unsigned long Offset; +static int +readSparseJensen32(pointer Base, register unsigned long Offset) { - unsigned long result; - unsigned long msb = 0; + register unsigned long result; + + mem_barrier(); + result = *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(3<<(SPARSE-2))); - if (xf86SparseShift != 7) { /* if not JENSEN, we may need HAE */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000UL; - Offset -= msb; - if (msb) { - sethae(msb); - } - } - } - result = *(vuip)((unsigned long)Base+(Offset<<xf86SparseShift)+(3<<(xf86SparseShift-2))); - if (msb) - sethae(0); return result; } -void xf86WriteSparse8(Value, Base, Offset) -int Value; -pointer Base; -unsigned long Offset; +static void +writeSparseJensen8(int Value, pointer Base, register unsigned long Offset) { - unsigned long msb = 0; - unsigned int b = Value & 0xffU; + register unsigned int b = Value & 0xffU; - if (xf86SparseShift != 7) { /* not JENSEN */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000; - Offset -= msb; - if (msb) { - sethae(msb); - } - } - } - *(vuip) ((unsigned long)Base + (Offset << xf86SparseShift)) = b * 0x01010101; - if (msb) - sethae(0); + write_mem_barrier(); + *(vuip) ((unsigned long)Base + (Offset << SPARSE)) = b * 0x01010101; } -void xf86WriteSparse16(Value, Base, Offset) -int Value; -pointer Base; -unsigned long Offset; +static void +writeSparseJensen16(int Value, pointer Base, register unsigned long Offset) { - unsigned long msb = 0; - unsigned int w = Value & 0xffffU; + register unsigned int w = Value & 0xffffU; - if (xf86SparseShift != 7) { /* not JENSEN */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000; - Offset -= msb; - if (msb) { - sethae(msb); - } - } - } - *(vuip)((unsigned long)Base+(Offset<<xf86SparseShift)+(1<<(xf86SparseShift-2))) = + write_mem_barrier(); + *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(1<<(SPARSE-2))) = w * 0x00010001; - if (msb) - sethae(0); } -void xf86WriteSparse32(Value, Base, Offset) -int Value; -pointer Base; -unsigned long Offset; +static void +writeSparseJensen32(int Value, pointer Base, register unsigned long Offset) { - unsigned long msb = 0; + write_mem_barrier(); + *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(3<<(SPARSE-2))) = Value; +} - if (xf86SparseShift != 7) { /* not JENSEN */ - if (Offset >= (1UL << 24)) { - msb = Offset & 0xf8000000; - Offset -= msb; - if (msb) { - sethae(msb); - } - } - } - *(vuip)((unsigned long)Base+(Offset<<xf86SparseShift)+(3<<(xf86SparseShift-2))) = Value; - if (msb) - sethae(0); +static void +writeSparseJensenNB8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned int b = Value & 0xffU; + + *(vuip) ((unsigned long)Base + (Offset << SPARSE)) = b * 0x01010101; } + +static void +writeSparseJensenNB16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned int w = Value & 0xffffU; + + *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(1<<(SPARSE-2))) = + w * 0x00010001; +} + +static void +writeSparseJensenNB32(int Value, pointer Base, register unsigned long Offset) +{ + *(vuip)((unsigned long)Base+(Offset<<SPARSE)+(3<<(SPARSE-2))) = Value; +} +#endif /* JENSEN_SUPPORT */ + #endif /* __alpha__ */ |