1428d7b3dSmrg/**************************************************************************
2428d7b3dSmrg
3428d7b3dSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4428d7b3dSmrgAll Rights Reserved.
5428d7b3dSmrg
6428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a
7428d7b3dSmrgcopy of this software and associated documentation files (the
8428d7b3dSmrg"Software"), to deal in the Software without restriction, including
9428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish,
10428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to
11428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to
12428d7b3dSmrgthe following conditions:
13428d7b3dSmrg
14428d7b3dSmrgThe above copyright notice and this permission notice (including the
15428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions
16428d7b3dSmrgof the Software.
17428d7b3dSmrg
18428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21428d7b3dSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22428d7b3dSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23428d7b3dSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24428d7b3dSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25428d7b3dSmrg
26428d7b3dSmrg**************************************************************************/
27428d7b3dSmrg
28428d7b3dSmrg#ifdef HAVE_CONFIG_H
29428d7b3dSmrg#include "config.h"
30428d7b3dSmrg#endif
31428d7b3dSmrg
32428d7b3dSmrg/*
33428d7b3dSmrg * Authors:
34428d7b3dSmrg *   Keith Whitwell <keith@tungstengraphics.com>
35428d7b3dSmrg *
36428d7b3dSmrg */
37428d7b3dSmrg
38428d7b3dSmrg#include "xorg-server.h"
39428d7b3dSmrg#include "xf86.h"
40428d7b3dSmrg#include "xf86_OSproc.h"
41428d7b3dSmrg
42428d7b3dSmrg#include "i810.h"
43428d7b3dSmrg#include "i810_reg.h"
44428d7b3dSmrg
45428d7b3dSmrgint
46428d7b3dSmrgI810AllocLow(I810MemRange * result, I810MemRange * pool, int size)
47428d7b3dSmrg{
48428d7b3dSmrg   if (size > (long)pool->Size)
49428d7b3dSmrg      return 0;
50428d7b3dSmrg
51428d7b3dSmrg   pool->Size -= size;
52428d7b3dSmrg   result->Size = size;
53428d7b3dSmrg   result->Start = pool->Start;
54428d7b3dSmrg   result->End = pool->Start += size;
55428d7b3dSmrg
56428d7b3dSmrg   return 1;
57428d7b3dSmrg}
58428d7b3dSmrg
59428d7b3dSmrgint
60428d7b3dSmrgI810AllocHigh(I810MemRange * result, I810MemRange * pool, int size)
61428d7b3dSmrg{
62428d7b3dSmrg   if (size > (long)pool->Size)
63428d7b3dSmrg      return 0;
64428d7b3dSmrg
65428d7b3dSmrg   pool->Size -= size;
66428d7b3dSmrg   result->Size = size;
67428d7b3dSmrg   result->End = pool->End;
68428d7b3dSmrg   result->Start = pool->End -= size;
69428d7b3dSmrg
70428d7b3dSmrg   return 1;
71428d7b3dSmrg}
72428d7b3dSmrg
73428d7b3dSmrgint
74428d7b3dSmrgI810AllocateGARTMemory(ScrnInfoPtr pScrn)
75428d7b3dSmrg{
76428d7b3dSmrg   unsigned long size = pScrn->videoRam * 1024UL;
77428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
78428d7b3dSmrg   int key;
79428d7b3dSmrg   long tom = 0;
80428d7b3dSmrg   unsigned long physical;
81428d7b3dSmrg
82428d7b3dSmrg   if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
83428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
84428d7b3dSmrg		 "AGP GART support is either not available or cannot be used.\n"
85428d7b3dSmrg		 "\tMake sure your kernel has agpgart support or has the\n"
86428d7b3dSmrg		 "\tagpgart module loaded.\n");
87428d7b3dSmrg      return FALSE;
88428d7b3dSmrg   }
89428d7b3dSmrg
90428d7b3dSmrg   /* This allows the 2d only Xserver to regen */
91428d7b3dSmrg   pI810->agpAcquired2d = TRUE;
92428d7b3dSmrg
93428d7b3dSmrg   /*
94428d7b3dSmrg    * I810/I815
95428d7b3dSmrg    *
96428d7b3dSmrg    * Treat the gart like video memory - we assume we own all that is
97428d7b3dSmrg    * there, so ignore EBUSY errors.  Don't try to remove it on
98428d7b3dSmrg    * failure, either, as other X server may be using it.
99428d7b3dSmrg    */
100428d7b3dSmrg
101428d7b3dSmrg   if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL)) == -1)
102428d7b3dSmrg      return FALSE;
103428d7b3dSmrg
104428d7b3dSmrg   pI810->VramOffset = 0;
105428d7b3dSmrg   pI810->VramKey = key;
106428d7b3dSmrg
107428d7b3dSmrg   if (!xf86BindGARTMemory(pScrn->scrnIndex, key, 0))
108428d7b3dSmrg      return FALSE;
109428d7b3dSmrg
110428d7b3dSmrg   pI810->SysMem.Start = 0;
111428d7b3dSmrg   pI810->SysMem.Size = size;
112428d7b3dSmrg   pI810->SysMem.End = size;
113428d7b3dSmrg   pI810->SavedSysMem = pI810->SysMem;
114428d7b3dSmrg
115428d7b3dSmrg   tom = pI810->SysMem.End;
116428d7b3dSmrg
117428d7b3dSmrg   pI810->DcacheMem.Start = 0;
118428d7b3dSmrg   pI810->DcacheMem.End = 0;
119428d7b3dSmrg   pI810->DcacheMem.Size = 0;
120428d7b3dSmrg   pI810->CursorPhysical = 0;
121428d7b3dSmrg   pI810->CursorARGBPhysical = 0;
122428d7b3dSmrg
123428d7b3dSmrg   /*
124428d7b3dSmrg    * Dcache - half the speed of normal ram, so not really useful for
125428d7b3dSmrg    * a 2d server.  Don't bother reporting its presence.  This is
126428d7b3dSmrg    * mapped in addition to the requested amount of system ram.
127428d7b3dSmrg    */
128428d7b3dSmrg
129428d7b3dSmrg   size = 1024 * 4096;
130428d7b3dSmrg
131428d7b3dSmrg   /*
132428d7b3dSmrg    * Keep it 512K aligned for the sake of tiled regions.
133428d7b3dSmrg    */
134428d7b3dSmrg
135428d7b3dSmrg   tom += 0x7ffff;
136428d7b3dSmrg   tom &= ~0x7ffff;
137428d7b3dSmrg
138428d7b3dSmrg   if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
139428d7b3dSmrg      pI810->DcacheOffset = tom;
140428d7b3dSmrg      pI810->DcacheKey = key;
141428d7b3dSmrg      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
142428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
143428d7b3dSmrg		    "Allocation of %ld bytes for DCACHE failed\n", size);
144428d7b3dSmrg	 pI810->DcacheKey = -1;
145428d7b3dSmrg      } else {
146428d7b3dSmrg	 pI810->DcacheMem.Start = tom;
147428d7b3dSmrg	 pI810->DcacheMem.Size = size;
148428d7b3dSmrg	 pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size;
149428d7b3dSmrg	 tom = pI810->DcacheMem.End;
150428d7b3dSmrg      }
151428d7b3dSmrg   } else {
152428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
153428d7b3dSmrg		 "No physical memory available for %ld bytes of DCACHE\n",
154428d7b3dSmrg		 size);
155428d7b3dSmrg      pI810->DcacheKey = -1;
156428d7b3dSmrg   }
157428d7b3dSmrg
158428d7b3dSmrg   /*
159428d7b3dSmrg    * Mouse cursor -- The i810 (crazy) needs a physical address in
160428d7b3dSmrg    * system memory from which to upload the cursor.  We get this from
161428d7b3dSmrg    * the agpgart module using a special memory type.
162428d7b3dSmrg    */
163428d7b3dSmrg
164428d7b3dSmrg   /*
165428d7b3dSmrg    * 4k for the cursor is excessive, I'm going to steal 3k for
166428d7b3dSmrg    * overlay registers later
167428d7b3dSmrg    */
168428d7b3dSmrg
169428d7b3dSmrg   size = 4096;
170428d7b3dSmrg
171428d7b3dSmrg   if ((key =
172428d7b3dSmrg	xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
173428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
174428d7b3dSmrg		 "No physical memory available for HW cursor\n");
175428d7b3dSmrg      pI810->HwcursKey = -1;
176428d7b3dSmrg      pI810->CursorStart = 0;
177428d7b3dSmrg   } else {
178428d7b3dSmrg      pI810->HwcursOffset = tom;
179428d7b3dSmrg      pI810->HwcursKey = key;
180428d7b3dSmrg      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
181428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
182428d7b3dSmrg		    "Allocation of %ld bytes for HW cursor failed\n", size);
183428d7b3dSmrg	 pI810->HwcursKey = -1;
184428d7b3dSmrg      } else {
185428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
186428d7b3dSmrg		    "Allocated of %ld bytes for HW cursor\n", size);
187428d7b3dSmrg	 pI810->CursorPhysical = physical;
188428d7b3dSmrg	 pI810->CursorStart = tom;
189428d7b3dSmrg	 tom += size;
190428d7b3dSmrg      }
191428d7b3dSmrg   }
192428d7b3dSmrg
193428d7b3dSmrg   /*
194428d7b3dSmrg    * 16k for the ARGB cursor
195428d7b3dSmrg    */
196428d7b3dSmrg
197428d7b3dSmrg   size = 16384;
198428d7b3dSmrg
199428d7b3dSmrg   if ((key =
200428d7b3dSmrg	xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
201428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
202428d7b3dSmrg		 "No physical memory available for ARGB HW cursor\n");
203428d7b3dSmrg      pI810->ARGBHwcursKey = -1;
204428d7b3dSmrg      pI810->CursorARGBStart = 0;
205428d7b3dSmrg   } else {
206428d7b3dSmrg      pI810->ARGBHwcursOffset = tom;
207428d7b3dSmrg      pI810->ARGBHwcursKey = key;
208428d7b3dSmrg      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
209428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
210428d7b3dSmrg		    "Allocation of %ld bytes for ARGB HW cursor failed\n", size);
211428d7b3dSmrg	 pI810->ARGBHwcursKey = -1;
212428d7b3dSmrg      } else {
213428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
214428d7b3dSmrg		    "Allocated of %ld bytes for ARGB HW cursor\n", size);
215428d7b3dSmrg	 pI810->CursorARGBPhysical = physical;
216428d7b3dSmrg	 pI810->CursorARGBStart = tom;
217428d7b3dSmrg	 tom += size;
218428d7b3dSmrg      }
219428d7b3dSmrg   }
220428d7b3dSmrg
221428d7b3dSmrg   /*
222428d7b3dSmrg    * Overlay register buffer -- Just like the cursor, the i810 needs a
223428d7b3dSmrg    * physical address in system memory from which to upload the overlay
224428d7b3dSmrg    * registers.
225428d7b3dSmrg    */
226428d7b3dSmrg
227428d7b3dSmrg   if (pI810->CursorStart != 0) {
228428d7b3dSmrg      pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
229428d7b3dSmrg      pI810->OverlayStart = pI810->CursorStart + 1024;
230428d7b3dSmrg   }
231428d7b3dSmrg
232428d7b3dSmrg   pI810->GttBound = 1;
233428d7b3dSmrg
234428d7b3dSmrg   return TRUE;
235428d7b3dSmrg}
236428d7b3dSmrg
237428d7b3dSmrg/* Tiled memory is good... really, really good...
238428d7b3dSmrg *
239428d7b3dSmrg * Need to make it less likely that we miss out on this - probably
240428d7b3dSmrg * need to move the frontbuffer away from the 'guarenteed' alignment
241428d7b3dSmrg * of the first memory segment, or perhaps allocate a discontigous
242428d7b3dSmrg * framebuffer to get more alignment 'sweet spots'.
243428d7b3dSmrg */
244428d7b3dSmrgvoid
245428d7b3dSmrgI810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned int start,
246428d7b3dSmrg		   unsigned int pitch, unsigned int size)
247428d7b3dSmrg{
248428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
249428d7b3dSmrg   I810RegPtr i810Reg = &pI810->ModeReg;
250428d7b3dSmrg   uint32_t val;
251428d7b3dSmrg   uint32_t fence_mask = 0;
252428d7b3dSmrg
253428d7b3dSmrg   if (nr < 0 || nr > 7) {
254428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s - fence %d out of range\n",
255428d7b3dSmrg		 "I810SetTiledMemory", nr);
256428d7b3dSmrg      return;
257428d7b3dSmrg   }
258428d7b3dSmrg
259428d7b3dSmrg   i810Reg->Fence[nr] = 0;
260428d7b3dSmrg
261428d7b3dSmrg   fence_mask = ~FENCE_START_MASK;
262428d7b3dSmrg
263428d7b3dSmrg   if (start & fence_mask) {
264428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
265428d7b3dSmrg		 "%s %d: start (%x) is not 512k aligned\n",
266428d7b3dSmrg		 "I810SetTiledMemory", nr, start);
267428d7b3dSmrg      return;
268428d7b3dSmrg   }
269428d7b3dSmrg
270428d7b3dSmrg   if (start % size) {
271428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
272428d7b3dSmrg		 "%s %d: start (%x) is not size (%x) aligned\n",
273428d7b3dSmrg		 "I810SetTiledMemory", nr, start, size);
274428d7b3dSmrg      return;
275428d7b3dSmrg   }
276428d7b3dSmrg
277428d7b3dSmrg   if (pitch & 127) {
278428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
279428d7b3dSmrg		 "%s %d: pitch (%x) not a multiple of 128 bytes\n",
280428d7b3dSmrg		 "I810SetTiledMemory", nr, pitch);
281428d7b3dSmrg      return;
282428d7b3dSmrg   }
283428d7b3dSmrg
284428d7b3dSmrg   val = (start | FENCE_X_MAJOR | FENCE_VALID);
285428d7b3dSmrg
286428d7b3dSmrg   switch (size) {
287428d7b3dSmrg   case KB(512):
288428d7b3dSmrg      val |= FENCE_SIZE_512K;
289428d7b3dSmrg      break;
290428d7b3dSmrg   case MB(1):
291428d7b3dSmrg      val |= FENCE_SIZE_1M;
292428d7b3dSmrg      break;
293428d7b3dSmrg   case MB(2):
294428d7b3dSmrg      val |= FENCE_SIZE_2M;
295428d7b3dSmrg      break;
296428d7b3dSmrg   case MB(4):
297428d7b3dSmrg      val |= FENCE_SIZE_4M;
298428d7b3dSmrg      break;
299428d7b3dSmrg   case MB(8):
300428d7b3dSmrg      val |= FENCE_SIZE_8M;
301428d7b3dSmrg      break;
302428d7b3dSmrg   case MB(16):
303428d7b3dSmrg      val |= FENCE_SIZE_16M;
304428d7b3dSmrg      break;
305428d7b3dSmrg   case MB(32):
306428d7b3dSmrg      val |= FENCE_SIZE_32M;
307428d7b3dSmrg      break;
308428d7b3dSmrg   default:
309428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
310428d7b3dSmrg		 "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
311428d7b3dSmrg		 size);
312428d7b3dSmrg      return;
313428d7b3dSmrg   }
314428d7b3dSmrg
315428d7b3dSmrg   switch (pitch / 128) {
316428d7b3dSmrg   case 1:
317428d7b3dSmrg      val |= FENCE_PITCH_1;
318428d7b3dSmrg      break;
319428d7b3dSmrg   case 2:
320428d7b3dSmrg      val |= FENCE_PITCH_2;
321428d7b3dSmrg      break;
322428d7b3dSmrg   case 4:
323428d7b3dSmrg      val |= FENCE_PITCH_4;
324428d7b3dSmrg      break;
325428d7b3dSmrg   case 8:
326428d7b3dSmrg      val |= FENCE_PITCH_8;
327428d7b3dSmrg      break;
328428d7b3dSmrg   case 16:
329428d7b3dSmrg      val |= FENCE_PITCH_16;
330428d7b3dSmrg      break;
331428d7b3dSmrg   case 32:
332428d7b3dSmrg      val |= FENCE_PITCH_32;
333428d7b3dSmrg      break;
334428d7b3dSmrg   default:
335428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
336428d7b3dSmrg		 "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
337428d7b3dSmrg		 size);
338428d7b3dSmrg      return;
339428d7b3dSmrg   }
340428d7b3dSmrg
341428d7b3dSmrg   i810Reg->Fence[nr] = val;
342428d7b3dSmrg}
343428d7b3dSmrg
344428d7b3dSmrgBool
345428d7b3dSmrgI810BindGARTMemory(ScrnInfoPtr pScrn)
346428d7b3dSmrg{
347428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
348428d7b3dSmrg
349428d7b3dSmrg   if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled
350428d7b3dSmrg       && !pI810->GttBound) {
351428d7b3dSmrg      if (!xf86AcquireGART(pScrn->scrnIndex))
352428d7b3dSmrg	 return FALSE;
353428d7b3dSmrg
354428d7b3dSmrg      if (pI810->VramKey != -1
355428d7b3dSmrg	  && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->VramKey,
356428d7b3dSmrg				 pI810->VramOffset))
357428d7b3dSmrg	 return FALSE;
358428d7b3dSmrg
359428d7b3dSmrg      if (pI810->DcacheKey != -1
360428d7b3dSmrg	  && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey,
361428d7b3dSmrg				 pI810->DcacheOffset))
362428d7b3dSmrg	 return FALSE;
363428d7b3dSmrg
364428d7b3dSmrg      if (pI810->HwcursKey != -1
365428d7b3dSmrg	  && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey,
366428d7b3dSmrg				 pI810->HwcursOffset))
367428d7b3dSmrg	 return FALSE;
368428d7b3dSmrg
369428d7b3dSmrg      if (pI810->ARGBHwcursKey != -1
370428d7b3dSmrg	  && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey,
371428d7b3dSmrg				 pI810->ARGBHwcursOffset))
372428d7b3dSmrg	 return FALSE;
373428d7b3dSmrg
374428d7b3dSmrg      pI810->GttBound = 1;
375428d7b3dSmrg   }
376428d7b3dSmrg
377428d7b3dSmrg   return TRUE;
378428d7b3dSmrg}
379428d7b3dSmrg
380428d7b3dSmrgBool
381428d7b3dSmrgI810UnbindGARTMemory(ScrnInfoPtr pScrn)
382428d7b3dSmrg{
383428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
384428d7b3dSmrg
385428d7b3dSmrg   if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled
386428d7b3dSmrg       && pI810->GttBound) {
387428d7b3dSmrg      if (pI810->VramKey != -1
388428d7b3dSmrg	  && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->VramKey))
389428d7b3dSmrg	 return FALSE;
390428d7b3dSmrg
391428d7b3dSmrg      if (pI810->DcacheKey != -1
392428d7b3dSmrg	  && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey))
393428d7b3dSmrg	 return FALSE;
394428d7b3dSmrg
395428d7b3dSmrg      if (pI810->HwcursKey != -1
396428d7b3dSmrg	  && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey))
397428d7b3dSmrg	 return FALSE;
398428d7b3dSmrg
399428d7b3dSmrg      if (pI810->ARGBHwcursKey != -1
400428d7b3dSmrg	  && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey))
401428d7b3dSmrg	 return FALSE;
402428d7b3dSmrg
403428d7b3dSmrg      if (!xf86ReleaseGART(pScrn->scrnIndex))
404428d7b3dSmrg	 return FALSE;
405428d7b3dSmrg
406428d7b3dSmrg      pI810->GttBound = 0;
407428d7b3dSmrg   }
408428d7b3dSmrg
409428d7b3dSmrg   return TRUE;
410428d7b3dSmrg}
411428d7b3dSmrg
412428d7b3dSmrgint
413428d7b3dSmrgI810CheckAvailableMemory(ScrnInfoPtr pScrn)
414428d7b3dSmrg{
415428d7b3dSmrg   AgpInfoPtr agpinf;
416428d7b3dSmrg   int maxPages;
417428d7b3dSmrg
418428d7b3dSmrg   if (!xf86AgpGARTSupported() ||
419428d7b3dSmrg       !xf86AcquireGART(pScrn->scrnIndex) ||
420428d7b3dSmrg       (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL ||
421428d7b3dSmrg       !xf86ReleaseGART(pScrn->scrnIndex))
422428d7b3dSmrg      return -1;
423428d7b3dSmrg
424428d7b3dSmrg   maxPages = agpinf->totalPages - agpinf->usedPages;
425428d7b3dSmrg   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %dk available\n",
426428d7b3dSmrg		  "I810CheckAvailableMemory", maxPages * 4);
427428d7b3dSmrg
428428d7b3dSmrg   return maxPages * 4;
429428d7b3dSmrg}
430