]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/drivers/mux_console.cpp
update
[l4.git] / kernel / fiasco / src / drivers / mux_console.cpp
1 INTERFACE:
2
3 #include "types.h"
4 #include "console.h"
5
6 /**
7  * Console multiplexer.
8  *
9  * This implementation of the Console interface can be used to
10  * multiplex among some input, output, and in-out consoles.
11  */
12 class Mux_console : public Console
13 {
14 public:
15
16   enum
17   {
18     SIZE = 8  ///< The maximum number of consoles to be multiplexed.
19   };
20
21   int  write(char const *str, size_t len);
22   int  getchar(bool blocking = true);
23   int  char_avail() const;
24
25 private:
26   int     _next_getchar;
27   int     _items;
28   Console *_cons[SIZE];
29 };
30
31
32 IMPLEMENTATION:
33
34 #include <cstdio>
35 #include "processor.h"
36
37 PUBLIC
38 Mux_console::Mux_console()
39   : _next_getchar(-1), _items(0)
40 {}
41
42 IMPLEMENT
43 int
44 Mux_console::write(char const *str, size_t len)
45 {
46   for (int i = 0; i < _items; ++i)
47     if (_cons[i] && (_cons[i]->state() & OUTENABLED))
48       _cons[i]->write(str, len);
49
50   return len;
51 }
52
53 IMPLEMENT
54 int
55 Mux_console::getchar(bool blocking)
56 {
57   if (_next_getchar != -1)
58     {
59       int c = _next_getchar;
60       _next_getchar = -1;
61       return c;
62     }
63
64   int ret = -1;
65   do
66     {
67       for (int i = 0; i < _items; ++i)
68         if (_cons[i] && (_cons[i]->state() & INENABLED))
69           {
70             ret = _cons[i]->getchar(false);
71             if (ret != -1)
72               return ret;
73           }
74
75       if (blocking)
76         Proc::pause();
77     }
78   while (blocking && ret == -1);
79
80   return ret;
81 }
82
83 /**
84  * deliver attributes of all subconsoles.
85  */
86 PUBLIC
87 Mword
88 Mux_console::get_attributes() const
89 {
90   Mword attr = 0;
91
92   for (int i = 0; i < _items; i++)
93     if (_cons[i])
94       attr |= _cons[i]->get_attributes();
95
96   return attr;
97 }
98
99 PUBLIC
100 void
101 Mux_console::getchar_chance()
102 {
103   for (int i = 0; i < _items; ++i)
104     if (   _cons[i] && (_cons[i]->state() & INENABLED)
105         && _cons[i]->char_avail() == 1)
106       {
107         int c = _cons[i]->getchar(false);
108         if (c != -1 && _next_getchar == -1)
109           _next_getchar = c;
110       }
111 }
112
113 IMPLEMENT
114 int
115 Mux_console::char_avail() const
116 {
117   int ret = -1;
118   for (int i = 0; i < _items; ++i)
119     if (_cons[i] && (_cons[i]->state() & INENABLED))
120       {
121         int tmp = _cons[i]->char_avail();
122         if (tmp == 1)
123           return 1;
124         else if (tmp == 0)
125           ret = tmp;
126       }
127   return ret;
128 }
129
130 /**
131  * Register a console to be multiplexed.
132  * @param cons the Console to add.
133  * @param pos the position of the console, normally not needed.
134  */
135 PUBLIC virtual
136 bool
137 Mux_console::register_console(Console *c, int pos = 0)
138 {
139   if (c->failed())
140     return false;
141
142   if (_items >= SIZE)
143     return false;
144
145   if (pos >= SIZE || pos < 0)
146     return false;
147
148   if (pos > _items)
149     pos = _items;
150
151   if (pos < _items)
152     for (int i = _items - 1; i >= pos; --i)
153       _cons[i + 1] = _cons[i];
154
155   _items++;
156   _cons[pos] = c;
157   if (_cons[pos]->state() & DISABLED_INIT)
158     _cons[pos]->state(DISABLED);
159   else
160     _cons[pos]->state(INENABLED | OUTENABLED);
161
162   return true;
163 }
164
165 /**
166  * Unregister a console from the multiplexer.
167  * @param cons the console to remove.
168  */
169 PUBLIC
170 bool
171 Mux_console::unregister_console(Console *c)
172 {
173   int pos;
174   for (pos = 0; pos < _items && _cons[pos] != c; pos++)
175     ;
176   if (pos == _items)
177     return false;
178
179   --_items;
180   for (int i = pos; i < _items; ++i)
181     _cons[i] = _cons[i + 1];
182
183   return true;
184 }
185
186 /**
187  * Change the state of a group of consoles specified by
188  *        attributes.
189  * @param any_true   match if console has any of these attributes
190  * @param all_false  match if console doesn't have any of these attributes
191  */
192 PUBLIC
193 void
194 Mux_console::change_state(Mword any_true, Mword all_false,
195                           Mword mask, Mword bits)
196 {
197   for (int i=0; i<_items; i++)
198     {
199       if (_cons[i])
200         {
201           Mword attr = _cons[i]->get_attributes();
202           if (   // any bit of the any_true attributes must be set
203                  (!any_true  || (attr & any_true)  != 0)
204                  // all bits of the all_false attributes must be cleared
205               && (!all_false || (attr & all_false) == 0))
206             {
207               _cons[i]->state((_cons[i]->state() & mask) | bits);
208             }
209         }
210     }
211 }
212
213 /**
214  * Find a console with a specific attribute.
215  * @param any_true match to console which has set any bit of this bitmask
216  */
217 PUBLIC
218 Console*
219 Mux_console::find_console(Mword any_true)
220 {
221   for (int i = 0; i < _items; i++)
222     if (_cons[i] && _cons[i]->get_attributes() & any_true)
223       return _cons[i];
224
225   return 0;
226 }
227
228 /**
229  * Start exclusive mode for a specific console. Only the one
230  *        console which matches to any_true is enabled for input and
231  *        output. All other consoles are disabled.
232  * @param any_true match to console which has set any bit of this bitmask
233  */
234 PUBLIC
235 void
236 Mux_console::start_exclusive(Mword any_true)
237 {
238   // enable exclusive console
239   change_state(any_true, 0, ~0UL, (OUTENABLED|INENABLED));
240   // disable all other consoles
241   change_state(0, any_true, ~(OUTENABLED|INENABLED), 0);
242 }
243
244 /**
245  * End exclusive mode for a specific console.
246  * @param any_true match to console which has set any bit of this bitmask
247  */
248 PUBLIC
249 void
250 Mux_console::end_exclusive(Mword any_true)
251 {
252   // disable exclusive console
253   change_state(any_true, 0, ~(OUTENABLED|INENABLED), 0);
254   // enable all other consoles
255   change_state(0, any_true, ~0UL, (OUTENABLED|INENABLED));
256 }
257
258
259 IMPLEMENTATION[debug]:
260
261 PUBLIC
262 void
263 Mux_console::list_consoles()
264 {
265   for (int i = 0; i < _items; i++)
266     if (_cons[i])
267       {
268         Mword attr = _cons[i]->get_attributes();
269
270         printf("  " L4_PTR_FMT "  %s  (%s)  ",
271                attr, _cons[i]->str_mode(), _cons[i]->str_state());
272         for (unsigned bit = 2; bit < sizeof(attr) * 4; bit++)
273           if (attr & (1 << bit))
274             printf("%s ", Console::str_attr(bit));
275         putchar('\n');
276       }
277 }