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 2005 Sun Microsystems, Inc. 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
13 * "Software"), to deal in the Software without restriction, including
14 * without limitation the rights to use, copy, modify, merge, publish,
15 * distribute, and/or sell copies of the Software, and to permit persons
16 * to whom the Software is furnished to do so, provided that the above
17 * copyright notice(s) and this permission notice appear in all copies of
18 * the Software and that both the above copyright notice(s) and this
19 * permission notice appear in supporting documentation.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
24 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
26 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
27 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
29 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 * Except as contained in this notice, the name of a copyright holder
32 * shall not be used in advertising or otherwise to promote the sale, use
33 * or other dealings in this Software without prior written authorization
34 * of the copyright holder.
37 #pragma ident "@(#)sun_agp.c 1.1 05/04/04 SMI"
39 #ifdef HAVE_XORG_CONFIG_H
40 #include <xorg-config.h>
46 #include "xf86_OSlib.h"
47 #include "xf86_OSproc.h"
49 #include <sys/ioccom.h>
50 #include <sys/types.h>
55 #define AGP_DEVICE "/dev/agpgart"
57 /* AGP page size is independent of the host page size. */
59 #define AGP_PAGE_SIZE 4096
62 static int gartFd
= -1;
63 static int acquiredScreen
= -1;
64 static Bool initDone
= FALSE
;
66 * Close /dev/agpgart. This frees all associated memory allocated during
67 * this server generation.
70 xf86GARTCloseScreen(int screenNum
)
78 xf86DrvMsg(screenNum
, X_INFO
,
79 "xf86GARTCloseScreen: device closed successfully\n");
86 * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called.
89 GARTInit(int screenNum
)
92 return (gartFd
!= -1);
95 gartFd
= open(AGP_DEVICE
, O_RDWR
);
100 xf86DrvMsg(screenNum
, X_ERROR
,
101 "GARTInit: Unable to open " AGP_DEVICE
" (%s)\n",
107 xf86DrvMsg(screenNum
, X_INFO
,
108 "GARTInit: " AGP_DEVICE
" opened successfully\n");
114 xf86AgpGARTSupported(void)
116 return (GARTInit(-1));
121 xf86GetAGPInfo(int screenNum
)
126 if (!GARTInit(screenNum
))
129 if ((info
= xcalloc(sizeof(AgpInfo
), 1)) == NULL
) {
130 xf86DrvMsg(screenNum
, X_ERROR
,
131 "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
135 if (ioctl(gartFd
, AGPIOC_INFO
, &agpinf
) != 0) {
136 xf86DrvMsg(screenNum
, X_ERROR
,
137 "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
142 info
->bridgeId
= agpinf
.agpi_devid
;
143 info
->agpMode
= agpinf
.agpi_mode
;
144 info
->base
= agpinf
.agpi_aperbase
;
145 info
->size
= agpinf
.agpi_apersize
;
146 info
->totalPages
= (unsigned long)agpinf
.agpi_pgtotal
;
147 info
->systemPages
= (unsigned long)agpinf
.agpi_pgsystem
;
148 info
->usedPages
= (unsigned long)agpinf
.agpi_pgused
;
154 xf86AcquireGART(int screenNum
)
157 if (!GARTInit(screenNum
))
160 if (acquiredScreen
!= screenNum
) {
161 if (ioctl(gartFd
, AGPIOC_ACQUIRE
, 0) != 0) {
162 xf86DrvMsg(screenNum
, X_WARNING
,
163 "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
167 acquiredScreen
= screenNum
;
168 xf86DrvMsg(screenNum
, X_INFO
,
169 "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n");
175 xf86ReleaseGART(int screenNum
)
178 if (!GARTInit(screenNum
))
181 if (acquiredScreen
== screenNum
) {
183 * The FreeBSD agp driver removes allocations on release.
184 * The Solaris driver doesn't. xf86ReleaseGART() is expected
185 * to give up access to the GART, but not to remove any
189 if (ioctl(gartFd
, AGPIOC_RELEASE
, 0) != 0) {
190 xf86DrvMsg(screenNum
, X_WARNING
,
191 "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
196 xf86DrvMsg(screenNum
, X_INFO
,
197 "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n");
204 xf86AllocateGARTMemory(int screenNum
, unsigned long size
, int type
,
205 unsigned long *physical
)
207 agp_allocate_t alloc
;
211 * Allocates "size" bytes of GART memory (rounds up to the next
212 * page multiple) or type "type". A handle (key) for the allocated
213 * memory is returned. On error, the return value is -1.
214 * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will
218 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
221 pages
= (size
/ AGP_PAGE_SIZE
);
222 if (size
% AGP_PAGE_SIZE
!= 0)
225 alloc
.agpa_pgcount
= pages
;
226 alloc
.agpa_type
= type
;
228 if (ioctl(gartFd
, AGPIOC_ALLOCATE
, &alloc
) != 0) {
229 xf86DrvMsg(screenNum
, X_WARNING
, "xf86AllocateGARTMemory: "
230 "allocation of %d pages failed\n\t(%s)\n", pages
,
236 *physical
= (unsigned long)alloc
.agpa_physical
;
238 return alloc
.agpa_key
;
242 xf86DeallocateGARTMemory(int screenNum
, int key
)
244 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
247 if (ioctl(gartFd
, AGPIOC_DEALLOCATE
, (int *)key
) != 0) {
248 xf86DrvMsg(screenNum
, X_WARNING
, "xf86DeAllocateGARTMemory: "
249 "deallocation of gart memory with key %d failed\n"
250 "\t(%s)\n", key
, strerror(errno
));
257 /* Bind GART memory with "key" at "offset" */
259 xf86BindGARTMemory(int screenNum
, int key
, unsigned long offset
)
264 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
267 if (offset
% AGP_PAGE_SIZE
!= 0) {
268 xf86DrvMsg(screenNum
, X_WARNING
, "xf86BindGARTMemory: "
269 "offset (0x%lx) is not page-aligned (%d)\n",
270 offset
, AGP_PAGE_SIZE
);
273 pageOffset
= offset
/ AGP_PAGE_SIZE
;
275 xf86DrvMsgVerb(screenNum
, X_INFO
, 3,
276 "xf86BindGARTMemory: bind key %d at 0x%08lx "
277 "(pgoffset %d)\n", key
, offset
, pageOffset
);
279 bind
.agpb_pgstart
= pageOffset
;
282 if (ioctl(gartFd
, AGPIOC_BIND
, &bind
) != 0) {
283 xf86DrvMsg(screenNum
, X_WARNING
, "xf86BindGARTMemory: "
284 "binding of gart memory with key %d\n"
285 "\tat offset 0x%lx failed (%s)\n",
286 key
, offset
, strerror(errno
));
293 /* Unbind GART memory with "key" */
295 xf86UnbindGARTMemory(int screenNum
, int key
)
299 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
303 unbind
.agpu_key
= key
;
305 if (ioctl(gartFd
, AGPIOC_UNBIND
, &unbind
) != 0) {
306 xf86DrvMsg(screenNum
, X_WARNING
, "xf86UnbindGARTMemory: "
307 "unbinding of gart memory with key %d "
308 "failed (%s)\n", key
, strerror(errno
));
312 xf86DrvMsgVerb(screenNum
, X_INFO
, 3,
313 "xf86UnbindGARTMemory: unbind key %d\n", key
);
319 /* XXX Interface may change. */
321 xf86EnableAGP(int screenNum
, CARD32 mode
)
325 if (!GARTInit(screenNum
) || (acquiredScreen
!= screenNum
))
328 setup
.agps_mode
= mode
;
329 if (ioctl(gartFd
, AGPIOC_SETUP
, &setup
) != 0) {
330 xf86DrvMsg(screenNum
, X_WARNING
, "xf86EnableAGP: "
331 "AGPIOC_SETUP with mode %x failed (%s)\n",
332 mode
, strerror(errno
));