L4Re - L4 Runtime Environment
vcon_svr
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 
27 namespace 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  */
45 template< typename SVR >
46 class Vcon_svr
47 {
48 public:
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) throw();
102  void vcon_write(const char *buf, unsigned size) throw();
103  int vcon_set_attr(l4_vcon_attr_t const *) throw()
104  { return -L4_EOK; }
105  int vcon_get_attr(l4_vcon_attr_t *attr) throw()
106  {
107  attr->l_flags = attr->o_flags = attr->i_flags = 0;
108  return -L4_EOK;
109  }
110 
111 private:
112  SVR const *this_vcon() const { return static_cast<SVR const *>(this); }
113  SVR *this_vcon() { return static_cast<SVR *>(this); }
114 };
115 
116 }}