Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / os-support / sco / sco_video.c
blob7edf71db3131f96894a4464ac8ff8caa3b9f798e
1 /*
2 * Copyright 2001 by J. Kean Johnston <jkj@sco.com>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name J. Kean Johnston not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. J. Kean Johnston makes no
11 * representations about the suitability of this software for any purpose.
12 * It is provided "as is" without express or implied warranty.
14 * J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 /* Re-written May 2001 to represent the current state of reality */
26 * This file contains the completely re-written SCO OpenServer video
27 * routines for XFree86 4.x. Much of this is based on the SCO X server
28 * code (which is an X11R5 server) and will probably only work on
29 * OpenServer versions 5.0.5, 5.0.6 and later. Please send me (jkj@sco.com)
30 * email if you have any questions.
32 * Ideally, you should use OSR5.0.6A or later, with the updated console
33 * driver for 5.0.6A (its the default driver in 5.0.7 and later).
34 * However, if you are running on an older system, this code will detect
35 * that and adjust accordingly.
38 #ifdef HAVE_XORG_CONFIG_H
39 #include <xorg-config.h>
40 #endif
42 #include <X11/X.h>
43 #include "input.h"
44 #include "scrnintstr.h"
46 #define _NEED_SYSI86
47 #include "xf86.h"
48 #include "xf86Priv.h"
49 #include "xf86OSpriv.h"
50 #include "xf86_OSlib.h"
52 #include <sys/ci/ciioctl.h>
53 #define MPXNAME "/dev/atp1"
54 #define BASECPU 1
56 Bool mpxLock = TRUE;
58 #define USE_VASMETHOD 1
60 /***************************************************************************/
61 /* Video Memory Mapping section */
62 /***************************************************************************/
64 static int sco_mcdone = 0, sco_ismc = 0;
66 /***************************************************************************/
68 * To map the video memory, we first need to see if we are on a multi-console
69 * system. If we are, we need to try to use an existing video class in the
70 * kernel. We do this by retrieving the list of currently defined classes
71 * (via the new CONS_GETCLASS ioctl()) to see if we have a class that will
72 * match the range of memory we desire. If we can't find one, we have an
73 * error and we abort.
75 * If we are not using a multi-console, we can simply use mmap() to map in
76 * the frame buffer, using the classs-access method as a fall-back only if
77 * the mmap() fails (it shouldn't). We always set the appropriate pointers
78 * in the config structure to point ot the right function to map and unmap
79 * the video memory. An alternative to using mmap() is to use the new
80 * CONS_ADDVAS call, which will use vasmalloc() and vasbind() in the kernel
81 * to map the physical address to a virtual one, which it then returns.
82 * I am not 100% sure if this is faster or not, but it may prove easier to
83 * debug things. Just to be on the safe side, I have included both methods
84 * here, and the mmap() method can be used by setting USE_VASMETHOD to 0
85 * above.
88 #if !defined(CONS_ADDVAS)
89 # undef USE_VASMETHOD
90 # define USE_VASMETHOD 0
91 #endif
93 static int
94 scoIsMultiConsole (void)
96 int x;
98 if (sco_mcdone)
99 return sco_ismc;
100 x = access ("/usr/lib/vidconf/.multiconsole", F_OK);
101 if (x == 0)
102 sco_ismc = 1;
103 sco_mcdone = 1;
104 return sco_ismc;
108 * This maps memory using mmap()
110 static pointer
111 mapVidMemMMAP(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
113 int fd;
114 unsigned long realBase, alignOff;
115 pointer base;
117 fd = open (DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
118 if (fd < 0) {
119 FatalError("xf86MapVidMem: failed to open %s (%s)\n", DEV_MEM,
120 strerror(errno));
121 return 0; /* NOTREACHED */
124 realBase = Base & ~(getpagesize() - 1);
125 alignOff = Base - realBase;
127 #ifdef DEBUG
128 ErrorF("base: %lx, realBase: %lx, alignOff: %lx\n", Base,realBase,alignOff);
129 #endif
131 base = mmap((caddr_t)0, Size + alignOff,
132 (flags & VIDMEM_READONLY) ? PROT_READ : (PROT_READ | PROT_WRITE),
133 MAP_SHARED, fd, (off_t)realBase);
134 close(fd);
135 if (base == MAP_FAILED) {
136 FatalError("xf86MapVidMem: Could not mmap framebuffer (0x%08x,0x%x) (%s)\n",
137 Base, Size, strerror(errno));
138 return 0; /* NOTREACHED */
141 #ifdef DEBUG
142 ErrorF("base: %lx aligned base: %lx\n",base, base + alignOff);
143 #endif
144 return (pointer)((char *)base + alignOff);
147 #if (USE_VASMETHOD)
149 * This maps memory using the virtual address space (VAS) console calls.
151 static pointer
152 mapVidMemVAS(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
154 struct vidvasmem vas;
155 pointer base;
157 vas.base = (long)Base;
158 vas.size = (long)Size;
160 base = (pointer)ioctl (xf86Info.consoleFd, CONS_ADDVAS, &vas);
161 if (base == (pointer)-1) {
162 return mapVidMemMMAP(ScreenNum, Base, Size, flags);
164 return base;
166 #endif /* USE_VASMETHOD */
168 struct vidclass vidclasslist[] = {
169 { "VBE", "", 0xf0000000, 0x2000000, 0 },
170 { "P9000", "", 0xc0000000, 0x400000, 0 },
171 { "TULIP", "", 0x80000000, 0x400000, 0 },
172 { "VIPER", "", 0xa0000000, 0x400000, 0 },
173 { "S3T", "", 0xa0000000, 0x200000, 0 },
174 { "S3DT", "", 0x4000000, 0x400000, 0 },
175 { "MGA", "", 0x2200000, 0x4000, 0 },
176 { "CLVGA", "", 0xa0000, 0x20000, 0 },
177 { "OLIVE", "", 0xd8000000, 0x400000, 0 },
178 { "S3C", "", 0xa0000, 0x10000, 0 },
179 { "MGAVLB", "", 0xac000, 0x34000, 0 },
180 { "ATI8514", "", 0xFF000, 0x1000, 0 },
181 { "GXREGS", "", 0xb0000, 0x10000, 0 },
182 { "GX", "", 0xa0000, 0x10000, 0 },
183 { "CT64300", "", 0xa0000000, 0x400000, 0 },
184 { "SVGA", "", 0xa0000, 0x20000, 0 },
185 { "S3V", "", 0xa0000000, 0x400000, 0 },
186 { "8514A", "", 0xFF000, 0x1000, 0 },
187 { "VGA", "", 0xa0000, 0x10000, 0 },
188 { 0 }
191 static pointer
192 mapVidMemVC(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
194 struct vidclass *vcp;
195 char *class = NULL;
196 pointer base;
198 for (vcp = vidclasslist; vcp->name; vcp++) {
199 if ((vcp->base == Base) && (vcp->size == Size)) {
200 class = vcp->name;
201 break;
205 if (class == NULL) {
207 * As a fall-back, we will try and use the mmap() approach. This may
208 * prove to be the wrong thing to do, but time and testing will tell.
210 ErrorF("xf86MapVidMem: No class map defined for (0x%08x,0x%08x)\n", Base, Size);
211 #if USE_VASMETHOD
212 return mapVidMemVAS(ScreenNum, Base, Size, flags);
213 #else /* !USE_VASMETHOD */
214 return mapVidMemMMAP(ScreenNum, Base, Size, flags);
215 #endif
219 * We found a suitable class. Try and use it.
221 base = (pointer)ioctl(xf86Info.consoleFd, MAP_CLASS, class);
222 if ((int)base == -1) {
223 FatalError("xf86MapVidMem: Failed to map video memory class `%s'\n", class);
224 return 0; /* NOTREACHED */
227 return base;
231 * Unmapping the video memory is easy. We always call munmap(), as it is
232 * safe to do so even if we haven't actually mapped in any pages via mmap().
233 * In the case where we used the video class, we don't need to do anything
234 * as the kernel will clean up the TSS when we exit, and will undo the
235 * vasbind() that was done when the class was originally mapped. If we used
236 * vasmap, we simply undo the map. Again, it is benign to call vasunmap
237 * even if we got the frame buffer via some other mechanism (like mmap).
240 static void
241 unmapVidMem(int ScreenNum, pointer Base, unsigned long Size)
243 #if USE_VASMETHOD
244 struct vidvasmem vas;
245 int x;
247 vas.base = (long)Base;
248 vas.size = (long)Size;
250 x = ioctl (xf86Info.consoleFd, CONS_DELVAS, &vas);
251 if (x == 0)
252 return;
253 #endif /* USE_VASMETHOD */
255 munmap(Base, Size);
259 * Set things up to point to our local functions. When the kernel gets
260 * MTRR support, we will need to add the required functions for that
261 * here too. MTRR support will most likely appear in 5.0.8 or 5.1.0.
263 * We also want to lock the X server process to the base CPU in an MPX
264 * system, since we will be going to IOPL 3. Most engine drivers can cope
265 * with I/O access on any CPU but there are a few (AST Manhattan I believe)
266 * that can't, so the server needs to be locked to CPU0.
268 void
269 xf86OSInitVidMem(VidMemInfoPtr pVidMem)
271 int mpx_fd;
273 if (scoIsMultiConsole ()) {
274 pVidMem->mapMem = mapVidMemVC;
275 } else {
276 #if USE_VASMETHOD
277 pVidMem->mapMem = mapVidMemVAS;
278 #else
279 pVidMem->mapMem = mapVidMemMMAP;
280 #endif
283 pVidMem->unmapMem = unmapVidMem;
284 pVidMem->linearSupported = TRUE;
285 pVidMem->initialised = TRUE;
287 if (mpxLock && (mpx_fd = open (MPXNAME, O_RDONLY)) > 0) {
288 if (ioctl (mpx_fd, ACPU_XLOCK, BASECPU) < 0)
289 ErrorF ("xf86OSInitVidMem: Can not bind to CPU 0 (%s)\n",
290 strerror(errno));
291 close (mpx_fd);