/*
 * 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 long 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 long 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 __user *) 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 __user *) 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 __user *) data,
				 sizeof(mem));

	switch (mem.type) {
	case VIA_MEM_VIDEO:
		if (via_fb_alloc(&mem) < 0)
			return -EFAULT;
		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
				       sizeof(mem));
		return 0;
	case VIA_MEM_AGP:
		if (via_agp_alloc(&mem) < 0)
			return -EFAULT;
		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) 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, VIA_MEM_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, VIA_MEM_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 __user *) data,
				 sizeof(mem));

	switch (mem.type) {

	case VIA_MEM_VIDEO:
		if (via_fb_free(&mem) == 0)
			return 0;
		break;
	case VIA_MEM_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, VIA_MEM_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, VIA_MEM_AGP, agp.free)) {
		retval = -1;
	}

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

	return retval;
}
