]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/drivers/mux_console.cpp
6ea475844f8d84d5dedb7f99b53b0fbb98fc3fe0
[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     for(int i=0; i<_items; ++i)
67       {
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   } while( blocking && ret==-1 );
78
79   return ret;
80 }
81
82 /**
83  * deliver attributes of all subconsoles.
84  */
85 PUBLIC
86 Mword
87 Mux_console::get_attributes() const
88 {
89   Mword attr = 0;
90
91   for (int i=0; i<_items; i++)
92     if(_cons[i])
93       attr |= _cons[i]->get_attributes();
94
95   return attr;
96 }
97
98 PUBLIC
99 void
100 Mux_console::getchar_chance ()
101 {
102   for (int i=0; i<_items; ++i)
103     {
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
114 IMPLEMENT
115 int
116 Mux_console::char_avail() const
117 {
118   int ret = -1;
119   for(int i=0; i<_items; ++i) 
120     if(_cons[i] && (_cons[i]->state() & INENABLED)) 
121       {
122         int tmp = _cons[i]->char_avail();
123         if(tmp==1) 
124           return 1;
125         else if(tmp==0)
126           ret = tmp;
127       }
128   return ret;
129 }
130
131 /**
132  * Register a console to be multiplexed.
133  * @param cons the Console to add.
134  * @param pos the position of the console, normally not needed.
135  */
136 PUBLIC virtual
137 bool
138 Mux_console::register_console( Console *c, int pos = 0)
139 {
140   if (c->failed())
141     return false;
142
143   if(_items >= SIZE) 
144     return false;
145
146   if(pos>=SIZE || pos<0) 
147     return false;
148
149   if(pos>_items)
150     pos = _items;
151
152   if(pos<_items) {
153     for(int i = _items-1; i>=pos; --i) 
154       _cons[i+1] = _cons[i];
155   } 
156   _items++;
157   _cons[pos] = c;
158   if (_cons[pos]->state() & DISABLED_INIT)
159       _cons[pos]->state(DISABLED);
160   else
161       _cons[pos]->state(INENABLED|OUTENABLED);
162
163   return true;
164 }
165
166 /**
167  * Unregister a console from the multiplexer.
168  * @param cons the console to remove.
169  */
170 PUBLIC
171 bool
172 Mux_console::unregister_console( Console *c )
173 {
174   int pos;
175   for(pos = 0; pos < _items && _cons[pos]!=c; pos++)
176     ;
177   if(pos==_items) 
178     return false;
179   
180   _items--;
181   for(int i = pos; i<_items; ++i) 
182     _cons[i] = _cons[i+1];
183
184   return true;
185 }
186
187 /**
188  * Change the state of a group of consoles specified by
189  *        attributes.
190  * @param any_true   match if console has any of these attributes
191  * @param all_false  match if console doesn't have any of these attributes
192  */
193 PUBLIC
194 void
195 Mux_console::change_state(Mword any_true, Mword all_false,
196                           Mword mask, Mword bits)
197 {
198   for (int i=0; i<_items; i++)
199     {
200       if (_cons[i])
201         {
202           Mword attr = _cons[i]->get_attributes();
203           if (   // any bit of the any_true attributes must be set
204                  (!any_true  || (attr & any_true)  != 0)
205                  // all bits of the all_false attributes must be cleared
206               && (!all_false || (attr & all_false) == 0))
207             {
208               _cons[i]->state((_cons[i]->state() & mask) | bits);
209             }
210         }
211     }
212 }
213
214 /**
215  * Find a console with a specific attribute.
216  * @param any_true match to console which has set any bit of this bitmask
217  */
218 PUBLIC
219 Console*
220 Mux_console::find_console(Mword any_true)
221 {
222   for (int i=0; i<_items; i++)
223     {
224       if (_cons[i] && _cons[i]->get_attributes() & any_true)
225         return _cons[i];
226     }
227
228   return 0;
229 }
230
231 /**
232  * Start exclusive mode for a specific console. Only the one
233  *        console which matches to any_true is enabled for input and
234  *        output. All other consoles are disabled.
235  * @param any_true match to console which has set any bit of this bitmask
236  */
237 PUBLIC
238 void
239 Mux_console::start_exclusive(Mword any_true)
240 {
241   // enable exclusive console
242   change_state(any_true, 0, ~0UL, (OUTENABLED|INENABLED));
243   // disable all other consoles
244   change_state(0, any_true, ~(OUTENABLED|INENABLED), 0);
245 }
246
247 /**
248  * End exclusive mode for a specific console.
249  * @param any_true match to console which has set any bit of this bitmask
250  */
251 PUBLIC
252 void
253 Mux_console::end_exclusive(Mword any_true)
254 {
255   // disable exclusive console
256   change_state(any_true, 0, ~(OUTENABLED|INENABLED), 0);
257   // enable all other consoles
258   change_state(0, any_true, ~0UL, (OUTENABLED|INENABLED));
259 }
260
261
262 IMPLEMENTATION[debug]:
263
264 PUBLIC
265 void
266 Mux_console::list_consoles()
267 {
268   for (int i=0; i<_items; i++)
269     {
270       if (_cons[i])
271         {
272           Mword attr = _cons[i]->get_attributes();
273
274           printf("  "L4_PTR_FMT"  %s  (%s)  ", 
275               attr, _cons[i]->str_mode(), _cons[i]->str_state());
276           for (unsigned bit=2; bit<sizeof(attr)*4; bit++)
277             if (attr & (1<<bit))
278               printf("%s ", Console::str_attr(bit));
279           putchar('\n');
280         }
281     }
282 }
283