/* 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; }
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; }
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; }
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; }