2 * Abstraction of the AGP GART interface.
4 * This version is for Solaris.
6 * Copyright © 2000 VA Linux Systems, Inc.
7 * Copyright © 2001 The XFree86 Project, Inc.
9 /* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
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:
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
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.
31 #ifdef HAVE_XORG_CONFIG_H
32 #include <xorg-config.h>
38 #include "xf86_OSlib.h"
39 #include "xf86_OSproc.h"
41 #include <sys/ioccom.h>
42 #include <sys/types.h>
44 #include <sys/agpgart.h>
46 /* AGP page size is independent of the host page size. */
48 #define AGP_PAGE_SIZE 4096
51 static int gartFd
= -1;
52 static int acquiredScreen
= -1;
53 static Bool initDone
= FALSE
;
56 * Close /dev/agpgart. This frees all associated memory allocated during
57 * this server generation.
60 xf86GARTCloseScreen(int screenNum
)
68 xf86DrvMsg(screenNum
, X_INFO
,
69 "xf86GARTCloseScreen: device closed successfully\n");
76 * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called.
79 GARTInit(int screenNum
)
85 gartFd
= open(AGP_DEVICE
, O_RDWR
);
90 xf86DrvMsg(screenNum
, X_ERROR
,
91 "GARTInit: Unable to open " AGP_DEVICE
" (%s)\n",
97 xf86DrvMsg(screenNum
, X_INFO
,
98 "GARTInit: " AGP_DEVICE
" opened successfully\n");
104 xf86AgpGARTSupported(void)
106 return (GARTInit(-1));
111 xf86GetAGPInfo(int screenNum
)
116 if (!GARTInit(screenNum
))
119 if (ioctl(gartFd
, AGPIOC_INFO
, &agpinf
) != 0) {
120 xf86DrvMsg(screenNum
, X_ERROR
,
121 "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
126 if ((info
= calloc(sizeof(AgpInfo
), 1)) == NULL
) {
127 xf86DrvMsg(screenNum
, X_ERROR
,
128 "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
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
;
144 xf86AcquireGART(int screenNum
)
147 if (!GARTInit(screenNum
))
150 if (acquiredScreen
!= screenNum
) {
151 if (ioctl(gartFd
, AGPIOC_ACQUIRE
, 0) != 0) {
152 xf86DrvMsg(screenNum
, X_WARNING
,
153 "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
157 acquiredScreen
= screenNum
;
158 xf86DrvMsg(screenNum
, X_INFO
,
159 "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n");
165 xf86ReleaseGART(int screenNum
)
168 if (!GARTInit(screenNum
))
171 if (acquiredScreen
== screenNum
) {
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
179 if (ioctl(gartFd
, AGPIOC_RELEASE
, 0) != 0) {
180 xf86DrvMsg(screenNum
, X_WARNING
,
181 "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
186 xf86DrvMsg(screenNum
, X_INFO
,
187 "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n");
194 xf86AllocateGARTMemory(int screenNum
, unsigned long size
, int type
,
195 unsigned long *physical
)
197 agp_allocate_t alloc
;
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
208 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
211 pages
= (size
/ AGP_PAGE_SIZE
);
212 if (size
% AGP_PAGE_SIZE
!= 0)
215 alloc
.agpa_pgcount
= pages
;
216 alloc
.agpa_type
= type
;
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
,
226 *physical
= (unsigned long) alloc
.agpa_physical
;
228 return alloc
.agpa_key
;
232 xf86DeallocateGARTMemory(int screenNum
, int key
)
234 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
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
));
247 /* Bind GART memory with "key" at "offset" */
249 xf86BindGARTMemory(int screenNum
, int key
, unsigned long offset
)
254 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
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
);
263 pageOffset
= offset
/ AGP_PAGE_SIZE
;
265 xf86DrvMsgVerb(screenNum
, X_INFO
, 3,
266 "xf86BindGARTMemory: bind key %d at 0x%08lx "
267 "(pgoffset %d)\n", key
, offset
, pageOffset
);
269 bind
.agpb_pgstart
= pageOffset
;
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
));
283 /* Unbind GART memory with "key" */
285 xf86UnbindGARTMemory(int screenNum
, int key
)
289 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
293 unbind
.agpu_key
= key
;
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
));
302 xf86DrvMsgVerb(screenNum
, X_INFO
, 3,
303 "xf86UnbindGARTMemory: unbind key %d\n", key
);
308 /* XXX Interface may change. */
310 xf86EnableAGP(int screenNum
, CARD32 mode
)
314 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
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
));