/*
* Copyright (c) 2006 Ondrej Palkovsky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup kernel_generic_ipc
* @{
*/
/** @file
*/
#include <synch/spinlock.h>
#include <ipc/ipc.h>
#include <arch.h>
#include <proc/task.h>
#include <ipc/ipcrsc.h>
#include <assert.h>
#include <abi/errno.h>
#include <cap/cap.h>
#include <mm/slab.h>
#include <stdlib.h>
static void phone_destroy(void *arg)
{
phone_t *phone = (phone_t *) arg;
if (phone->hangup_call)
kobject_put(phone->hangup_call->kobject);
slab_free(phone_cache, phone);
}
kobject_ops_t phone_kobject_ops = {
.destroy = phone_destroy
};
/** Allocate new phone in the specified task.
*
* @param[in] task Task for which to allocate a new phone.
* @param[in] publish If true, the new capability will be published.
* @param[out] phandle New phone capability handle.
* @param[out] kobject New phone kobject.
*
* @return An error code if a new capability cannot be allocated.
*/
errno_t phone_alloc(task_t *task, bool publish, cap_phone_handle_t *phandle,
kobject_t **kobject)
{
cap_handle_t handle;
errno_t rc = cap_alloc(task, &handle);
if (rc == EOK) {
phone_t *phone = slab_alloc(phone_cache, FRAME_ATOMIC);
if (!phone) {
cap_free(TASK, handle);
return ENOMEM;
}
kobject_t *kobj = kobject_alloc(FRAME_ATOMIC);
if (!kobj) {
cap_free(TASK, handle);
slab_free(phone_cache, phone);
return ENOMEM;
}
call_t *hcall = ipc_call_alloc();
if (!hcall) {
cap_free(TASK, handle);
slab_free(phone_cache, phone);
free(kobj);
return ENOMEM;
}
ipc_phone_init(phone, task);
phone->state = IPC_PHONE_CONNECTING;
phone->hangup_call = hcall;
kobject_initialize(kobj, KOBJECT_TYPE_PHONE, phone);
phone->kobject = kobj;
if (publish)
cap_publish(task, handle, kobj);
*phandle = handle;
if (kobject)
*kobject = kobj;
}
return rc;
}
/** Free slot from a disconnected phone.
*
* All already sent messages will be correctly processed.
*
* @param handle Phone capability handle of the phone to be freed.
*
*/
void phone_dealloc(cap_phone_handle_t handle)
{
kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_PHONE);
if (!kobj)
return;
kobject_put(kobj);
cap_free(TASK, handle);
}
/** @}
*/