2021-05-23 22:24:02 +08:00

126 lines
2.9 KiB
C

#include <lib/syscall.h>
#include <lib/ipc.h>
#include <lib/defs.h>
#include <lib/string.h>
#include <lib/print.h>
ipc_msg_t *ipc_create_msg(ipc_struct_t * icb, u64 data_len, u64 cap_slot_number)
{
ipc_msg_t *ipc_msg;
int i;
ipc_msg = (ipc_msg_t *) icb->shared_buf;
ipc_msg->data_len = data_len;
ipc_msg->cap_slot_number = cap_slot_number;
ipc_msg->data_offset = sizeof(*ipc_msg);
ipc_msg->cap_slots_offset = ipc_msg->data_offset + data_len;
memset(ipc_get_msg_data(ipc_msg), 0, data_len);
for (i = 0; i < cap_slot_number; i++)
ipc_set_msg_cap(ipc_msg, i, -1);
return ipc_msg;
}
char *ipc_get_msg_data(ipc_msg_t * ipc_msg)
{
return (char *)ipc_msg + ipc_msg->data_offset;
}
int ipc_set_msg_data(ipc_msg_t * ipc_msg, char *data, u64 offset, u64 len)
{
if (offset + len < offset || offset + len > ipc_msg->data_len)
return -1;
memcpy(ipc_get_msg_data(ipc_msg) + offset, data, len);
return 0;
}
static u64 *ipc_get_msg_cap_ptr(ipc_msg_t * ipc_msg, u64 cap_id)
{
return (u64 *) ((char *)ipc_msg + ipc_msg->cap_slots_offset) + cap_id;
}
u64 ipc_get_msg_cap(ipc_msg_t * ipc_msg, u64 cap_slot_index)
{
if (cap_slot_index >= ipc_msg->cap_slot_number)
return -1;
return *ipc_get_msg_cap_ptr(ipc_msg, cap_slot_index);
}
int ipc_set_msg_cap(ipc_msg_t * ipc_msg, u64 cap_slot_index, u32 cap)
{
if (cap_slot_index >= ipc_msg->cap_slot_number)
return -1;
*ipc_get_msg_cap_ptr(ipc_msg, cap_slot_index) = cap;
return 0;
}
/* FIXME: currently ipc_msg is not dynamically allocated so that no need to free */
int ipc_destroy_msg(ipc_msg_t * ipc_msg)
{
return 0;
}
#define SERVER_STACK_BASE 0x7000000
#define SERVER_STACK_SIZE 0x1000
#define SERVER_BUF_BASE 0x7400000
#define SERVER_BUF_SIZE 0x1000
#define CLIENT_BUF_BASE 0x7800000
#define CLIENT_BUF_SIZE 0x1000
#define MAX_CLIENT 16
int ipc_register_server(server_handler server_handler)
{
struct ipc_vm_config vm_config = {
.stack_base_addr = SERVER_STACK_BASE,
.stack_size = SERVER_STACK_SIZE,
.buf_base_addr = SERVER_BUF_BASE,
.buf_size = SERVER_BUF_SIZE,
};
return usys_register_server((u64) server_handler, MAX_CLIENT,
(u64) & vm_config);
}
int ipc_register_client(int server_thread_cap, ipc_struct_t * ipc_struct)
{
int conn_cap;
struct ipc_vm_config vm_config = {
.buf_base_addr = CLIENT_BUF_BASE,
.buf_size = CLIENT_BUF_SIZE,
};
conn_cap = usys_register_client((u32) server_thread_cap,
(u64) & vm_config);
if (conn_cap < 0)
return -1;
ipc_struct->shared_buf = vm_config.buf_base_addr;
ipc_struct->shared_buf_len = vm_config.buf_size;
ipc_struct->conn_cap = conn_cap;
return 0;
}
int ipc_call(ipc_struct_t * icb, ipc_msg_t * ipc_msg)
{
u64 ret = 0;
ret = usys_ipc_call(icb->conn_cap, (u64) ipc_msg);
return ret;
}
int ipc_reg_call(ipc_struct_t * icb, u64 arg)
{
u64 ret = 0;
ret = usys_ipc_reg_call(icb->conn_cap, (u64) arg);
return ret;
}
void ipc_return(int ret)
{
usys_ipc_return((u64) ret);
}