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}