Root/include/devices.hhp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/devices.hhp: interfaces for core devices.
4// Copyright 2009 Bas Wijnen <wijnen@debian.org>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#ifndef __IRIS_DEVICES_HH
20#define __IRIS_DEVICES_HH
21
22#include "iris.hh"
23
24namespace Iris:
25    // Caplist interface.
26    template <typename _T> //
27    struct Caplist : public Caps:
28        Caplist (Caps c = Cap ()) : Caps (c):
29        Caplist <_T> create (unsigned size, Memory mem = my_memory):
30            return Caplist <_T> (mem.create_caps (size))
31        void set (unsigned idx, _T value):
32            return Caps::set (idx, value)
33        _T get (unsigned idx):
34            return _T (Caps::get (idx))
35
36    struct _Locker_base:
37        enum request:
38            LOCK_RO = 0x2001
39            UNLOCK_RO
40            SET_CHANGE_CB
41            NUM
42    template <typename _T> //
43    struct Locker : public _Locker_base, public _T:
44        // Lock the object for reading. Multiple read locks can exist simultaneously, but no write lock can be present.
45        void lock_ro ():
46            _T::call (CAP_MASTER_DIRECT | LOCK_RO)
47        // Release a read-only lock.
48        void unlock_ro ():
49            _T::call (CAP_MASTER_DIRECT | UNLOCK_RO)
50        // Register a callback when the backing store is changed.
51        // The cb is invoked with data[0] set to the position of the first change and data[1] set to the length of the changed part.
52        // The accuracy of this is not guaranteed. Servers which only want to provide an event should set data[0] == 0, data[1] == ~0.
53        // The change invoke must happen before this function's reply is sent.
54        void set_change_cb (Listitem cb):
55            _T::ocall (cb, CAP_MASTER_DIRECT | SET_CHANGE_CB)
56        Locker ():
57        Locker (Cap c) : _T (c):
58
59    struct _WLocker_base:
60        enum request:
61            LOCK = _Locker_base::NUM
62            UNLOCK
63            NUM
64    template <typename _T> //
65    struct WLocker : public _WLocker_base, public _T:
66        // Lock the object. Write operations can only be done when the object is locked.
67        void lock ():
68            _T::call (CAP_MASTER_DIRECT | LOCK)
69        // Unlock the object. Write operations can only be done when the object is locked.
70        void unlock ():
71            _T::call (CAP_MASTER_DIRECT | UNLOCK)
72        WLocker ():
73        WLocker (Cap c) : _T (c):
74
75    /// A short block of data with a size and content. Any character can be stored in it (including '\0').
76    struct _String : public Cap:
77        _String (Cap c = Cap ()) : Cap (c):
78        enum request:
79            GET_SIZE = _WLocker_base::NUM
80            GET_CHARS
81            ID
82        /// Get the size of the string.
83        Num get_size ():
84            return call (CAP_MASTER_DIRECT | GET_SIZE)
85        /// Get exactly 16 characters. There is no alignment requirement.
86        char *get_chars (Num idx, char buffer[16]):
87            call (CAP_MASTER_DIRECT | GET_CHARS, idx)
88            unsigned *b = (unsigned *)buffer
89            b[0] = recv.data[0].l
90            b[1] = recv.data[0].h
91            b[2] = recv.data[1].l
92            b[3] = recv.data[1].h
93            return buffer
94    typedef Locker <_String> String
95
96    /// A block of data with a size and content. Any character can be stored in it (including '\0').
97    struct _Block : public Cap:
98        _Block (Cap c = Cap ()) : Cap (c):
99        enum request:
100            GET_SIZE = _String::ID
101            GET_ALIGN_BITS
102            GET_BLOCK
103            ID
104        /// Get the size of the block.
105        Num get_size ():
106            return call (CAP_MASTER_DIRECT | GET_SIZE)
107        /// Get the number of bits that page accesses must be aligned to. Cannot be more than PAGE_BITS.
108        unsigned get_align_bits ():
109            return call (CAP_MASTER_DIRECT | GET_ALIGN_BITS).l
110        /// Helper function for get_block.
111        static Page _create_paying_page ():
112            Page ret = my_memory.create_page ()
113            ret.set_flags (Page::PAYING)
114            return ret
115        /// Get a block from the block; place it at offset on page. This need not be implemented for blocks smaller than PAGE_SIZE. All arguments must be aligned. If size is PAGE_SIZE, the caller may lose the frame in the transaction.
116        Cap get_block (Num idx, unsigned size = PAGE_SIZE, unsigned offset = 0, Page ret = _create_paying_page ()):
117            ocall (ret, Iris::Num (CAP_MASTER_DIRECT | GET_BLOCK, size << 16 | offset), idx)
118            return ret
119    typedef Locker <_Block> Block
120
121    /// A writable String.
122    struct _WString : public String:
123        _WString (Cap c = Cap ()) : String (c):
124        enum request:
125            TRUNCATE = _Block::ID
126            SET_CHARS
127            ID
128        /// Set the size of the string. Strings may have a limit to this setting.
129        void truncate (Num size):
130            call (CAP_MASTER_DIRECT | TRUNCATE, size)
131        /// Set exactly 4 characters. If the size is shorter than idx + 4, the extra characters are ignored.
132        void set_chars (Num idx, char buffer[4]):
133            call (Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
134    typedef WLocker <_WString> WString
135
136    /// A writable Block.
137    struct _WBlock : public Block:
138        _WBlock (Cap c = Cap ()) : Block (c):
139        enum request:
140            TRUNCATE = _WString::TRUNCATE
141            SET_BLOCK = _WString::ID
142            ID
143        /// Set the size of the block. This setting may have a limited range, or not be supported at all.
144        void truncate (Num size):
145            call (CAP_MASTER_DIRECT | TRUNCATE, size)
146        /// Overwrite a block from the block with data at offset on the page. All arguments must be aligned. If size is PAGE_SIZE, the caller may lose the frame in the transaction. Only the specified part of the page is used for overwriting data.
147        void set_block (Num idx, Page page, unsigned size = PAGE_SIZE, unsigned offset = 0):
148            ocall (page, Iris::Num (CAP_MASTER_DIRECT | SET_BLOCK, size << 16 | offset), idx)
149    typedef WLocker <_WBlock> WBlock
150
151    // This interface allows another kernel to be booted by Iris.
152    struct Boot : public Cap:
153        Boot (Cap c = Cap ()) : Cap (c):
154        enum request:
155            BOOT = _WBlock::ID
156            ID
157        // Boot a new kernel.
158        void boot (String code, unsigned load, unsigned entry):
159            ocall (code, CAP_MASTER_DIRECT | BOOT, Iris::Num (load, entry))
160
161    // Every process which wants to be switchable through a terminal must implement this interface.
162    struct Device : public Cap:
163        Device (Cap c = Cap ()) : Cap (c):
164        enum request:
165            RESET = Boot::ID
166            ID
167        // Reset the device. This is called by the terminal while switching owners.
168        void reset ():
169            call (CAP_MASTER_DIRECT | RESET)
170
171    struct Event : public Device:
172        Event (Cap c = Cap ()) : Device (c):
173        enum request:
174            SET_CB = Device::ID
175            ID
176        // Set the event callback. Pending event emit to the new callback immediately.
177        void set_cb (Cap cb):
178            ocall (cb, CAP_MASTER_DIRECT | SET_CB)
179
180    struct Elfrun : public Cap:
181        Elfrun (Cap c = Cap ()) : Cap (c):
182        enum request:
183            RUN_BLOCK = Event::ID
184            RUN_CAPS
185            ID
186        enum arg_pos:
187            PARENT_MEMORY
188            DATA
189            PARENT
190        Caps run_block (Memory parent_memory, Block data, Cap parent, unsigned num_slots = 8, unsigned num_caps = 32):
191            Caps caps = my_memory.create_caps (3)
192            caps.set (PARENT_MEMORY, parent_memory)
193            caps.set (DATA, data)
194            caps.set (PARENT, parent)
195            iocall (caps.copy (), CAP_MASTER_DIRECT | RUN_BLOCK, Num (num_slots, num_caps))
196            Caps ret = get_arg ()
197            my_memory.destroy (caps)
198            free_cap (caps)
199            return ret
200        Caps run_caps (Memory parent_memory, Caps data, Cap parent, unsigned pages, unsigned num_slots = 8, unsigned num_caps = 32):
201            Caps caps = my_memory.create_caps (3)
202            caps.set (PARENT_MEMORY, parent_memory)
203            caps.set (DATA, data)
204            caps.set (PARENT, parent)
205            iocall (caps.copy (), Num (CAP_MASTER_DIRECT | RUN_CAPS, pages), Num (num_slots, num_caps))
206            Caps ret = get_arg ()
207            my_memory.destroy (caps)
208            free_cap (caps)
209            return ret
210
211    // Interface for talking to the parent process.
212    struct Parent : public Cap:
213        Parent (Cap c = Cap ()) : Cap (c):
214        enum request:
215            GET_CAPABILITY = Elfrun::ID
216            PROVIDE_CAPABILITY
217            WAIT
218            GET_MEMORY
219            PROVIDE_MEMORY
220            INIT_DONE
221            EXIT
222            ID
223        // Get a handle.
224        template <typename _T> _T get_capability (unsigned num = 0):
225            icall (Num (CAP_MASTER_DIRECT | GET_CAPABILITY, num), _T::ID)
226            return get_arg ()
227        // Provide a device handle.
228        template <typename _T> void provide_capability (Cap cap, unsigned num = 0):
229            ocall (cap, Num (CAP_MASTER_DIRECT | PROVIDE_CAPABILITY, num), _T::ID)
230        // Wait until a device is used by the caller again.
231        template <typename _T> void wait (unsigned num = 0):
232            call (Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
233        // Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user.
234        Memory get_memory (Cap target):
235            iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
236            return get_arg ()
237        // Get a handle that another thread can use to call get_memory on. The actual limit on the created memory is floor(limit, thread address space limit).
238        Cap provide_memory (unsigned limit):
239            icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
240            return get_arg ()
241        // Signal the parent that the initialisation phase is over.
242        void init_done (Num stage = 0):
243            call (CAP_MASTER_DIRECT | INIT_DONE, stage)
244        // Exit the program. The parent does not reply, but kills the process.
245        void exit (Num code):
246            call (CAP_MASTER_DIRECT | EXIT, code)
247
248    // Keyboard interface.
249    struct Keyboard : public Event:
250        Keyboard (Cap c = Cap ()) : Event (c):
251        enum request:
252            GET_NUM_KEYS = Parent::ID
253            GET_KEYS
254            ID
255        // At event: the callback is called with a keycode. One bit defines if it's a press or release event.
256        enum constant:
257            RELEASE = 1 << 31
258        // Get the number of keys on the keyboard.
259        unsigned get_num_keys ():
260            return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
261        // Get the keycodes for the keys. The reply sends 4 key codes (32 bit each).
262        void get_keys (unsigned first):
263            call (CAP_MASTER_DIRECT | GET_KEYS, first)
264
265    // Buzzer interface.
266    struct Buzzer : public Device:
267        Buzzer (Cap c = Cap ()) : Device (c):
268        enum request:
269            BEEP = Keyboard::ID
270            STOP
271            ID
272        // Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted.
273        void beep (unsigned freq, unsigned ms, unsigned volume, Cap cb = Cap ()):
274            ocall (cb, Num (CAP_MASTER_DIRECT | BEEP, volume), Num (freq, ms))
275        // Abort current beep, if any.
276        void stop ():
277            call (CAP_MASTER_DIRECT | STOP)
278
279    // Display interface.
280    struct Display : public Device:
281        Display (Cap c = Cap ()) : Device (c):
282        enum request:
283            SET_EOF_CB = Buzzer::ID
284            MAP_FB
285            UNMAP_FB
286            GET_INFO
287            ID
288        // Register an end-of-frame callback.
289        // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
290        void set_eof_cb (Cap cb):
291            ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
292        // Map the framebuffer into memory.
293        Caps map_fb (unsigned address, Memory mem = my_memory, bool use = true):
294            iocall (mem, Num (CAP_MASTER_DIRECT | MAP_FB, use ? 1 : 0), address)
295            return get_arg ()
296        void unmap_fb (Caps caps):
297            ocall (caps, CAP_MASTER_DIRECT | UNMAP_FB)
298        // Get information about the display.
299        void get_info ():
300            // TODO: Interface is to be designed.
301            panic (0, "using undefined interface Display::get_info ()")
302
303    // Font interface.
304    // This can be used to turn a Display into a tty
305    struct Font : public Cap:
306        Font (Cap c = Cap ()) : Cap (c):
307        enum request:
308            SET_DISPLAY = Display::ID
309            LOAD_FONT
310            SETUP
311            AT
312            WRITE
313            GET_POS
314            GET_SIZE
315            ID
316        // Connect this font to new Display.
317        void set_display (Display d):
318            ocall (d, CAP_MASTER_DIRECT | SET_DISPLAY)
319        // Load new glyphs.
320        void load_font (String font):
321            ocall (font, CAP_MASTER_DIRECT | LOAD_FONT)
322        // Set some things up, like colours.
323        void setup ():
324            // TODO: Interface is to be designed.
325            panic (0, "using undefined interface Font::setup ()")
326        // Set new cursor position.
327        void at (int x, int y, bool delta_x = false, bool delta_y = false):
328            call (Num (CAP_MASTER_DIRECT | AT, delta_x + 2 * delta_y), Num (x, y))
329        // Write one glyph to the display.
330        void write (char c):
331            call (CAP_MASTER_DIRECT | WRITE, c)
332        // Write some glyphs to the display.
333        void write (char const *text):
334            for char const *t = text; *t; ++t:
335                invoke (CAP_MASTER_DIRECT | WRITE, *t)
336        // Write some glyphs to the display.
337        void write (char const *text, unsigned size):
338            for unsigned t = 0; t < size; ++t:
339                invoke (CAP_MASTER_DIRECT | WRITE, text[t])
340        void get_pos (unsigned &x, unsigned &y):
341            call (CAP_MASTER_DIRECT | GET_POS)
342            x = recv.data[0].l
343            y = recv.data[1].l
344        // Determine the size of a character.
345        void get_size (unsigned c, unsigned &width, unsigned &height, unsigned &baseline):
346            Num ret = call (CAP_MASTER_DIRECT | GET_SIZE, c)
347            width = recv.data[1].l
348            height = ret.h
349            baseline = ret.l
350        void write (unsigned num, unsigned base = 10):
351            char const *encode = "0123456789abcdef"
352            unsigned digits = 1
353            unsigned power = 1
354            while power <= num / base:
355                power *= base
356                ++digits
357            for unsigned i = 0; i < digits; ++i:
358                unsigned d = num / power
359                write (encode[d])
360                num -= d * power
361                power /= base
362        #ifndef __NATIVE__
363        void printf (char const *f, ...):
364            unsigned *last = (unsigned *)&f
365            while *f:
366                if *f == '\r':
367                    at (0, 0, false, true)
368                else if *f == '\n':
369                    at (0, 16, false, true)
370                else if *f == '%':
371                    ++f
372                    switch *f:
373                        case '%':
374                            write ('%')
375                            break
376                        case 'd':
377                            ++last
378                            write (*last)
379                            break
380                        case 'x':
381                            ++last
382                            write (*last, 0x10)
383                            break
384                        case 's':
385                            ++last
386                            write ((char *)*last)
387                            break
388                        case 'c':
389                            ++last
390                            write ((char)*last)
391                            break
392                        default:
393                            panic (*f, "invalid code character in dbg format string")
394                else:
395                    write (*f)
396                ++f
397        #endif
398
399    // Numerical setting, such as a display backlight.
400    struct Setting : public Device:
401        Setting (Cap c = Cap ()) : Device (c):
402        enum request:
403            SET = Font::ID
404            GET_RANGE
405            ID
406        // Set a new value.
407        void set (unsigned value):
408            call (CAP_MASTER_DIRECT | SET, value)
409        // Get the maximum value for this setting. Using a higher value with SET gives undefined results.
410        unsigned get_range ():
411            return call (CAP_MASTER_DIRECT | GET_RANGE).l
412
413    // File system interface.
414    // filesystem-related interfaces: directory, stream, seekable.
415    // Normal files implement stream and/or seekable. Directories implement directory.
416    // Seekable is not a class, it is identical to [W]String.
417
418    // Directory interface.
419    struct _Directory : public Cap:
420        _Directory (Cap c = Cap ()) : Cap (c):
421        enum request:
422            GET_SIZE = Setting::ID
423            GET_NAME
424            GET_FILE_RO
425            GET_FILE_INFO
426            ID
427        // Get the number of entries in this directory.
428        Num get_size ():
429            return call (CAP_MASTER_DIRECT | GET_SIZE)
430        // Get the filename.
431        String get_name (Num idx):
432            icall (CAP_MASTER_DIRECT | GET_NAME, idx)
433            return get_arg ()
434        // Get the file.
435        Cap get_file_ro (Num idx):
436            icall (CAP_MASTER_DIRECT | GET_FILE_RO, idx)
437            return get_arg ()
438        // Get file info. TODO: define possible types.
439        Num get_file_info (Num idx, unsigned type):
440            return icall (Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
441    typedef Locker <_Directory> Directory
442
443    struct _WDirectory : public Directory:
444        _WDirectory (Cap c = Cap ()) : Directory (c):
445        enum request:
446            GET_FILE = _Directory::ID
447            CREATE_FILE
448            DELETE_FILE
449            ID
450        // Get the file.
451        Cap get_file (Num idx):
452            icall (CAP_MASTER_DIRECT | GET_FILE, idx)
453            return get_arg ()
454        // Create a new file. After this, any index may map to a different file.
455        Cap create_file (String name):
456            icall (CAP_MASTER_DIRECT | CREATE_FILE)
457            return get_arg ()
458        // Delete a file. After this, any index may map to a different file.
459        void delete_file (Num idx):
460            call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
461    typedef WLocker <_WDirectory> WDirectory
462
463    // Stream interface.
464    struct Stream : public Cap:
465        Stream (Cap c = Cap ()) : Cap (c):
466        enum request:
467            READ = _WDirectory::ID
468            WRITE
469            ID
470        // Try to read size bytes. Returns the number of bytes successfully read.
471        Num read (Num size, bool block):
472            return icall (Num (CAP_MASTER_DIRECT | READ, block), size)
473        // Try to write size bytes. Returns the number of bytes successfully written.
474        Num write (String s, Num size):
475            return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
476
477    struct UI : public Cap:
478        UI (Cap c = Cap ()) : Cap (c):
479        enum request:
480            GET_STATE = Stream::ID
481            EVENT
482            EXIT
483            ID
484        enum constant:
485            INPUT = 1 << 31
486        void get_state (Cap cap):
487            ocall (cap, CAP_MASTER_DIRECT | GET_STATE)
488        void event (unsigned code, Iris::Num value = 0):
489            call (Num (CAP_MASTER_DIRECT | EVENT, code), value)
490        void exit ():
491            call (CAP_MASTER_DIRECT | EXIT)
492    
493    struct RTC : public Cap:
494        RTC (Cap c = Cap ()) : Cap (c):
495        enum request:
496            SETUP = UI::ID
497            GET_TIME
498            SET_TIME
499            GET_ALARM
500            UNSET_ALARM
501            SET_ALARM
502            ID
503        void setup (unsigned hz, unsigned adjc):
504            call (CAP_MASTER_DIRECT | SETUP, Num (hz, adjc))
505        unsigned get_time ():
506            return call (CAP_MASTER_DIRECT | GET_TIME).l
507        unsigned set_time (unsigned time):
508            return call (CAP_MASTER_DIRECT | SET_TIME, time).l
509        unsigned get_alarm ():
510            return call (CAP_MASTER_DIRECT | GET_ALARM).l
511        unsigned unset_alarm ():
512            return call (CAP_MASTER_DIRECT | UNSET_ALARM).l
513        unsigned set_alarm (unsigned time, Cap cb):
514            return ocall (cb, CAP_MASTER_DIRECT | SET_ALARM, time).l
515
516// TODO.
517// Sound interface.
518// Usb interfaces (port, device).
519// Pointer interface. (Only movement; buttons follow keyboard interface.)
520// Network interface.
521// Camera interface.
522
523#endif
524

Archive Download this file

Branches:
master



interactive