]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/vlog.cpp
d34d1e3659f492e0283a3f1e16f99ff74c9104fb
[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 }
83
84 PUBLIC
85 void
86 Vlog::unbind_irq()
87 {
88   _irq = 0;
89   Vkey::irq(0);
90 }
91
92 PRIVATE inline NOEXPORT
93 void
94 Vlog::log_string(Syscall_frame *f, Utcb const *u)
95 {
96   L4_snd_item_iter snd_items(u, f->tag().words());
97
98   unsigned len = u->values[1];
99   char const *str = (char const *)&u->values[2];
100
101   if (len > sizeof(u->values) - sizeof(u->values[0]) * 2)
102     return;
103
104   while (len--)
105     {
106       int c = *str++;
107
108       if (_o_flags & F_ONLCR && c == '\n')
109         putchar('\r');
110
111       if (_o_flags & F_OCRNL && c == '\r')
112         c = '\n';
113
114       if (_o_flags & F_ONLRET && c == '\r')
115         continue;
116
117       putchar(c);
118     }
119 }
120
121 PRIVATE inline NOEXPORT
122 L4_msg_tag
123 Vlog::get_input(Mword rights, Syscall_frame *f, Utcb *u)
124 {
125   (void)f;
126
127   if (!have_receive(u))
128     return commit_result(0);
129
130   if (!(rights & L4_fpage::X))
131     return commit_result(-L4_err::EPerm);
132
133   char *buffer = reinterpret_cast<char *>(&u->values[1]);
134   long cnt_down = u->values[0] >> 16;
135   int i = 0;
136   while (cnt_down && (i = Vkey::get()) != -1)
137     {
138       Vkey::clear();
139
140       if (_i_flags & F_INLCR && i == '\n')
141         i = '\r';
142
143       if (_i_flags & F_IGNCR && i == '\r')
144         continue;
145
146       if (_i_flags & F_ICRNL && i == '\r')
147         i = '\n';
148
149       *buffer = i;
150       ++buffer;
151       --cnt_down;
152     }
153
154   u->values[0] = buffer - reinterpret_cast<char *>(&u->values[1]);
155   if (i == -1)
156     u->values[0] |= 1UL<<31;
157   return commit_result(0);
158 }
159
160 PUBLIC
161 L4_msg_tag
162 Vlog::icu_bind_irq(Irq *irq_o, unsigned irqnum)
163 {
164   if (irqnum > 0)
165     return commit_result(-L4_err::EInval);
166
167   if (_irq)
168     _irq->pin()->unbind_irq();
169
170   irq_o->pin()->unbind_irq();
171   irq_o->pin()->replace<Vlog_irq_pin>(this);
172   _irq = irq_o;
173   Vkey::irq(irq_o);
174   return commit_result(0);
175 }
176
177
178 PRIVATE inline NOEXPORT
179 L4_msg_tag
180 Vlog::set_attr(Mword, Syscall_frame const *, Utcb const *u)
181 {
182   _i_flags = u->values[1];
183   _o_flags = u->values[2];
184   _l_flags = u->values[3];
185   Vkey::set_echo((!(_l_flags & F_ECHO))
186                   ? Vkey::Echo_off
187                   : (_o_flags & F_OCRNL
188                     ? Vkey::Echo_crnl
189                     : Vkey::Echo_on));
190
191   return commit_result(0);
192 }
193
194 PRIVATE inline NOEXPORT
195 L4_msg_tag
196 Vlog::get_attr(Mword, Syscall_frame *, Utcb *u)
197 {
198   if (!have_receive(u))
199     return commit_result(0);
200
201   u->values[1] = _i_flags;
202   u->values[2] = _o_flags;
203   u->values[3] = _l_flags;
204   return commit_result(0, 4);
205 }
206
207 PUBLIC inline
208 Irq_base *
209 Vlog::icu_get_irq(unsigned irqnum)
210 {
211   if (irqnum > 0)
212     return 0;
213
214   return _irq;
215 }
216
217
218 PUBLIC inline
219 void
220 Vlog::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
221 {
222   *features = 0; // supported features (only normal irqs)
223   *num_irqs = 1;
224   *num_msis = 0;
225 }
226
227
228 PUBLIC
229 L4_msg_tag
230 Vlog::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
231               Utcb const *r_msg, Utcb *s_msg)
232 {
233   L4_msg_tag const t = f->tag();
234
235   if (t.proto() == L4_msg_tag::Label_irq)
236     return Icu_h<Vlog>::icu_invoke(ref, rights, f, r_msg, s_msg);
237   else if (t.proto() != L4_msg_tag::Label_log)
238     return commit_result(-L4_err::EBadproto);
239
240   switch (r_msg->values[0])
241     {
242     case 0:
243       log_string(f, r_msg);
244       return no_reply();
245
246     case 2: // set attr
247       return set_attr(rights, f, r_msg);
248
249     case 3: // get attr
250       return get_attr(rights, f, s_msg);
251
252     default:
253       return get_input(rights, f, s_msg);
254     }
255 }
256