diff options
Diffstat (limited to 'src/legacy/i810/i810_memory.c')
-rw-r--r-- | src/legacy/i810/i810_memory.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/src/legacy/i810/i810_memory.c b/src/legacy/i810/i810_memory.c new file mode 100644 index 00000000..f57ddbe2 --- /dev/null +++ b/src/legacy/i810/i810_memory.c @@ -0,0 +1,428 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "i810.h" +#include "i810_reg.h" + +int +I810AllocLow(I810MemRange * result, I810MemRange * pool, int size) +{ + if (size > (long)pool->Size) + return 0; + + pool->Size -= size; + result->Size = size; + result->Start = pool->Start; + result->End = pool->Start += size; + + return 1; +} + +int +I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size) +{ + if (size > (long)pool->Size) + return 0; + + pool->Size -= size; + result->Size = size; + result->End = pool->End; + result->Start = pool->End -= size; + + return 1; +} + +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; +} + +/* Tiled memory is good... really, really good... + * + * Need to make it less likely that we miss out on this - probably + * need to move the frontbuffer away from the 'guarenteed' alignment + * of the first memory segment, or perhaps allocate a discontigous + * framebuffer to get more alignment 'sweet spots'. + */ +void +I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned int start, + unsigned int pitch, unsigned int size) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RegPtr i810Reg = &pI810->ModeReg; + uint32_t val; + uint32_t fence_mask = 0; + + if (nr < 0 || nr > 7) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s - fence %d out of range\n", + "I810SetTiledMemory", nr); + return; + } + + i810Reg->Fence[nr] = 0; + + fence_mask = ~FENCE_START_MASK; + + if (start & fence_mask) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: start (%x) is not 512k aligned\n", + "I810SetTiledMemory", nr, start); + return; + } + + if (start % size) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: start (%x) is not size (%x) aligned\n", + "I810SetTiledMemory", nr, start, size); + return; + } + + if (pitch & 127) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: pitch (%x) not a multiple of 128 bytes\n", + "I810SetTiledMemory", nr, pitch); + return; + } + + val = (start | FENCE_X_MAJOR | FENCE_VALID); + + switch (size) { + case KB(512): + val |= FENCE_SIZE_512K; + break; + case MB(1): + val |= FENCE_SIZE_1M; + break; + case MB(2): + val |= FENCE_SIZE_2M; + break; + case MB(4): + val |= FENCE_SIZE_4M; + break; + case MB(8): + val |= FENCE_SIZE_8M; + break; + case MB(16): + val |= FENCE_SIZE_16M; + break; + case MB(32): + val |= FENCE_SIZE_32M; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr, + size); + return; + } + + switch (pitch / 128) { + case 1: + val |= FENCE_PITCH_1; + break; + case 2: + val |= FENCE_PITCH_2; + break; + case 4: + val |= FENCE_PITCH_4; + break; + case 8: + val |= FENCE_PITCH_8; + break; + case 16: + val |= FENCE_PITCH_16; + break; + case 32: + val |= FENCE_PITCH_32; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr, + size); + return; + } + + i810Reg->Fence[nr] = val; +} + +Bool +I810BindGARTMemory(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled + && !pI810->GttBound) { + if (!xf86AcquireGART(pScrn->scrnIndex)) + return FALSE; + + if (pI810->VramKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->VramKey, + pI810->VramOffset)) + return FALSE; + + if (pI810->DcacheKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey, + pI810->DcacheOffset)) + return FALSE; + + if (pI810->HwcursKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey, + pI810->HwcursOffset)) + return FALSE; + + if (pI810->ARGBHwcursKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey, + pI810->ARGBHwcursOffset)) + return FALSE; + + pI810->GttBound = 1; + } + + return TRUE; +} + +Bool +I810UnbindGARTMemory(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled + && pI810->GttBound) { + if (pI810->VramKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->VramKey)) + return FALSE; + + if (pI810->DcacheKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey)) + return FALSE; + + if (pI810->HwcursKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey)) + return FALSE; + + if (pI810->ARGBHwcursKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey)) + return FALSE; + + if (!xf86ReleaseGART(pScrn->scrnIndex)) + return FALSE; + + pI810->GttBound = 0; + } + + return TRUE; +} + +int +I810CheckAvailableMemory(ScrnInfoPtr pScrn) +{ + AgpInfoPtr agpinf; + int maxPages; + + if (!xf86AgpGARTSupported() || + !xf86AcquireGART(pScrn->scrnIndex) || + (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL || + !xf86ReleaseGART(pScrn->scrnIndex)) + return -1; + + maxPages = agpinf->totalPages - agpinf->usedPages; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %dk available\n", + "I810CheckAvailableMemory", maxPages * 4); + + return maxPages * 4; +} |