]> 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 Irq_chip_soft
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_base *_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
49 FIASCO_DEFINE_KOBJ(Vlog);
50
51 PUBLIC
52 Vlog::Vlog()
53 : _irq(0),
54   _i_flags(F_ICRNL), _o_flags(F_ONLCR), _l_flags(F_ECHO)
55 {
56   Vkey::set_echo(Vkey::Echo_crnl);
57   // CAP idx 5 is the initial kernel stream
58   initial_kobjects.register_obj(this, 5);
59 }
60
61 PUBLIC void
62 Vlog::operator delete (void *)
63 {
64   printf("WARNING: tried to delete kernel Vlog object.\n");
65 }
66
67
68 PRIVATE inline NOEXPORT
69 void
70 Vlog::log_string(Syscall_frame *f, Utcb const *u)
71 {
72   L4_snd_item_iter snd_items(u, f->tag().words());
73
74   unsigned len = u->values[1];
75   char const *str = (char const *)&u->values[2];
76
77   if (len > sizeof(u->values) - sizeof(u->values[0]) * 2)
78     return;
79
80   while (len--)
81     {
82       int c = *str++;
83
84       // the kernel does this anyway
85 #if 0
86       if (_o_flags & F_ONLCR && c == '\n')
87         putchar('\r');
88 #endif
89
90       if (_o_flags & F_OCRNL && c == '\r')
91         c = '\n';
92
93       if (_o_flags & F_ONLRET && c == '\r')
94         continue;
95
96       putchar(c);
97     }
98 }
99
100 PRIVATE inline NOEXPORT
101 L4_msg_tag
102 Vlog::get_input(L4_fpage::Rights rights, Syscall_frame *f, Utcb *u)
103 {
104   (void)f;
105
106   if (!have_receive(u))
107     return commit_result(0);
108
109   if (!(rights & L4_fpage::Rights::X()))
110     return commit_result(-L4_err::EPerm);
111
112   char *buffer = reinterpret_cast<char *>(&u->values[1]);
113   long cnt_down = min<Mword>(u->values[0] >> 16,
114                              sizeof(u->values) - sizeof(u->values[0]));
115   int i = 0;
116   while (cnt_down && (i = Vkey::get()) != -1)
117     {
118       Vkey::clear();
119
120       if (_i_flags & F_INLCR && i == '\n')
121         i = '\r';
122
123       if (_i_flags & F_IGNCR && i == '\r')
124         continue;
125
126       if (_i_flags & F_ICRNL && i == '\r')
127         i = '\n';
128
129       *buffer = i;
130       ++buffer;
131       --cnt_down;
132     }
133
134   u->values[0] = buffer - reinterpret_cast<char *>(&u->values[1]);
135   if (i == -1)
136     u->values[0] |= 1UL<<31;
137   return commit_result(0);
138 }
139
140 PUBLIC
141 void
142 Vlog::bind(Irq_base *irq, Mword irqnum)
143 {
144   Irq_chip_soft::bind(irq, irqnum);
145   _irq = irq;
146   Vkey::irq(irq);
147 }
148
149 PUBLIC
150 L4_msg_tag
151 Vlog::icu_bind_irq(Irq *irq_o, unsigned irqnum)
152 {
153   if (irqnum > 0)
154     return commit_result(-L4_err::EInval);
155
156   if (_irq)
157     _irq->unbind();
158
159   bind(irq_o, irqnum);
160   return commit_result(0);
161 }
162
163 PUBLIC
164 L4_msg_tag
165 Vlog::icu_set_mode(Mword pin, Irq_chip::Mode)
166 {
167   if (pin != 0)
168     return commit_result(-L4_err::EInval);
169
170   if (_irq)
171     _irq->switch_mode(true);
172   return commit_result(0);
173 }
174
175 PRIVATE inline NOEXPORT
176 L4_msg_tag
177 Vlog::set_attr(L4_fpage::Rights, Syscall_frame const *, Utcb const *u)
178 {
179   _i_flags = u->values[1];
180   _o_flags = u->values[2] | F_ONLCR;
181   _l_flags = u->values[3];
182   Vkey::set_echo((!(_l_flags & F_ECHO))
183                   ? Vkey::Echo_off
184                   : (_o_flags & F_OCRNL
185                     ? Vkey::Echo_crnl
186                     : Vkey::Echo_on));
187
188   return commit_result(0);
189 }
190
191 PRIVATE inline NOEXPORT
192 L4_msg_tag
193 Vlog::get_attr(L4_fpage::Rights, Syscall_frame *, Utcb *u)
194 {
195   if (!have_receive(u))
196     return commit_result(0);
197
198   u->values[1] = _i_flags;
199   u->values[2] = _o_flags;
200   u->values[3] = _l_flags;
201   return commit_result(0, 4);
202 }
203
204 PUBLIC inline
205 Irq_base *
206 Vlog::icu_get_irq(unsigned irqnum)
207 {
208   if (irqnum > 0)
209     return 0;
210
211   return _irq;
212 }
213
214
215 PUBLIC inline
216 void
217 Vlog::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
218 {
219   *features = 0; // supported features (only normal irqs)
220   *num_irqs = 1;
221   *num_msis = 0;
222 }
223
224
225 PUBLIC
226 L4_msg_tag
227 Vlog::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights, Syscall_frame *f,
228               Utcb const *r_msg, Utcb *s_msg)
229 {
230   L4_msg_tag const t = f->tag();
231
232   if (t.proto() == L4_msg_tag::Label_irq)
233     return Icu_h<Vlog>::icu_invoke(ref, rights, f, r_msg, s_msg);
234   else if (t.proto() != L4_msg_tag::Label_log)
235     return commit_result(-L4_err::EBadproto);
236
237   switch (r_msg->values[0])
238     {
239     case 0:
240       log_string(f, r_msg);
241       return no_reply();
242
243     case 2: // set attr
244       return set_attr(rights, f, r_msg);
245
246     case 3: // get attr
247       return get_attr(rights, f, s_msg);
248
249     default:
250       return get_input(rights, f, s_msg);
251     }
252 }
253
254
255 static Vlog __vlog;
256