]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/vlog.cpp
update
[l4.git] / kernel / fiasco / src / kern / vlog.cpp
1 INTERFACE:
2
3 #include "icu_helper.h"
4
5 class Irq;
6
7 class Vlog : public Icu_h<Vlog>, public Kobject
8 {
9   FIASCO_DECLARE_KOBJ();
10 public:
11   enum O_flags
12   {
13     F_ONLCR  = 000004, ///< Map NL to CR-NL on output
14     F_OCRNL  = 000010, ///< Map CR to NL on output
15     F_ONLRET = 000040, ///< Do not ouput CR
16   };
17
18   enum I_flags
19   {
20     F_INLCR = 000100,
21     F_IGNCR = 000200,
22     F_ICRNL = 000400,
23   };
24
25   enum L_flags
26   {
27     F_ECHO = 000010,
28   };
29
30 private:
31   Irq *_irq;
32   Mword _i_flags;
33   Mword _o_flags;
34   Mword _l_flags;
35 };
36
37 IMPLEMENTATION:
38
39 #include "entry_frame.h"
40 #include "map_util.h"
41 #include "mem_space.h"
42 #include "l4_buf_iter.h"
43 #include "thread.h"
44 #include "vkey.h"
45 #include "irq.h"
46 #include "irq_controller.h"
47
48 class Vlog_irq_pin : public Sw_irq_pin
49 {};
50
51
52 PUBLIC inline explicit
53 Vlog_irq_pin::Vlog_irq_pin(Vlog *i)
54 { payload()[0] = Mword(i); }
55
56 PUBLIC inline
57 Vlog *
58 Vlog_irq_pin::vlog() const
59 { return (Vlog*)payload()[0]; }
60
61
62 PUBLIC
63 void
64 Vlog_irq_pin::unbind_irq()
65 {
66   Vlog *l = vlog();
67   if (l)
68     l->unbind_irq();
69
70   replace<Sw_irq_pin>();
71 }
72
73
74 FIASCO_DEFINE_KOBJ(Vlog);
75
76 PUBLIC
77 Vlog::Vlog()
78 : _irq(0),
79   _i_flags(F_ICRNL), _o_flags(F_ONLRET | F_OCRNL), _l_flags(F_ECHO)
80 {
81   Vkey::set_echo(Vkey::Echo_crnl);
82   // CAP idx 5 is the initial kernel stream
83   initial_kobjects.register_obj(this, 5);
84 }
85
86 PUBLIC
87 void
88 Vlog::unbind_irq()
89 {
90   _irq = 0;
91   Vkey::irq(0);
92 }
93
94 PRIVATE inline NOEXPORT
95 void
96 Vlog::log_string(Syscall_frame *f, Utcb const *u)
97 {
98   L4_snd_item_iter snd_items(u, f->tag().words());
99
100   unsigned len = u->values[1];
101   char const *str = (char const *)&u->values[2];
102
103   if (len > sizeof(u->values) - sizeof(u->values[0]) * 2)
104     return;
105
106   while (len--)
107     {
108       int c = *str++;
109
110       if (_o_flags & F_ONLCR && c == '\n')
111         putchar('\r');
112
113       if (_o_flags & F_OCRNL && c == '\r')
114         c = '\n';
115
116       if (_o_flags & F_ONLRET && c == '\r')
117         continue;
118
119       putchar(c);
120     }
121 }
122
123 PRIVATE inline NOEXPORT
124 L4_msg_tag
125 Vlog::get_input(Mword rights, Syscall_frame *f, Utcb *u)
126 {
127   (void)f;
128
129   if (!have_receive(u))
130     return commit_result(0);
131
132   if (!(rights & L4_fpage::X))
133     return commit_result(-L4_err::EPerm);
134
135   char *buffer = reinterpret_cast<char *>(&u->values[1]);
136   long cnt_down = u->values[0] >> 16;
137   int i = 0;
138   while (cnt_down && (i = Vkey::get()) != -1)
139     {
140       Vkey::clear();
141
142       if (_i_flags & F_INLCR && i == '\n')
143         i = '\r';
144
145       if (_i_flags & F_IGNCR && i == '\r')
146         continue;
147
148       if (_i_flags & F_ICRNL && i == '\r')
149         i = '\n';
150
151       *buffer = i;
152       ++buffer;
153       --cnt_down;
154     }
155
156   u->values[0] = buffer - reinterpret_cast<char *>(&u->values[1]);
157   if (i == -1)
158     u->values[0] |= 1UL<<31;
159   return commit_result(0);
160 }
161
162 PUBLIC
163 L4_msg_tag
164 Vlog::icu_bind_irq(Irq *irq_o, unsigned irqnum)
165 {
166   if (irqnum > 0)
167     return commit_result(-L4_err::EInval);
168
169   if (_irq)
170     _irq->pin()->unbind_irq();
171
172   irq_o->pin()->unbind_irq();
173   irq_o->pin()->replace<Vlog_irq_pin>(this);
174   _irq = irq_o;
175   Vkey::irq(irq_o);
176   return commit_result(0);
177 }
178
179
180 PRIVATE inline NOEXPORT
181 L4_msg_tag
182 Vlog::set_attr(Mword, Syscall_frame const *, Utcb const *u)
183 {
184   _i_flags = u->values[1];
185   _o_flags = u->values[2];
186   _l_flags = u->values[3];
187   Vkey::set_echo((!(_l_flags & F_ECHO))
188                   ? Vkey::Echo_off
189                   : (_o_flags & F_OCRNL
190                     ? Vkey::Echo_crnl
191                     : Vkey::Echo_on));
192
193   return commit_result(0);
194 }
195
196 PRIVATE inline NOEXPORT
197 L4_msg_tag
198 Vlog::get_attr(Mword, Syscall_frame *, Utcb *u)
199 {
200   if (!have_receive(u))
201     return commit_result(0);
202
203   u->values[1] = _i_flags;
204   u->values[2] = _o_flags;
205   u->values[3] = _l_flags;
206   return commit_result(0, 4);
207 }
208
209 PUBLIC inline
210 Irq_base *
211 Vlog::icu_get_irq(unsigned irqnum)
212 {
213   if (irqnum > 0)
214     return 0;
215
216   return _irq;
217 }
218
219
220 PUBLIC inline
221 void
222 Vlog::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
223 {
224   *features = 0; // supported features (only normal irqs)
225   *num_irqs = 1;
226   *num_msis = 0;
227 }
228
229
230 PUBLIC
231 L4_msg_tag
232 Vlog::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
233               Utcb const *r_msg, Utcb *s_msg)
234 {
235   L4_msg_tag const t = f->tag();
236
237   if (t.proto() == L4_msg_tag::Label_irq)
238     return Icu_h<Vlog>::icu_invoke(ref, rights, f, r_msg, s_msg);
239   else if (t.proto() != L4_msg_tag::Label_log)
240     return commit_result(-L4_err::EBadproto);
241
242   switch (r_msg->values[0])
243     {
244     case 0:
245       log_string(f, r_msg);
246       return no_reply();
247
248     case 2: // set attr
249       return set_attr(rights, f, r_msg);
250
251     case 3: // get attr
252       return get_attr(rights, f, s_msg);
253
254     default:
255       return get_input(rights, f, s_msg);
256     }
257 }
258
259
260 static Vlog __vlog;
261