1/*
2 * Copyright 2016, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(D61_BSD)
11 */
12
13#include "../../state.h"
14#include "../../device_timer.h"
15#include "../dispatch.h"
16#include "timer_dspace.h"
17#include <refos/refos.h>
18
19/*! @file
20    @brief Timer dataspace interface functions.
21
22    This module implements a subset of the dataspace interface (<refos-rpc/data_server.h>),
23    for timer devices. The common dataspace dispatcher module delegates calls to us if it has
24    decided that the recieved message is a timer dataspace call.
25
26    This is a thin layer basically wrapping the device_timer module, which has the concrete
27    implementations.
28*/
29
30seL4_CPtr
31timer_open_handler(void *rpc_userptr , char* rpc_name , int rpc_flags , int rpc_mode ,
32                              int rpc_size , int* rpc_errno)
33{
34    /* Return the timer dataspace badged EP. */
35    assert(timeServ.timerBadgeEP);
36    SET_ERRNO_PTR(rpc_errno, ESUCCESS);
37    return timeServ.timerBadgeEP;
38}
39
40int
41timer_write_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
42                         rpc_buffer_t rpc_buf , uint32_t rpc_count)
43{
44    struct srv_client *c = (struct srv_client *) rpc_userptr;
45    assert(c && c->magic == TIMESERV_CLIENT_MAGIC);
46    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);
47
48    if (rpc_buf.count < sizeof(uint64_t)) {
49        return -EINVALIDPARAM;
50    }
51
52    /* Writing to the timer dataspace results in a sleep call. */
53    uint64_t timeWait = *( (uint64_t*) (rpc_buf.data) );
54    dvprintf("timer_write_handler client waiting for %llu nanoseconds.\n", timeWait);
55
56    int error = device_timer_save_caller_as_waiter(&timeServ.devTimer, c, timeWait);
57    if (error == ESUCCESS) {
58        c->rpcClient.skip_reply = true;
59    }
60    return -error;
61}
62
63int
64timer_read_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
65                        rpc_buffer_t rpc_buf , uint32_t rpc_count)
66{
67    if (!rpc_buf.count) {
68        return -EINVALIDPARAM;
69    }
70    if (rpc_buf.count < sizeof(uint64_t)) {
71        ROS_WARNING("Buffer not large enough: need %d only got %d.", sizeof(uint64_t),
72                    rpc_buf.count);
73        return 0;
74    }
75
76    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);
77
78    /* Reading from the timer dataspace results in a sys_get_time call. */
79    uint64_t time = device_timer_get_time(&timeServ.devTimer);
80    memcpy(rpc_buf.data, &time, sizeof(uint64_t));
81    return sizeof(uint64_t);
82}