Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / solaris / sun_agp.c
CommitLineData
a09e091a
JB
1/*
2 * Abstraction of the AGP GART interface.
3 *
4 * This version is for Solaris.
5 *
6 * Copyright © 2000 VA Linux Systems, Inc.
7 * Copyright © 2001 The XFree86 Project, Inc.
8 */
9/* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
20 * Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 */
30
31#ifdef HAVE_XORG_CONFIG_H
32#include <xorg-config.h>
33#endif
34
35#include <X11/X.h>
36#include "xf86.h"
37#include "xf86Priv.h"
38#include "xf86_OSlib.h"
39#include "xf86_OSproc.h"
40#include <unistd.h>
41#include <sys/ioccom.h>
42#include <sys/types.h>
43#include <fcntl.h>
44#include <sys/agpgart.h>
45
46/* AGP page size is independent of the host page size. */
47#ifndef AGP_PAGE_SIZE
48#define AGP_PAGE_SIZE 4096
49#endif
50
51static int gartFd = -1;
52static int acquiredScreen = -1;
53static Bool initDone = FALSE;
54
55/*
56 * Close /dev/agpgart. This frees all associated memory allocated during
57 * this server generation.
58 */
59Bool
60xf86GARTCloseScreen(int screenNum)
61{
62 if (gartFd != -1) {
63 close(gartFd);
64 acquiredScreen = -1;
65 gartFd = -1;
66 initDone = FALSE;
67
68 xf86DrvMsg(screenNum, X_INFO,
69 "xf86GARTCloseScreen: device closed successfully\n");
70
71 }
72 return TRUE;
73}
74
75/*
76 * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called.
77 */
78static Bool
79GARTInit(int screenNum)
80{
81 if (initDone)
82 return gartFd != -1;
83
84 if (gartFd == -1)
85 gartFd = open(AGP_DEVICE, O_RDWR);
86 else
87 return FALSE;
88
89 if (gartFd == -1) {
90 xf86DrvMsg(screenNum, X_ERROR,
91 "GARTInit: Unable to open " AGP_DEVICE " (%s)\n",
92 strerror(errno));
93 return FALSE;
94 }
95
96 initDone = TRUE;
97 xf86DrvMsg(screenNum, X_INFO,
98 "GARTInit: " AGP_DEVICE " opened successfully\n");
99
100 return TRUE;
101}
102
103Bool
104xf86AgpGARTSupported(void)
105{
106 return (GARTInit(-1));
107
108}
109
110AgpInfoPtr
111xf86GetAGPInfo(int screenNum)
112{
113 agp_info_t agpinf;
114 AgpInfoPtr info;
115
116 if (!GARTInit(screenNum))
117 return NULL;
118
119 if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
120 xf86DrvMsg(screenNum, X_ERROR,
121 "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
122 strerror(errno));
123 return NULL;
124 }
125
126 if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) {
127 xf86DrvMsg(screenNum, X_ERROR,
128 "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
129 return NULL;
130 }
131
132 info->bridgeId = agpinf.agpi_devid;
133 info->agpMode = agpinf.agpi_mode;
134 info->base = agpinf.agpi_aperbase;
135 info->size = agpinf.agpi_apersize;
136 info->totalPages = (unsigned long) agpinf.agpi_pgtotal;
137 info->systemPages = (unsigned long) agpinf.agpi_pgsystem;
138 info->usedPages = (unsigned long) agpinf.agpi_pgused;
139
140 return info;
141}
142
143Bool
144xf86AcquireGART(int screenNum)
145{
146
147 if (!GARTInit(screenNum))
148 return FALSE;
149
150 if (acquiredScreen != screenNum) {
151 if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) {
152 xf86DrvMsg(screenNum, X_WARNING,
153 "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
154 strerror(errno));
155 return FALSE;
156 }
157 acquiredScreen = screenNum;
158 xf86DrvMsg(screenNum, X_INFO,
159 "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n");
160 }
161 return TRUE;
162}
163
164Bool
165xf86ReleaseGART(int screenNum)
166{
167
168 if (!GARTInit(screenNum))
169 return FALSE;
170
171 if (acquiredScreen == screenNum) {
172 /*
173 * The FreeBSD agp driver removes allocations on release.
174 * The Solaris driver doesn't. xf86ReleaseGART() is expected
175 * to give up access to the GART, but not to remove any
176 * allocations.
177 */
178
179 if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) {
180 xf86DrvMsg(screenNum, X_WARNING,
181 "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
182 strerror(errno));
183 return FALSE;
184 }
185 acquiredScreen = -1;
186 xf86DrvMsg(screenNum, X_INFO,
187 "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n");
188 return TRUE;
189 }
190 return FALSE;
191}
192
193int
194xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
195 unsigned long *physical)
196{
197 agp_allocate_t alloc;
198 int pages;
199
200 /*
201 * Allocates "size" bytes of GART memory (rounds up to the next
202 * page multiple) or type "type". A handle (key) for the allocated
203 * memory is returned. On error, the return value is -1.
204 * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will
205 * return error.
206 */
207
208 if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
209 return -1;
210
211 pages = (size / AGP_PAGE_SIZE);
212 if (size % AGP_PAGE_SIZE != 0)
213 pages++;
214
215 alloc.agpa_pgcount = pages;
216 alloc.agpa_type = type;
217
218 if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) {
219 xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: "
220 "allocation of %d pages failed\n\t(%s)\n", pages,
221 strerror(errno));
222 return -1;
223 }
224
225 if (physical)
226 *physical = (unsigned long) alloc.agpa_physical;
227
228 return alloc.agpa_key;
229}
230
231Bool
232xf86DeallocateGARTMemory(int screenNum, int key)
233{
234 if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
235 return FALSE;
236
237 if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *) (uintptr_t) key) != 0) {
238 xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: "
239 "deallocation of gart memory with key %d failed\n"
240 "\t(%s)\n", key, strerror(errno));
241 return FALSE;
242 }
243
244 return TRUE;
245}
246
247/* Bind GART memory with "key" at "offset" */
248Bool
249xf86BindGARTMemory(int screenNum, int key, unsigned long offset)
250{
251 agp_bind_t bind;
252 int pageOffset;
253
254 if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
255 return FALSE;
256
257 if (offset % AGP_PAGE_SIZE != 0) {
258 xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
259 "offset (0x%lx) is not page-aligned (%d)\n",
260 offset, AGP_PAGE_SIZE);
261 return FALSE;
262 }
263 pageOffset = offset / AGP_PAGE_SIZE;
264
265 xf86DrvMsgVerb(screenNum, X_INFO, 3,
266 "xf86BindGARTMemory: bind key %d at 0x%08lx "
267 "(pgoffset %d)\n", key, offset, pageOffset);
268
269 bind.agpb_pgstart = pageOffset;
270 bind.agpb_key = key;
271
272 if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) {
273 xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
274 "binding of gart memory with key %d\n"
275 "\tat offset 0x%lx failed (%s)\n",
276 key, offset, strerror(errno));
277 return FALSE;
278 }
279
280 return TRUE;
281}
282
283/* Unbind GART memory with "key" */
284Bool
285xf86UnbindGARTMemory(int screenNum, int key)
286{
287 agp_unbind_t unbind;
288
289 if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
290 return FALSE;
291
292 unbind.agpu_pri = 0;
293 unbind.agpu_key = key;
294
295 if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) {
296 xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: "
297 "unbinding of gart memory with key %d "
298 "failed (%s)\n", key, strerror(errno));
299 return FALSE;
300 }
301
302 xf86DrvMsgVerb(screenNum, X_INFO, 3,
303 "xf86UnbindGARTMemory: unbind key %d\n", key);
304
305 return TRUE;
306}
307
308/* XXX Interface may change. */
309Bool
310xf86EnableAGP(int screenNum, CARD32 mode)
311{
312 agp_setup_t setup;
313
314 if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
315 return FALSE;
316
317 setup.agps_mode = mode;
318 if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) {
319 xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: "
320 "AGPIOC_SETUP with mode %x failed (%s)\n",
321 (unsigned int) mode, strerror(errno));
322 return FALSE;
323 }
324
325 return TRUE;
326}