示例#1
0
/* Allocate pool space that isn't pre-allocated */
Bool
I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
{
   I830Ptr pI830 = I830PTR(pScrn);

   DPRINTF(PFX, "I830DoPoolAllocation\n");

   if (!pool)
      return FALSE;

   /*
    * Sanity check: there shouldn't be an allocation required when
    * there is only stolen memory.
    */
   if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		 "I830DoPoolAllocation(): pool size is greater than the "
		 "preallocated size,\n\t"
		 "and there is no allocatable memory.\n");
      return FALSE;
   }

   if (pool->Total.Size > pool->Fixed.Size) {
      pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
      pool->Allocated.Key =
	    xf86AllocateGARTMemory(pScrn->scrnIndex, pool->Allocated.Size,
				   0, NULL);
      if (pool->Allocated.Key == -1) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
	 return FALSE;
      }
      pool->Allocated.Start = pool->Fixed.End;
      pool->Allocated.End = pool->Total.Size;
      pool->Allocated.Offset = pool->Allocated.Start;
   } else
      pool->Allocated.Key = -1;
   return TRUE;
}
示例#2
0
int
I810AllocateGARTMemory(ScrnInfoPtr pScrn)
{
   unsigned long size = pScrn->videoRam * 1024;
   I810Ptr pI810 = I810PTR(pScrn);
   int key;
   long tom = 0;
   unsigned long physical;

   if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		 "AGP GART support is either not available or cannot be used.\n"
		 "\tMake sure your kernel has agpgart support or has the\n"
		 "\tagpgart module loaded.\n");
      return FALSE;
   }

   /* This allows the 2d only Xserver to regen */
   pI810->agpAcquired2d = TRUE;

   /*
    * I810/I815
    *
    * Treat the gart like video memory - we assume we own all that is
    * there, so ignore EBUSY errors.  Don't try to remove it on
    * failure, either, as other X server may be using it.
    */

   if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL)) == -1)
      return FALSE;

   pI810->VramOffset = 0;
   pI810->VramKey = key;

   if (!xf86BindGARTMemory(pScrn->scrnIndex, key, 0))
      return FALSE;

   pI810->SysMem.Start = 0;
   pI810->SysMem.Size = size;
   pI810->SysMem.End = size;
   pI810->SavedSysMem = pI810->SysMem;

   tom = pI810->SysMem.End;

   pI810->DcacheMem.Start = 0;
   pI810->DcacheMem.End = 0;
   pI810->DcacheMem.Size = 0;
   pI810->CursorPhysical = 0;
   pI810->CursorARGBPhysical = 0;

   /*
    * Dcache - half the speed of normal ram, so not really useful for
    * a 2d server.  Don't bother reporting its presence.  This is
    * mapped in addition to the requested amount of system ram.
    */

   size = 1024 * 4096;

   /*
    * Keep it 512K aligned for the sake of tiled regions.
    */

   tom += 0x7ffff;
   tom &= ~0x7ffff;

   if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
      pI810->DcacheOffset = tom;
      pI810->DcacheKey = key;
      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		    "Allocation of %ld bytes for DCACHE failed\n", size);
	 pI810->DcacheKey = -1;
      } else {
	 pI810->DcacheMem.Start = tom;
	 pI810->DcacheMem.Size = size;
	 pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size;
	 tom = pI810->DcacheMem.End;
      }
   } else {
      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		 "No physical memory available for %ld bytes of DCACHE\n",
		 size);
      pI810->DcacheKey = -1;
   }

   /*
    * Mouse cursor -- The i810 (crazy) needs a physical address in
    * system memory from which to upload the cursor.  We get this from
    * the agpgart module using a special memory type.
    */

   /*
    * 4k for the cursor is excessive, I'm going to steal 3k for
    * overlay registers later
    */

   size = 4096;

   if ((key =
	xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		 "No physical memory available for HW cursor\n");
      pI810->HwcursKey = -1;
      pI810->CursorStart = 0;
   } else {
      pI810->HwcursOffset = tom;
      pI810->HwcursKey = key;
      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		    "Allocation of %ld bytes for HW cursor failed\n", size);
	 pI810->HwcursKey = -1;
      } else {
	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		    "Allocated of %ld bytes for HW cursor\n", size);
	 pI810->CursorPhysical = physical;
	 pI810->CursorStart = tom;
	 tom += size;
      }
   }

   /*
    * 16k for the ARGB cursor
    */

   size = 16384;

   if ((key =
	xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		 "No physical memory available for ARGB HW cursor\n");
      pI810->ARGBHwcursKey = -1;
      pI810->CursorARGBStart = 0;
   } else {
      pI810->ARGBHwcursOffset = tom;
      pI810->ARGBHwcursKey = key;
      if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		    "Allocation of %ld bytes for ARGB HW cursor failed\n", size);
	 pI810->ARGBHwcursKey = -1;
      } else {
	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		    "Allocated of %ld bytes for ARGB HW cursor\n", size);
	 pI810->CursorARGBPhysical = physical;
	 pI810->CursorARGBStart = tom;
	 tom += size;
      }
   }

   /*
    * Overlay register buffer -- Just like the cursor, the i810 needs a
    * physical address in system memory from which to upload the overlay
    * registers.
    */

   if (pI810->CursorStart != 0) {
      pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
      pI810->OverlayStart = pI810->CursorStart + 1024;
   }

   pI810->GttBound = 1;

   return TRUE;
}
示例#3
0
Bool
I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
{
   I830Ptr pI830 = I830PTR(pScrn);
   unsigned long size, alloced;
   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
   int verbosity = dryrun ? 4 : 1;
   const char *s = dryrun ? "[dryrun] " : "";
   Bool tileable;
   int align, alignflags;

   DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
	   BOOLTOSTRING(flags & ALLOC_INITIAL));

   if (!pI830->StolenOnly &&
       (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
      if (!dryrun) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "AGP GART support is either not available or cannot "
		    "be used.\n"
		    "\tMake sure your kernel has agpgart support or has the\n"
		    "\tagpgart module loaded.\n");
      }
      return FALSE;
   }


   /*
    * The I830 is slightly different from the I830/I815, it has no
    * dcache and it has stolen memory by default in its gtt.  All
    * additional memory must go after it.
    */

   DPRINTF(PFX,
	   "size == %luk (%lu bytes == pScrn->videoRam)\n"
	   "pI830->StolenSize == %luk (%lu bytes)\n",
	   pScrn->videoRam, pScrn->videoRam * 1024,
	   pI830->StolenPool.Free.Size / 1024,
	   pI830->StolenPool.Free.Size);

   if (flags & ALLOC_INITIAL) {
      unsigned long minspace, avail, lineSize;
      int cacheLines, maxCacheLines;

      if (pI830->NeedRingBufferLow)
	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);

      /* Clear everything first. */
      memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox));
      memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
      pI830->FrontBuffer.Key = -1;

      pI830->FbMemBox.x1 = 0;
      pI830->FbMemBox.x2 = pScrn->displayWidth;
      pI830->FbMemBox.y1 = 0;
      pI830->FbMemBox.y2 = pScrn->virtualY;

      /*
       * Calculate how much framebuffer memory to allocate.  For the
       * initial allocation, calculate a reasonable minimum.  This is
       * enough for the virtual screen size, plus some pixmap cache
       * space.
       */

      lineSize = pScrn->displayWidth * pI830->cpp;
      minspace = lineSize * pScrn->virtualY;
      avail = pScrn->videoRam * 1024;
      maxCacheLines = (avail - minspace) / lineSize;
      /* This shouldn't happen. */
      if (maxCacheLines < 0) {
	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		    "Internal Error: "
		    "maxCacheLines < 0 in I830Allocate2DMemory()\n");
	 maxCacheLines = 0;
      }
      if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
	 maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;

      if (pI830->CacheLines >= 0) {
	 cacheLines = pI830->CacheLines;
      } else {
#if 1
	 /* Make sure there is enough for two DVD sized YUV buffers */
	 cacheLines = (pScrn->depth == 24) ? 256 : 384;
	 if (pScrn->displayWidth <= 1024)
	    cacheLines *= 2;
#else
	 /*
	  * Make sure there is enough for two DVD sized YUV buffers.
	  * Make that 1.5MB, which is around what was allocated with
	  * the old algorithm
	  */
	 cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
#endif
      }
      if (cacheLines > maxCacheLines)
	 cacheLines = maxCacheLines;

      pI830->FbMemBox.y2 += cacheLines;

      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		     "%sAllocating at least %d scanlines for pixmap cache\n",
		     s, cacheLines);

      tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
		 IsTileable(pScrn->displayWidth * pI830->cpp);
      if (tileable) {
	 align = KB(512);
	 alignflags = ALIGN_BOTH_ENDS;
      } else {
	 align = KB(64);
	 alignflags = 0;
      }

      size = lineSize * (pScrn->virtualY + cacheLines);
      size = ROUND_TO_PAGE(size);
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		     "%sInitial framebuffer allocation size: %d kByte\n", s,
		     size / 1024);
      alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
				&(pI830->StolenPool), size, align,
				flags | alignflags |
				FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate framebuffer.\n");
	 }
	 return FALSE;
      }
   } else {
      unsigned long lineSize;
      unsigned long extra = 0;
      unsigned long maxFb = 0;

      /*
       * XXX Need to "free" up any 3D allocations if the DRI ended up
       * and make them available for 2D.  The best way to do this would
       * be position all of those regions contiguously at the end of the
       * StolenPool.
       */
      extra = GetFreeSpace(pScrn);

      if (extra == 0)
	 return TRUE;

      maxFb = pI830->FrontBuffer.Size + extra;
      lineSize = pScrn->displayWidth * pI830->cpp;
      maxFb = ROUND_DOWN_TO(maxFb, lineSize);
      if (maxFb > lineSize * MAX_DISPLAY_HEIGHT)
	 maxFb = lineSize * MAX_DISPLAY_HEIGHT;
      if (maxFb > pI830->FrontBuffer.Size) {
	 unsigned long oldsize;
	 /*
	  * Sanity check -- the fb should be the last thing allocated at
	  * the bottom of the stolen pool.
	  */
	 if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Internal error in I830Allocate2DMemory():\n\t"
		       "Framebuffer isn't the last allocation at the bottom"
		       " of StolenPool\n\t(%x != %x).\n",
		       pI830->FrontBuffer.End,
		       pI830->StolenPool.Free.Start);
	    return FALSE;
	 }
	 /*
	  * XXX Maybe should have a "Free" function.  This should be
	  * the only place where a region is resized, and we know that
	  * the fb is always at the bottom of the aperture/stolen pool,
	  * and is the only region that is allocated bottom-up.
	  * Allowing for more general realloction would require a smarter
	  * allocation system.
	  */
	 oldsize = pI830->FrontBuffer.Size;
	 pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
	 pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sUpdated framebuffer allocation size from %d "
			"to %d kByte\n", s, oldsize / 1024, maxFb / 1024);
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sUpdated pixmap cache from %d scanlines to %d "
			"scanlines\n", s,
			oldsize / lineSize - pScrn->virtualY,
			maxFb / lineSize - pScrn->virtualY);
	 pI830->FbMemBox.y2 = maxFb / lineSize;
	 tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
		 IsTileable(pScrn->displayWidth * pI830->cpp);
	 if (tileable) {
	    align = KB(512);
	    alignflags = ALIGN_BOTH_ENDS;
	 } else {
	    align = KB(64);
	    alignflags = 0;
	 }
	 alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
				   &(pI830->StolenPool), maxFb, align,
				   flags | alignflags |
				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
	 if (alloced < maxFb) {
	    if (!dryrun) {
	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			  "Failed to re-allocate framebuffer\n");
	    }
	    return FALSE;
	 }
      }
      return TRUE;
   }

#if REMAP_RESERVED
   /*
    * Allocate a dummy page to pass when attempting to rebind the
    * pre-allocated region.
    */
   if (!dryrun) {
      memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
      pI830->Dummy.Key =
	   xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
      pI830->Dummy.Offset = 0;
   }
#endif

   /* Clear cursor info */
   memset(&(pI830->CursorMem), 0, sizeof(pI830->CursorMem));
   pI830->CursorMem.Key = -1;

   if (!pI830->SWCursor) {
      int cursFlags = 0;
      /*
       * Mouse cursor -- The i810-i830 need a physical address in system
       * memory from which to upload the cursor.  We get this from
       * the agpgart module using a special memory type.
       */

      size = HWCURSOR_SIZE;
      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
      if (pI830->CursorNeedsPhysical)
	 cursFlags |= NEED_PHYSICAL_ADDR;

      alloced = I830AllocVidMem(pScrn, &(pI830->CursorMem),
				&(pI830->StolenPool), size,
				GTT_PAGE_SIZE, flags | cursFlags);
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate HW cursor space.\n");
	 }
      } else {
	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
			"%sAllocated %d kB for HW cursor at 0x%x", s,
			alloced / 1024, pI830->CursorMem.Start);
	 if (pI830->CursorNeedsPhysical)
	    xf86ErrorFVerb(verbosity, " (0x%08x)", pI830->CursorMem.Physical);
	 xf86ErrorFVerb(verbosity, "\n");
      }
   }

#ifdef I830_XV
   AllocateOverlay(pScrn, flags);
#endif

   if (!pI830->NeedRingBufferLow)
      AllocateRingBuffer(pScrn, flags);

   /* Clear scratch info */
   memset(&(pI830->Scratch), 0, sizeof(pI830->Scratch));
   pI830->Scratch.Key = -1;

   if (!pI830->noAccel) {
      size = MAX_SCRATCH_BUFFER_SIZE;
      alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), &(pI830->StolenPool),
				size, GTT_PAGE_SIZE,
				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
      if (alloced < size) {
	 size = MIN_SCRATCH_BUFFER_SIZE;
         alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
				   &(pI830->StolenPool), size,
				   GTT_PAGE_SIZE,
				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
      }
      if (alloced < size) {
	 if (!dryrun) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate scratch buffer space\n");
	 }
	 return FALSE;
      }
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
		    "%sAllocated %d kB for the scratch buffer at 0x%x\n", s,
		    alloced / 1024, pI830->Scratch.Start);
   }
   return TRUE;
}
示例#4
0
static unsigned long
AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, unsigned long size,
	     unsigned long alignment, int flags)
{
   I830Ptr pI830 = I830PTR(pScrn);
   unsigned long start, end;
   unsigned long newApStart, newApEnd;
   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);

   if (!result || !size)
      return 0;

   if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		 "AllocFromAGP(): can't allocate from "
		 "bottom when there is stolen memory\n");
      return 0;
   }

   if (size > pI830->FreeMemory) {
      if (dryrun)
	 pI830->FreeMemory = size;
      else
	 return 0;
   }

   /* Calculate offset */
   if (flags & ALLOCATE_AT_BOTTOM) {
      start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
      if (flags & ALIGN_BOTH_ENDS)
	 end = ROUND_TO(start + size, alignment);
      else
	 end = start + size;
      newApStart = end;
      newApEnd = pI830->MemoryAperture.End;
   } else {
      if (flags & ALIGN_BOTH_ENDS)
	 end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
      else
	 end = pI830->MemoryAperture.End;
      start = ROUND_DOWN_TO(end - size, alignment);
      newApStart = pI830->MemoryAperture.Start;
      newApEnd = start;
   }

   if (!dryrun) {
      if (newApStart > newApEnd)
	 return 0;

      if (flags & NEED_PHYSICAL_ADDR) {
	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
					      &(result->Physical));
      } else {
	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
      }
      if (result->Key == -1)
	 return 0;
   }

   pI830->allocatedMemory += size;
   pI830->MemoryAperture.Start = newApStart;
   pI830->MemoryAperture.End = newApEnd;
   pI830->MemoryAperture.Size = newApEnd - newApStart;
   pI830->FreeMemory -= size;
   result->Start = start;
   result->End = start + size;
   result->Size = size;
   result->Offset = start;
   result->Alignment = alignment;
   result->Pool = NULL;

   return size;
}