11558Srgrimes/*
21558Srgrimes * Copyright 2016, Data61
31558Srgrimes * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
41558Srgrimes * ABN 41 687 119 230.
51558Srgrimes *
61558Srgrimes * This software may be distributed and modified according to the terms of
71558Srgrimes * the BSD 2-Clause license. Note that NO WARRANTY is provided.
81558Srgrimes * See "LICENSE_BSD2.txt" for details.
91558Srgrimes *
101558Srgrimes * @TAG(D61_BSD)
111558Srgrimes */
121558Srgrimes
131558Srgrimes#include "../../state.h"
141558Srgrimes#include "../../device_timer.h"
151558Srgrimes#include "../dispatch.h"
161558Srgrimes#include "timer_dspace.h"
171558Srgrimes#include <refos/refos.h>
181558Srgrimes
191558Srgrimes/*! @file
201558Srgrimes    @brief Timer dataspace interface functions.
211558Srgrimes
221558Srgrimes    This module implements a subset of the dataspace interface (<refos-rpc/data_server.h>),
231558Srgrimes    for timer devices. The common dataspace dispatcher module delegates calls to us if it has
241558Srgrimes    decided that the recieved message is a timer dataspace call.
251558Srgrimes
261558Srgrimes    This is a thin layer basically wrapping the device_timer module, which has the concrete
271558Srgrimes    implementations.
281558Srgrimes*/
291558Srgrimes
301558SrgrimesseL4_CPtr
311558Srgrimestimer_open_handler(void *rpc_userptr , char* rpc_name , int rpc_flags , int rpc_mode ,
321558Srgrimes                              int rpc_size , int* rpc_errno)
331558Srgrimes{
341558Srgrimes    /* Return the timer dataspace badged EP. */
351558Srgrimes    assert(timeServ.timerBadgeEP);
361558Srgrimes    SET_ERRNO_PTR(rpc_errno, ESUCCESS);
371558Srgrimes    return timeServ.timerBadgeEP;
381558Srgrimes}
391558Srgrimes
401558Srgrimesint
411558Srgrimestimer_write_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
421558Srgrimes                         rpc_buffer_t rpc_buf , uint32_t rpc_count)
431558Srgrimes{
441558Srgrimes    struct srv_client *c = (struct srv_client *) rpc_userptr;
451558Srgrimes    assert(c && c->magic == TIMESERV_CLIENT_MAGIC);
461558Srgrimes    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);
471558Srgrimes
481558Srgrimes    if (rpc_buf.count < sizeof(uint64_t)) {
491558Srgrimes        return -EINVALIDPARAM;
501558Srgrimes    }
511558Srgrimes
521558Srgrimes    /* Writing to the timer dataspace results in a sleep call. */
531558Srgrimes    uint64_t timeWait = *( (uint64_t*) (rpc_buf.data) );
541558Srgrimes    dvprintf("timer_write_handler client waiting for %llu nanoseconds.\n", timeWait);
551558Srgrimes
561558Srgrimes    int error = device_timer_save_caller_as_waiter(&timeServ.devTimer, c, timeWait);
571558Srgrimes    if (error == ESUCCESS) {
581558Srgrimes        c->rpcClient.skip_reply = true;
591558Srgrimes    }
601558Srgrimes    return -error;
611558Srgrimes}
621558Srgrimes
631558Srgrimesint
641558Srgrimestimer_read_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
651558Srgrimes                        rpc_buffer_t rpc_buf , uint32_t rpc_count)
661558Srgrimes{
671558Srgrimes    if (!rpc_buf.count) {
681558Srgrimes        return -EINVALIDPARAM;
691558Srgrimes    }
701558Srgrimes    if (rpc_buf.count < sizeof(uint64_t)) {
711558Srgrimes        ROS_WARNING("Buffer not large enough: need %d only got %d.", sizeof(uint64_t),
721558Srgrimes                    rpc_buf.count);
731558Srgrimes        return 0;
741558Srgrimes    }
751558Srgrimes
761558Srgrimes    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);
771558Srgrimes
781558Srgrimes    /* Reading from the timer dataspace results in a sys_get_time call. */
791558Srgrimes    uint64_t time = device_timer_get_time(&timeServ.devTimer);
801558Srgrimes    memcpy(rpc_buf.data, &time, sizeof(uint64_t));
811558Srgrimes    return sizeof(uint64_t);
821558Srgrimes}