1/*
2 * Copyright (c) 1993-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28
29#ifdef HAVE_XORG_CONFIG_H
30#include <xorg-config.h>
31#endif
32
33#include <X11/X.h>
34#include "input.h"
35#include "scrnintstr.h"
36
37#include "xf86.h"
38#include "xf86Priv.h"
39#include "xf86_OSlib.h"
40#include "xf86OSpriv.h"
41
42/*
43 * This file contains the common part of the video memory mapping functions
44 */
45
46/*
47 * Get a piece of the ScrnInfoRec.  At the moment, this is only used to hold
48 * the MTRR option information, but it is likely to be expanded if we do
49 * auto unmapping of memory at VT switch.
50 *
51 */
52
53typedef struct {
54	unsigned long 	physBase;
55	unsigned long 	size;
56	pointer		virtBase;
57	pointer 	mtrrInfo;
58	int		flags;
59} MappingRec, *MappingPtr;
60
61typedef struct {
62	int		numMappings;
63	MappingPtr *	mappings;
64	Bool		mtrrEnabled;
65	MessageType	mtrrFrom;
66	Bool		mtrrOptChecked;
67	ScrnInfoPtr	pScrn;
68} VidMapRec, *VidMapPtr;
69
70static int vidMapIndex = -1;
71
72#define VIDMAPPTR(p) ((VidMapPtr)((p)->privates[vidMapIndex].ptr))
73
74static VidMemInfo vidMemInfo = {FALSE, };
75static VidMapRec  vidMapRec  = {0, NULL, TRUE, X_DEFAULT, FALSE, NULL};
76
77static VidMapPtr
78getVidMapRec(int scrnIndex)
79{
80	VidMapPtr vp;
81	ScrnInfoPtr pScrn;
82
83	if ((scrnIndex < 0) ||
84	    !(pScrn = xf86Screens[scrnIndex]))
85		return &vidMapRec;
86
87	if (vidMapIndex < 0)
88		vidMapIndex = xf86AllocateScrnInfoPrivateIndex();
89
90	if (VIDMAPPTR(pScrn) != NULL)
91		return VIDMAPPTR(pScrn);
92
93	vp = pScrn->privates[vidMapIndex].ptr = xnfcalloc(sizeof(VidMapRec), 1);
94	vp->mtrrEnabled = TRUE;	/* default to enabled */
95	vp->mtrrFrom = X_DEFAULT;
96	vp->mtrrOptChecked = FALSE;
97	vp->pScrn = pScrn;
98	return vp;
99}
100
101static MappingPtr
102newMapping(VidMapPtr vp)
103{
104	vp->mappings = xnfrealloc(vp->mappings, sizeof(MappingPtr) *
105				  (vp->numMappings + 1));
106	vp->mappings[vp->numMappings] = xnfcalloc(sizeof(MappingRec), 1);
107	return vp->mappings[vp->numMappings++];
108}
109
110static MappingPtr
111findMapping(VidMapPtr vp, pointer vbase, unsigned long size)
112{
113	int i;
114
115	for (i = 0; i < vp->numMappings; i++) {
116		if (vp->mappings[i]->virtBase == vbase &&
117		    vp->mappings[i]->size == size)
118			return vp->mappings[i];
119	}
120	return NULL;
121}
122
123static void
124removeMapping(VidMapPtr vp, MappingPtr mp)
125{
126	int i, found = 0;
127
128	for (i = 0; i < vp->numMappings; i++) {
129		if (vp->mappings[i] == mp) {
130			found = 1;
131			free(vp->mappings[i]);
132		} else if (found) {
133			vp->mappings[i - 1] = vp->mappings[i];
134		}
135	}
136	vp->numMappings--;
137	vp->mappings[vp->numMappings] = NULL;
138}
139
140enum { OPTION_MTRR };
141static const OptionInfoRec opts[] =
142{
143	{ OPTION_MTRR, "mtrr", OPTV_BOOLEAN, {0}, FALSE },
144	{ -1, NULL, OPTV_NONE, {0}, FALSE }
145};
146
147static void
148checkMtrrOption(VidMapPtr vp)
149{
150	if (!vp->mtrrOptChecked && vp->pScrn && vp->pScrn->options != NULL) {
151		OptionInfoPtr options;
152
153		options = xnfalloc(sizeof(opts));
154		(void)memcpy(options, opts, sizeof(opts));
155		xf86ProcessOptions(vp->pScrn->scrnIndex, vp->pScrn->options,
156					options);
157		if (xf86GetOptValBool(options, OPTION_MTRR, &vp->mtrrEnabled))
158			vp->mtrrFrom = X_CONFIG;
159		free(options);
160		vp->mtrrOptChecked = TRUE;
161	}
162}
163
164void
165xf86MakeNewMapping(int ScreenNum, int Flags, unsigned long Base, unsigned long Size, pointer Vbase)
166{
167	VidMapPtr vp;
168	MappingPtr mp;
169
170	vp = getVidMapRec(ScreenNum);
171	mp = newMapping(vp);
172	mp->physBase = Base;
173	mp->size = Size;
174	mp->virtBase = Vbase;
175	mp->flags = Flags;
176}
177
178void
179xf86InitVidMem(void)
180{
181	if (!vidMemInfo.initialised) {
182		memset(&vidMemInfo, 0, sizeof(VidMemInfo));
183		xf86OSInitVidMem(&vidMemInfo);
184	}
185}
186
187pointer
188xf86MapVidMem(int ScreenNum, int Flags, unsigned long Base, unsigned long Size)
189{
190	pointer vbase = NULL;
191	VidMapPtr vp;
192	MappingPtr mp;
193
194	if (((Flags & VIDMEM_FRAMEBUFFER) &&
195	     (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT))))
196	    FatalError("Mapping memory with more than one type\n");
197
198	xf86InitVidMem();
199	if (!vidMemInfo.initialised || !vidMemInfo.mapMem)
200		return NULL;
201
202	vbase = vidMemInfo.mapMem(ScreenNum, Base, Size, Flags);
203
204	if (!vbase || vbase == (pointer)-1)
205		return NULL;
206
207	vp = getVidMapRec(ScreenNum);
208	mp = newMapping(vp);
209	mp->physBase = Base;
210	mp->size = Size;
211	mp->virtBase = vbase;
212	mp->flags = Flags;
213
214	/*
215	 * Check the "mtrr" option even when MTRR isn't supported to avoid
216	 * warnings about unrecognised options.
217	 */
218	checkMtrrOption(vp);
219
220	if (vp->mtrrEnabled && vidMemInfo.setWC) {
221		if (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT))
222			mp->mtrrInfo =
223				vidMemInfo.setWC(ScreenNum, Base, Size, FALSE,
224						 vp->mtrrFrom);
225		else if (Flags & VIDMEM_FRAMEBUFFER)
226			mp->mtrrInfo =
227				vidMemInfo.setWC(ScreenNum, Base, Size, TRUE,
228						 vp->mtrrFrom);
229	}
230	return vbase;
231}
232
233void
234xf86UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size)
235{
236	VidMapPtr vp;
237	MappingPtr mp;
238
239	if (!vidMemInfo.initialised || !vidMemInfo.unmapMem) {
240		xf86DrvMsg(ScreenNum, X_WARNING,
241		  "xf86UnMapVidMem() called before xf86MapVidMem()\n");
242		return;
243	}
244
245	vp = getVidMapRec(ScreenNum);
246	mp = findMapping(vp, Base, Size);
247	if (!mp) {
248		xf86DrvMsg(ScreenNum, X_WARNING,
249		  "xf86UnMapVidMem: cannot find region for [%p,0x%lx]\n",
250		  Base, Size);
251		return;
252	}
253	if (vp->mtrrEnabled && vidMemInfo.undoWC && mp)
254		vidMemInfo.undoWC(ScreenNum, mp->mtrrInfo);
255
256	vidMemInfo.unmapMem(ScreenNum, Base, Size);
257	removeMapping(vp, mp);
258}
259
260Bool
261xf86CheckMTRR(int ScreenNum)
262{
263	VidMapPtr vp = getVidMapRec(ScreenNum);
264
265	/*
266	 * Check the "mtrr" option even when MTRR isn't supported to avoid
267	 * warnings about unrecognised options.
268	 */
269	checkMtrrOption(vp);
270
271	if (vp->mtrrEnabled && vidMemInfo.setWC)
272		return TRUE;
273
274	return FALSE;
275}
276
277Bool
278xf86LinearVidMem(void)
279{
280	xf86InitVidMem();
281	return vidMemInfo.linearSupported;
282}
283
284void
285xf86MapReadSideEffects(int ScreenNum, int Flags, pointer base,
286			unsigned long Size)
287{
288	if (!(Flags & VIDMEM_READSIDEEFFECT))
289		return;
290
291	if (!vidMemInfo.initialised || !vidMemInfo.readSideEffects)
292		return;
293
294	vidMemInfo.readSideEffects(ScreenNum, base, Size);
295}
296
297