
/*
 * reserve.c: generic reserve handling functions
 *
 * Copyright (C) 2000 TimeSys Corporation
 *
 * This is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * This file is derived from software distributed under the following terms:
 *
 * Real-Time and Multimedia Systems Laboratory
 * Copyright (c) 2000 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Real-Time and Multimedia Systems Laboratory
 *  Attn: Prof. Raj Rajkumar
 *  Electrical and Computer Engineering, and Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 *  or via email to raj@ece.cmu.edu
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#include <rk/rk_linux.h>
#include <rk/rk_error.h>
#include <rk/rk.h>
#include <asm/uaccess.h>

void rk_reserve_init(void)
{
    void cpu_reserve_init(void);
#ifdef	RK_NET_RSV
    void net_reserve_init(void);
#endif

    cpu_reserve_init();
#ifdef	RK_NET_RSV
    net_reserve_init();
#endif
}

void rk_reserve_cleanup(void)
{
#ifdef	RK_NET_RSV
    void net_reserve_cleanup(void);

    net_reserve_cleanup();
#endif
}

rk_reserve_t
rk_reserve_create(rk_resource_set_t rs, rk_reserve_type_t type)
{
    rk_reserve_t rsv;

    rsv = malloc(sizeof(struct rk_reserve));
    bzero(rsv, sizeof(struct rk_reserve));
#ifdef	DEBUG_RK
    printk("rk_reserve_create: rs(0x%x) type(0x%x) -> rsv(0x%x)\n",
	   (int) rs, (int) type, (int) rsv);
#endif
    INIT_LIST_HEAD(&rsv->rsv_rs_link);

    /* type is used below */
    rsv->rsv_type = type;
    rsv->rsv_rs = rs;

#ifdef	linux
    /* create entry as /proc/rk/<rs_id>/<rsv_id> */
    rk_proc_reserve_create(rsv);
#endif				/* linux */

    return rsv;
}

int rk_reserve_destroy(rk_reserve_t rsv)
{
#ifdef	DEBUG_RK
    printk("rk_reserve_destroy: rsv(0x%x)\n", (int) rsv);
#endif
    /* if reserve has some capacity reserved */
    if (rsv->rsv_rsv) {
	return RK_ERROR;	/* error */
    }
#ifdef	linux
    /* remove entry under /proc/rk/<rs_id>
     * must be before rk_resource_set_detach_reserve()
     * since resource_set is reffered in rk_proc_reserve_destroy()
     */
    rk_proc_reserve_destroy(rsv);
#endif				/* linux */

    /* if reserve is in a resource_set */
    if (rsv->rsv_rs) {
	rk_resource_set_detach_reserve(rsv->rsv_rs, rsv);
    }

    /* finally free it */
    bzero(rsv, sizeof(struct rk_reserve));	/* for sure */
    free(rsv);
    return RK_SUCCESS;		/* success */
}

asmlinkage int
sys_rk_reserve_update_account(rk_reserve_t rsv, unsigned long account)
{
    if (rsv && rk_valid_rset(rsv->rsv_rs) && rsv->rsv_ops->update_account) {
	rsv->rsv_ops->update_account(rsv, account);
	return RK_SUCCESS;
    }
    return RK_ERROR;

}

asmlinkage int
sys_rk_reserve_quota_query(rk_reserve_t rsv, unsigned long *account)
{
    unsigned long tmp;
    if (rsv && rk_valid_rset(rsv->rsv_rs) && rsv->rsv_ops->quota_query) {
	rsv->rsv_ops->quota_query(rsv, &tmp);
	if (verify_area(VERIFY_WRITE, account, sizeof(unsigned long))) {
	    return -EFAULT;
	}
	if (copy_to_user(account, &tmp, sizeof(unsigned long))) {
	    return -EFAULT;
	}
	return RK_SUCCESS;
    }
    return RK_ERROR;
}

asmlinkage void sys_rk_reserve_wait_on_quota(rk_reserve_t rsv)
{
    if (rsv && rk_valid_rset(rsv->rsv_rs) && rsv->rsv_ops->wait_on_quota) {
	rsv->rsv_ops->wait_on_quota(rsv);
    } else {
	/* Hmmm...This reserve doesn't provide this functionality */
	printk(" No support for wait_on_quota \n");
    }
}
