diff options
Diffstat (limited to 'src/mesa/drivers/dri/savage/savagedma.c')
-rw-r--r-- | src/mesa/drivers/dri/savage/savagedma.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/savage/savagedma.c b/src/mesa/drivers/dri/savage/savagedma.c new file mode 100644 index 0000000000..9b0bdc8b9f --- /dev/null +++ b/src/mesa/drivers/dri/savage/savagedma.c @@ -0,0 +1,298 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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 + * VIA, S3 GRAPHICS, 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. + */ + +#include <X11/Xlibint.h> +#include <stdio.h> +#include "savageioctl.h" +#include "savagedma.h" +#include "savage_bci.h" +#include <time.h> +#include <unistd.h> + +/* Commit does not depend on whether we use real DMA or fake it via the BCI */ +void savageDMACommit (savageContextPtr imesa, void *endPtr) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + GLuint end = (GLuint)endPtr; + + /* make sure that enough space was allocated */ + assert (end <= dmaBuff->allocEnd); + + dmaBuff->allocEnd = dmaBuff->end = end; + + /* TODO: check commands, either here or in flush */ +} + +#if SAVAGE_CMD_DMA +/* flag = + 0 return -1 if no available page + 1 wait until a page be available */ +static GLuint getDMAPage (savageContextPtr imesa, int flag) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + GLuint page; + GLuint eventTag1; + + if (dmaBuff->kickFlag == GL_FALSE) + return dmaBuff->usingPage; + + page = dmaBuff->usingPage + 1; + + /* overflow */ + if (page >= (dmaBuff->buf->size * dmaBuff->buf->type)/DMA_PAGE_SIZE) + page = 0; + + eventTag1 = GET_EVENTTAG; + if ( eventTag1 == page) { /* is kicking off */ + if (flag == 1) + while (GET_EVENTTAG == page); /* FIXME: add a max loop count? */ + else + return -1; + } + + /* ok, that's it */ + dmaBuff->usingPage = page; + dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = + (dmaBuff->buf->linear + DMA_PAGE_SIZE * page); + dmaBuff->kickFlag = GL_FALSE; + + return page; +} + +/* Allocate space in a real DMA buffer */ +void *savageDMAAlloc (savageContextPtr imesa, GLuint size) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + + /* make sure that everything has been filled in and committed */ + assert (dmaBuff->end == dmaBuff->allocEnd); + + size *= sizeof (GLuint); /* size in bytes */ + if (dmaBuff->kickFlag == GL_TRUE) { + if (size > DMA_PAGE_SIZE) + return NULL; + getDMAPage (imesa, 1); + } else if (dmaBuff->end + size >= + dmaBuff->buf->linear + DMA_PAGE_SIZE*(dmaBuff->usingPage+1)) { + /* need kick off */ + savageDMAFlush (imesa); + getDMAPage (imesa, 1); + } + dmaBuff->allocEnd = dmaBuff->end + size; + return (void *)dmaBuff->end; +} + +/* Flush DMA buffer via DMA */ +void savageDMAFlush (savageContextPtr imesa) { + volatile GLuint* BCIbase; + DMABufferPtr dmaBuff = &imesa->DMABuf; + GLuint phyAddress; + GLuint dmaCount, dmaCount1, remain; + int i; + + /* make sure that everything has been filled in and committed */ + assert (dmaBuff->allocEnd == dmaBuff->end); + + if (dmaBuff->kickFlag == GL_TRUE) /* has been kicked off? */ + return; + if (dmaBuff->start == dmaBuff->end) /* no command? */ + return; + + /* get bci base */ + BCIbase = (volatile GLuint *)SAVAGE_GET_BCI_POINTER(imesa,4); + + /* set the eventtag */ + *BCIbase = (dmaBuff->usingPage & 0xffffL) | (CMD_UpdateShadowStat << 27) + | (1 << 22); + *BCIbase = 0x96010051; /* set register x51*/ + /* set the DMA buffer address */ + phyAddress = (dmaBuff->buf->phyaddress + dmaBuff->usingPage*DMA_PAGE_SIZE) + & MDT_SRCADD_ALIGMENT; + if (dmaBuff->buf->location == DRM_SAVAGE_MEM_LOCATION_AGP) + *BCIbase = (phyAddress) | MDT_SRC_AGP; + else + *BCIbase = (phyAddress) | MDT_SRC_PCI; + + /* pad with noops to multiple of 32 bytes */ + dmaCount = (GLuint)(dmaBuff->end - dmaBuff->start); + dmaCount1 = (dmaCount + 31UL) & ~31UL; + remain = (dmaCount1 - dmaCount) >> 2; + for (i = 0; i < remain; i++) { + *((GLuint *)dmaBuff->end) = 0x40000000L; + dmaBuff->end+=4; + } + dmaCount = (dmaCount1 >> 3) - 1; + dmaBuff->allocEnd = dmaBuff->end; + + /* kick off */ + *BCIbase = (0xA8000000L)|dmaCount; + dmaBuff->kickFlag = GL_TRUE; +} + +/* Init real DMA */ +int savageDMAInit (savageContextPtr imesa) +{ + DMABufferPtr dmaBuff = &imesa->DMABuf; + drm_savage_alloc_cont_mem_t * req; + int i; + long ret; + + req = (drm_savage_alloc_cont_mem_t *) + malloc (sizeof(drm_savage_alloc_cont_mem_t)); + if (!req) + return GL_FALSE; + + req->type = DRM_SAVAGE_MEM_PAGE; + req->linear = 0; + + /* try agp first */ + req->phyaddress = imesa->sarea->agp_offset; + if (req->phyaddress) { + if (drmMap (imesa->driFd, + req->phyaddress, + DRM_SAVAGE_DMA_AGP_SIZE, + (drmAddressPtr)&req->linear) < 0) { + fprintf (stderr, "AGP map error.\n"); + goto dma; + } + if (0) fprintf (stderr,"Using AGP dma|\n"); + req->location = DRM_SAVAGE_MEM_LOCATION_AGP; + req->size = DRM_SAVAGE_DMA_AGP_SIZE/DRM_SAVAGE_MEM_PAGE; + } + + dma: + if (!req->linear) { + req->size = DMA_BUFFER_SIZE/DRM_SAVAGE_MEM_PAGE; + for (i = 0; i < DMA_TRY_COUNT; i++) { + if ((ret = savageAllocDMABuffer (imesa, req)) != 0) + break; + req->size = req->size/2; + } + + if (ret <= 0) { + fprintf(stderr, "Can't alloc DMA memory(system and agp)\n"); + return GL_FALSE; + } + req->location = DRM_SAVAGE_MEM_LOCATION_PCI; + } + + dmaBuff->buf = req; + + dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = req->linear; + dmaBuff->usingPage = 0; + dmaBuff->kickFlag = GL_FALSE; + + return GL_TRUE; +} + +/* Close real DMA */ +int savageDMAClose (savageContextPtr imesa) +{ + DMABufferPtr dmaBuff = &imesa->DMABuf; + drm_savage_alloc_cont_mem_t * req = dmaBuff->buf; + + if(req->location == DRM_SAVAGE_MEM_LOCATION_PCI) + savageFreeDMABuffer (imesa, req); + else { /* AGP memory */ + drmUnmap ((drmAddress)req->linear, req->size*req->type); + drmRmMap (imesa->driFd, req->phyaddress); + } + free (req); + + return GL_TRUE; +} +#else +/* Allocate space in faked DMA buffer */ +void *savageDMAAlloc (savageContextPtr imesa, GLuint size) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + + /* make sure that everything has been filled in and committed */ + assert (dmaBuff->end == dmaBuff->allocEnd); + + size *= sizeof (GLuint); /* size in bytes */ + if (dmaBuff->end + size >= dmaBuff->buf->linear + DMA_PAGE_SIZE) { + /* need kick off */ + savageDMAFlush (imesa); + } + dmaBuff->allocEnd = dmaBuff->end + size; + return (void *)dmaBuff->end; +} + +/* Flush DMA buffer via BCI (faked DMA) */ +void savageDMAFlush(savageContextPtr imesa) { + volatile GLuint* BCIbase; + DMABufferPtr dmaBuff = &imesa->DMABuf; + GLuint *entry; + + /* make sure that everything has been filled in and committed */ + assert (dmaBuff->allocEnd == dmaBuff->end); + + if (dmaBuff->start == dmaBuff->end) /* no command? */ + return; + + /* get bci base */ + BCIbase = (volatile GLuint *)SAVAGE_GET_BCI_POINTER( + imesa, (dmaBuff->end - dmaBuff->start) / sizeof (GLuint)); + + for (entry = (GLuint *)dmaBuff->start; + entry < (GLuint *)dmaBuff->end; ++entry) + *BCIbase = *entry; + + dmaBuff->end = dmaBuff->allocEnd = dmaBuff->start; +} + +/* Init faked DMA */ +int savageDMAInit (savageContextPtr imesa) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + drm_savage_alloc_cont_mem_t * req; + + req = (drm_savage_alloc_cont_mem_t *) + malloc (sizeof(drm_savage_alloc_cont_mem_t)); + if (!req) + return GL_FALSE; + + req->linear = (GLuint)malloc (DMA_PAGE_SIZE); + if (!req->linear) { + free (req); + return GL_FALSE; + } + + dmaBuff->buf = req; + + dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = req->linear; + dmaBuff->usingPage = 0; + dmaBuff->kickFlag = GL_FALSE; + + return GL_TRUE; +} + +/* Close faked DMA */ +int savageDMAClose (savageContextPtr imesa) { + DMABufferPtr dmaBuff = &imesa->DMABuf; + drm_savage_alloc_cont_mem_t * req = dmaBuff->buf; + + free ((void *)req->linear); + free (req); + + return GL_TRUE; +} + +#endif |