1// vi:set ft=cpp: -*- Mode: C++ -*- 2/* 3 * (c) 2008-2011 Alexander Warg <warg@os.inf.tu-dresden.de>, 4 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de> 5 * Adam Lackorzysnski <adam@os.inf.tu-dresden.de> 6 * economic rights: Technische Universität Dresden (Germany) 7 * 8 * This file is part of TUD:OS and distributed under the terms of the 9 * GNU General Public License 2. 10 * Please see the COPYING-GPL-2 file for details. 11 * 12 * As a special exception, you may use this file as part of a free software 13 * library without restriction. Specifically, if other files instantiate 14 * templates or use macros or inline functions from this file, or you compile 15 * this file and link it with other files to produce an executable, this 16 * file does not by itself cause the resulting executable to be covered by 17 * the GNU General Public License. This exception does not however 18 * invalidate any other reasons why the executable file might be covered by 19 * the GNU General Public License. 20 */ 21#pragma once 22 23#include <l4/sys/types.h> 24#include <l4/sys/vcon> 25#include <l4/sys/cxx/ipc_legacy> 26 27namespace L4Re { namespace Util { 28 29/** 30 * \brief Console server template class. 31 * \ingroup api_l4re_util 32 * 33 * This template uses vcon_write() and vcon_read() to get and deliver data 34 * from the implementor. 35 * 36 * vcon_read() needs to update the status argument with the 37 * L4_vcon_read_stat flags, especially the L4_VCON_READ_STAT_DONE flag 38 * to indicate that there's nothing more to read for the other end. 39 * 40 * vcon_write() gets the live data from the UTCB. Make sure to copy out the 41 * data before using the UTCB again. 42 * 43 * The size parameter of both functions is given in bytes. 44 */ 45template< typename SVR > 46class Vcon_svr 47{ 48public: 49 L4_RPC_LEGACY_DISPATCH(L4::Vcon); 50 51 l4_msgtag_t op_dispatch(l4_utcb_t *utcb, l4_msgtag_t tag, L4::Vcon::Rights) 52 { 53 l4_msg_regs_t *m = l4_utcb_mr_u(utcb); 54 L4::Opcode op = m->mr[0]; 55 56 switch (op) 57 { 58 case L4_VCON_WRITE_OP: 59 if (tag.words() < 3) 60 return l4_msgtag(-L4_ENOREPLY, 0, 0, 0); 61 62 this_vcon()->vcon_write((char const *)&m->mr[2], m->mr[1]); 63 return l4_msgtag(-L4_ENOREPLY, 0, 0, 0); 64 65 case L4_VCON_SET_ATTR_OP: 66 if (tag.words() < 4) 67 return l4_msgtag(-L4_EINVAL, 0, 0, 0); 68 69 return l4_msgtag(this_vcon()->vcon_set_attr((l4_vcon_attr_t const *)&m->mr[1]), 70 0, 0, 0); 71 72 case L4_VCON_GET_ATTR_OP: 73 return l4_msgtag(this_vcon()->vcon_get_attr((l4_vcon_attr_t *)&m->mr[1]), 74 4, 0, 0); 75 76 default: 77 break; 78 } 79 80 unsigned size = op >> 16; 81 82 if (size > (L4_UTCB_GENERIC_DATA_SIZE - 1) * sizeof(l4_utcb_mr()->mr[0])) 83 size = (L4_UTCB_GENERIC_DATA_SIZE - 1) * sizeof(l4_utcb_mr()->mr[0]); 84 85 char buf[size]; 86 // Hmm, could we avoid the double copy here? 87 l4_umword_t v = this_vcon()->vcon_read(buf, size); 88 unsigned bytes = v & L4_VCON_READ_SIZE_MASK; 89 90 if (bytes < size) 91 v |= L4_VCON_READ_STAT_DONE; 92 93 m->mr[0] = v; 94 __builtin_memcpy(&m->mr[1], buf, bytes); 95 96 return l4_msgtag(0, 97 (bytes + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t) + 1, 98 0, 0); 99 } 100 101 unsigned vcon_read(char *buf, unsigned size) noexcept; 102 void vcon_write(const char *buf, unsigned size) noexcept; 103 int vcon_set_attr(l4_vcon_attr_t const *) noexcept 104 { return -L4_EOK; } 105 int vcon_get_attr(l4_vcon_attr_t *attr) noexcept 106 { 107 attr->l_flags = attr->o_flags = attr->i_flags = 0; 108 return -L4_EOK; 109 } 110 111private: 112 SVR const *this_vcon() const { return static_cast<SVR const *>(this); } 113 SVR *this_vcon() { return static_cast<SVR *>(this); } 114}; 115 116}} 117