diff options
Diffstat (limited to 'bsd/sis/sis_mm.c')
-rw-r--r-- | bsd/sis/sis_mm.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/bsd/sis/sis_mm.c b/bsd/sis/sis_mm.c new file mode 100644 index 00000000..c00aa7e5 --- /dev/null +++ b/bsd/sis/sis_mm.c @@ -0,0 +1,300 @@ +/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * 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, sublicense, + * 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 NONINFRINGEMENT. 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. + * + * Authors: + * Sung-Ching Lin <sclin@sis.com.tw> + * + */ + +#ifdef __linux +#define __NO_VERSION__ +#include <linux/sisfb.h> +#endif + +#include "sis.h" +#include "drmP.h" +#include "sis_drm.h" +#include "sis_drv.h" +#include "sis_ds.h" + +#define MAX_CONTEXT 100 +#define VIDEO_TYPE 0 +#define AGP_TYPE 1 + +typedef struct { + int used; + int context; + set_t *sets[2]; /* 0 for video, 1 for AGP */ +} sis_context_t; + +static sis_context_t global_ppriv[MAX_CONTEXT]; + +static int add_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + + for(i = 0; i < MAX_CONTEXT; i++) + if(global_ppriv[i].used && global_ppriv[i].context == context){ + retval = setAdd(global_ppriv[i].sets[type], val); + break; + } + return retval; +} + +static int del_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + for(i = 0; i < MAX_CONTEXT; i++) + if(global_ppriv[i].used && global_ppriv[i].context == context){ + retval = setDel(global_ppriv[i].sets[type], val); + break; + } + return retval; +} + +/* fb management via fb device */ +#if 1 +int sis_fb_alloc( DRM_OS_IOCTL ) +{ + drm_sis_mem_t fb; + struct sis_memreq req; + int retval = 0; + + DRM_OS_KRNFROMUSR( fb, (drm_sis_mem_t *) data, sizeof(fb) ); + + req.size = fb.size; + sis_malloc(&req); + if(req.offset){ + /* TODO */ + fb.offset = req.offset; + fb.free = req.offset; + if(!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)){ + DRM_DEBUG("adding to allocation set fails"); + sis_free(req.offset); + retval = -1; + } + } + else{ + fb.offset = 0; + fb.size = 0; + fb.free = 0; + } + + DRM_OS_KRNTOUSR( (drm_sis_mem_t *) data, fb, sizeof(fb) ); + + DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + + return retval; +} + +int sis_fb_free( DRM_OS_IOCTL ) +{ + drm_sis_mem_t fb; + int retval = 0; + + DRM_OS_KRNFROMUSR( fb, (drm_sis_mem_t *) data, sizeof(fb) ); + + if(!fb.free){ + return -1; + } + + sis_free(fb.free); + if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) + retval = -1; + + DRM_DEBUG("free fb, offset = %d\n", fb.free); + + return retval; +} + +#else + +int sis_fb_alloc( DRM_OS_IOCTL ) +{ + return -1; +} + +int sis_fb_free( DRM_OS_IOCTL ) +{ + return 0; +} + +#endif + +/* agp memory management */ +#if 1 + +static memHeap_t *AgpHeap = NULL; + +int sisp_agp_init( DRM_OS_IOCTL ) +{ + drm_sis_agp_t agp; + + DRM_OS_KRNFROMUSR( agp, (drm_sis_agp_t *) data, sizeof(agp) ); + + AgpHeap = mmInit(agp.offset, agp.size); + + DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + + return 0; +} + +int sisp_agp_alloc( DRM_OS_IOCTL ) +{ + drm_sis_mem_t agp; + PMemBlock block; + int retval = 0; + + if(!AgpHeap) + return -1; + + DRM_OS_KRNFROMUSR( agp, (drm_sis_mem_t *) data, sizeof(agp)); + + block = mmAllocMem(AgpHeap, agp.size, 0, 0); + if(block){ + /* TODO */ + agp.offset = block->ofs; + agp.free = (unsigned int)block; + if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){ + DRM_DEBUG("adding to allocation set fails"); + mmFreeMem((PMemBlock)agp.free); + retval = -1; + } + } + else{ + agp.offset = 0; + agp.size = 0; + agp.free = 0; + } + + DRM_OS_KRNTOUSR( (drm_sis_mem_t *) data, agp, sizeof(agp) ); + + DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); + + return retval; +} + +int sisp_agp_free( DRM_OS_IOCTL ) +{ + drm_sis_mem_t agp; + int retval = 0; + + if(!AgpHeap) + return -1; + + DRM_OS_KRNFROMUSR( agp, (drm_sis_mem_t *) data, sizeof(agp)); + + if(!agp.free){ + return -1; + } + + mmFreeMem((PMemBlock)agp.free); + if(!del_alloc_set(agp.context, AGP_TYPE, agp.free)) + retval = -1; + + DRM_DEBUG("free agp, free = %d\n", agp.free); + + return retval; +} + +#endif + +int sis_init_context(int context) +{ + int i; + + for(i = 0; i < MAX_CONTEXT ; i++) + if(global_ppriv[i].used && (global_ppriv[i].context == context)) + break; + + if(i >= MAX_CONTEXT){ + for(i = 0; i < MAX_CONTEXT ; i++){ + if(!global_ppriv[i].used){ + global_ppriv[i].context = context; + global_ppriv[i].used = 1; + global_ppriv[i].sets[0] = setInit(); + global_ppriv[i].sets[1] = setInit(); + DRM_DEBUG("init allocation set, socket=%d, context = %d\n", + i, context); + break; + } + } + if((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || + (global_ppriv[i].sets[1] == NULL)){ + return 0; + } + } + + return 1; +} + +int sis_final_context(int context) +{ + int i; + + for(i=0; i<MAX_CONTEXT; i++) + if(global_ppriv[i].used && (global_ppriv[i].context == context)) + break; + + if(i < MAX_CONTEXT){ + set_t *set; + unsigned int item; + int retval; + + DRM_DEBUG("find socket %d, context = %d\n", i, context); + + /* Video Memory */ + set = global_ppriv[i].sets[0]; + retval = setFirst(set, &item); + while(retval){ + DRM_DEBUG("free video memory 0x%x\n", item); +#if 0 + sis_free(item); +#endif + retval = setNext(set, &item); + } + setDestroy(set); + + /* AGP Memory */ + set = global_ppriv[i].sets[1]; + retval = setFirst(set, &item); + while(retval){ + DRM_DEBUG("free agp memory 0x%x\n", item); + mmFreeMem((PMemBlock)item); + retval = setNext(set, &item); + } + setDestroy(set); + + global_ppriv[i].used = 0; + } + + /* turn-off auto-flip */ + /* TODO */ +#if defined(SIS_STEREO) + flip_final(); +#endif + + return 1; +} |