1/*
2 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
3 * Copyright 1993 by David Wexelblat <dwex@goblin.org>
4 * Copyright 1999 by David Holland <davidh@iquest.net>
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting documentation, and
10 * that the names of the copyright holders not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission.  The copyright holders make no representations
13 * about the suitability of this software for any purpose.  It is provided "as
14 * is" without express or implied warranty.
15 *
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
18 * SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 *
24 */
25/* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
26 *
27 * Permission is hereby granted, free of charge, to any person obtaining a
28 * copy of this software and associated documentation files (the "Software"),
29 * to deal in the Software without restriction, including without limitation
30 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
31 * and/or sell copies of the Software, and to permit persons to whom the
32 * Software is furnished to do so, subject to the following conditions:
33 *
34 * The above copyright notice and this permission notice (including the next
35 * paragraph) shall be included in all copies or substantial portions of the
36 * Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
41 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
44 * DEALINGS IN THE SOFTWARE.
45 */
46
47#ifdef HAVE_XORG_CONFIG_H
48#include <xorg-config.h>
49#endif
50
51#include <sys/types.h> /* get __x86 definition if not set by compiler */
52
53#if defined(__i386__) || defined(__i386) || defined(__x86)
54# define _NEED_SYSI86
55#endif
56#include "xf86.h"
57#include "xf86Priv.h"
58#include "xf86_OSlib.h"
59#include "xf86OSpriv.h"
60#include <sys/mman.h>
61
62/***************************************************************************/
63/* Video Memory Mapping section 					   */
64/***************************************************************************/
65
66static char *apertureDevName = NULL;
67static int apertureDevFD_ro = -1;
68static int apertureDevFD_rw = -1;
69
70static Bool
71solOpenAperture(void)
72{
73    if (apertureDevName == NULL)
74    {
75	apertureDevName = "/dev/xsvc";
76	if ((apertureDevFD_rw = open(apertureDevName, O_RDWR)) < 0)
77	{
78	    xf86MsgVerb(X_WARNING, 0,
79			"solOpenAperture: failed to open %s (%s)\n",
80			apertureDevName, strerror(errno));
81	    apertureDevName = "/dev/fbs/aperture";
82	    apertureDevFD_rw = open(apertureDevName, O_RDWR);
83	}
84	apertureDevFD_ro = open(apertureDevName, O_RDONLY);
85
86	if ((apertureDevFD_rw < 0) || (apertureDevFD_ro < 0))
87	{
88	    xf86MsgVerb(X_WARNING, 0,
89			"solOpenAperture: failed to open %s (%s)\n",
90			apertureDevName, strerror(errno));
91	    xf86MsgVerb(X_WARNING, 0,
92			"solOpenAperture: either /dev/fbs/aperture"
93			" or /dev/xsvc required\n");
94
95	    apertureDevName = NULL;
96
97	    if (apertureDevFD_rw >= 0)
98	    {
99		close(apertureDevFD_rw);
100	    }
101	    apertureDevFD_rw = -1;
102
103	    if (apertureDevFD_ro >= 0)
104	    {
105		close(apertureDevFD_ro);
106	    }
107	    apertureDevFD_ro = -1;
108
109	    return FALSE;
110	}
111    }
112    return TRUE;
113}
114
115static pointer
116solMapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int Flags)
117{
118    pointer base;
119    int fd;
120    int prot;
121
122    if (Flags & VIDMEM_READONLY)
123    {
124	fd = apertureDevFD_ro;
125	prot = PROT_READ;
126    }
127    else
128    {
129	fd = apertureDevFD_rw;
130	prot = PROT_READ | PROT_WRITE;
131    }
132
133    if (fd < 0)
134    {
135	xf86DrvMsg(ScreenNum, X_ERROR,
136		   "solMapVidMem: failed to open %s (%s)\n",
137		   apertureDevName, strerror(errno));
138	return NULL;
139    }
140
141    base = mmap(NULL, Size, prot, MAP_SHARED, fd, (off_t)Base);
142
143    if (base == MAP_FAILED) {
144        xf86DrvMsg(ScreenNum, X_ERROR,
145		   "solMapVidMem: failed to mmap %s (0x%08lx,0x%lx) (%s)\n",
146		   apertureDevName, Base, Size, strerror(errno));
147	return NULL;
148    }
149
150    return base;
151}
152
153/* ARGSUSED */
154static void
155solUnMapVidMem(int ScreenNum, pointer Base, unsigned long Size)
156{
157    if (munmap(Base, Size) != 0) {
158	xf86DrvMsgVerb(ScreenNum, X_WARNING, 0,
159		       "solUnMapVidMem: failed to unmap %s"
160		       " (0x%p,0x%lx) (%s)\n",
161		       apertureDevName, Base, Size,
162		       strerror(errno));
163    }
164}
165
166_X_HIDDEN void
167xf86OSInitVidMem(VidMemInfoPtr pVidMem)
168{
169    pVidMem->linearSupported = solOpenAperture();
170    if (pVidMem->linearSupported) {
171	pVidMem->mapMem = solMapVidMem;
172	pVidMem->unmapMem = solUnMapVidMem;
173    } else {
174	xf86MsgVerb(X_WARNING, 0,
175		    "xf86OSInitVidMem: linear memory access disabled\n");
176    }
177    pVidMem->initialised = TRUE;
178}
179
180/*
181 * Read BIOS via mmap()ing physical memory.
182 */
183int
184xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf,
185	     int Len)
186{
187    unsigned char *ptr;
188    int psize;
189    int mlen;
190
191    psize = getpagesize();
192    Offset += Base & (psize - 1);
193    Base &= ~(psize - 1);
194    mlen = (Offset + Len + psize - 1) & ~(psize - 1);
195
196    if (solOpenAperture() == FALSE)
197    {
198	xf86Msg(X_WARNING,
199		"xf86ReadBIOS: Failed to open aperture to read BIOS\n");
200	return -1;
201    }
202
203    ptr = (unsigned char *)mmap(NULL, mlen, PROT_READ,
204				MAP_SHARED, apertureDevFD_ro, (off_t)Base);
205    if (ptr == MAP_FAILED)
206    {
207	xf86Msg(X_WARNING, "xf86ReadBIOS: %s mmap failed [0x%08lx, 0x%04x]\n",
208		apertureDevName, Base, mlen);
209	return -1;
210    }
211
212    (void)memcpy(Buf, (void *)(ptr + Offset), Len);
213    if (munmap((caddr_t)ptr, mlen) != 0) {
214	xf86MsgVerb(X_WARNING, 0,
215		    "xf86ReadBIOS: failed to unmap %s (0x%p,0x%x) (%s)\n",
216		    apertureDevName, ptr, mlen, strerror(errno));
217    }
218
219    return Len;
220}
221
222
223/***************************************************************************/
224/* I/O Permissions section						   */
225/***************************************************************************/
226
227#if defined(__i386__) || defined(__i386) || defined(__x86)
228static Bool ExtendedEnabled = FALSE;
229#endif
230
231Bool
232xf86EnableIO(void)
233{
234#if defined(__i386__) || defined(__i386) || defined(__x86)
235    if (ExtendedEnabled)
236	return TRUE;
237
238    if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0) {
239	xf86Msg(X_WARNING, "xf86EnableIOPorts: Failed to set IOPL for I/O\n");
240	return FALSE;
241    }
242    ExtendedEnabled = TRUE;
243#endif /* i386 */
244    return TRUE;
245}
246
247void
248xf86DisableIO(void)
249{
250#if defined(__i386__) || defined(__i386) || defined(__x86)
251    if(!ExtendedEnabled)
252	return;
253
254    sysi86(SI86V86, V86SC_IOPL, 0);
255
256    ExtendedEnabled = FALSE;
257#endif /* i386 */
258}
259