summaryrefslogtreecommitdiff
path: root/hw/xfree86/os-support/sco/sco_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/os-support/sco/sco_video.c')
-rw-r--r--hw/xfree86/os-support/sco/sco_video.c457
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;
-}