/* 
 * 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.
 */
/*
 * Portable QoS manager, implementing the comcepts described in
 * ``Adaptive Bandwidth Reservation for Multimedia Computing''
 * by L. Abeni and G. Buttazzo
 * IEEE Real Time Computing Systems and Applications 1999
 *
 *			program developed by Luca Abeni
 *					luca@sssup.it
 *					http://hartik.sssup.it/~luca
 */

/************************************************************************/
/*	HARTIK dependent layer... Not finished yet!!!			*/
/************************************************************************/

float glob_getband(ID id)
{
    prop_getband(set[id].compress);	/* We are in the HARIK file.. ID = Num */
}

PORT makeport(char *name)
{
    PORT p;

    p = port_create(name, sizeof(struct qoscmd), NBUFF, MAILBOX, READ);

    return p;
}

PORT connecttoport(char *name)
{
    PORT p;

    p = port_connect(name, sizeof(struct qoscmd), MAILBOX, WRITE);

    return p;
}

void receivefromport(PORT p, void *data)
{
    port_receive(p, data, BLOCK);
} void qos_abort(int num)
{
    sys_abort(num);
} DWORD sys_utilization(void)
{
    int i;
    DWORD tot;

    tot = 0;
    for (i = 0; i < MAX_PROC; i++) {
	if ((proc_table[i].status != FREE) &&
	    ((proc_table[i].pclass == SOFT) ||
	     (proc_table[i].pclass == HARD))) {
	    tot += (proc_table[i].wcet * 100) / proc_table[i].drel;
	}
    }
    return tot;
}

void server_create()
{
    MODEL m = BASE_MODEL;

    task_set_wcet(m, 1000);
    task_use_math(m);

    /* Warning!!!! This was a dependency on sys_tick!!!! */
    if (task_create
	("QoS_Manager", manager, SOFT, APERIODIC, 10 * (1000 / sys_tick),
	 &m) == -1) {
	perror("QTask Init Error:");
	sys_abort(1000);
    }

    task_activate(task_pid("QoS_Manager"));
}

int inittask(char *name, void *body,
	     WORD arg, DWORD q, DWORD period, DWORD drel, BYTE model)
{
    int res;
    MODEL m = BASE_MODEL;
    BYTE tm;

    newtask = getfreedescriptor();

    switch (model) {
    case MMTASK:
	tm = PERIODIC;
	break;
    case EDTASK:
	tm = APERIODIC;
	break;
    default:
	return -1;
    }
    task_set_arg(m, arg);
    task_set_wcet(m, q);

    task_use_math(m);
    m.drel = drel;
#ifdef QOSDBG
    cprintf("Creatin' task...%d\n", set[i].per);
#endif
    res = task_create(name, body, SOFT, tm, period, &m);
#ifdef QOSDBG
    cprintf("Created!!!\n");
#endif
    if (res == -1) {
	perror("QTask Create Error:");
	sys_abort(1001);
    }

    qtask_register(band, weight, period, deadline);

    task_activate(res);

    return res;
}

struct qtask *getnewdescriptor(void)
{
    int i, done;

    i = 0;
    done = 0;
    while ((i < MAXTASK) && (!done)) {
	if (set[i].valid != UNVALID) {
	    i++;
	} else {
	    done = 1;
	}
    }
}

void createppstask(char *name, void *body, WORD arg, DWORD q)
{
    int res;
    MODEL m = BASE_MODEL;

    task_set_arg(m, arg);
    task_set_wcet(m, q);

    task_use_math(m);

    /* Create the task with a long period (like a bkg task...) */
    res = task_create(name, body, SOFT, tm, 1000000, &m);


    newtask = getfreedescriptor();

    /* Probably I don't need it...
       W += t->w;
     */

    if (t->quantum != 0) {
	q = t->quantum;
    } else {
	q = ppsq;
    }

    /* Create the global structure, and change periods... */
    pstask_register(newtask, t->w, q);

    task_activate(res);
}
