/*
 * 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 "drmP.h"
#include "via_drm.h"
#include "via_drv.h"
#include "via_ds.h"
#include "via_mm.h"

#define MAX_CONTEXT 100

typedef struct {
	int used;
	int context;
	set_t *sets[2];		/* 0 for frame buffer, 1 for AGP , 2 for System */
} via_context_t;

static via_context_t global_ppriv[MAX_CONTEXT];

static int via_agp_alloc(drm_via_mem_t * mem);
static int via_agp_free(drm_via_mem_t * mem);
static int via_fb_alloc(drm_via_mem_t * mem);
static int via_fb_free(drm_via_mem_t * mem);

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 = via_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 = via_setDel(global_ppriv[i].sets[type], val);
			break;
		}

	return retval;
}

/* agp memory management */
static memHeap_t *AgpHeap = NULL;

int via_agp_init(DRM_IOCTL_ARGS)
{
	drm_via_agp_t agp;

	DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *) data, sizeof(agp));

	AgpHeap = via_mmInit(agp.offset, agp.size);

	DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);

	return 0;
}

/* fb memory management */
static memHeap_t *FBHeap = NULL;

int via_fb_init(DRM_IOCTL_ARGS)
{
	drm_via_fb_t fb;

	DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *) data, sizeof(fb));

	FBHeap = via_mmInit(fb.offset, fb.size);

	DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);

	return 0;
}

int via_init_context(struct drm_device *dev, 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] = via_setInit();
				global_ppriv[i].sets[1] = via_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 via_final_context(struct drm_device *dev, int context)
{	
        int i;
	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;

	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;
		ITEM_TYPE item;
		int retval;

		DRM_DEBUG("find socket %d, context = %d\n", i, context);

		/* Video Memory */
		set = global_ppriv[i].sets[0];
		retval = via_setFirst(set, &item);
		while (retval) {
			DRM_DEBUG("free video memory 0x%lx\n", item);
			via_mmFreeMem((PMemBlock) item);
			retval = via_setNext(set, &item);
		}
		via_setDestroy(set);

		/* AGP Memory */
		set = global_ppriv[i].sets[1];
		retval = via_setFirst(set, &item);
		while (retval) {
			DRM_DEBUG("free agp memory 0x%lx\n", item);
			via_mmFreeMem((PMemBlock) item);
			retval = via_setNext(set, &item);
		}
		via_setDestroy(set);
		global_ppriv[i].used = 0;
	}
	via_release_futex(dev_priv, context); 
	
			
#if defined(__linux__)
	/* Linux specific until context tracking code gets ported to BSD */
	/* Last context, perform cleanup */
	if (dev->ctx_count == 1 && dev->dev_private) {
	        DRM_DEBUG("Last Context\n");
		if (dev->irq)
			drm_irq_uninstall(dev);

		via_cleanup_futex(dev_priv);
		via_do_cleanup_map(dev);
	}
#endif

	return 1;
}

int via_mem_alloc(DRM_IOCTL_ARGS)
{
	drm_via_mem_t mem;

	DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));

	switch (mem.type) {
	case VIDEO:
		if (via_fb_alloc(&mem) < 0)
			return -EFAULT;
		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
				       sizeof(mem));
		return 0;
	case AGP:
		if (via_agp_alloc(&mem) < 0)
			return -EFAULT;
		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
				       sizeof(mem));
		return 0;
	}

	return -EFAULT;
}

static int via_fb_alloc(drm_via_mem_t * mem)
{
	drm_via_mm_t fb;
	PMemBlock block;
	int retval = 0;

	if (!FBHeap)
		return -1;

	fb.size = mem->size;
	fb.context = mem->context;

	block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
	if (block) {
		fb.offset = block->ofs;
		fb.free = (unsigned long)block;
		if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
			DRM_DEBUG("adding to allocation set fails\n");
			via_mmFreeMem((PMemBlock) fb.free);
			retval = -1;
		}
	} else {
		fb.offset = 0;
		fb.size = 0;
		fb.free = 0;
		retval = -1;
	}

	mem->offset = fb.offset;
	mem->index = fb.free;

	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
		  (int)fb.offset);

	return retval;
}

static int via_agp_alloc(drm_via_mem_t * mem)
{
	drm_via_mm_t agp;
	PMemBlock block;
	int retval = 0;

	if (!AgpHeap)
		return -1;

	agp.size = mem->size;
	agp.context = mem->context;

	block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
	if (block) {
		agp.offset = block->ofs;
		agp.free = (unsigned long)block;
		if (!add_alloc_set(agp.context, AGP, agp.free)) {
			DRM_DEBUG("adding to allocation set fails\n");
			via_mmFreeMem((PMemBlock) agp.free);
			retval = -1;
		}
	} else {
		agp.offset = 0;
		agp.size = 0;
		agp.free = 0;
	}

	mem->offset = agp.offset;
	mem->index = agp.free;

	DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
		  (unsigned int)agp.offset);
	return retval;
}

int via_mem_free(DRM_IOCTL_ARGS)
{
	drm_via_mem_t mem;

	DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));

	switch (mem.type) {

	case VIDEO:
		if (via_fb_free(&mem) == 0)
			return 0;
		break;
	case AGP:
		if (via_agp_free(&mem) == 0)
			return 0;
		break;
	}

	return -EFAULT;
}

static int via_fb_free(drm_via_mem_t * mem)
{
	drm_via_mm_t fb;
	int retval = 0;

	if (!FBHeap) {
		return -1;
	}

	fb.free = mem->index;
	fb.context = mem->context;

	if (!fb.free) {
		return -1;

	}

	via_mmFreeMem((PMemBlock) fb.free);

	if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
		retval = -1;
	}

	DRM_DEBUG("free fb, free = %ld\n", fb.free);

	return retval;
}

static int via_agp_free(drm_via_mem_t * mem)
{
	drm_via_mm_t agp;

	int retval = 0;

	agp.free = mem->index;
	agp.context = mem->context;

	if (!agp.free)
		return -1;

	via_mmFreeMem((PMemBlock) agp.free);

	if (!del_alloc_set(agp.context, AGP, agp.free)) {
		retval = -1;
	}

	DRM_DEBUG("free agp, free = %ld\n", agp.free);

	return retval;
}
