2 * Abstraction of the AGP GART interface.
4 * This version is for both Linux and FreeBSD.
6 * Copyright © 2000-2001 Nokia Home Communications
7 * Copyright © 2000 VA Linux Systems, Inc.
11 Permission is hereby granted, free of charge, to any person obtaining
12 a 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,
22 EXPRESS 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
26 SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
27 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29 CONNECTION 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.
39 * Author: Pontus Lidman <pontus.lidman@nokia.com> (adaption to KDrive) and others
43 #include <kdrive-config.h>
49 #include <sys/types.h>
52 #include <sys/ioctl.h>
62 #include <asm/ioctl.h>
64 #include <linux/agpgart.h>
66 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
67 #include <sys/ioctl.h>
68 #include <sys/agpio.h>
72 #define AGP_DEVICE "/dev/agpgart"
74 /* AGP page size is independent of the host page size. */
76 #define AGP_PAGE_SIZE 4096
78 #define AGPGART_MAJOR_VERSION 0
79 #define AGPGART_MINOR_VERSION 99
81 static int gartFd
= -1;
82 static int acquiredScreen
= -1;
85 * Open /dev/agpgart. Keep it open until server exit.
91 static Bool initDone
= FALSE
;
92 struct _agp_info agpinf
;
95 return (gartFd
!= -1);
100 gartFd
= open(AGP_DEVICE
, O_RDWR
, 0);
105 fprintf(stderr
, "Unable to open " AGP_DEVICE
" (%s)\n",
111 /* Check the kernel driver version. */
112 if (ioctl(gartFd
, AGPIOC_INFO
, &agpinf
) != 0) {
113 fprintf(stderr
, "GARTInit: AGPIOC_INFO failed (%s)\n",
122 /* Per Dave Jones, every effort will be made to keep the
123 * agpgart interface backwards compatible, so allow all
127 #if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */
128 agpinf
.version
.major
< AGPGART_MAJOR_VERSION
||
130 (agpinf
.version
.major
== AGPGART_MAJOR_VERSION
&&
131 agpinf
.version
.minor
< AGPGART_MINOR_VERSION
)) {
133 "Kernel agpgart driver version is not current"
134 " (%d.%d vs %d.%d)\n",
135 agpinf
.version
.major
, agpinf
.version
.minor
,
136 AGPGART_MAJOR_VERSION
, AGPGART_MINOR_VERSION
);
153 KdGetAGPInfo(int screenNum
)
155 struct _agp_info agpinf
;
162 if ((info
= calloc(sizeof(AgpInfo
), 1)) == NULL
) {
163 fprintf(stderr
, "Failed to allocate AgpInfo\n");
167 if (ioctl(gartFd
, AGPIOC_INFO
, &agpinf
) != 0) {
169 "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
174 info
->bridgeId
= agpinf
.bridge_id
;
175 info
->agpMode
= agpinf
.agp_mode
;
176 info
->base
= agpinf
.aper_base
;
177 info
->size
= agpinf
.aper_size
;
178 info
->totalPages
= agpinf
.pg_total
;
179 info
->systemPages
= agpinf
.pg_system
;
180 info
->usedPages
= agpinf
.pg_used
;
186 * XXX If multiple screens can acquire the GART, should we have a reference
187 * count instead of using acquiredScreen?
191 KdAcquireGART(int screenNum
)
193 if (screenNum
!= -1 && !GARTInit())
196 if (screenNum
== -1 || acquiredScreen
!= screenNum
) {
197 if (ioctl(gartFd
, AGPIOC_ACQUIRE
, 0) != 0) {
199 "AGPIOC_ACQUIRE failed (%s)\n",
203 acquiredScreen
= screenNum
;
210 KdReleaseGART(int screenNum
)
212 if (screenNum
!= -1 && !GARTInit())
215 if (acquiredScreen
== screenNum
) {
216 if (ioctl(gartFd
, AGPIOC_RELEASE
, 0) != 0) {
218 "AGPIOC_RELEASE failed (%s)\n",
229 KdAllocateGARTMemory(int screenNum
, unsigned long size
, int type
,
230 unsigned long *physical
)
232 struct _agp_allocate alloc
;
236 * Allocates "size" bytes of GART memory (rounds up to the next
237 * page multiple) or type "type". A handle (key) for the allocated
238 * memory is returned. On error, the return value is -1.
241 if (!GARTInit() || acquiredScreen
!= screenNum
)
244 pages
= (size
/ AGP_PAGE_SIZE
);
245 if (size
% AGP_PAGE_SIZE
!= 0)
248 /* XXX check for pages == 0? */
250 alloc
.pg_count
= pages
;
253 if (ioctl(gartFd
, AGPIOC_ALLOCATE
, &alloc
) != 0) {
254 fprintf(stderr
, "KdAllocateGARTMemory: "
255 "allocation of %d pages failed\n\t(%s)\n", pages
,
261 *physical
= alloc
.physical
;
267 /* Bind GART memory with "key" at "offset" */
269 KdBindGARTMemory(int screenNum
, int key
, unsigned long offset
)
271 struct _agp_bind bind
;
274 if (!GARTInit() || acquiredScreen
!= screenNum
)
277 if (acquiredScreen
!= screenNum
) {
279 "AGP not acquired by this screen\n");
283 if (offset
% AGP_PAGE_SIZE
!= 0) {
284 fprintf(stderr
, "KdBindGARTMemory: "
285 "offset (0x%lx) is not page-aligned (%d)\n",
286 offset
, AGP_PAGE_SIZE
);
289 pageOffset
= offset
/ AGP_PAGE_SIZE
;
291 bind
.pg_start
= pageOffset
;
294 if (ioctl(gartFd
, AGPIOC_BIND
, &bind
) != 0) {
295 fprintf(stderr
, "KdBindGARTMemory: "
296 "binding of gart memory with key %d\n"
297 "\tat offset 0x%lx failed (%s)\n",
298 key
, offset
, strerror(errno
));
306 /* Unbind GART memory with "key" */
308 KdUnbindGARTMemory(int screenNum
, int key
)
310 struct _agp_unbind unbind
;
312 if (!GARTInit() || acquiredScreen
!= screenNum
)
315 if (acquiredScreen
!= screenNum
) {
317 "AGP not acquired by this screen\n");
324 if (ioctl(gartFd
, AGPIOC_UNBIND
, &unbind
) != 0) {
325 fprintf(stderr
, "KdUnbindGARTMemory: "
326 "unbinding of gart memory with key %d "
327 "failed (%s)\n", key
, strerror(errno
));
335 /* XXX Interface may change. */
337 KdEnableAGP(int screenNum
, CARD32 mode
)
341 if (!GARTInit() || acquiredScreen
!= screenNum
)
344 setup
.agp_mode
= mode
;
345 if (ioctl(gartFd
, AGPIOC_SETUP
, &setup
) != 0) {
346 fprintf(stderr
, "KdEnableAGP: "
347 "AGPIOC_SETUP with mode %ld failed (%s)\n",
348 mode
, strerror(errno
));