diff options
Diffstat (limited to 'hw/xfree86/os-support/sco/sco_video.c')
-rw-r--r-- | hw/xfree86/os-support/sco/sco_video.c | 457 |
1 files changed, 232 insertions, 225 deletions
diff --git a/hw/xfree86/os-support/sco/sco_video.c b/hw/xfree86/os-support/sco/sco_video.c index 14947fa85..eb4b80c48 100644 --- a/hw/xfree86/os-support/sco/sco_video.c +++ b/hw/xfree86/os-support/sco/sco_video.c @@ -1,29 +1,41 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_video.c,v 3.2.2.1 1997/07/19 04:59:31 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_video.c,v 3.8 2002/06/03 21:22:10 dawes Exp $ */ /* - * Copyright 1993 by David McCullough <davidm@stallion.oz.au> - * Copyright 1993 by David Wexelblat <dwex@goblin.org> + * Copyright 2001 by J. Kean Johnston <jkj@sco.com> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting - * documentation, and that the names of David McCullough and David Wexelblat - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. David McCullough and - * David Wexelblat makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. + * documentation, and that the name J. Kean Johnston not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. J. Kean Johnston makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. * - * DAVID MCCULLOUGH AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL DAVID MCCULLOUGH OR DAVID WEXELBLAT BE - * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XConsortium$ */ + +/* Re-written May 2001 to represent the current state of reality */ + +/* + * This file contains the completely re-written SCO OpenServer video + * routines for XFree86 4.x. Much of this is based on the SCO X server + * code (which is an X11R5 server) and will probably only work on + * OpenServer versions 5.0.5, 5.0.6 and later. Please send me (jkj@sco.com) + * email if you have any questions. * + * Ideally, you should use OSR5.0.6A or later, with the updated console + * driver for 5.0.6A (its the default driver in 5.0.7 and later). + * However, if you are running on an older system, this code will detect + * that and adjust accordingly. */ -/* $Xorg: sco_video.c,v 1.3 2000/08/17 19:51:29 cpqbld Exp $ */ #include "X.h" #include "input.h" @@ -32,253 +44,248 @@ #define _NEED_SYSI86 #include "xf86.h" #include "xf86Priv.h" +#include "xf86OSpriv.h" #include "xf86_OSlib.h" +#include <sys/ci/ciioctl.h> +#define MPXNAME "/dev/atp1" +#define BASECPU 1 + +Bool mpxLock = TRUE; + +#define USE_VASMETHOD 1 + /***************************************************************************/ /* Video Memory Mapping section */ /***************************************************************************/ -static struct kd_memloc MapDSC[MAXSCREENS][NUM_REGIONS]; -static int ver_once = 1; +static int sco_mcdone = 0, sco_ismc = 0; /***************************************************************************/ /* - * To map the video-memory, we use the MAP_CLASS ioctl. - * Different drivers may have to do another one of these - * for their own special registers (ie., ATI). To find - * out which strings are valid look in /etc/conf/pack.d/cn/class.h + * To map the video memory, we first need to see if we are on a multi-console + * system. If we are, we need to try to use an existing video class in the + * kernel. We do this by retrieving the list of currently defined classes + * (via the new CONS_GETCLASS ioctl()) to see if we have a class that will + * match the range of memory we desire. If we can't find one, we have an + * error and we abort. * - * if we fail to find one of these we try for the dmmap driver + * If we are not using a multi-console, we can simply use mmap() to map in + * the frame buffer, using the classs-access method as a fall-back only if + * the mmap() fails (it shouldn't). We always set the appropriate pointers + * in the config structure to point ot the right function to map and unmap + * the video memory. An alternative to using mmap() is to use the new + * CONS_ADDVAS call, which will use vasmalloc() and vasbind() in the kernel + * to map the physical address to a virtual one, which it then returns. + * I am not 100% sure if this is faster or not, but it may prove easier to + * debug things. Just to be on the safe side, I have included both methods + * here, and the mmap() method can be used by setting USE_VASMETHOD to 0 + * above. */ -struct { - unsigned long base, size; - char *class; -} SCO_Mapping[] = { - {0xA0000, 0x10000, "VGA"}, - {0xA0000, 0x20000, "SVGA"}, - {0xB0000, 0x08000, "HGA"}, - {0x0, 0x0, ""}, -}; +#if !defined(CONS_ADDVAS) +# undef USE_VASMETHOD +# define USE_VASMETHOD 0 +#endif -/* ARGSUSED */ -pointer xf86MapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +static int +scoIsMultiConsole (void) { - int i; - char *class = (char *)NULL; - pointer base; - - for (i=0; SCO_Mapping[i].base != 0; i++) - { - if (((pointer)SCO_Mapping[i].base == Base) && - (SCO_Mapping[i].size == Size)) - { - class = SCO_Mapping[i].class; - break; - } - } - if (class == (char *)NULL) - { - int fd; - -#if defined(SVR4) || defined(SCO325) - if ((fd = open(DEV_MEM, O_RDWR)) < 0) - { - FatalError("xf86MapVidMem: failed to open %s (%s)\n", - DEV_MEM, strerror(errno)); - } - base = (pointer)mmap((caddr_t)0, Size, PROT_READ|PROT_WRITE, - MAP_SHARED, fd, (off_t)Base); - close(fd); - if ((long)base == -1) - { - FatalError("%s: Could not mmap framebuffer [s=%x,a=%x] (%s)\n", - "xf86MapVidMem", Size, Base, strerror(errno)); - } - - return(base); -#else - MapDSC[ScreenNum][Region].vaddr = (char *) NULL; - MapDSC[ScreenNum][Region].physaddr = (char *) Base; - MapDSC[ScreenNum][Region].length = Size; - MapDSC[ScreenNum][Region].ioflg = 1; - if ((fd = open("/dev/dmmap", O_RDWR)) >= 0) { - if (ioctl(fd, KDMAPDISP, &MapDSC[ScreenNum][Region]) == -1) - ErrorF("xf86MapVidMem: dmmap KDMAPDISP failed (%s)\n", - strerror(errno)); - else { - if (ver_once) - ErrorF("Using dmmap version 0x%04x.\n", - ioctl(fd, -1)); - ver_once = 0; - close(fd); - return(MapDSC[ScreenNum][Region].vaddr); - } - close(fd); - } - FatalError("xf86MapVidMem:No class map defined for (%x,%x)\n", - Base, Size); - /* NOTREACHED */ -#endif - } - - base = (pointer)ioctl(xf86Info.consoleFd, MAP_CLASS, class); - if ((int)base == -1) - { - FatalError("xf86MapVidMem:Failed to map video mem class %s\n", - class); - /* NOTREACHED */ - } - return(base); + int x; + + if (sco_mcdone) + return sco_ismc; + x = access ("/usr/lib/vidconf/.multiconsole", F_OK); + if (x == 0) + sco_ismc = 1; + sco_mcdone = 1; + return sco_ismc; } /* - * Nothing to do here if it wasn't mapped using the dmmap driver + * This maps memory using mmap() */ -/* ARGSUSED */ -void xf86UnMapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +static pointer +mapVidMemMMAP(int ScreenNum, unsigned long Base, unsigned long Size, int flags) { - int fd; - -#if defined (SVR4) || defined(SCO325) - munmap(Base, Size); -#else /* SVR4 */ - if (MapDSC[ScreenNum][Region].vaddr) { - if ((fd = open("/dev/dmmap", O_RDWR)) < 0) { - if (ioctl(fd, KDUNMAPDISP, &MapDSC[ScreenNum][Region]) == -1) - ErrorF("xf86UnMapVidMem: dmmap KDUNMAPDISP failed (%s)\n", - strerror(errno)); - close(fd); - } - MapDSC[ScreenNum][Region].vaddr = (char *) NULL; - MapDSC[ScreenNum][Region].physaddr = (char *) NULL; - MapDSC[ScreenNum][Region].length = 0; - MapDSC[ScreenNum][Region].ioflg = 0; - } + int fd; + unsigned long realBase, alignOff; + pointer base; + + fd = open (DEV_MEM, O_RDWR); + if (fd < 0) { + FatalError("xf86MapVidMem: failed to open %s (%s)\n", DEV_MEM, + strerror(errno)); + return 0; /* NOTREACHED */ + } + + realBase = Base & ~(getpagesize() - 1); + alignOff = Base - realBase; + +#ifdef DEBUG + ErrorF("base: %lx, realBase: %lx, alignOff: %lx\n", Base,realBase,alignOff); #endif - return; -} - -/* ARGSUSED */ -Bool xf86LinearVidMem() -{ - int fd, ver; -#if defined(SVR4) || defined(SCO325) - return TRUE; -#else - if ((fd = open("/dev/dmmap", O_RDWR)) >= 0) { - ver = ioctl(fd, -1); - close(fd); - if (ver >= 0) { - if (ver_once) - ErrorF("Using dmmap version 0x%04x.\n", ver); - ver_once = 0; - return(TRUE); - } - } - return(FALSE); + base = mmap((caddr_t)0, Size + alignOff, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, (off_t)realBase); + close(fd); + if (base == MAP_FAILED) { + FatalError("xf86MapVidMem: Could not mmap framebuffer (0x%08x,0x%x) (%s)\n", + Base, Size, strerror(errno)); + return 0; /* NOTREACHED */ + } + +#ifdef DEBUG + ErrorF("base: %lx aligned base: %lx\n",base, base + alignOff); #endif + return (pointer)((char *)base + alignOff); } -/***************************************************************************/ -/* I/O Permissions section */ -/***************************************************************************/ +#if (USE_VASMETHOD) +/* + * This maps memory using the virtual address space (VAS) console calls. + */ +static pointer +mapVidMemVAS(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + struct vidvasmem vas; + pointer base; -static Bool ScreenEnabled[MAXSCREENS]; -static Bool IOEnabled = FALSE; -static Bool InitDone = FALSE; + vas.base = (long)Base; + vas.size = (long)Size; -void xf86ClearIOPortList(ScreenNum) -int ScreenNum; -{ - int i; - - if (!InitDone) - { - for (i = 0; i < MAXSCREENS; i++) - ScreenEnabled[i] = FALSE; - InitDone = TRUE; - } + base = (pointer)ioctl (xf86Info.consoleFd, CONS_ADDVAS, &vas); + if (base == (pointer)-1) { + return mapVidMemMMAP(ScreenNum, Base, Size, flags); + } + return base; } +#endif /* USE_VASMETHOD */ + +struct vidclass vidclasslist[] = { + { "VBE", "", 0xf0000000, 0x2000000, 0 }, + { "P9000", "", 0xc0000000, 0x400000, 0 }, + { "TULIP", "", 0x80000000, 0x400000, 0 }, + { "VIPER", "", 0xa0000000, 0x400000, 0 }, + { "S3T", "", 0xa0000000, 0x200000, 0 }, + { "S3DT", "", 0x4000000, 0x400000, 0 }, + { "MGA", "", 0x2200000, 0x4000, 0 }, + { "CLVGA", "", 0xa0000, 0x20000, 0 }, + { "OLIVE", "", 0xd8000000, 0x400000, 0 }, + { "S3C", "", 0xa0000, 0x10000, 0 }, + { "MGAVLB", "", 0xac000, 0x34000, 0 }, + { "ATI8514", "", 0xFF000, 0x1000, 0 }, + { "GXREGS", "", 0xb0000, 0x10000, 0 }, + { "GX", "", 0xa0000, 0x10000, 0 }, + { "CT64300", "", 0xa0000000, 0x400000, 0 }, + { "SVGA", "", 0xa0000, 0x20000, 0 }, + { "S3V", "", 0xa0000000, 0x400000, 0 }, + { "8514A", "", 0xFF000, 0x1000, 0 }, + { "VGA", "", 0xa0000, 0x10000, 0 }, + { 0 } +}; -/* ARGSUSED */ -void xf86AddIOPorts(ScreenNum, NumPorts, Ports) -int ScreenNum; -int NumPorts; -unsigned *Ports; +static pointer +mapVidMemVC(int ScreenNum, unsigned long Base, unsigned long Size, int flags) { + struct vidclass *vcp; + char *class = NULL; + pointer base; + + for (vcp = vidclasslist; vcp->name; vcp++) { + if ((vcp->base == Base) && (vcp->size == Size)) { + class = vcp->name; + break; + } + } + + if (class == NULL) { + /* + * As a fall-back, we will try and use the mmap() approach. This may + * prove to be the wrong thing to do, but time and testing will tell. + */ + ErrorF("xf86MapVidMem: No class map defined for (0x%08x,0x%08x)\n", Base, Size); +#if USE_VASMETHOD + return mapVidMemVAS(ScreenNum, Base, Size, flags); +#else /* !USE_VASMETHOD */ + return mapVidMemMMAP(ScreenNum, Base, Size, flags); +#endif + } + + /* + * We found a suitable class. Try and use it. + */ + base = (pointer)ioctl(xf86Info.consoleFd, MAP_CLASS, class); + if ((int)base == -1) { + FatalError("xf86MapVidMem: Failed to map video memory class `%s'\n", class); + return 0; /* NOTREACHED */ + } + + return base; } -void xf86EnableIOPorts(ScreenNum) -int ScreenNum; -{ - ScreenEnabled[ScreenNum] = TRUE; - - if (IOEnabled) - return; - - if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0) - FatalError("Failed to set IOPL for extended I/O\n"); - IOEnabled = TRUE; - return; -} +/* + * Unmapping the video memory is easy. We always call munmap(), as it is + * safe to do so even if we haven't actually mapped in any pages via mmap(). + * In the case where we used the video class, we don't need to do anything + * as the kernel will clean up the TSS when we exit, and will undo the + * vasbind() that was done when the class was originally mapped. If we used + * vasmap, we simply undo the map. Again, it is benign to call vasunmap + * even if we got the frame buffer via some other mechanism (like mmap). + */ -void xf86DisableIOPorts(ScreenNum) -int ScreenNum; +static void +unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) { - int i; +#if USE_VASMETHOD + struct vidvasmem vas; + int x; - ScreenEnabled[ScreenNum] = FALSE; + vas.base = (long)Base; + vas.size = (long)Size; - if (!IOEnabled) - return; + x = ioctl (xf86Info.consoleFd, CONS_DELVAS, &vas); + if (x == 0) + return; +#endif /* USE_VASMETHOD */ - for (i = 0; i < MAXSCREENS; i++) - if (ScreenEnabled[i]) - return; - sysi86(SI86V86, V86SC_IOPL, 0); - IOEnabled = FALSE; - return; + munmap(Base, Size); } -void xf86DisableIOPrivs() +/* + * Set things up to point to our local functions. When the kernel gets + * MTRR support, we will need to add the required functions for that + * here too. MTRR support will most likely appear in 5.0.8 or 5.1.0. + * + * We also want to lock the X server process to the base CPU in an MPX + * system, since we will be going to IOPL 3. Most engine drivers can cope + * with I/O access on any CPU but there are a few (AST Manhattan I believe) + * that can't, so the server needs to be locked to CPU0. + */ +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) { - if (IOEnabled) - sysi86(SI86V86, V86SC_IOPL, 0); - return; -} + int mpx_fd; -/***************************************************************************/ -/* Interrupt Handling section */ -/***************************************************************************/ - -Bool xf86DisableInterrupts() -{ -#ifdef __GNUC__ - __asm__ __volatile__("cli"); -#else - asm("cli"); -#endif /* __GNUC__ */ - - return(TRUE); + if (scoIsMultiConsole ()) { + pVidMem->mapMem = mapVidMemVC; + } else { +#if USE_VASMETHOD + pVidMem->mapMem = mapVidMemVAS; +#else + pVidMem->mapMem = mapVidMemMMAP; +#endif + } + + pVidMem->unmapMem = unmapVidMem; + pVidMem->linearSupported = TRUE; + pVidMem->initialised = TRUE; + + if (mpxLock && (mpx_fd = open (MPXNAME, O_RDONLY)) > 0) { + if (ioctl (mpx_fd, ACPU_XLOCK, BASECPU) < 0) + ErrorF ("xf86OSInitVidMem: Can not bind to CPU 0 (%s)\n", + strerror(errno)); + close (mpx_fd); + } } -void xf86EnableInterrupts() -{ -#ifdef __GNUC__ - __asm__ __volatile__("sti"); -#else - asm("sti"); -#endif /* __GNUC__ */ - - return; -} |