Date:2010-04-30 23:13:49 (4 years 5 months ago)
Author:Bas Wijnen
Commit:12bfb320f773347a3eb5335bdecfed61dec8e6b7
Message:make things work with unfinished new startup procedure

Files: .gitignore (1 diff)
Makefile (1 diff)
alloc.ccp (13 diffs)
boot-programs/bootinit.ccp (1 diff)
boot-programs/crt0.ccp (4 diffs)
boot-programs/init.ccp (1 diff)
boot-programs/udc.ccp (11 diffs)
devices.hhp (1 diff)
init.config (1 diff)
invoke.ccp (27 diffs)
iris.hhp (8 diffs)
kernel.hhp (12 diffs)
memory.ccp (1 diff)
mips/arch.ccp (2 diffs)
mips/init.ccp (8 diffs)
mips/interrupts.ccp (9 diffs)
mips/nanonote/Makefile.arch (2 diffs)
mips/nanonote/jz4740.hhp (2 diffs)
mips/nanonote/server/usb-server.ccp (5 diffs)
mips/nanonote/threadlist.S (1 diff)
mips/trendtac/jz4730.hhp (2 diffs)
panic.ccp (3 diffs)
plan (1 diff)
schedule.ccp (2 diffs)
source/#buzzer.ccp (1 diff)
source/#gpio.ccp (1 diff)
source/#lcd.ccp (1 diff)
source/#nanonote-gpio.ccp (1 diff)
source/ball.ccp (1 diff)
source/bsquare.ccp (1 diff)
source/buzzer.ccp (1 diff)
source/crt0.ccp (6 diffs)
source/display-emu.ccp (1 diff)
source/display-emu2.ccp (1 diff)
source/elfrun.ccp (1 diff)
source/gpio.ccp (1 diff)
source/init.ccp (1 diff)
source/lcd.ccp (1 diff)
source/metronome.ccp (3 diffs)
source/nanonote-gpio.ccp (1 diff)
source/trendtac-gpio.ccp (1 diff)

Change Details

.gitignore
2121mips/nanonote/server/install-sh
2222mips/nanonote/server/missing
2323mips/nanonote/server/usb-server
24fs/
Makefile
5151    $(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
5252    $(OBJCOPY) -S $(OBJCOPYFLAGS) $@
5353
54fs/%: %
55    ln -s ../$< $@
56
5457clean:
5558    rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
5659
alloc.ccp
171171            ((kFree *)self->prev)->next = self->next
172172        else:
173173            frees = (kFree *)self->next
174        //kdebug ("freeing page: ")
175        //kdebug_num ((unsigned)self - SIZE)
176        //kdebug ("\n")
174177        pfree ((unsigned)self - SIZE)
175178
176179kPage *kMemory::alloc_page ():
...... 
292295    kMemory_arch_init (ret)
293296    return ret
294297
295void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr):
298void kCaps::set (unsigned index, kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr):
296299    if index >= size:
297300        kdebug ("size: ")
298301        kdebug_num (size)
...... 
300303        dpanic (index, "index too large for kCaps")
301304        return
302305    kCapability *c = &caps[index]
303    if (unsigned)target == 0x81fdc350:
304        kdebug ("setting cap ")
305        kdebug_num (index)
306        kdebug (" old target: ")
307        kdebug_num ((unsigned)c->target)
308306    c->target = target
309307    c->protected_data = pdata
310308    c->parent = parent
...... 
321319            c->sibling_next.reset ()
322320    if c->sibling_next.valid ():
323321        c->sibling_next->sibling_prev = kCapRef (this, index)
324    if (unsigned)target == 0x81fdc350:
325        kdebug (" done\n")
326322
327323void kCaps::clone (unsigned index, kCapRef source, bool copy):
328324    cap (index)->invalidate ()
...... 
341337void kMemory::free_page (kPage *page):
342338    if page->mapping != ~0:
343339        page->address_space->unmap (page)
344    if page->flags & Kernel::Page::PAYING:
340    page->forget ()
341    if page->flags & Iris::Page::PAYING:
345342        unuse ()
346    if page->frame:
347        pfree (page->frame)
348343    free_obj (page, (kPointer *)&pages)
349344
350345void kThread::unset_slot (unsigned s):
...... 
367362    for unsigned i = 0; i < thread->slots; ++i:
368363        thread->unset_slot (i)
369364    free_obj (thread, (void **)&threads)
365    if old_current == thread:
366        old_current = NULL
370367
371368void kMemory::free_message (kReceiver *owner, kMessage *message):
372369    for unsigned i = 0; i < 2; ++i:
...... 
382379    while receiver->messages:
383380        free_message (receiver, receiver->messages)
384381    free_obj (receiver, (void **)&receivers)
382    if receiver == reply_target:
383        reply_target = NULL
384        // Signal that it is correct to not reply here.
385        reply_protected.l = 1
385386
386387void kReceiver::orphan ():
387388    if prev_owned:
388389        prev_owned->next_owned = next_owned
389    else:
390    else if owner:
390391        owner->receivers = next_owned
391392    if next_owned:
392393        next_owned->prev_owned = prev_owned
...... 
404405void kCapability::invalidate ():
405406    if !target:
406407        return
408    //kdebug_num ((unsigned)this)
409    //kdebug ("\n")
407410    //kdebug_num ((unsigned)target)
408411    //kdebug (":")
409412    //kdebug_num ((unsigned)protected_data.l)
410413    //kdebug ("\n")
414    if (unsigned)this == dbg_code.h:
415        dpanic (0, "invalidating watched capability")
411416    if sibling_prev.valid ():
412417        sibling_prev->sibling_next = sibling_next
413418    else if parent.valid ():
...... 
429434        if !next:
430435            next = c->parent.deref ()
431436        c->target = NULL
437        if c->parent.valid ():
438            c->parent->children = c->sibling_next
432439        c->parent.reset ()
433440        c->children.reset ()
434441        c->sibling_prev.reset ()
...... 
492499
493500void kMemory::free_memory (kMemory *mem):
494501    while mem->pages:
495        free_page (mem->pages)
502        //kdebug ("freeing page ")
503        //kdebug_num ((unsigned)mem->pages)
504        //kdebug (", next = ")
505        //kdebug_num ((unsigned)mem->pages->next)
506        //kdebug ("\n")
507        mem->free_page (mem->pages)
496508    while mem->capses:
497        free_caps (mem->capses)
509        mem->free_caps (mem->capses)
498510    while mem->threads:
499        free_thread (mem->threads)
511        mem->free_thread (mem->threads)
500512    while mem->memories:
501        free_memory (mem->memories)
513        mem->free_memory (mem->memories)
502514    while mem->receivers:
503        free_receiver (mem->receivers)
515        mem->free_receiver (mem->receivers)
504516    while mem->lists:
505        free_list (mem->lists)
517        mem->free_list (mem->lists)
506518    while mem->listitems:
507        free_listitem (mem->listitems)
519        mem->free_listitem (mem->listitems)
508520    if mem->frees:
509521        panic (0, "kernel memory leak: memory still in use")
510522    free_obj (mem, (void **)&memories)
...... 
519531        share_next = NULL
520532    else:
521533        // If the page has a frame and should be freed, free it.
522        if !((flags ^ Kernel::Page::FRAME) & (Kernel::Page::PHYSICAL | Kernel::Page::FRAME)):
534        if !((flags ^ Iris::Page::FRAME) & (Iris::Page::PHYSICAL | Iris::Page::FRAME)):
523535            raw_pfree (frame)
524536    frame = 0
525    flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED)
537    flags &= ~(Iris::Page::FRAME | Iris::Page::SHARED | Iris::Page::PHYSICAL | Iris::Page::UNCACHED)
526538    kPage_arch_update_mapping (this)
527539
528540static void check_receiver (kReceiver *r, kCapRef cap, unsigned line):
...... 
546558            kdebug ("!= receiver\n")
547559            dpanic (line, "consistency bug in kernel capabilities")
548560    for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
561        if c->protected_data.value () != cap->protected_data.value () || c->target != cap->target:
562            dpanic (line, "capability db bug")
549563        check_receiver (r, c, line)
550564
551565void kReceiver::check (unsigned line):
...... 
556570    for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
557571        r->check (line)
558572    for kThread *t = threads; t; t = (kThread *)t->next:
559        if t->flags & Kernel::Thread::RUNNING && t->pc == 0:
573        if t->flags & Iris::Thread::RUNNING && t->pc == 0:
560574            kdebug_num ((unsigned)t)
561575            kdebug ("\n")
562576            panic (line, "pc is 0")
boot-programs/bootinit.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/bootinit.ccp: Bootstrapping code.
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#include "devices.hh"
20#include "iris.hh"
21#include <elf.h>
22
23#define ELFRUN_NAME "elfrun.elf"
24#define INIT_NAME "init.elf"
25#define NUM_SLOTS 8
26#define NUM_CAPS 32
27
28static unsigned _free
29extern unsigned _end
30
31void init_alloc ():
32    _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK
33
34char *alloc_space (unsigned pages):
35    unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
36    _free = ret + (pages << PAGE_BITS)
37    return (char *)ret
38
39void *operator new[] (unsigned size):
40    //kdebug ("new ")
41    void *ret = (void *)_free
42    size = (size + 3) & ~3
43    unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
44    if rest < size:
45        unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
46        for unsigned p = 0; p < pages; ++p:
47            Iris::Page page = Iris::my_memory.create_page ()
48            page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
49            Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS))
50            Iris::free_cap (page)
51    _free += size
52    //kdebug_num ((unsigned)ret)
53    //kdebug ("+")
54    //kdebug_num (size)
55    //kdebug ("\n")
56    return ret
57
58void *operator new (unsigned size):
59    return new char[size]
60
61static bool have_data_mem, have_fs_mem
62static Iris::Memory data_mem, fs_mem
63
64// Get the initial block device and filesystem.
65static Iris::Directory receive_devices ():
66    Iris::Caps data, fs
67    bool have_data = false, have_fs = false
68    Iris::Device fs_dev, data_dev
69    for unsigned i = 0; i < 2; ++i:
70        Iris::wait ()
71        if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE:
72            Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.")
73        switch Iris::recv.data[1].l:
74            case Iris::String::ID:
75                if have_data:
76                    Iris::panic (0, "duplicate device.")
77                data_dev = Iris::get_arg ()
78                Iris::recv.reply.invoke ()
79                have_data = true
80                break
81            case Iris::Filesystem::ID:
82                if have_fs:
83                    Iris::panic (0, "duplicate filesystem.")
84                fs_dev = Iris::get_arg ()
85                Iris::recv.reply.invoke ()
86                have_fs = true
87                break
88            default:
89                Iris::panic (Iris::recv.data[1].l, "unexpected device")
90    // Initialize the root file system.
91    data = data_dev.create_user (Iris::my_memory)
92    data_dev.use (data)
93    fs = fs_dev.create_user (Iris::my_memory)
94    fs_dev.use (fs)
95    Iris::Filesystem fs_cap = fs.get (0)
96    Iris::Directory root = fs_cap.use_device_ro (data.copy ())
97    have_data_mem = data_dev.call (0).l
98    if have_data_mem:
99        data_mem = Iris::get_arg ()
100    have_fs_mem = fs_dev.call (0).l
101    if have_fs_mem:
102        fs_mem = Iris::get_arg ()
103    Iris::free_cap (data)
104    Iris::free_cap (fs)
105    Iris::free_cap (fs_cap)
106    Iris::free_cap (data_dev)
107    Iris::free_cap (fs_dev)
108    return root
109
110static bool stringcmp (char const *s1, char const *s2, unsigned size):
111    for unsigned t = 0; t < size; ++t:
112        if s1[t] != s2[t]:
113            return false
114    return true
115
116static Iris::String find (Iris::Directory root, char const *name):
117    unsigned size = 0
118    while name[size]:
119        ++size
120    Iris::Num num_files = root.get_size ()
121    for Iris::Num i = 0; i.value () < num_files.value (); i = i.value () + 1:
122        Iris::String n = root.get_name (i)
123        char current_name[16]
124        n.get_chars (0, current_name)
125        Iris::free_cap (n)
126        if !stringcmp (current_name, name, size):
127            continue
128        // Found elfrun.
129        Iris::String ret = root.get_file_ro (i)
130        return ret
131    Iris::panic (0, "bootfile not found")
132
133static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent):
134    // Get the size.
135    Iris::Num size = data.get_size ()
136    if size.value () == 0:
137        Iris::panic (0, "elfrun is empty")
138    // Allocate a caps with all the pages.
139    unsigned pages = (size.value () + PAGE_SIZE - 1) >> PAGE_BITS
140    Iris::Caps pages_caps = Iris::my_memory.create_caps (pages)
141    unsigned slot = pages_caps.use ()
142    // Map them into the address space as well.
143    char *mapping = alloc_space (pages)
144    // Create a memory for the program.
145    Iris::Memory mem = parent_memory.create_memory ()
146    // Load the file into memory and map it.
147    for unsigned p = 0; p < pages; ++p:
148        //kdebug_num (p)
149        //kdebug ("/")
150        //kdebug_num (pages)
151        //kdebug ("\n")
152        Iris::set_recv_arg (Iris::Cap (slot, p))
153        Iris::my_memory.create_page ()
154        Iris::Page (slot, p).set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
155        data.get_page (p << PAGE_BITS, Iris::Cap (slot, p))
156        Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
157    Iris::Thread thread = mem.create_thread (NUM_SLOTS)
158    Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
159    for unsigned j = 0; j < SELFMAG; ++j:
160        if header->e_ident[j] != ELFMAG[j]:
161            Iris::panic (header->e_ident[j], "invalid ELF magic")
162            return
163    if header->e_ident[EI_CLASS] != ELFCLASS32:
164        kdebug ("invalid ELF class:")
165        kdebug_num (header->e_ident[EI_CLASS])
166        kdebug (" != ")
167        kdebug_num (ELFCLASS32)
168        kdebug ("\n")
169        Iris::panic (0)
170        return
171    if header->e_ident[EI_DATA] != ELFDATA2LSB:
172        Iris::panic (header->e_ident[EI_DATA], "invalid ELF data")
173    if header->e_ident[EI_VERSION] != EV_CURRENT:
174        Iris::panic (header->e_ident[EI_VERSION], "invalid ELF version")
175    if header->e_type != ET_EXEC:
176        Iris::panic (header->e_type, "invalid ELF type")
177    if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
178        Iris::panic (header->e_machine, "invalid ELF machine")
179    thread.set_pc (header->e_entry)
180    thread.set_sp (0x80000000)
181    for unsigned section = 0; section < header->e_shnum; ++section:
182        Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
183        if ~shdr->sh_flags & SHF_ALLOC:
184            continue
185        bool readonly = !(shdr->sh_flags & SHF_WRITE)
186        //bool executable = shdr->sh_flags & SHF_EXEC_INSTR
187        if shdr->sh_type != SHT_NOBITS:
188            unsigned file_offset = shdr->sh_offset >> PAGE_BITS
189            if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
190                Iris::panic (shdr->sh_size, "thread too large")
191                return
192            for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
193                unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
194                unsigned idx = file_offset + section_offset
195                Iris::Page page = mem.mapping ((void *)p)
196                if Iris::recv.data[0].l == Iris::NO_ERROR:
197                    // The address already has a mapping; assume that it is correct.
198                    Iris::free_cap (page)
199                    continue
200                Iris::free_cap (page)
201                page = mem.create_page ()
202                unsigned f
203                if readonly:
204                    f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY
205                else:
206                    f = Iris::Page::PAYING
207                page.set_flags (f, f)
208                Iris::Page (slot, idx).share (page, 0)
209                //kdebug ("mapping at ")
210                //kdebug_num (p)
211                //if readonly:
212                // kdebug (" (readonly)")
213                //kdebug ("\n")
214                if !mem.map (page, p):
215                    Iris::panic (0, "unable to map page")
216                    return
217                Iris::free_cap (page)
218        else:
219            if readonly:
220                Iris::panic (0, "unwritable bss section")
221                return
222            for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
223                Iris::Page page = mem.mapping ((void *)p)
224                if Iris::recv.data[0].l == Iris::NO_ERROR:
225                    // No error means there is a mapping.
226                    Iris::free_cap (page)
227                    for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
228                        if a >= shdr->sh_addr + shdr->sh_size:
229                            break
230                        if a < shdr->sh_addr:
231                            continue
232                        ((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
233                else:
234                    Iris::free_cap (page)
235                    page = mem.create_page ()
236                    if Iris::recv.data[0].l != Iris::NO_ERROR:
237                        Iris::panic (Iris::recv.data[0].l, "out of memory")
238                    if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME):
239                        Iris::panic (0, "out of memory")
240                    if !mem.map (page, p):
241                        Iris::panic (0, "unable to map bss page")
242                    Iris::free_cap (page)
243    for unsigned p = 0; p < pages; ++p:
244        Iris::my_memory.destroy (Iris::Page (slot, p))
245    Iris::my_memory.destroy (pages_caps)
246    Iris::free_slot (slot)
247    Iris::Page stackpage = mem.create_page ()
248    stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME)
249    if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
250        Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page")
251    Iris::free_cap (stackpage)
252    Iris::Caps caps = mem.create_caps (NUM_CAPS)
253    thread.use (caps, 0)
254    thread.set_info (Iris::Thread::A0, NUM_SLOTS)
255    thread.set_info (Iris::Thread::A1, NUM_CAPS)
256    Iris::Receiver receiver = mem.create_receiver ()
257    receiver.set_owner (thread.copy ())
258    Iris::Cap call = receiver.create_call_capability ()
259    caps.set (__caps_num, caps.copy ())
260    caps.set (__receiver_num, receiver.copy ())
261    caps.set (__thread_num, thread.copy ())
262    caps.set (__memory_num, mem.copy ())
263    caps.set (__call_num, call.copy ())
264    caps.set (__parent_num, parent)
265    thread.run ()
266    Iris::free_cap (receiver)
267    Iris::free_cap (thread)
268    Iris::free_cap (call)
269    Iris::free_cap (caps)
270
271Iris::Num start ():
272    // Wait for the debugging device to be active, in case there is one.
273    Iris::schedule ()
274    kdebug ("Starting bootinit\n")
275    init_alloc ()
276    Iris::Memory top_memory = Iris::get_top_memory ()
277    Iris::Directory root = receive_devices ()
278    root.lock_ro ()
279    Iris::String run_string = find (root, ELFRUN_NAME)
280    Iris::Cap parent_cap = Iris::my_receiver.create_capability (0)
281    run (run_string, top_memory, parent_cap)
282    Iris::wait ()
283    if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE || Iris::recv.data[1].l != Iris::Elfrun::ID:
284        Iris::panic (0, "elfrun doesn't provide correct capability")
285    Iris::Cap reply = Iris::get_reply ()
286    Iris::Device elfrun_dev = Iris::get_arg ()
287    Iris::my_caps.set (parent_cap.idx (), Iris::Cap (CAP_NONE))
288    Iris::free_cap (parent_cap)
289    reply.invoke ()
290    Iris::free_cap (reply)
291
292    parent_cap = Iris::my_receiver.create_capability (0)
293    Iris::Caps elfrun = elfrun_dev.create_user (Iris::my_memory)
294    elfrun_dev.use (elfrun)
295    Iris::Elfrun elfrun_cap = elfrun.get (0)
296    Iris::free_cap (elfrun)
297    Iris::String init_string = find (root, INIT_NAME)
298    Iris::Caps init_caps = elfrun_cap.run_string (top_memory.copy (), init_string.copy (), parent_cap.copy ())
299
300    Iris::Thread init = init_caps.get (__thread_num)
301    init.make_priv ()
302    init.run ()
303    Iris::free_cap (init)
304    Iris::free_cap (init_caps)
305
306    bool have_root = false
307    bool have_elfrun = false
308    while true:
309        Iris::wait ()
310        switch Iris::recv.data[0].l:
311            case Iris::Parent::GET_DEVICE:
312                switch Iris::recv.data[1].l:
313                    case Iris::Directory::ID:
314                        if have_root:
315                            Iris::panic (0, "Init requests root directory twice")
316                        Iris::recv.reply.invoke (0, 0, root.copy ())
317                        have_root = true
318                        break
319                    case Iris::Elfrun::ID:
320                        if have_elfrun:
321                            Iris::panic (0, "Init requests elfrun twice")
322                        Iris::recv.reply.invoke (0, 0, elfrun_cap.copy ())
323                        have_elfrun = true
324                        break
325                    default:
326                        Iris::panic (0, "Invalid device requested by init")
327                break
328            case Iris::Parent::INIT_DONE:
329                if Iris::recv.data[1].value () != 0:
330                    Iris::recv.reply.invoke ()
331                    break
332                // Special response: kill boot threads.
333                Iris::Cap reply = Iris::get_reply ()
334                root.unlock_ro ()
335                if have_data_mem:
336                    top_memory.destroy (data_mem)
337                if have_fs_mem:
338                    top_memory.destroy (fs_mem)
339                reply.invoke ()
340                Iris::free_cap (reply)
341                top_memory.destroy (Iris::my_memory)
342                Iris::panic (0, "bootinit should be destroyed")
343            default:
344                Iris::panic (Iris::recv.data[0].l, "invalid operation from init")
boot-programs/crt0.ccp
2929static list *__slot_admin, *__cap_admin
3030static list *__first_free_slot, *__first_free_cap
3131
32namespace Kernel:
32namespace Iris:
33    Caps my_caps
3334    Receiver my_receiver
3435    Thread my_thread
3536    Memory my_memory
...... 
7778        if !__first_free_slot:
7879            // Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
7980            kdebug ("out of slots!\n")
80            Kernel::panic (0)
81            Iris::panic (0)
8182            return ~0
8283        list *ret = __first_free_slot
8384        __first_free_slot = ret->next
...... 
9091        if !__first_free_cap:
9192            // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
9293            kdebug ("out of capabilities!\n")
93            Kernel::panic (0)
94            Iris::panic (0)
9495            return Cap (0, CAP_NONE)
9596        list *ret = __first_free_cap
9697        __first_free_cap = ret->next
...... 
106107        __cap_admin = cap_admin
107108        __first_free_slot = NULL
108109        for unsigned i = 1; i < __slots; ++i:
109            Kernel::free_slot (i)
110            Iris::free_slot (i)
110111        __first_free_cap = NULL
111        for unsigned i = 7; i < __caps; ++i:
112            Kernel::free_cap (Kernel::Cap (0, i))
113        Kernel::my_receiver = Kernel::Cap (0, __receiver_num)
114        Kernel::my_thread = Kernel::Cap (0, __thread_num)
115        Kernel::my_memory = Kernel::Cap (0, __memory_num)
116        Kernel::my_call = Kernel::Cap (0, __call_num)
117        Kernel::my_parent = Kernel::Cap (0, __parent_num)
118        Kernel::recv.reply = Kernel::alloc_cap ()
119        Kernel::recv.arg = Kernel::alloc_cap ()
120        Kernel::Num ret = start ()
121        Kernel::my_parent.exit (ret)
122        Kernel::my_memory.destroy (Kernel::my_thread)
112        for unsigned i = 6; i < __caps; ++i:
113            Iris::free_cap (Iris::Cap (0, i))
114        Iris::my_caps = Iris::Cap (0, __caps_num)
115        Iris::my_receiver = Iris::Cap (0, __receiver_num)
116        Iris::my_thread = Iris::Cap (0, __thread_num)
117        Iris::my_memory = Iris::Cap (0, __memory_num)
118        Iris::my_call = Iris::Cap (0, __call_num)
119        Iris::my_parent = Iris::Cap (0, __parent_num)
120        Iris::recv.reply = Iris::alloc_cap ()
121        Iris::recv.arg = Iris::alloc_cap ()
122        Iris::Num ret = start ()
123        Iris::my_parent.exit (ret)
124        Iris::my_memory.destroy (Iris::my_thread)
123125        // The program no longer exists. If it somehow does, generate an address fault.
124126        while true:
125127            *(volatile unsigned *)~0
boot-programs/init.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// bootstrap/init.ccp: Bootstrapping code.
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#include "devices.hh"
20#include "iris.hh"
21#include "keys.hh"
22#include <elf.h>
23
24#define NUM_SLOTS 8
25#define NUM_CAPS 32
26
27enum Cap_codes:
28    SYSREQ = 1 << 16
29    THREAD
30    KEYBOARD
31
32static unsigned _free
33extern unsigned _end
34
35void init_alloc ():
36    _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK
37
38char *alloc_space (unsigned pages):
39    unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
40    _free = ret + (pages << PAGE_BITS)
41    return (char *)ret
42
43void *operator new[] (unsigned size):
44    //kdebug ("new ")
45    void *ret = (void *)_free
46    size = (size + 3) & ~3
47    unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1)
48    if rest < size:
49        unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS
50        for unsigned p = 0; p < pages; ++p:
51            Kernel::Page page = Kernel::my_memory.create_page ()
52            page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
53            Kernel::my_memory.map (page, _free + rest + (p << PAGE_BITS))
54            Kernel::free_cap (page)
55    _free += size
56    //kdebug_num ((unsigned)ret)
57    //kdebug ("+")
58    //kdebug_num (size)
59    //kdebug ("\n")
60    return ret
61
62void *operator new (unsigned size):
63    return new char[size]
64
65struct file:
66    unsigned size
67    // Only the first 16 characters of the name are used, because that's much easier.
68    // This means that file names must be different in the first 16 characters if sort order matters.
69    char name[16]
70    String string
71
72static unsigned num_files
73static file *files
74static unsigned *index
75static Kernel::Memory top_memory
76static unsigned slot
77static unsigned max_pages
78static char *mapping
79static unsigned current_thread
80static Kernel::Caps terminals
81static unsigned terminal_slot
82static Kernel::Caps memories
83static unsigned memory_slot
84static unsigned *inuse
85
86// Get the initial block device and filesystem.
87static Directory receive_devices ():
88    Kernel::Caps data, fs
89    bool have_data = false, have_fs = false
90    Device fs_dev, data_dev
91    for unsigned i = 0; i < 2; ++i:
92        Kernel::wait ()
93        if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
94            Kernel::panic (Kernel::recv.data[0].l, "Invalid bootstrap request.")
95        switch Kernel::recv.data[1].l:
96            case String::ID:
97                if have_data:
98                    Kernel::panic (0, "duplicate device.")
99                data_dev = Kernel::get_arg ()
100                Kernel::recv.reply.invoke ()
101                have_data = true
102                break
103            case Filesystem::ID:
104                if have_fs:
105                    Kernel::panic (0, "duplicate filesystem.")
106                fs_dev = Kernel::get_arg ()
107                Kernel::recv.reply.invoke ()
108                have_fs = true
109                break
110            default:
111                Kernel::panic (Kernel::recv.data[1].l, "unexpected device")
112    // Initialize the root file system.
113    data = data_dev.create_user (Kernel::my_memory)
114    data_dev.use (data)
115    fs = fs_dev.create_user (Kernel::my_memory)
116    fs_dev.use (fs)
117    Filesystem fs_cap = fs.get (0)
118    Directory root = fs_cap.use_device_ro (data.copy ())
119    Kernel::free_cap (data)
120    Kernel::free_cap (fs)
121    Kernel::free_cap (fs_cap)
122    Kernel::free_cap (data_dev)
123    Kernel::free_cap (fs_dev)
124    return root
125
126// Make a list of all files.
127static void list_files (Directory root):
128    Kernel::Num fullsize = root.get_size ()
129    if fullsize.h != 0:
130        kdebug ("Too many files in bootstrap directory:")
131        kdebug_num (fullsize.h)
132        kdebug (":")
133        kdebug_num (fullsize.l)
134        kdebug ("\n")
135        Kernel::panic (0)
136    num_files = fullsize.l
137    files = new file[num_files]
138    Kernel::Caps caps = Kernel::my_memory.create_caps (num_files)
139    unsigned slot = Kernel::alloc_slot ()
140    caps.use (slot)
141    Kernel::free_cap (caps)
142    for unsigned i = 0; i < num_files; ++i:
143        String n = root.get_name (i)
144        n.get_chars (0, files[i].name)
145        Kernel::free_cap (n)
146        Kernel::set_recv_arg (Kernel::Cap (slot, i))
147        files[i].string = root.get_file_ro (i)
148        Kernel::Num fullsize = files[i].string.get_size ()
149        if fullsize.h != 0:
150            kdebug ("initial file size too large: ")
151            kdebug_num (fullsize.h)
152            kdebug (":")
153            kdebug_num (fullsize.l)
154            kdebug (".\n")
155            Kernel::panic (0)
156        files[i].size = fullsize.l
157        if max_pages < (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS:
158            max_pages = (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS
159
160// Sort the list of files.
161static bool is_less (file *f1, file *f2):
162    for unsigned i = 0; i < 16; ++i:
163        if f1->name[i] < f2->name[i]:
164            return true
165        if f1->name[i] > f2->name[i]:
166            return false
167    return false
168
169// Bubble sort.
170static void sort ():
171    index = new unsigned[num_files]
172    index[0] = 0
173    // Invariant: index[0...f-1] is sorted.
174    for unsigned f = 1; f < num_files; ++f:
175        // Bubble up until top. Test for less-than, because it wraps to maxunsigned.
176        unsigned i
177        // Invariant: index[0...f] \ index[i+1] is sorted and index[i+1...f] is sorted.
178        for i = f - 1; i < f; --i:
179            if is_less (&files[index[i]], &files[f]):
180                break
181            index[i + 1] = index[i]
182        index[i + 1] = f
183
184static void run (file *f, bool priv, int id):
185    Kernel::Memory mem = Kernel::Cap (memory_slot, id)
186    Kernel::set_recv_arg (mem)
187    top_memory.create_memory ()
188    unsigned num_pages = (f->size + PAGE_SIZE - 1) >> PAGE_BITS
189    for unsigned p = 0; p < num_pages; ++p:
190        //kdebug_num (p)
191        //kdebug ("/")
192        //kdebug_num (num_pages)
193        //kdebug ("\n")
194        Kernel::set_recv_arg (Kernel::Cap (slot, p))
195        Kernel::my_memory.create_page ()
196        Kernel::Page (slot, p).set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
197        f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p))
198        Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
199    Kernel::Thread thread = mem.create_thread (NUM_SLOTS)
200    if priv:
201        thread.make_priv ()
202    Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
203    for unsigned j = 0; j < SELFMAG; ++j:
204        if header->e_ident[j] != ELFMAG[j]:
205            Kernel::panic (header->e_ident[j], "invalid ELF magic")
206            return
207    if header->e_ident[EI_CLASS] != ELFCLASS32:
208        kdebug ("invalid ELF class:")
209        kdebug_num (header->e_ident[EI_CLASS])
210        kdebug (" != ")
211        kdebug_num (ELFCLASS32)
212        kdebug ("\n")
213        Kernel::panic (0)
214        return
215    if header->e_ident[EI_DATA] != ELFDATA2LSB:
216        Kernel::panic (header->e_ident[EI_DATA], "invalid ELF data")
217    if header->e_ident[EI_VERSION] != EV_CURRENT:
218        Kernel::panic (header->e_ident[EI_VERSION], "invalid ELF version")
219    if header->e_type != ET_EXEC:
220        Kernel::panic (header->e_type, "invalid ELF type")
221    if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
222        Kernel::panic (header->e_machine, "invalid ELF machine")
223    thread.set_pc (header->e_entry)
224    thread.set_sp (0x80000000)
225    for unsigned section = 0; section < header->e_shnum; ++section:
226        Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
227        if ~shdr->sh_flags & SHF_ALLOC:
228            continue
229        bool readonly = !(shdr->sh_flags & SHF_WRITE)
230        //bool executable = shdr->sh_flags & SHF_EXEC_INSTR
231        if shdr->sh_type != SHT_NOBITS:
232            unsigned file_offset = shdr->sh_offset >> PAGE_BITS
233            if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
234                Kernel::panic (shdr->sh_size, "thread too large")
235                return
236            for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
237                unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
238                unsigned idx = file_offset + section_offset
239                Kernel::Page page = mem.mapping ((void *)p)
240                if Kernel::recv.data[0].l == Kernel::NO_ERROR:
241                    // The address already has a mapping; assume that it is correct.
242                    Kernel::free_cap (page)
243                    continue
244                Kernel::free_cap (page)
245                page = mem.create_page ()
246                unsigned f
247                if readonly:
248                    f = Kernel::Page::PAYING | Kernel::Page::MAPPED_READONLY
249                else:
250                    f = Kernel::Page::PAYING
251                page.set_flags (f, f)
252                Kernel::Page (slot, idx).share (page, 0)
253                //kdebug ("mapping at ")
254                //kdebug_num (p)
255                //if readonly:
256                // kdebug (" (readonly)")
257                //kdebug ("\n")
258                if !mem.map (page, p):
259                    Kernel::panic (0, "unable to map page")
260                    return
261                Kernel::free_cap (page)
262        else:
263            if readonly:
264                Kernel::panic (0, "unwritable bss section")
265                return
266            for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
267                Kernel::Page page = mem.mapping ((void *)p)
268                if Kernel::recv.data[0].l == Kernel::NO_ERROR:
269                    // No error means there is a mapping.
270                    Kernel::free_cap (page)
271                    for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
272                        if a >= shdr->sh_addr + shdr->sh_size:
273                            break
274                        if a < shdr->sh_addr:
275                            continue
276                        ((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
277                else:
278                    Kernel::free_cap (page)
279                    page = mem.create_page ()
280                    if Kernel::recv.data[0].l != Kernel::NO_ERROR:
281                        Kernel::panic (Kernel::recv.data[0].l, "out of memory")
282                    if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME):
283                        Kernel::panic (0, "out of memory")
284                    if !mem.map (page, p):
285                        Kernel::panic (0, "unable to map bss page")
286                    Kernel::free_cap (page)
287    for unsigned p = 0; p < num_pages; ++p:
288        Kernel::my_memory.destroy (Kernel::Page (slot, p))
289    Kernel::Page stackpage = mem.create_page ()
290    stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
291    if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
292        Kernel::panic (Kernel::recv.data[0].l, "unable to map initial stack page")
293    Kernel::free_cap (stackpage)
294    Kernel::Caps caps = mem.create_caps (NUM_CAPS)
295    thread.use (caps, 0)
296    thread.set_info (Kernel::Thread::A0, NUM_SLOTS)
297    thread.set_info (Kernel::Thread::A1, NUM_CAPS)
298    Kernel::Receiver receiver = mem.create_receiver ()
299    receiver.set_owner (thread.copy ())
300    Kernel::Cap call = receiver.create_call_capability ()
301    Kernel::Cap parent = Kernel::my_receiver.create_capability (Kernel::Num (current_thread++, THREAD))
302    caps.set (__receiver_num, receiver.copy ())
303    caps.set (__thread_num, thread.copy ())
304    caps.set (__memory_num, mem.copy ())
305    caps.set (__call_num, call.copy ())
306    caps.set (__parent_num, parent.copy ())
307    thread.run ()
308    Kernel::free_cap (receiver)
309    Kernel::free_cap (thread)
310    Kernel::free_cap (call)
311    Kernel::free_cap (parent)
312    Kernel::free_cap (caps)
313
314static void kdebug_name (char const *t, file *f):
315    kdebug (t)
316    for unsigned j = 0; j < 16; ++j:
317        if f->name[j] != 0:
318            kdebug_char (f->name[j])
319    kdebug ("...")
320
321static Device sysreq_dev
322
323struct Dev:
324    static Dev *devs
325    static unsigned num_devs
326    Dev *next
327    unsigned code, idx, id
328    Device dev
329    static Dev *find (unsigned c, unsigned i):
330        for Dev *d = devs; d; d = d->next:
331            if d->code == c && d->idx == i:
332                return d
333        return NULL
334    static void add (unsigned c, unsigned i, Kernel::Cap cap):
335        if c == Keyboard::ID && i == 1:
336            sysreq_dev = cap
337            return
338        while find (c, i):
339            ++i
340        Dev *d = new Dev ()
341        d->next = devs
342        d->code = c
343        d->idx = i
344        d->dev = cap
345        devs = d
346        d->id = num_devs++
347    static void kdebug_list ():
348        for Dev *d = devs; d; d = d->next:
349            kdebug (">")
350            kdebug_num (d->code)
351            kdebug (":")
352            kdebug_num (d->idx)
353
354Dev *Dev::devs
355unsigned Dev::num_devs
356
357static void handle_init (unsigned id):
358    while true:
359        Kernel::wait ()
360        switch Kernel::recv.data[0].l:
361            case Parent::PROVIDE_DEVICE:
362                kdebug ("adding dev ")
363                kdebug_num (Kernel::recv.data[1].l)
364                kdebug (":")
365                kdebug_num (Kernel::recv.data[0].h)
366                kdebug (" as ")
367                kdebug_num (Dev::num_devs)
368                kdebug ("\n")
369                Kernel::Cap reply = Kernel::get_reply ()
370                Dev::add (Kernel::recv.data[1].l, Kernel::recv.data[0].h, Kernel::get_arg ())
371                reply.invoke ()
372                Kernel::free_cap (reply)
373                break
374            case Parent::INIT_DONE:
375                Kernel::Cap reply = Kernel::get_reply ()
376                memories.set (id + num_files, reply.copy ())
377                Kernel::free_cap (reply)
378                return
379            default:
380                kdebug ("unknown init request\n")
381                Kernel::panic (Kernel::recv.data[0].l)
382
383static void get_device ():
384    Kernel::Cap reply = Kernel::get_reply ()
385    unsigned id = Kernel::recv.protected_data.l
386    Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h)
387    if d:
388        if inuse[id * Dev::num_devs + d->id] > 0:
389            Kernel::panic (id, "requesting device twice")
390        kdebug ("giving dev ")
391        kdebug_num (Kernel::recv.data[1].l)
392        kdebug (":")
393        kdebug_num (Kernel::recv.data[0].h)
394        kdebug (" = ")
395        kdebug_num (d->id)
396        kdebug (" to ")
397        kdebug_num (id)
398        kdebug ("\n")
399        Kernel::Caps cap = d->dev.create_user (Kernel::Memory (memory_slot, id), 0, 0x15000)
400        Kernel::Caps (terminal_slot, id).set (d->id, cap.copy ())
401        for unsigned i = 0; i < num_files; ++i:
402            if inuse[i * Dev::num_devs + d->id] == 2:
403                inuse[i * Dev::num_devs + d->id] = 1
404        inuse[id * Dev::num_devs + d->id] = 2
405        d->dev.use (cap)
406        Kernel::Cap ret = cap.get (0)
407        reply.invoke (0, 0, ret.copy ())
408        Kernel::free_cap (ret)
409        Kernel::free_cap (cap)
410    else:
411        kdebug ("device not found: ")
412        kdebug_num (Kernel::recv.data[1].l)
413        kdebug (":")
414        kdebug_num (Kernel::recv.data[0].h)
415        Dev::kdebug_list ()
416        kdebug ("\n")
417        reply.invoke (~0, ~0)
418        Kernel::panic (0)
419    Kernel::free_cap (reply)
420
421static void draw_ball ():
422    int const r = 50
423    for int y = -r; y < r; ++y:
424        for int x = -r; x < r; ++x:
425            if x * x + y * y > r * r:
426                ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0x000000
427            else:
428                ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0x3f30ff
429
430static void draw_square ():
431    int const r = 50
432    for int y = -r; y < r; ++y:
433        for int x = -r; x < r; ++x:
434            ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0xffff00
435
436Kernel::Num start ():
437    // Wait for the debugging device to be active, in case there is one.
438    Kernel::schedule ()
439    Dev::devs = NULL
440    Dev::num_devs = 0
441    init_alloc ()
442    top_memory = Kernel::get_top_memory ()
443    Directory root = receive_devices ()
444    root.lock_ro ()
445    list_files (root)
446    sort ()
447    Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages)
448    slot = caps.use ()
449    mapping = alloc_space (max_pages)
450    terminals = Kernel::my_memory.create_caps (num_files)
451    terminal_slot = terminals.use ()
452    // Two times, because it holds the memory and the init_done reply for each task.
453    memories = Kernel::my_memory.create_caps (num_files * 2)
454    memory_slot = memories.use ()
455    for unsigned i = 0; i < num_files; ++i:
456        kdebug_name ("loading ", &files[index[i]])
457        run (&files[index[i]], files[index[i]].name[0] == '#', i)
458        kdebug ("running\n")
459        handle_init (i)
460    inuse = new unsigned[num_files * Dev::num_devs]
461    for unsigned f = 0; f < num_files; ++f:
462        for unsigned d = 0; d < Dev::num_devs; ++d:
463            inuse[f * Dev::num_devs + d] = 0
464    // Notify all programs that they may start.
465    for unsigned i = 0; i < num_files; ++i:
466        Kernel::Cap (memory_slot, i + num_files).invoke ()
467    // create terminals.
468    for unsigned i = 0; i < num_files; ++i:
469        Kernel::Caps term (terminal_slot, i)
470        Kernel::Memory mem (memory_slot, i)
471        Kernel::set_recv_arg (term)
472        mem.create_caps (Dev::num_devs)
473    // set up system request.
474    Kernel::Caps sysreq_caps = sysreq_dev.create_user (Kernel::my_memory)
475    sysreq_dev.use (sysreq_caps)
476    Keyboard sysreq = sysreq_caps.get (0)
477    Kernel::free_cap (sysreq_dev)
478    Kernel::free_cap (sysreq_caps)
479    Kernel::Cap cap = Kernel::my_receiver.create_capability (Kernel::Num (0, SYSREQ))
480    sysreq.set_cb (cap.copy ())
481    Kernel::free_cap (sysreq)
482    Kernel::free_cap (cap)
483    // set up own capabilities.
484    Dev *display_dev = Dev::find (Display::ID, 0)
485    if !display_dev:
486        Kernel::panic (0, "no display")
487    Kernel::Caps display_caps = display_dev->dev.create_user (Kernel::my_memory, 0, 0x15000)
488    Display display = display_caps.get (0)
489    draw_ball ()
490    Dev *keyboard_dev = Dev::find (Keyboard::ID, 0)
491    if !keyboard_dev:
492        Kernel::panic (0, "no keyboard")
493    Kernel::Caps keyboard_caps = keyboard_dev->dev.create_user (Kernel::my_memory, 0, 0x15000)
494    Keyboard keyboard = keyboard_caps.get (0)
495    kdebug ("init done\n")
496    root.unlock_ro ()
497    Kernel::free_slot (slot)
498    Kernel::my_memory.destroy (caps)
499    Dev **waiter = new Dev *[num_files]
500    Kernel::Cap keyboard_cb = Kernel::my_receiver.create_capability (Kernel::Num (0, KEYBOARD))
501    bool in_system = false
502    while true:
503        Kernel::wait ()
504        switch Kernel::recv.protected_data.h:
505            case SYSREQ:
506                // System request.
507                if Kernel::recv.data[0].l & Keyboard::RELEASE:
508                    continue
509                keyboard_dev->dev.use (keyboard_caps)
510                display_dev->dev.use (display_caps)
511                keyboard.set_cb (keyboard_cb)
512                in_system = true
513                continue
514            case THREAD:
515                // Request for something from a child thread.
516                switch Kernel::recv.data[0].l:
517                    case Parent::INIT_DONE:
518                        Kernel::panic (Kernel::recv.protected_data.l, "double init_done")
519                    case Parent::PROVIDE_DEVICE:
520                        Kernel::panic (Kernel::recv.protected_data.l, "too late now for provide")
521                    case Parent::GET_DEVICE:
522                        get_device ()
523                        break
524                    case Parent::WAIT:
525                        unsigned id = Kernel::recv.protected_data.l
526                        Dev *dev = Dev::find (Kernel::recv.data[1].l, 0)
527                        if id >= num_files:
528                            Kernel::panic (0, "invalid id")
529                        if !dev:
530                            Kernel::panic (0, "invalid dev")
531                        switch inuse[id * Dev::num_devs + dev->id]:
532                            case 0:
533                                Kernel::panic (0, "waiting for non-owned device")
534                            case 2:
535                                if !in_system:
536                                    Kernel::recv.reply.invoke ()
537                                    break
538                                // fall through.
539                            case 1:
540                                Kernel::Cap reply = Kernel::get_reply ()
541                                memories.set (id + num_files, reply.copy ())
542                                Kernel::free_cap (reply)
543                                waiter[id] = dev
544                                break
545                        break
546                    case Parent::EXIT:
547                        Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported")
548                    default:
549                        Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child")
550                break
551            case KEYBOARD:
552                if !in_system:
553                    break
554                if Kernel::recv.data[0].l == (Key::ENTER | Keyboard::RELEASE):
555                    for Dev *d = Dev::devs; d; d = d->next:
556                        if d->idx != 0:
557                            continue
558                        for unsigned i = 0; i < num_files; ++i:
559                            if inuse[i * Dev::num_devs + d->id] == 2:
560                                Kernel::Cap c = Kernel::Caps (terminal_slot, i).get (d->id)
561                                d->dev.use (c)
562                                Kernel::free_cap (c)
563                                if waiter[i] == d:
564                                    Kernel::Cap (memory_slot, i + num_files).invoke ()
565                                    waiter[i] = NULL
566                    in_system = false
567                    break
568                if Kernel::recv.data[0].l & Keyboard::RELEASE:
569                    continue
570                unsigned which = 0
571                switch Kernel::recv.data[0].l:
572                    case Key::VOLUME_DOWN:
573                        // Set ball.
574                        draw_ball ()
575                        which = 2
576                        break
577                    case Key::VOLUME_UP:
578                        // Set square.
579                        draw_square ()
580                        which = 1
581                        break
582                if which != 0:
583                    for Dev *d = Dev::devs; d; d = d->next:
584                        if d->code != Display::ID || d->idx != 0:
585                            continue
586                        for unsigned f = 0; f < num_files; ++f:
587                            if inuse[f * Dev::num_devs + d->id] == 0:
588                                continue
589                            inuse[f * Dev::num_devs + d->id] = (--which ? 2 : 1)
590                break
591            default:
592                Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request")
boot-programs/udc.ccp
162162    char log_buffer[1000]
163163    unsigned log_buffer_size
164164    unsigned log_buffer_start
165    Kernel::Cap caller, caller_arg
165    Iris::Cap caller, caller_arg
166166    bool have_caller
167167    unsigned *page
168168    unsigned *p
169    Kernel::Page buffer_page
169    Iris::Page buffer_page
170170    public:
171171    void init ()
172172    void log (unsigned c)
173173    void interrupt (unsigned cmd)
174    void send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg)
174    void send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg)
175175
176176Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
177177Udc::my_config Udc::config_descriptor = {
...... 
217217    // Normally a normal new page should be allocated here, but new isn't implemented at this point.
218218    page = (unsigned *)LCD_FRAMEBUFFER_BASE
219219    p = page
220    buffer_page = Kernel::my_memory.create_page ()
221    buffer_page.set_flags (Kernel::Page::FRAME | Kernel::Page::PAYING, Kernel::Page::FRAME | Kernel::Page::PAYING)
222    Kernel::my_memory.map (buffer_page, (unsigned)page)
220    buffer_page = Iris::my_memory.create_page ()
221    buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING, Iris::Page::FRAME | Iris::Page::PAYING)
222    Iris::my_memory.map (buffer_page, (unsigned)page)
223223
224224    // Disconnect from the bus and don't try to get high-speed.
225225    UDC_POWER = 0
...... 
242242    UDC_INTROUTE = 1 << 1
243243    // Wait a while.
244244    for unsigned w = 0; w < 10000; ++w:
245        Kernel::schedule ()
245        Iris::schedule ()
246246    // Connect to the host.
247247    UDC_POWER = UDC_POWER_SOFTCONN
248248
249249bool Udc::vendor (Setup *s, unsigned cmd):
250250    if !(s->request_type & 0x80):
251251        kdebug ("data to device without size\n")
252        Kernel::panic (0)
252        Iris::panic (0)
253253        return true
254254    if s->request == 10:
255255        static unsigned b[2]
...... 
258258        if cmd_code != ~0:
259259            b[0] = cmd_code
260260            b[1] = cmd_arg
261            if cmd_code == Directory::LOCK_RO || cmd_code == Directory::UNLOCK_RO:
261            if cmd_code == Iris::Directory::LOCK_RO || cmd_code == Iris::Directory::UNLOCK_RO:
262262                caller.invoke ()
263                Kernel::free_cap (caller)
264                Kernel::free_cap (caller_arg)
263                Iris::free_cap (caller)
264                Iris::free_cap (caller_arg)
265265                have_caller = false
266266                //kdebug ("(un)lock response\n")
267267            cmd_code = ~0
...... 
283283    state = TX
284284    return true
285285
286void Udc::send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg):
286void Udc::send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg):
287287    if cmd_code != ~0:
288288        kdebug ("new code sent while old one wasn't finished.\n")
289        Kernel::panic (0)
289        Iris::panic (0)
290290    cmd_code = code
291291    cmd_arg = narg
292292    caller = reply
...... 
404404    switch state:
405405        case IDLE:
406406            if rebooting:
407                Kernel::reboot ()
407                Iris::reboot ()
408408            if !(csr & UDC_CSR0_OUTPKTRDY):
409409                return
410410            union { unsigned d[2]; Setup s; } packet
...... 
439439        case RX:
440440            // The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
441441            switch rx_request & 0xff:
442                case Directory::GET_SIZE & 0xff:
442                case Iris::Directory::GET_SIZE & 0xff:
443443                    if !have_caller:
444444                        kdebug ("received dir size from server without a caller waiting\n")
445                        Kernel::panic (0)
445                        Iris::panic (0)
446446                    unsigned size_l = UDC_FIFO (0)
447447                    unsigned size_h = UDC_FIFO (0)
448                    caller.invoke (Kernel::Num (size_l, size_h))
449                    Kernel::free_cap (caller)
450                    Kernel::free_cap (caller_arg)
448                    caller.invoke (Iris::Num (size_l, size_h))
449                    Iris::free_cap (caller)
450                    Iris::free_cap (caller_arg)
451451                    have_caller = false
452452                    //kdebug ("get_size response\n")
453453                    break
454                case Directory::GET_NAME & 0xff:
454                case Iris::Directory::GET_NAME & 0xff:
455455                    if !have_caller:
456456                        kdebug ("received filename from server without a caller waiting\n")
457                        Kernel::panic (0)
457                        Iris::panic (0)
458458                    unsigned n[4]
459459                    for unsigned i = 0; i < 4; ++i:
460460                        n[i] = UDC_FIFO (0)
461                    caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
462                    Kernel::free_cap (caller)
463                    Kernel::free_cap (caller_arg)
461                    caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
462                    Iris::free_cap (caller)
463                    Iris::free_cap (caller_arg)
464464                    //kdebug ("get_name response\n")
465465                    have_caller = false
466466                    break
467                case ::String::GET_SIZE & 0xff:
467                case Iris::String::GET_SIZE & 0xff:
468468                    if !have_caller:
469469                        kdebug ("received string size from server without a caller waiting\n")
470                        Kernel::panic (0)
470                        Iris::panic (0)
471471                    unsigned size_l = UDC_FIFO (0)
472472                    unsigned size_h = UDC_FIFO (0)
473                    caller.invoke (Kernel::Num (size_l, size_h))
474                    Kernel::free_cap (caller)
475                    Kernel::free_cap (caller_arg)
473                    caller.invoke (Iris::Num (size_l, size_h))
474                    Iris::free_cap (caller)
475                    Iris::free_cap (caller_arg)
476476                    have_caller = false
477477                    //kdebug ("get_filesize response\n")
478478                    break
479                case ::String::GET_CHARS & 0xff:
479                case Iris::String::GET_CHARS & 0xff:
480480                    if !have_caller:
481481                        kdebug ("received string char data from server without a caller waiting\n")
482                        Kernel::panic (0)
482                        Iris::panic (0)
483483                    unsigned n[4]
484484                    for unsigned i = 0; i < 4; ++i:
485485                        n[i] = UDC_FIFO (0)
486                    caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
487                    Kernel::free_cap (caller)
488                    Kernel::free_cap (caller_arg)
486                    caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
487                    Iris::free_cap (caller)
488                    Iris::free_cap (caller_arg)
489489                    have_caller = false
490490                    //kdebug ("get_chars response\n")
491491                    break
...... 
493493                    kdebug ("invalid vendor request: ")
494494                    kdebug_num (rx_request)
495495                    kdebug ("\n")
496                    Kernel::panic (0)
496                    Iris::panic (0)
497497            UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
498498            state = IDLE
499499            break
...... 
504504    UDC_INDEX = 1
505505    if !have_caller:
506506        kdebug ("received bulk data from server without a caller waiting\n")
507        Kernel::panic (0)
507        Iris::panic (0)
508508    unsigned size = UDC_OUTCOUNT
509509    unsigned csr = UDC_OUTCSR
510510    //kdebug ("handling bulk interrupt for ")
...... 
516516    for unsigned i = 0; i < size; i += 4:
517517        *p++ = UDC_FIFO (1)
518518    if p - page == PAGE_SIZE >> 2:
519        buffer_page.share (caller_arg, Kernel::Page::FORGET)
520        buffer_page.set_flags (Kernel::Page::FRAME, Kernel::Page::FRAME)
519        buffer_page.share (caller_arg, Iris::Page::FORGET)
520        buffer_page.set_flags (Iris::Page::FRAME, Iris::Page::FRAME)
521521        caller.invoke ()
522        Kernel::free_cap (caller)
523        Kernel::free_cap (caller_arg)
522        Iris::free_cap (caller)
523        Iris::free_cap (caller_arg)
524524        have_caller = false
525525        //kdebug ("bulk response\n")
526526        p = page
...... 
561561    FILE
562562    NAME
563563
564Kernel::Num start ():
564Iris::Num start ():
565565    map_udc ()
566566    map_gpio ()
567567    map_cpm ()
568568    Udc udc
569569
570    Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
570    Iris::Cap logcap = Iris::my_receiver.create_capability (LOG)
571571    __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
572572    udc.init ()
573    Kernel::register_interrupt (IRQ_UDC)
574    Device fs_dev = Kernel::my_receiver.create_capability (FS)
575    Device data_dev = Kernel::my_receiver.create_capability (DATA)
576    Kernel::my_parent.provide_device <Filesystem> (fs_dev.copy ())
577    Kernel::my_parent.provide_device <String> (data_dev.copy ())
578    Kernel::free_cap (fs_dev)
579    Kernel::free_cap (data_dev)
573    Iris::register_interrupt (IRQ_UDC)
574    Iris::Device fs_dev = Iris::my_receiver.create_capability (FS)
575    Iris::Device data_dev = Iris::my_receiver.create_capability (DATA)
576    Iris::my_parent.provide_device <Iris::Filesystem> (fs_dev.copy ())
577    Iris::my_parent.provide_device <Iris::String> (data_dev.copy ())
578    Iris::free_cap (fs_dev)
579    Iris::free_cap (data_dev)
580580    unsigned data_current_user = 0, fs_current_user = 0
581581    unsigned next_user
582582    unsigned state = 0
583583    while true:
584        Kernel::wait ()
585        Kernel::Cap reply = Kernel::get_reply ()
586        Kernel::Cap arg = Kernel::get_arg ()
587        switch Kernel::recv.protected_data.h:
584        Iris::wait ()
585        Iris::Cap reply = Iris::get_reply ()
586        Iris::Cap arg = Iris::get_arg ()
587        switch Iris::recv.protected_data.h:
588588            case 0:
589                switch Kernel::recv.protected_data.l:
589                switch Iris::recv.protected_data.l:
590590                    case IRQ_UDC:
591591                        udc.interrupt (state)
592                        Kernel::register_interrupt (IRQ_UDC)
592                        Iris::register_interrupt (IRQ_UDC)
593593                        break
594594                    case LOG:
595                        udc.log (Kernel::recv.data[0].l)
595                        udc.log (Iris::recv.data[0].l)
596596                        break
597597                    case FS:
598                        Device::host (FS, fs_current_user, reply, arg)
598                        Iris::Device::host (FS, fs_current_user, reply, arg)
599599                        continue
600600                    case DATA:
601                        Device::host (DATA, data_current_user, reply, arg)
601                        Iris::Device::host (DATA, data_current_user, reply, arg)
602602                        continue
603603                    default:
604604                        udc.log ('~')
605605                        char digit[] = "0123456789abcdef"
606606                        for unsigned i = 0; i < 8; ++i:
607                            udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
607                            udc.log (digit[(Iris::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
608608                        udc.log ('\n')
609609                        break
610610                break
611611            case DATA:
612                if data_current_user != Kernel::recv.protected_data.l:
612                if data_current_user != Iris::recv.protected_data.l:
613613                    break
614                switch Kernel::recv.data[0].l:
615                    case ::String::GET_SIZE:
616                    case ::String::GET_CHARS:
614                switch Iris::recv.data[0].l:
615                    case Iris::String::GET_SIZE:
616                    case Iris::String::GET_CHARS:
617617                        reply.invoke (0)
618                        Kernel::free_cap (reply)
619                        Kernel::free_cap (arg)
618                        Iris::free_cap (reply)
619                        Iris::free_cap (arg)
620620                        continue
621                    case ::String::GET_PAGE:
621                    case Iris::String::GET_PAGE:
622622                    default:
623                        reply.invoke (Kernel::ERR_INVALID_OPERATION)
624                        Kernel::free_cap (reply)
625                        Kernel::free_cap (arg)
623                        reply.invoke (Iris::ERR_INVALID_OPERATION)
624                        Iris::free_cap (reply)
625                        Iris::free_cap (arg)
626626                        continue
627627                break
628628            case FS:
629                if fs_current_user != Kernel::recv.protected_data.l:
629                if fs_current_user != Iris::recv.protected_data.l:
630630                    break
631                switch Kernel::recv.data[0].l:
632                    case Filesystem::USE_DEVICE:
633                    case Filesystem::USE_DEVICE_RO:
634                        Directory dir = Kernel::my_receiver.create_capability (Kernel::Num (0, DIRECTORY))
631                switch Iris::recv.data[0].l:
632                    case Iris::Filesystem::USE_DEVICE:
633                    case Iris::Filesystem::USE_DEVICE_RO:
634                        Iris::Directory dir = Iris::my_receiver.create_capability (Iris::Num (0, DIRECTORY))
635635                        reply.invoke (0, 0, dir.copy ())
636                        Kernel::free_cap (dir)
637                        Kernel::free_cap (reply)
638                        Kernel::free_cap (arg)
636                        Iris::free_cap (dir)
637                        Iris::free_cap (reply)
638                        Iris::free_cap (arg)
639639                        continue
640640                    default:
641                        reply.invoke (Kernel::ERR_INVALID_OPERATION)
642                        Kernel::free_cap (reply)
643                        Kernel::free_cap (arg)
641                        reply.invoke (Iris::ERR_INVALID_OPERATION)
642                        Iris::free_cap (reply)
643                        Iris::free_cap (arg)
644644                        continue
645645                break
646646            case DIRECTORY:
647                switch Kernel::recv.data[0].l:
648                    case Directory::GET_NAME:
649                        Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, NAME))
647                switch Iris::recv.data[0].l:
648                    case Iris::Directory::GET_NAME:
649                        Iris::Cap name = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, NAME))
650650                        reply.invoke (0, 0, name.copy ())
651                        Kernel::free_cap (name)
652                        Kernel::free_cap (reply)
653                        Kernel::free_cap (arg)
651                        Iris::free_cap (name)
652                        Iris::free_cap (reply)
653                        Iris::free_cap (arg)
654654                        continue
655                    case Directory::GET_SIZE:
656                    case Directory::LOCK_RO:
657                    case Directory::UNLOCK_RO:
658                        state = Kernel::recv.data[0].l
659                        if Kernel::recv.data[1].h != 0:
655                    case Iris::Directory::GET_SIZE:
656                    case Iris::Directory::LOCK_RO:
657                    case Iris::Directory::UNLOCK_RO:
658                        state = Iris::recv.data[0].l
659                        if Iris::recv.data[1].h != 0:
660660                            kdebug ("index out of supported range\n")
661                            Kernel::panic (0)
662                        udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l, reply, arg)
661                            Iris::panic (0)
662                        udc.send (Iris::recv.data[0].l, Iris::recv.data[1].l, reply, arg)
663663                        continue
664                    case Directory::GET_FILE_RO:
665                        if Kernel::recv.data[1].h != 0:
664                    case Iris::Directory::GET_FILE_RO:
665                        if Iris::recv.data[1].h != 0:
666666                            kdebug ("index out of supported range\n")
667                            Kernel::panic (0)
667                            Iris::panic (0)
668668                        //kdebug ("sending file\n")
669                        Kernel::Cap file = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, FILE))
669                        Iris::Cap file = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, FILE))
670670                        reply.invoke (0, 0, file.copy ())
671                        Kernel::free_cap (file)
672                        Kernel::free_cap (reply)
673                        Kernel::free_cap (arg)
671                        Iris::free_cap (file)
672                        Iris::free_cap (reply)
673                        Iris::free_cap (arg)
674674                        continue
675                    case Directory::GET_FILE_INFO:
675                    case Iris::Directory::GET_FILE_INFO:
676676                    default:
677                        reply.invoke (Kernel::ERR_INVALID_OPERATION)
678                        Kernel::free_cap (reply)
679                        Kernel::free_cap (arg)
677                        reply.invoke (Iris::ERR_INVALID_OPERATION)
678                        Iris::free_cap (reply)
679                        Iris::free_cap (arg)
680680                        continue
681681                break
682682            case FILE:
683                switch Kernel::recv.data[0].l:
684                    case ::String::GET_SIZE:
685                    case ::String::GET_CHARS:
686                    case ::String::GET_PAGE:
687                        udc.send (Kernel::recv.data[0].l | ((Kernel::recv.data[1].l >> PAGE_BITS) << 16), Kernel::recv.protected_data.l, reply, arg)
683                switch Iris::recv.data[0].l:
684                    case Iris::String::GET_SIZE:
685                    case Iris::String::GET_CHARS:
686                    case Iris::String::GET_PAGE:
687                        udc.send (Iris::recv.data[0].l | ((Iris::recv.data[1].l >> PAGE_BITS) << 16), Iris::recv.protected_data.l, reply, arg)
688688                        continue
689689                    default:
690                        reply.invoke (Kernel::ERR_INVALID_OPERATION)
691                        Kernel::free_cap (reply)
692                        Kernel::free_cap (arg)
690                        reply.invoke (Iris::ERR_INVALID_OPERATION)
691                        Iris::free_cap (reply)
692                        Iris::free_cap (arg)
693693                        continue
694694                break
695695            case NAME:
696                switch Kernel::recv.data[0].l:
697                    case ::String::GET_SIZE:
696                switch Iris::recv.data[0].l:
697                    case Iris::String::GET_SIZE:
698698                        reply.invoke (16)
699                        Kernel::free_cap (reply)
700                        Kernel::free_cap (arg)
699                        Iris::free_cap (reply)
700                        Iris::free_cap (arg)
701701                        continue
702                    case ::String::GET_CHARS:
703                        state = Kernel::recv.data[0].l
704                        udc.send (Directory::GET_NAME, Kernel::recv.protected_data.l, reply, arg)
702                    case Iris::String::GET_CHARS:
703                        state = Iris::recv.data[0].l
704                        udc.send (Iris::Directory::GET_NAME, Iris::recv.protected_data.l, reply, arg)
705705                        continue
706706                    default:
707                        reply.invoke (Kernel::ERR_INVALID_OPERATION)
708                        Kernel::free_cap (reply)
709                        Kernel::free_cap (arg)
707                        reply.invoke (Iris::ERR_INVALID_OPERATION)
708                        Iris::free_cap (reply)
709                        Iris::free_cap (arg)
710710                        continue
711711        reply.invoke ()
712        Kernel::free_cap (reply)
713        Kernel::free_cap (arg)
712        Iris::free_cap (reply)
713        Iris::free_cap (arg)
devices.hhp
2121
2222#include "iris.hh"
2323
24// List interface.
25template <typename _T> //
26struct List : public Kernel::Caps:
27    List (Kernel::Caps c = Kernel::Cap ()) : Kernel::Caps (c):
28    List <_T> create (unsigned size, Kernel::Memory mem = Kernel::my_memory):
29        return List <_T> (mem.create_caps (size))
30    void set (unsigned idx, _T value):
31        return Kernel::Caps::set (idx, value)
32    _T get (unsigned idx):
33        return _T (Kernel::Caps::get (idx))
24namespace Iris:
25    // Caplist interface.
26    template <typename _T> //
27    struct Caplist : public Iris::Caps:
28        Caplist (Iris::Caps c = Iris::Cap ()) : Iris::Caps (c):
29        Caplist <_T> create (unsigned size, Iris::Memory mem = Iris::my_memory):
30            return Caplist <_T> (mem.create_caps (size))
31        void set (unsigned idx, _T value):
32            return Iris::Caps::set (idx, value)
33        _T get (unsigned idx):
34            return _T (Iris::Caps::get (idx))
3435
35/// A block of data with a size and content. Any character can be stored in it (including '\0').
36struct String : public Kernel::Cap:
37    String (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
38    enum request:
39        GET_SIZE = 0x2001
40        GET_CHARS
41        GET_PAGE
42        ID
43    /// Get the size of the string.
44    Kernel::Num get_size ():
45        return call (CAP_MASTER_DIRECT | GET_SIZE)
46    /// Get exactly 16 characters. The index must be word-aligned.
47    char *get_chars (Kernel::Num idx, char buffer[16]):
48        call (CAP_MASTER_DIRECT | GET_CHARS, idx)
49        unsigned *b = (unsigned *)buffer
50        b[0] = Kernel::recv.data[0].l
51        b[1] = Kernel::recv.data[0].h
52        b[2] = Kernel::recv.data[1].l
53        b[3] = Kernel::recv.data[1].h
54        return buffer
55    /// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned.
56    Cap get_page (Kernel::Num idx, Kernel::Page ret = Kernel::my_memory.create_page ()):
57        ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx)
58        return ret
36    /// A block of data with a size and content. Any character can be stored in it (including '\0').
37    struct String : public Iris::Cap:
38        String (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
39        enum request:
40            GET_SIZE = 0x2001
41            GET_CHARS
42            GET_PAGE
43            ID
44        /// Get the size of the string.
45        Iris::Num get_size ():
46            return call (CAP_MASTER_DIRECT | GET_SIZE)
47        /// Get exactly 16 characters. The index must be word-aligned.
48        char *get_chars (Iris::Num idx, char buffer[16]):
49            call (CAP_MASTER_DIRECT | GET_CHARS, idx)
50            unsigned *b = (unsigned *)buffer
51            b[0] = Iris::recv.data[0].l
52            b[1] = Iris::recv.data[0].h
53            b[2] = Iris::recv.data[1].l
54            b[3] = Iris::recv.data[1].h
55            return buffer
56        /// Helper function for get_page.
57        static Iris::Page _create_paying_page ():
58            Iris::Page ret = Iris::my_memory.create_page ()
59            ret.set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
60            return ret
61        /// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned.
62        Cap get_page (Iris::Num idx, Iris::Page ret = _create_paying_page ()):
63            ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx)
64            return ret
5965
60/// A writable String.
61struct WString : public String:
62    WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
63    enum request:
64        TRUNCATE = String::ID
65        SET_CHARS
66        SET_PAGE
67        ID
68    /// Set the size of the string. Strings may have a limit to this setting.
69    void truncate (Kernel::Num size):
70        call (CAP_MASTER_DIRECT | TRUNCATE, size)
71    /// Set exactly 4 characters. The index must be word-aligned.
72    void set_chars (Kernel::Num idx, char buffer[4]):
73        call (Kernel::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
74    /// Overwrite a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. The caller may lose the frame in the transaction.
75    void set_page (Kernel::Num idx, Kernel::Page page):
76        ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
66    /// A writable String.
67    struct WString : public String:
68        WString (Iris::Cap c = Iris::Cap ()) : String (c):
69        enum request:
70            TRUNCATE = String::ID
71            SET_CHARS
72            SET_PAGE
73            ID
74        /// Set the size of the string. Strings may have a limit to this setting.
75        void truncate (Iris::Num size):
76            call (CAP_MASTER_DIRECT | TRUNCATE, size)
77        /// Set exactly 4 characters. The index must be word-aligned.
78        void set_chars (Iris::Num idx, char buffer[4]):
79            call (Iris::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
80        /// Overwrite a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. The caller may lose the frame in the transaction.
81        void set_page (Iris::Num idx, Iris::Page page):
82            ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
7783
78// Every process which wants to be switchable through a terminal must implement this interface.
79struct Device : public Kernel::Cap:
80    Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
81    enum request:
82        CREATE_USER = WString::ID
83        DESTROY_USER
84        UNUSE
85        USE
86        ID
87    // Create a new user for this device. It will not be the active user.
88    // The provided storage must allow object creation; no other actions may be used by the terminal.
89    Kernel::Cap create_user (Kernel::Memory storage, unsigned arg1 = 0, Kernel::Num arg2 = 0):
90        iocall (storage, Kernel::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2)
91        return Kernel::get_arg ()
92    // Destroy a user. It is made inactive if it was active.
93    void destroy_user (Kernel::Cap user):
94        ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
95    // Make user inactive.
96    void unuse (Kernel::Cap user):
97        ocall (user, CAP_MASTER_DIRECT | UNUSE)
98    // Make user active. It makes the previous active user inactive.
99    void use (Kernel::Cap user):
100        ocall (user, CAP_MASTER_DIRECT | USE)
101    // Convenience function for threads implementing a device.
102    static void host (unsigned id, unsigned &current_user, Kernel::Cap &reply, Kernel::Cap &arg, unsigned capssize = 3, unsigned (*create)(Kernel::Memory mem, Kernel::Caps caps) = NULL, void (*destroy)(unsigned id, Kernel::Caps caps) = NULL, void (*use)(unsigned id, Kernel::Caps caps) = NULL, void (*unuse)(unsigned id, Kernel::Caps caps) = NULL):
103        static unsigned last_user
104        switch Kernel::recv.data[0].l:
105            case Device::CREATE_USER:
106                Kernel::Memory mem (arg)
107                Kernel::Caps caps = mem.create_caps (capssize)
108                unsigned user
109                if create:
110                    user = create (mem, caps)
111                else:
112                    // Increment last_user; skip 0.
113                    // FIXME: if this really wraps, it is possible that two users share their id.
114                    if !++last_user:
115                        ++last_user
116                    user = last_user
117                Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (user, id))
118                caps.set (0, c.copy ())
119                caps.set (1, mem.copy ())
120                reply.invoke (0, 0, caps.copy ())
121                Kernel::free_cap (c)
122                Kernel::free_cap (caps)
123                Kernel::free_cap (reply)
124                Kernel::free_cap (arg)
125                break
126            case Device::DESTROY_USER:
127                Kernel::Caps caps (arg)
128                Kernel::Cap c = caps.get (0)
129                Kernel::Num user = Kernel::my_receiver.get_protected (c)
130                Kernel::free_cap (c)
131                if user.h != id:
132                    Kernel::panic (user.h, "invalid id for destroy")
133                // TODO: unuse.
134                if destroy:
135                    destroy (user.l, caps)
136                reply.invoke ()
137                Kernel::free_cap (reply)
138                Kernel::free_cap (arg)
139                break
140            case Device::USE:
141                Kernel::Caps caps (arg)
142                Kernel::Cap c = caps.get (0)
143                Kernel::Num user = Kernel::my_receiver.get_protected (c)
144                Kernel::free_cap (c)
145                if user.h != id:
146                    Kernel::panic (user.h, "invalid id for use")
147                // TODO: send unuse signal.
148                current_user = user.l
149                if use:
150                    use (user.l, caps)
151                c = caps.get (2)
152                c.invoke (1)
153                Kernel::free_cap (c)
154                reply.invoke ()
155                Kernel::free_cap (reply)
156                Kernel::free_cap (arg)
157                break
158            case Device::UNUSE:
159                Kernel::Caps caps (arg)
160                Kernel::Cap c = caps.get (0)
161                Kernel::Num user = Kernel::my_receiver.get_protected (c)
162                Kernel::free_cap (c)
163                if user.h != id:
164                    Kernel::panic (user.h, "invalid id for unuse")
165                if unuse:
166                    unuse (user.l, caps)
167                if user.l == current_user:
84    // Every process which wants to be switchable through a terminal must implement this interface.
85    struct Device : public Iris::Cap:
86        Device (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
87        enum request:
88            CREATE_USER = WString::ID
89            DESTROY_USER
90            UNUSE
91            USE
92            ID
93        // Create a new user for this device. It will not be the active user.
94        // The provided storage must allow object creation; no other actions may be used by the terminal.
95        Iris::Cap create_user (Iris::Memory storage, unsigned arg1 = 0, Iris::Num arg2 = 0):
96            iocall (storage, Iris::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2)
97            return Iris::get_arg ()
98        // Destroy a user. It is made inactive if it was active.
99        void destroy_user (Iris::Cap user):
100            ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
101        // Make user inactive.
102        void unuse (Iris::Cap user):
103            ocall (user, CAP_MASTER_DIRECT | UNUSE)
104        // Make user active. It makes the previous active user inactive.
105        void use (Iris::Cap user):
106            ocall (user, CAP_MASTER_DIRECT | USE)
107        // Convenience function for threads implementing a device.
108        static void host (unsigned id, unsigned &current_user, Iris::Cap &reply, Iris::Cap &arg, unsigned capssize = 3, unsigned (*create)(Iris::Memory mem, Iris::Caps caps) = NULL, void (*destroy)(unsigned id, Iris::Caps caps) = NULL, void (*use)(unsigned id, Iris::Caps caps) = NULL, void (*unuse)(unsigned id, Iris::Caps caps) = NULL):
109            static unsigned last_user
110            switch Iris::recv.data[0].l:
111                case Device::CREATE_USER:
112                    Iris::Memory mem (arg)
113                    Iris::Caps caps = mem.create_caps (capssize)
114                    unsigned user
115                    if create:
116                        user = create (mem, caps)
117                    else:
118                        // Increment last_user; skip 0.
119                        // FIXME: if this really wraps, it is possible that two users share their id.
120                        if !++last_user:
121                            ++last_user
122                        user = last_user
123                    Iris::Cap c = Iris::my_receiver.create_capability (Iris::Num (user, id))
124                    caps.set (0, c.copy ())
125                    caps.set (1, mem.copy ())
126                    reply.invoke (0, 0, caps.copy ())
127                    Iris::free_cap (c)
128                    Iris::free_cap (caps)
129                    Iris::free_cap (reply)
130                    Iris::free_cap (arg)
131                    break
132                case Device::DESTROY_USER:
133                    Iris::Caps caps (arg)
134                    Iris::Cap c = caps.get (0)
135                    Iris::Num user = Iris::my_receiver.get_protected (c)
136                    Iris::free_cap (c)
137                    if user.h != id:
138                        Iris::panic (user.h, "invalid id for destroy")
139                    // TODO: unuse.
140                    if destroy:
141                        destroy (user.l, caps)
142                    reply.invoke ()
143                    Iris::free_cap (reply)
144                    Iris::free_cap (arg)
145                    break
146                case Device::USE:
147                    Iris::Caps caps (arg)
148                    Iris::Cap c = caps.get (0)
149                    Iris::Num user = Iris::my_receiver.get_protected (c)
150                    Iris::free_cap (c)
151                    if user.h != id:
152                        Iris::panic (user.h, "invalid id for use")
153                    // TODO: send unuse signal.
154                    current_user = user.l
155                    if use:
156                        use (user.l, caps)
168157                    c = caps.get (2)
169                    c.invoke (0)
170                    Kernel::free_cap (c)
171                    current_user = 0
172                reply.invoke ()
173                Kernel::free_cap (reply)
174                Kernel::free_cap (arg)
175                break
158                    c.invoke (1)
159                    Iris::free_cap (c)
160                    reply.invoke ()
161                    Iris::free_cap (reply)
162                    Iris::free_cap (arg)
163                    break
164                case Device::UNUSE:
165                    Iris::Caps caps (arg)
166                    Iris::Cap c = caps.get (0)
167                    Iris::Num user = Iris::my_receiver.get_protected (c)
168                    Iris::free_cap (c)
169                    if user.h != id:
170                        Iris::panic (user.h, "invalid id for unuse")
171                    if unuse:
172                        unuse (user.l, caps)
173                    if user.l == current_user:
174                        c = caps.get (2)
175                        c.invoke (0)
176                        Iris::free_cap (c)
177                        current_user = 0
178                    reply.invoke ()
179                    Iris::free_cap (reply)
180                    Iris::free_cap (arg)
181                    break
182                default:
183                    kdebug ("invalid request\n")
184                    reply.invoke (~0)
185                    Iris::free_cap (reply)
186                    Iris::free_cap (arg)
187                    break
176188
177// Interface for talking to the parent process.
178struct Parent : public Kernel::Cap:
179    Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
180    enum request:
181        GET_DEVICE = Device::ID
182        PROVIDE_DEVICE
183        WAIT
184        GET_MEMORY
185        PROVIDE_MEMORY
186        INIT_DONE
187        EXIT
188        ID
189    // Get a device handle.
190    template <typename _T> _T get_device (unsigned num = 0):
191        icall (Kernel::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
192        return Kernel::get_arg ()
193    // Provide a device handle.
194    template <typename _T> void provide_device (Device dev, unsigned num = 0):
195        ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
196    // Wait until a device is used by the caller again.
197    template <typename _T> void wait (unsigned num = 0):
198        call (Kernel::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
199    // 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.
200    Kernel::Memory get_memory (Kernel::Cap target):
201        iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
202        return Kernel::get_arg ()
203    // 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).
204    Kernel::Cap provide_memory (unsigned limit):
205        icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
206        return Kernel::get_arg ()
207    // Signal the parent that the initialisation phase is over.
208    void init_done ():
209        call (CAP_MASTER_DIRECT | INIT_DONE)
210    // Exit the program. The parent does not reply, but kills the process.
211    void exit (Kernel::Num code):
212        call (CAP_MASTER_DIRECT | EXIT, code)
189    struct Elfrun : public Iris::Cap:
190        Elfrun (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
191        enum request:
192            RUN_STRING = Device::ID
193            RUN_CAPS
194            ID
195        enum arg_pos:
196            PARENT_MEMORY
197            DATA
198            PARENT
199        Iris::Caps run_string (Memory parent_memory, String data, Cap parent, unsigned num_slots = 8, unsigned num_caps = 32):
200            Iris::Caps caps = Iris::my_memory.create_caps (3)
201            caps.set (PARENT_MEMORY, parent_memory)
202            caps.set (DATA, data)
203            caps.set (PARENT, parent)
204            iocall (caps.copy (), CAP_MASTER_DIRECT | RUN_STRING, Iris::Num (num_slots, num_caps))
205            Iris::Caps ret = Iris::get_arg ()
206            Iris::my_memory.destroy (caps)
207            Iris::free_cap (caps)
208            return ret
209        Iris::Caps run_caps (Memory parent_memory, Caps data, Cap parent, unsigned pages, unsigned num_slots = 8, unsigned num_caps = 32):
210            Iris::Caps caps = Iris::my_memory.create_caps (3)
211            caps.set (PARENT_MEMORY, parent_memory)
212            caps.set (DATA, data)
213            caps.set (PARENT, parent)
214            iocall (caps.copy (), Iris::Num (CAP_MASTER_DIRECT | RUN_CAPS, pages), Iris::Num (num_slots, num_caps))
215            Iris::Caps ret = Iris::get_arg ()
216            Iris::my_memory.destroy (caps)
217            Iris::free_cap (caps)
218            return ret
213219
214// Keyboard interface.
215struct Keyboard : public Kernel::Cap:
216    Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
217    enum request:
218        SET_CB = Parent::ID
219        GET_NUM_KEYS
220        GET_KEYS
221        ID
222    // At event: the callback is called with a keycode. One bit defines if it's a press or release event.
223    enum constant:
224        RELEASE = 1 << 31
225    // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
226    void set_cb (Kernel::Cap cb):
227        ocall (cb, CAP_MASTER_DIRECT | SET_CB)
228    // Get the number of keys on the keyboard.
229    unsigned get_num_keys ():
230        return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
231    // Get the keycodes for the keys. The reply sends 4 key codes (32 bit each).
232    void get_keys (unsigned first):
233        call (CAP_MASTER_DIRECT | GET_KEYS, first)
220    // Interface for talking to the parent process.
221    struct Parent : public Iris::Cap:
222        Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
223        enum request:
224            GET_DEVICE = Elfrun::ID
225            PROVIDE_DEVICE
226            WAIT
227            GET_MEMORY
228            PROVIDE_MEMORY
229            INIT_DONE
230            EXIT
231            ID
232        // Get a device handle.
233        template <typename _T> _T get_device (unsigned num = 0):
234            icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
235            return Iris::get_arg ()
236        // Provide a device handle.
237        template <typename _T> void provide_device (Device dev, unsigned num = 0):
238            ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
239        // Wait until a device is used by the caller again.
240        template <typename _T> void wait (unsigned num = 0):
241            call (Iris::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
242        // 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.
243        Iris::Memory get_memory (Iris::Cap target):
244            iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
245            return Iris::get_arg ()
246        // 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).
247        Iris::Cap provide_memory (unsigned limit):
248            icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
249            return Iris::get_arg ()
250        // Signal the parent that the initialisation phase is over.
251        void init_done (Iris::Num stage = 0):
252            call (CAP_MASTER_DIRECT | INIT_DONE, stage)
253        // Exit the program. The parent does not reply, but kills the process.
254        void exit (Iris::Num code):
255            call (CAP_MASTER_DIRECT | EXIT, code)
234256
235// Buzzer interface.
236struct Buzzer : public Kernel::Cap:
237    Buzzer (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
238    enum request:
239        BEEP = Keyboard::ID
240        STOP
241        ID
242    // Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted.
243    void beep (unsigned freq, unsigned ms, unsigned volume, Kernel::Cap cb = Kernel::Cap ()):
244        ocall (cb, Kernel::Num (CAP_MASTER_DIRECT | BEEP, volume), Kernel::Num (freq, ms))
245    // Abort current beep, if any.
246    void stop ():
247        call (CAP_MASTER_DIRECT | STOP)
257    // Keyboard interface.
258    struct Keyboard : public Iris::Cap:
259        Keyboard (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
260        enum request:
261            SET_CB = Parent::ID
262            GET_NUM_KEYS
263            GET_KEYS
264            ID
265        // At event: the callback is called with a keycode. One bit defines if it's a press or release event.
266        enum constant:
267            RELEASE = 1 << 31
268        // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
269        void set_cb (Iris::Cap cb):
270            ocall (cb, CAP_MASTER_DIRECT | SET_CB)
271        // Get the number of keys on the keyboard.
272        unsigned get_num_keys ():
273            return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
274        // Get the keycodes for the keys. The reply sends 4 key codes (32 bit each).
275        void get_keys (unsigned first):
276            call (CAP_MASTER_DIRECT | GET_KEYS, first)
248277
249// Display interface.
250struct Display : public Kernel::Cap:
251    Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
252    enum request:
253        SET_EOF_CB = Buzzer::ID
254        MAP_FB
255        GET_INFO
256        ID
257    // Register an end-of-frame callback.
258    // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
259    void set_eof_cb (Kernel::Cap cb):
260        ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
261    // Map the framebuffer into memory.
262    void map_fb (unsigned address):
263        call (CAP_MASTER_DIRECT | MAP_FB, address)
264    // Get information about the display.
265    void get_info ():
266        // TODO: Interface is to be designed.
267        kdebug ("using undefined interface Display::get_info ()\n")
268        Kernel::panic (0)
278    // Buzzer interface.
279    struct Buzzer : public Iris::Cap:
280        Buzzer (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
281        enum request:
282            BEEP = Keyboard::ID
283            STOP
284            ID
285        // Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted.
286        void beep (unsigned freq, unsigned ms, unsigned volume, Iris::Cap cb = Iris::Cap ()):
287            ocall (cb, Iris::Num (CAP_MASTER_DIRECT | BEEP, volume), Iris::Num (freq, ms))
288        // Abort current beep, if any.
289        void stop ():
290            call (CAP_MASTER_DIRECT | STOP)
269291
270// Numerical setting, such as a display backlight.
271struct Setting : public Kernel::Cap:
272    Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
273    enum request:
274        SET = Display::ID
275        GET_RANGE
276        ID
277    // Set a new value.
278    void set (unsigned value):
279        call (CAP_MASTER_DIRECT | SET, value)
280    // Get the maximum value for this setting. Using a higher value with SET gives undefined results.
281    unsigned get_range ():
282        return call (CAP_MASTER_DIRECT | GET_RANGE).l
292    // Display interface.
293    struct Display : public Iris::Cap:
294        Display (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
295        enum request:
296            SET_EOF_CB = Buzzer::ID
297            MAP_FB
298            GET_INFO
299            ID
300        // Register an end-of-frame callback.
301        // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
302        void set_eof_cb (Iris::Cap cb):
303            ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
304        // Map the framebuffer into memory.
305        void map_fb (unsigned address):
306            call (CAP_MASTER_DIRECT | MAP_FB, address)
307        // Get information about the display.
308        void get_info ():
309            // TODO: Interface is to be designed.
310            Iris::panic (0, "using undefined interface Display::get_info ()")
283311
284// File system interface.
285// filesystem-related interfaces: directory, stream, seekable.
286// Normal files implement stream and/or seekable. Directories implement directory.
287// Seekable is not a class, it is identical to [W]String.
312    // Numerical setting, such as a display backlight.
313    struct Setting : public Iris::Cap:
314        Setting (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
315        enum request:
316            SET = Display::ID
317            GET_RANGE
318            ID
319        // Set a new value.
320        void set (unsigned value):
321            call (CAP_MASTER_DIRECT | SET, value)
322        // Get the maximum value for this setting. Using a higher value with SET gives undefined results.
323        unsigned get_range ():
324            return call (CAP_MASTER_DIRECT | GET_RANGE).l
288325
289// Directory interface.
290struct Directory : public Kernel::Cap:
291    Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
292    enum request:
293        GET_SIZE = Setting::ID
294        GET_NAME
295        GET_FILE_RO
296        GET_FILE_INFO
297        LOCK_RO
298        UNLOCK_RO
299        ID
300    // Get the number of entries in this directory.
301    Kernel::Num get_size ():
302        return call (CAP_MASTER_DIRECT | GET_SIZE)
303    // Get the filename.
304    String get_name (Kernel::Num idx):
305        icall (CAP_MASTER_DIRECT | GET_NAME, idx)
306        return Kernel::get_arg ()
307    // Get the file.
308    Kernel::Cap get_file_ro (Kernel::Num idx):
309        icall (CAP_MASTER_DIRECT | GET_FILE_RO, idx)
310        return Kernel::get_arg ()
311    // Get file info. TODO: define possible types.
312    Kernel::Num get_file_info (Kernel::Num idx, unsigned type):
313        return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
314    // Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present.
315    void lock_ro ():
316        call (CAP_MASTER_DIRECT | LOCK_RO)
317    // Release a read-only lock. Write operations can only be done when the directory is locked.
318    void unlock_ro ():
319        call (CAP_MASTER_DIRECT | UNLOCK_RO)
320struct WDirectory : public Directory:
321    WDirectory (Kernel::Cap c = Kernel::Cap ()) : Directory (c):
322    enum request:
323        GET_FILE = Directory::ID
324        CREATE_FILE
325        DELETE_FILE
326        LOCK
327        UNLOCK
328        ID
329    // Get the file.
330    Kernel::Cap get_file (Kernel::Num idx):
331        icall (CAP_MASTER_DIRECT | GET_FILE, idx)
332        return Kernel::get_arg ()
333    // Create a new file. After this, any index may map to a different file.
334    Kernel::Cap create_file (String name):
335        icall (CAP_MASTER_DIRECT | CREATE_FILE)
336        return Kernel::get_arg ()
337    // Delete a file. After this, any index may map to a different file.
338    void delete_file (Kernel::Num idx):
339        call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
340    // Lock the directory. Write operations can only be done when the directory is locked.
341    void lock ():
342        call (CAP_MASTER_DIRECT | LOCK)
343    // Unlock the directory. Write operations can only be done when the directory is locked.
344    void unlock ():
345        call (CAP_MASTER_DIRECT | UNLOCK)
326    // File system interface.
327    // filesystem-related interfaces: directory, stream, seekable.
328    // Normal files implement stream and/or seekable. Directories implement directory.
329    // Seekable is not a class, it is identical to [W]String.
346330
347// A filesystem turns a String into a Directory.
348struct Filesystem : public Device:
349    Filesystem (Kernel::Cap c = Kernel::Cap ()) : Device (c):
350    enum request:
351        USE_DEVICE = WDirectory::ID
352        USE_DEVICE_RO
353        ID
354    WDirectory use_device (WString dev):
355        ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE)
356        return Kernel::get_arg ()
357    Directory use_device_ro (String dev):
358        ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO)
359        return Kernel::get_arg ()
331    // Directory interface.
332    struct Directory : public Iris::Cap:
333        Directory (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
334        enum request:
335            GET_SIZE = Setting::ID
336            GET_NAME
337            GET_FILE_RO
338            GET_FILE_INFO
339            LOCK_RO
340            UNLOCK_RO
341            ID
342        // Get the number of entries in this directory.
343        Iris::Num get_size ():
344            return call (CAP_MASTER_DIRECT | GET_SIZE)
345        // Get the filename.
346        String get_name (Iris::Num idx):
347            icall (CAP_MASTER_DIRECT | GET_NAME, idx)
348            return Iris::get_arg ()
349        // Get the file.
350        Iris::Cap get_file_ro (Iris::Num idx):
351            icall (CAP_MASTER_DIRECT | GET_FILE_RO, idx)
352            return Iris::get_arg ()
353        // Get file info. TODO: define possible types.
354        Iris::Num get_file_info (Iris::Num idx, unsigned type):
355            return icall (Iris::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
356        // Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present.
357        void lock_ro ():
358            call (CAP_MASTER_DIRECT | LOCK_RO)
359        // Release a read-only lock. Write operations can only be done when the directory is locked.
360        void unlock_ro ():
361            call (CAP_MASTER_DIRECT | UNLOCK_RO)
362    struct WDirectory : public Directory:
363        WDirectory (Iris::Cap c = Iris::Cap ()) : Directory (c):
364        enum request:
365            GET_FILE = Directory::ID
366            CREATE_FILE
367            DELETE_FILE
368            LOCK
369            UNLOCK
370            ID
371        // Get the file.
372        Iris::Cap get_file (Iris::Num idx):
373            icall (CAP_MASTER_DIRECT | GET_FILE, idx)
374            return Iris::get_arg ()
375        // Create a new file. After this, any index may map to a different file.
376        Iris::Cap create_file (String name):
377            icall (CAP_MASTER_DIRECT | CREATE_FILE)
378            return Iris::get_arg ()
379        // Delete a file. After this, any index may map to a different file.
380        void delete_file (Iris::Num idx):
381            call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
382        // Lock the directory. Write operations can only be done when the directory is locked.
383        void lock ():
384            call (CAP_MASTER_DIRECT | LOCK)
385        // Unlock the directory. Write operations can only be done when the directory is locked.
386        void unlock ():
387            call (CAP_MASTER_DIRECT | UNLOCK)
360388
361// Stream interface.
362struct Stream : public Kernel::Cap:
363    Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
364    enum request:
365        READ = Filesystem::ID
366        WRITE
367        ID
368    // Try to read size bytes. Returns the number of bytes successfully read.
369    Kernel::Num read (Kernel::Num size, bool block):
370        return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, block), size)
371    // Try to write size bytes. Returns the number of bytes successfully written.
372    Kernel::Num write (String s, Kernel::Num size):
373        return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
389    // A filesystem turns a String into a Directory.
390    struct Filesystem : public Device:
391        Filesystem (Iris::Cap c = Iris::Cap ()) : Device (c):
392        enum request:
393            USE_DEVICE = WDirectory::ID
394            USE_DEVICE_RO
395            ID
396        WDirectory use_device (WString dev):
397            ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE)
398            return Iris::get_arg ()
399        Directory use_device_ro (String dev):
400            ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO)
401            return Iris::get_arg ()
374402
403    // Stream interface.
404    struct Stream : public Iris::Cap:
405        Stream (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
406        enum request:
407            READ = Filesystem::ID
408            WRITE
409            ID
410        // Try to read size bytes. Returns the number of bytes successfully read.
411        Iris::Num read (Iris::Num size, bool block):
412            return icall (Iris::Num (CAP_MASTER_DIRECT | READ, block), size)
413        // Try to write size bytes. Returns the number of bytes successfully written.
414        Iris::Num write (String s, Iris::Num size):
415            return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
375416
376417
377// Block device interface.
378struct Block_device : public WString:
379    Block_device (Kernel::Cap c = Kernel::Cap ()) : WString (c):
380    // TODO: to be designed.
418
419    // Block device interface.
420    struct Block_device : public WString:
421        Block_device (Iris::Cap c = Iris::Cap ()) : WString (c):
422        // TODO: to be designed.
381423
382424
383425// TODO.
init.config
1    # load <name> = '<filename>' load a file into memory. Don't use this after killbootthreads.
2    load session = "session.config"
3    load driver_lcd = "lcd.elf"
4    load driver_buzzer = "buzzer.elf"
5    load driver_gpio = "gpio.elf"
6# load driver_audio = "audio.elf"
7# load driver_udc = "udc.elf"
8# load driver_nand = "nand.elf"
9
10# load emu_lcd = "emu_display.elf"
11# load emu_buzzer = "emu_buzzer.elf"
12# load emu_keyboard = "emu_keyboard.elf"
13# load emu_audio = "emu_audio.elf"
14# load emu_udc = "emu_udc.elf"
15
16    # killbootthreads destroy bootinit, bootfs and bootstore.
17    killbootthreads
18
19    # receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
20    receive driver_lcd / Display = display
21    receive driver_lcd / Setting = display_bright
22    receive driver_buzzer / Buzzer = buzzer
23    receive driver_gpio / Keyboard , 0 = keyboard
24    receive driver_gpio / Keyboard , 1 = sysreq
25# receive driver_audio / Audio = audio
26# receive driver_udc / Udc = udc
27# receive driver_nand / WString = nand
28
29    # driver <name> run a previously loaded program priviledged.
30    driver driver_lcd
31    driver driver_buzzer
32    driver driver_gpio
33# driver driver_audio
34# driver driver_udc
35# driver driver_nand
36
37    # wait wait until all expected capabilities are received.
38    wait
39
40    # sysreq <cap> use a capability as the system request keyboard.
41    sysreq sysreq
42
43    # give <name> (<type> [, <index>]) = <cap> give this capability to this program when it requests it.
44# give emu_display (display) = display
45# give emu_display_bright (setting) = display_bright
46# give emu_buzzer (buzzer) = buzzer
47# give emu_keyboard (keyboard, 0) = keyboard
48# give emu_audio (audio) = audio
49# give emu_udc (udc) = udc
50
51    # run <name> run a previously loaded program (normally).
52# run emu_lcd
53# run emu_buzzer
54# run emu_keyboard
55# run emu_audio
56# run emu_udc
57
58    # include <name> include a loaded file as another config file.
59    include session
invoke.ccp
6060    kdebug (':')
6161    kdebug_num ((unsigned)old_current)
6262    kdebug ('/')
63    if code < Kernel::NUM_EXCEPTION_CODES:
64        kdebug (Kernel::exception_name[code])
63    if code < Iris::NUM_EXCEPTION_CODES:
64        kdebug (Iris::exception_name[code])
6565    else:
6666        kdebug ("invalid code:")
6767        kdebug_num (code)
...... 
7373    if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target:
7474        return
7575    kCapability::Context c
76    c.data[0] = Kernel::Num (code, data)
76    c.data[0] = Iris::Num (code, data)
7777    slot[0].caps->cap (0)->invoke (&c)
7878
7979// From user-provided, thus untrusted, data, find a capability.
...... 
128128    return true
129129
130130// Send a message to a receiver; try to deliver it immediately.
131bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c):
131bool kReceiver::send_message (Iris::Num protected_data, kCapability::Context *c):
132132    //log_message ("send_message", (unsigned)this, protected_data.l, c)
133133    if owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()):
134134        if protected_only:
...... 
161161    return true
162162
163163static kCapability::Context *context
164static kReceiver *reply_target
165static Kernel::Num reply_protected
166164
167static void reply_num (Kernel::Num num):
165static void reply_num (Iris::Num num):
168166    kCapability::Context c
169167    c.data[0] = num
170168    c.data[1] = 0
171169    if reply_target:
172170        reply_target->send_message (reply_protected, &c)
173    else:
171    else if reply_protected.l == 0:
174172        dpanic (0, "nothing to reply to")
173    else:
174        kdebug ("not replying, because receiver was destroyed in the operation\n")
175175
176176static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
177177    kCapability::Context c
178    c.data[0] = Kernel::Num (num1, num2)
178    c.data[0] = Iris::Num (num1, num2)
179179    c.data[1] = num3
180180    if reply_target:
181181        reply_target->send_message (reply_protected, &c)
182    else:
182    else if reply_protected.l == 0:
183183        dpanic (0, "nothing to reply to")
184    else:
185        kdebug ("not replying, because receiver was destroyed in the operation\n")
184186
185static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref, unsigned num = 0):
187static void reply_cap (unsigned target, Iris::Num protected_data, kCapRef *ref, unsigned num = 0):
186188    if !reply_target:
187        dpanic (0, "nothing to reply to")
189        if reply_protected.l == 0:
190            dpanic (0, "nothing to reply to")
191        else:
192            kdebug ("not replying, because receiver was destroyed in the operation\n")
188193        return
189194    replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
190195    kCapability::Context c
191196    c.arg = kCapRef (&replied_caps, 0)
192197    c.copy[1] = true
193    c.data[0] = Kernel::Num (num, 0)
198    c.data[0] = Iris::Num (num, 0)
194199    reply_target->send_message (reply_protected, &c)
195200    c.arg->invalidate ()
196201
197static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
202static void receiver_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
198203    kReceiver *receiver = (kReceiver *)protected_data.l
199204    switch cmd:
200        case Kernel::Receiver::SET_OWNER & REQUEST_MASK:
205        case Iris::Receiver::SET_OWNER & REQUEST_MASK:
201206            if !c->arg.valid ():
202                reply_num (Kernel::ERR_INVALID_ARGUMENT)
207                reply_num (Iris::ERR_INVALID_ARGUMENT)
203208                return
204209            unsigned cap = (unsigned)c->arg->target
205            if cap != (CAPTYPE_THREAD | CAP_MASTER) && cap != (CAPTYPE_THREAD | Kernel::Thread::SET_OWNER):
210            if cap != (CAPTYPE_THREAD | CAP_MASTER) && cap != (CAPTYPE_THREAD | Iris::Thread::SET_OWNER):
206211                // FIXME: This makes it impossible to use a fake kThread capability.
207212                return
208213            receiver->own ((kThread *)c->arg->protected_data.l)
209214            break
210        case Kernel::Receiver::CREATE_CAPABILITY & REQUEST_MASK:
215        case Iris::Receiver::CREATE_CAPABILITY & REQUEST_MASK:
211216            reply_cap ((unsigned)receiver, c->data[1], &receiver->capabilities)
212217            return
213        case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
214            reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Kernel::Receiver::CALL_ASYNC : Kernel::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
218        case Iris::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
219            reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Iris::Receiver::CALL_ASYNC : Iris::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
215220            return
216        case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
221        case Iris::Receiver::GET_PROTECTED & REQUEST_MASK:
217222            if !c->arg.valid () || c->arg->target != receiver:
218223                if !c->arg.valid ():
219224                    kdebug ("invalid arg\n")
...... 
226231                    kdebug_num ((unsigned)c->arg->protected_data.l)
227232                    kdebug ("\n")
228233                dpanic (0, "wrong argument for get_protected")
229                reply_num (Kernel::ERR_INVALID_ARGUMENT)
234                reply_num (Iris::ERR_INVALID_ARGUMENT)
230235                return
231236            reply_num (c->arg->protected_data)
232237            return
233        case Kernel::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK:
238        case Iris::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK:
234239            reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0)
235240            return
236        case Kernel::Receiver::SET_REPLY_PROTECTED_DATA & REQUEST_MASK:
241        case Iris::Receiver::SET_REPLY_PROTECTED_DATA & REQUEST_MASK:
237242            receiver->reply_protected_data = c->data[1]
238243            break
239        case Kernel::Receiver::GET_ALARM & REQUEST_MASK:
244        case Iris::Receiver::GET_ALARM & REQUEST_MASK:
240245            reply_num (receiver->alarm_count)
241246            return
242        case Kernel::Receiver::SET_ALARM & REQUEST_MASK:
243        case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
247        case Iris::Receiver::SET_ALARM & REQUEST_MASK:
248        case Iris::Receiver::ADD_ALARM & REQUEST_MASK:
244249            unsigned old = receiver->alarm_count
245            if cmd == (Kernel::Receiver::SET_ALARM & REQUEST_MASK):
250            if cmd == (Iris::Receiver::SET_ALARM & REQUEST_MASK):
246251                receiver->alarm_count = c->data[1].l
247252            else:
248253                receiver->alarm_count += c->data[1].l
...... 
267272            return
268273        default:
269274            dpanic (cmd, "invalid receiver operation")
270            reply_num (Kernel::ERR_INVALID_OPERATION)
275            reply_num (Iris::ERR_INVALID_OPERATION)
271276            return
272277    reply_num (0)
273278
274static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
279static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
275280    kMemory *mem = (kMemory *)protected_data.l
276281    switch cmd:
277        case Kernel::Memory::CREATE & REQUEST_MASK:
282        case Iris::Memory::CREATE & REQUEST_MASK:
278283            switch c->data[0].h:
279284                case CAPTYPE_RECEIVER:
280285                    kReceiver *ret = mem->alloc_receiver ()
...... 
282287                        reply_cap (CAPTYPE_RECEIVER | CAP_MASTER, (unsigned)ret, &ret->refs)
283288                    else:
284289                        dpanic (0x03311992, "out of memory creating receiver")
285                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
290                        reply_num (Iris::ERR_OUT_OF_MEMORY)
286291                    return
287292                case CAPTYPE_MEMORY:
288293                    kMemory *ret = mem->alloc_memory ()
...... 
290295                        reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)ret, &ret->refs)
291296                    else:
292297                        dpanic (0x13311992, "out of memory creating memory")
293                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
298                        reply_num (Iris::ERR_OUT_OF_MEMORY)
294299                    return
295300                case CAPTYPE_THREAD:
296301                    kThread *ret = mem->alloc_thread (c->data[1].l)
...... 
301306                        kdebug (")")
302307                    else:
303308                        dpanic (0x23311992, "out of memory creating thread")
304                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
309                        reply_num (Iris::ERR_OUT_OF_MEMORY)
305310                    return
306311                case CAPTYPE_PAGE:
307312                    kPage *ret = mem->alloc_page ()
...... 
309314                        reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
310315                    else:
311316                        dpanic (0x33311992, "out of memory creating page")
312                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
317                        reply_num (Iris::ERR_OUT_OF_MEMORY)
313318                    return
314319                case CAPTYPE_CAPS:
315320                    kCaps *ret = mem->alloc_caps (c->data[1].l)
...... 
317322                        reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)ret, &ret->refs)
318323                    else:
319324                        dpanic (0x43311992, "out of memory creating caps")
320                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
325                        reply_num (Iris::ERR_OUT_OF_MEMORY)
321326                    return
322327                default:
323328                    dpanic (0, "invalid create type")
324                    reply_num (Kernel::ERR_INVALID_ARGUMENT)
329                    reply_num (Iris::ERR_INVALID_ARGUMENT)
325330                    return
326331            break
327        case Kernel::Memory::DESTROY & REQUEST_MASK:
332        case Iris::Memory::DESTROY & REQUEST_MASK:
328333            if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || !c->arg->target || ((kObject *)c->arg->protected_data.l)->address_space != mem:
329                reply_num (Kernel::ERR_INVALID_ARGUMENT)
334                reply_num (Iris::ERR_INVALID_ARGUMENT)
330335                return
331336            switch (unsigned)c->arg->target & CAPTYPE_MASK:
332337                case CAPTYPE_RECEIVER:
...... 
348353                    panic (0x55228930, "invalid case")
349354                    return
350355            break
351        case Kernel::Memory::LIST & REQUEST_MASK:
356        case Iris::Memory::LIST & REQUEST_MASK:
352357            // TODO
353358            break
354        case Kernel::Memory::MAP & REQUEST_MASK:
359        case Iris::Memory::MAP & REQUEST_MASK:
355360            // FIXME: this should work for fake pages as well.
356361            if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || ((unsigned)c->arg->target & CAPTYPE_MASK) != CAPTYPE_PAGE:
357362                dpanic (0x22993341, "Trying to map non-page")
358                reply_num (Kernel::ERR_INVALID_ARGUMENT)
363                reply_num (Iris::ERR_INVALID_ARGUMENT)
359364                return
360365            kPage *page = (kPage *)c->arg->protected_data.l
361366            if page->address_space != mem:
362367                dpanic (0x52993341, "Trying to map foreign page")
363                reply_num (Kernel::ERR_INVALID_ARGUMENT)
368                reply_num (Iris::ERR_INVALID_ARGUMENT)
364369                return
365            if c->data[1].l & (unsigned)c->arg->target & Kernel::Page::READONLY:
370            if c->data[1].l & (unsigned)c->arg->target & Iris::Page::READONLY:
366371                kdebug ("Mapping readonly because capability is readonly\n")
367                page->flags |= Kernel::Page::MAPPED_READONLY
372                page->flags |= Iris::Page::MAPPED_READONLY
368373            mem->map (page, c->data[1].l & PAGE_MASK)
369374            break
370        case Kernel::Memory::MAPPING & REQUEST_MASK:
375        case Iris::Memory::MAPPING & REQUEST_MASK:
371376            kPage *page = mem->get_mapping (c->data[1].l)
372377            if !page:
373                reply_num (Kernel::ERR_UNMAPPED_READ)
378                reply_num (Iris::ERR_UNMAPPED_READ)
374379                return
375380            unsigned t = CAPTYPE_PAGE | CAP_MASTER
376            if page->flags & Kernel::Page::MAPPED_READONLY:
377                t |= Kernel::Page::READONLY
381            if page->flags & Iris::Page::MAPPED_READONLY:
382                t |= Iris::Page::READONLY
378383            reply_cap (t, (unsigned)page, &page->refs)
379384            return
380        case Kernel::Memory::GET_LIMIT & REQUEST_MASK:
385        case Iris::Memory::GET_LIMIT & REQUEST_MASK:
381386            reply_num (mem->limit)
382387            return
383        case Kernel::Memory::SET_LIMIT & REQUEST_MASK:
388        case Iris::Memory::SET_LIMIT & REQUEST_MASK:
384389            mem->limit = c->data[1].l
385390            break
386391        default:
387392            dpanic (0, "invalid memory operation")
388            reply_num (Kernel::ERR_INVALID_OPERATION)
393            reply_num (Iris::ERR_INVALID_OPERATION)
389394            return
390395    reply_num (0)
391396
392static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
397static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
398    dbg_push (__LINE__)
393399    kThread *thread = (kThread *)protected_data.l
394400    switch cmd:
395        case Kernel::Thread::GET_INFO & REQUEST_MASK:
401        case Iris::Thread::GET_INFO & REQUEST_MASK:
396402            switch c->data[0].h:
397                case Kernel::Thread::PC:
403                case Iris::Thread::PC:
398404                    reply_num (thread->pc)
399405                    return
400                case Kernel::Thread::SP:
406                case Iris::Thread::SP:
401407                    reply_num (thread->sp)
402408                    return
403                case Kernel::Thread::FLAGS:
409                case Iris::Thread::FLAGS:
404410                    reply_num (thread->flags)
405411                    return
406412                default:
407413                    reply_num (*kThread_arch_info (thread, c->data[0].h))
408414                    return
409        case Kernel::Thread::SET_INFO & REQUEST_MASK:
415        case Iris::Thread::SET_INFO & REQUEST_MASK:
410416            unsigned *value
411417            switch c->data[0].h:
412                case Kernel::Thread::PC:
418                case Iris::Thread::PC:
413419                    value = &thread->pc
414420                    break
415                case Kernel::Thread::SP:
421                case Iris::Thread::SP:
416422                    value = &thread->sp
417423                    break
418                case Kernel::Thread::FLAGS:
424                case Iris::Thread::FLAGS:
419425                    // It is not possible to set the PRIV flag (but it can be reset).
420                    if c->data[1].l & Kernel::Thread::PRIV:
421                        c->data[1].h &= ~Kernel::Thread::PRIV
426                    if c->data[1].l & Iris::Thread::PRIV:
427                        c->data[1].h &= ~Iris::Thread::PRIV
422428                    value = &thread->flags
423                    if c->data[1].h & ~Kernel::Thread::USER_FLAGS:
429                    if c->data[1].h & ~Iris::Thread::USER_FLAGS:
424430                        unsigned v = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
425                        if (v & Kernel::Thread::WAITING) != (*value & Kernel::Thread::WAITING):
426                            if v & Kernel::Thread::WAITING:
431                        if (v & Iris::Thread::WAITING) != (*value & Iris::Thread::WAITING):
432                            if v & Iris::Thread::WAITING:
427433                                thread->wait ()
428434                            else
429435                                thread->unwait ()
430                        if (v & Kernel::Thread::RUNNING) != (*value & Kernel::Thread::RUNNING):
431                            if v & Kernel::Thread::RUNNING:
436                        if (v & Iris::Thread::RUNNING) != (*value & Iris::Thread::RUNNING):
437                            if v & Iris::Thread::RUNNING:
432438                                thread->run ()
433439                            else:
434440                                thread->unrun ()
...... 
439445            if value:
440446                *value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
441447            break
442        case Kernel::Thread::USE_SLOT & REQUEST_MASK:
448        case Iris::Thread::USE_SLOT & REQUEST_MASK:
449            dbg_push (__LINE__)
443450            if c->data[1].l >= thread->slots || !c->arg.valid ():
451                if c->data[1].l == 0xdeadbeef:
452                    bool dummy
453                    dbg_code.h = (unsigned)c->arg.deref ()
454                    break
444455                dbg_send (5, 3)
445456                dpanic (c->data[1].l, "no argument given for USE_SLOT")
446                reply_num (Kernel::ERR_INVALID_ARGUMENT)
457                reply_num (Iris::ERR_INVALID_ARGUMENT)
447458                return
448459            // FIXME: This doesn't allow using a fake caps.
449            if (unsigned)c->arg->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->arg->target != (CAPTYPE_CAPS | Kernel::Caps::USE):
450                dpanic (0, "argument for USE_SLOT is not a caps")
451                reply_num (Kernel::ERR_INVALID_ARGUMENT)
460            if (unsigned)c->arg->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->arg->target != (CAPTYPE_CAPS | Iris::Caps::USE):
461                dpanic ((unsigned)c->arg->target, "argument for USE_SLOT is not a caps")
462                reply_num (Iris::ERR_INVALID_ARGUMENT)
452463                return
464            dbg_push (__LINE__)
453465            unsigned slot = c->data[1].l
466            dbg_push (__LINE__)
454467            kCaps *new_caps = (kCaps *)c->arg->protected_data.l
468            dbg_push (__LINE__)
455469            if slot >= thread->slots:
456470                dpanic (0, "using invalid slot")
457471                return
472            dbg_push (__LINE__)
458473            thread->unset_slot (slot)
474            dbg_push (__LINE__)
459475            thread->slot[slot].caps = new_caps
476            dbg_push (__LINE__)
460477            if new_caps:
478                dbg_push (__LINE__)
461479                thread->slot[slot].next = new_caps->first_slot
462480                thread->slot[slot].caps = new_caps
463481                new_caps->first_slot.thread = thread
464482                new_caps->first_slot.index = slot
483            dbg_push (__LINE__)
465484            break
466        case Kernel::Thread::GET_CAPS & REQUEST_MASK:
485        case Iris::Thread::GET_CAPS & REQUEST_MASK:
467486            unsigned slot = c->data[1].l
468487            if slot < thread->slots:
469488                reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->slot[slot].caps, &thread->slot[slot].caps->refs, thread->slots)
470489            else:
471490                reply_num (thread->slots)
472491            return
473        case Kernel::Thread::SCHEDULE & REQUEST_MASK:
492        case Iris::Thread::SCHEDULE & REQUEST_MASK:
474493            do_schedule = true
475494            return
476495        default:
477            if !(thread->flags & Kernel::Thread::PRIV):
496            if !(thread->flags & Iris::Thread::PRIV):
478497                dpanic (0, "invalid thread operation")
479                reply_num (Kernel::ERR_INVALID_OPERATION)
498                reply_num (Iris::ERR_INVALID_OPERATION)
480499                return
481500            switch cmd:
482                case Kernel::Thread::PRIV_REGISTER_INTERRUPT & REQUEST_MASK:
501                case Iris::Thread::PRIV_REGISTER_INTERRUPT & REQUEST_MASK:
483502                    arch_register_interrupt (c->data[1].l, c->arg.valid () && (((unsigned)c->arg->target) & ~REQUEST_MASK) == CAPTYPE_RECEIVER ? (kReceiver *)c->arg->protected_data.l : NULL)
484503                    break
485                case Kernel::Thread::PRIV_GET_TOP_MEMORY & REQUEST_MASK:
504                case Iris::Thread::PRIV_GET_TOP_MEMORY & REQUEST_MASK:
486505                    reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)&top_memory, &top_memory.refs)
487506                    return
488                case Kernel::Thread::PRIV_MAKE_PRIV & REQUEST_MASK:
507                case Iris::Thread::PRIV_MAKE_PRIV & REQUEST_MASK:
489508                    if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_THREAD:
490509                        dpanic (0, "not a thread argument for make priv")
491                        reply_num (Kernel::ERR_INVALID_ARGUMENT)
510                        reply_num (Iris::ERR_INVALID_ARGUMENT)
492511                        return
493                    ((kThread *)c->arg->protected_data.l)->flags |= Kernel::Thread::PRIV
512                    ((kThread *)c->arg->protected_data.l)->flags |= Iris::Thread::PRIV
494513                    break
495                case Kernel::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
514                case Iris::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
496515                    if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
497516                        panic (0x54365435, "non-memory argument to alloc_range")
498                        reply_num (Kernel::ERR_INVALID_ARGUMENT)
517                        reply_num (Iris::ERR_INVALID_ARGUMENT)
499518                        return
500519                    kMemory *mem = (kMemory *)c->arg->protected_data.l
501520                    if !mem->use (c->data[1].l):
502521                        dpanic (0x34365435, "out of memory during alloc_range")
503                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
522                        reply_num (Iris::ERR_OUT_OF_MEMORY)
504523                        return
505524                    unsigned data = phys_alloc (c->data[1].l)
506525                    if !data:
507526                        mem->unuse (c->data[1].l)
508527                        dpanic (0x14365435, "out of memory during alloc_range")
509                        reply_num (Kernel::ERR_OUT_OF_MEMORY)
528                        reply_num (Iris::ERR_OUT_OF_MEMORY)
510529                        return
511530                    reply_num (data & ~0xc0000000)
512531                    return
513                case Kernel::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK:
532                case Iris::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK:
514533                    if !c->arg.valid ():
515534                        panic (0x71342134, "no argument provided for alloc physical")
516                        reply_num (Kernel::ERR_INVALID_ARGUMENT)
535                        reply_num (Iris::ERR_INVALID_ARGUMENT)
517536                        return
518537                    if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
519538                        panic (0x21342134, "no page provided for alloc physical")
520                        reply_num (Kernel::ERR_INVALID_ARGUMENT)
539                        reply_num (Iris::ERR_INVALID_ARGUMENT)
521540                        return
522541                    kPage *page = (kPage *)c->arg->protected_data.l
523542                    page->forget ()
524543                    if !(c->data[1].l & 2):
525                        if page->flags & Kernel::Page::PAYING:
526                            page->flags &= ~Kernel::Page::PAYING
544                        if page->flags & Iris::Page::PAYING:
545                            page->flags &= ~Iris::Page::PAYING
527546                            page->address_space->unuse ()
528547                    else:
529548                        // This is for mapping allocated ranges. They are already paid for. Record that.
530                        if page->flags & Kernel::Page::PAYING:
549                        if page->flags & Iris::Page::PAYING:
531550                            page->address_space->unuse ()
532551                        else:
533                            page->flags |= Kernel::Page::PAYING
552                            page->flags |= Iris::Page::PAYING
534553                    page->frame = (c->data[1].l & PAGE_MASK) | 0x80000000
535                    page->flags |= Kernel::Page::FRAME
554                    page->flags |= Iris::Page::FRAME
536555                    if !(c->data[1].l & 1):
537                        page->flags |= Kernel::Page::UNCACHED
556                        page->flags |= Iris::Page::UNCACHED
538557                    if !(c->data[1].l & 2):
539                        page->flags |= Kernel::Page::PHYSICAL
558                        page->flags |= Iris::Page::PHYSICAL
540559                    kPage_arch_update_mapping (page)
541560                    break
542                case Kernel::Thread::PRIV_PHYSICAL_ADDRESS & REQUEST_MASK:
561                case Iris::Thread::PRIV_PHYSICAL_ADDRESS & REQUEST_MASK:
543562                    if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_PAGE:
544563                        dpanic (0x99049380, "invalid page for physical address")
545                        reply_num (Kernel::ERR_INVALID_ARGUMENT)
564                        reply_num (Iris::ERR_INVALID_ARGUMENT)
546565                        return
547566                    kPage *page = (kPage *)c->arg->protected_data.l
548567                    reply_num (page->frame & ~0xc0000000)
549568                    return
550                case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK:
569                case Iris::Thread::PRIV_REBOOT & REQUEST_MASK:
551570                    arch_reboot ()
552                case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
571                case Iris::Thread::PRIV_PANIC & REQUEST_MASK:
553572                    if c->data[1].l == 0xdeaddead:
554573                        dbg_code.l = 1
555574                        break
556575                    panic (c->data[1].l, "panic requested by thread")
557576                    reply_num (~0)
558577                    return
559                case Kernel::Thread::DBG_SEND & REQUEST_MASK:
578                case Iris::Thread::DBG_SEND & REQUEST_MASK:
560579                    dbg_send (c->data[1].l, c->data[1].h)
561580                    break
562581                default:
563582                    dpanic (0, "invalid priv thread operation")
564                    reply_num (Kernel::ERR_INVALID_OPERATION)
583                    reply_num (Iris::ERR_INVALID_OPERATION)
565584                    return
585    dbg_push (__LINE__)
566586    reply_num (0)
587    dbg_push (__LINE__)
567588    return
568589
569590static void page_check_payment (kPage *page):
570591    kPage *p
571592    for p = page; p; p = p->share_prev:
572        if p->flags & Kernel::Page::PAYING:
593        if p->flags & Iris::Page::PAYING:
573594            return
574595    for p = page->share_next; p; p = p->share_next:
575        if p->flags & Kernel::Page::PAYING:
596        if p->flags & Iris::Page::PAYING:
576597            return
577598    // No kPage is paying for this frame anymore.
578599    raw_pfree (page->frame)
...... 
581602        p->frame = NULL
582603        p->share_prev = NULL
583604        p->share_next = NULL
584        p->flags &= ~(Kernel::Page::SHARED | Kernel::Page::FRAME)
605        p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
585606        kPage_arch_update_mapping (p)
586607    for p = page, next = p->share_next; p; p = next, next = p->share_next:
587608        p->frame = NULL
588609        p->share_prev = NULL
589610        p->share_next = NULL
590        p->flags &= ~(Kernel::Page::SHARED | Kernel::Page::FRAME)
611        p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME)
591612        kPage_arch_update_mapping (p)
592613
593static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
614static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
594615    kPage *page = (kPage *)protected_data.l
595    switch cmd & ~Kernel::Page::READONLY:
596        case Kernel::Page::SHARE & REQUEST_MASK:
616    switch cmd & ~Iris::Page::READONLY:
617        case Iris::Page::SHARE & REQUEST_MASK:
597618            if !c->arg.valid ():
598619                // Cannot share without a target page.
599620                dpanic (0, "no target page for share")
600                reply_num (Kernel::ERR_INVALID_ARGUMENT)
621                reply_num (Iris::ERR_INVALID_ARGUMENT)
601622                return
602623            if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
603624                // FIXME: This makes it impossible to use a fake kPage capability.
604625                dpanic (0, "share target is no page")
605                reply_num (Kernel::ERR_INVALID_ARGUMENT)
626                reply_num (Iris::ERR_INVALID_ARGUMENT)
606627                return
607628            kPage *t = (kPage *)c->arg->protected_data.l
629            //kdebug ("sharing from ")
630            //kdebug_num ((unsigned)page)
631            //kdebug (" (frame ")
632            //kdebug_num (page->frame)
633            //kdebug (") to ")
634            //kdebug_num ((unsigned)t)
635            //kdebug (" (frame ")
636            //kdebug_num (t->frame)
637            //kdebug (")\n")
608638            if t != page:
609639                t->forget ()
610            if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY:
611                t->flags |= Kernel::Page::READONLY
612            if !(page->flags & Kernel::Page::FRAME):
640            if c->data[0].h & Iris::Page::READONLY || cmd & Iris::Page::READONLY:
641                t->flags |= Iris::Page::READONLY
642            if !(page->flags & Iris::Page::FRAME):
613643                kdebug ("share problem: ")
614644                kdebug_num (page->flags)
615645                kdebug ("\n")
616646                dpanic (0, "sharing nothing results in lost page")
617647                kPage_arch_update_mapping (t)
618648                break
619            if c->data[0].h & Kernel::Page::COPY:
620                if ~t->flags & Kernel::Page::PAYING:
649            if c->data[0].h & Iris::Page::COPY:
650                if ~t->flags & Iris::Page::PAYING:
621651                    kPage_arch_update_mapping (t)
622652                    break
623                if !(c->data[0].h & Kernel::Page::FORGET) || page->flags & Kernel::Page::SHARED:
653                if !(c->data[0].h & Iris::Page::FORGET) || page->flags & Iris::Page::SHARED:
624654                    unsigned *d = (unsigned *)page->frame
625655                    if t == page:
626656                        kPage *other = page->share_next ? page->share_next : page->share_prev
...... 
635665                        page->share_prev = NULL
636666                        page_check_payment (other)
637667                    else:
638                        t->flags |= Kernel::Page::FRAME
668                        t->flags |= Iris::Page::FRAME
639669                    t->frame = raw_zalloc ()
640670                    for unsigned i = 0; i < PAGE_SIZE; i += 4:
641671                        ((unsigned *)t->frame)[i >> 2] = d[i >> 2]
642                    if c->data[0].h & Kernel::Page::FORGET:
672                    if c->data[0].h & Iris::Page::FORGET:
643673                        page->frame = NULL
644                        page->flags &= ~Kernel::Page::FRAME
674                        page->flags &= ~Iris::Page::FRAME
645675                        kPage_arch_update_mapping (page)
646676                else:
647677                    if t != page:
648678                        t->frame = page->frame
649                        t->flags |= Kernel::Page::FRAME
679                        t->flags |= Iris::Page::FRAME
650680                        page->frame = NULL
651                        page->flags &= ~Kernel::Page::FRAME
681                        page->flags &= ~Iris::Page::FRAME
652682                        kPage_arch_update_mapping (page)
653683                    else:
654684                        dpanic (0, "sharing page with itself...")
...... 
657687                    dpanic (0, "sharing page with itself")
658688                    kPage_arch_update_mapping (t)
659689                    break
660                if c->data[0].h & Kernel::Page::FORGET:
661                    if ~page->flags & Kernel::Page::SHARED:
662                        if t->flags & Kernel::Page::PAYING:
690                if c->data[0].h & Iris::Page::FORGET:
691                    if ~page->flags & Iris::Page::SHARED:
692                        if t->flags & Iris::Page::PAYING:
663693                            t->frame = page->frame
664                            t->flags |= Kernel::Page::FRAME
694                            t->flags |= Iris::Page::FRAME
665695                        else:
666696                            dpanic (0, "move page failed because target is not paying")
667697                        page->frame = NULL
668                        page->flags &= ~Kernel::Page::FRAME
698                        page->flags &= ~Iris::Page::FRAME
669699                        kPage_arch_update_mapping (page)
670700                    else:
671701                        t->share_prev = page->share_prev
...... 
685715                    if t->share_prev:
686716                        t->share_prev->share_next = t
687717                    t->frame = page->frame
688                    t->flags |= Kernel::Page::FRAME
718                    t->flags |= Iris::Page::FRAME
689719            kPage_arch_update_mapping (t)
690720            break
691        case Kernel::Page::SET_FLAGS & REQUEST_MASK:
692            if cmd & Kernel::Page::READONLY:
721        case Iris::Page::SET_FLAGS & REQUEST_MASK:
722            if cmd & Iris::Page::READONLY:
693723                dpanic (0, "setting page flags denied")
694                reply_num (Kernel::ERR_WRITE_DENIED)
724                reply_num (Iris::ERR_WRITE_DENIED)
695725                return
696726            // Always refuse to set reserved flags.
697            c->data[1].h &= ~(Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED)
727            c->data[1].h &= ~(Iris::Page::PHYSICAL | Iris::Page::UNCACHED)
698728            // Remember the old flags.
699729            unsigned old = page->flags
700730            // Compute the new flags.
701731            page->flags = (page->flags & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
702732
703733            // If we stop paying, see if the frame is still paid for. If not, free it.
704            if ~page->flags & old & Kernel::Page::PAYING:
734            if ~page->flags & old & Iris::Page::PAYING:
705735                // Decrease the use counter in any case.
706736                page->address_space->unuse ()
707737                page_check_payment (page)
708738
709739            // If we start paying, increase the use counter.
710            if page->flags & ~old & Kernel::Page::PAYING:
740            if page->flags & ~old & Iris::Page::PAYING:
711741                if !page->address_space->use():
712742                    dpanic (0, "cannot pay for frame")
713743                    // If it doesn't work, refuse to set the flag, and refuse to allocate a frame.
714                    page->flags &= ~(Kernel::Page::PAYING | Kernel::Page::FRAME)
744                    page->flags &= ~(Iris::Page::PAYING | Iris::Page::FRAME)
715745                    // However, if there already was a frame, keep it.
716                    if old & Kernel::Page::FRAME:
717                        page->flags |= Kernel::Page::FRAME
746                    if old & Iris::Page::FRAME:
747                        page->flags |= Iris::Page::FRAME
718748
719749            // If we want a frame, see if we can get it.
720            if ~old & page->flags & Kernel::Page::FRAME:
721                if ~page->flags & Kernel::Page::PAYING:
750            if ~old & page->flags & Iris::Page::FRAME:
751                if ~page->flags & Iris::Page::PAYING:
722752                    dpanic (0, "cannot have frame without paying")
723                    page->flags &= ~Kernel::Page::FRAME
753                    page->flags &= ~Iris::Page::FRAME
724754                else:
725755                    page->frame = page->address_space->zalloc ()
726756                    kPage_arch_update_mapping (page)
727757            break
728758        default:
729759            dpanic (0, "invalid page operation")
730            reply_num (Kernel::ERR_INVALID_OPERATION)
760            reply_num (Iris::ERR_INVALID_OPERATION)
731761            return
732762    if page->flags > 0x7f:
733763        dpanic (page->flags, "weird output from page operation")
...... 
755785    else:
756786        kdebug (']')
757787
758static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
788static void caps_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
759789    kCaps *caps = (kCapsP)protected_data.l
760790    switch cmd:
761        case Kernel::Caps::GET & REQUEST_MASK:
791        case Iris::Caps::GET & REQUEST_MASK:
762792            if c->data[1].l >= caps->size:
763                reply_num (Kernel::ERR_INVALID_ARGUMENT)
793                reply_num (Iris::ERR_INVALID_ARGUMENT)
764794                kdebug_num ((unsigned)caps)
765795                kdebug (" size: ")
766796                kdebug_num (caps->size)
...... 
782812            #endif
783813            reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities)
784814            return
785        case Kernel::Caps::GET_SIZE & REQUEST_MASK:
815        case Iris::Caps::GET_SIZE & REQUEST_MASK:
786816            reply_num (caps->size)
787817            return
788        case Kernel::Caps::SET & REQUEST_MASK:
818        case Iris::Caps::SET & REQUEST_MASK:
789819            if c->data[1].l >= caps->size:
790820                dpanic (0, "invalid index for set caps")
791821                return
...... 
802832            //kdebug_num (caps->caps[c->data[1].l].protected_data.l)
803833            //kdebug ("\n")
804834            return
805        case Kernel::Caps::TRUNCATE & REQUEST_MASK:
835        case Iris::Caps::TRUNCATE & REQUEST_MASK:
806836            dpanic (0, "truncate caps is not implemented yet.")
807837            return
808        case Kernel::Caps::PRINT & REQUEST_MASK:
838        case Iris::Caps::PRINT & REQUEST_MASK:
809839            if c->data[1].l >= caps->size:
810840                dpanic (0, "invalid caps for print")
811841                return
...... 
839869            return
840870        default:
841871            dpanic (cmd, "invalid caps operation")
842            reply_num (Kernel::ERR_INVALID_OPERATION)
872            reply_num (Iris::ERR_INVALID_OPERATION)
843873            return
844874
845static void list_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
875static void list_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
846876    kList *list = (kListP)protected_data.l
847    if cmd == Kernel::List::SET_CB & REQUEST_MASK:
877    if cmd == Iris::List::SET_CB & REQUEST_MASK:
848878        list->owner.clone (0, c->arg, c->copy[1])
849879        return
850880    kListitem *item
...... 
853883    else:
854884        if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_LISTITEM:
855885            dpanic (0, "invalid request for list: arg is no listitem")
856            reply_num (Kernel::ERR_INVALID_ARGUMENT)
886            reply_num (Iris::ERR_INVALID_ARGUMENT)
857887            return
858888        item = (kListitem *)c->arg->protected_data.l
859889        if item->list != list:
860890            dpanic (0, "item list is not equal to called object")
861            reply_num (Kernel::ERR_INVALID_ARGUMENT)
891            reply_num (Iris::ERR_INVALID_ARGUMENT)
862892            return
863893    switch cmd:
864        case Kernel::List::GET_NEXT & REQUEST_MASK:
894        case Iris::List::GET_NEXT & REQUEST_MASK:
865895            if !item:
866896                item = list->first_listitem
867897            else:
868                if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::LIST:
898                if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Iris::Listitem::LIST:
869899                    dpanic (0, "trying to get next listitem with insufficient rights")
870                    reply_num (Kernel::ERR_INVALID_ARGUMENT)
900                    reply_num (Iris::ERR_INVALID_ARGUMENT)
871901                    return
872902                item = item->next_item
873903            if !item:
874904                reply_num (0)
875905                return
876            reply_cap (CAPTYPE_LISTITEM | Kernel::Listitem::LIST, (unsigned)item, &item->refs)
906            reply_cap (CAPTYPE_LISTITEM | Iris::Listitem::LIST, (unsigned)item, &item->refs)
877907            return
878        case Kernel::List::ADD_ITEM & REQUEST_MASK:
908        case Iris::List::ADD_ITEM & REQUEST_MASK:
879909            if !item:
880910                dpanic (0, "invalid request: no listitem for List::ADD_ITEM")
881                reply_num (Kernel::ERR_INVALID_ARGUMENT)
911                reply_num (Iris::ERR_INVALID_ARGUMENT)
882912                return
883            if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::ADD:
913            if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Iris::Listitem::ADD:
884914                dpanic (0, "trying to add listitem with insufficient rights")
885                reply_num (Kernel::ERR_INVALID_ARGUMENT)
915                reply_num (Iris::ERR_INVALID_ARGUMENT)
886916                return
887917            ((kListitem *)c->arg->protected_data.l)->add (list)
888918            break
889        case Kernel::List::GET_INFO & REQUEST_MASK:
919        case Iris::List::GET_INFO & REQUEST_MASK:
890920            if !item:
891921                dpanic (0, "no item for List::GET_INFO")
892                reply_num (Kernel::ERR_INVALID_ARGUMENT, ~0, ~0)
922                reply_num (Iris::ERR_INVALID_ARGUMENT, ~0, ~0)
893923                return
894924            reply_num (item->info)
895925            return
896        case Kernel::List::SET_INFO & REQUEST_MASK:
926        case Iris::List::SET_INFO & REQUEST_MASK:
897927            if !item:
898928                dpanic (0, "no item for List::SET_INFO")
899                reply_num (Kernel::ERR_INVALID_ARGUMENT)
929                reply_num (Iris::ERR_INVALID_ARGUMENT)
900930                return
901931            item->info = c->data[1]
902932            break
903        case Kernel::List::GET_CAP & REQUEST_MASK:
933        case Iris::List::GET_CAP & REQUEST_MASK:
904934            if !item:
905935                dpanic (0, "no item for List::GET_CAP")
906                reply_num (Kernel::ERR_INVALID_ARGUMENT)
936                reply_num (Iris::ERR_INVALID_ARGUMENT)
907937                return
908938            kCapability *cap = item->target.cap (0)
909939            reply_cap ((unsigned)cap->target, cap->protected_data, ((unsigned)cap->target & ~KERNEL_MASK) == 0 ? &((kObject *)cap->target)->refs : &cap->target->capabilities)
910940            return
911941        default:
912942            dpanic (0, "invalid list operation")
913            reply_num (Kernel::ERR_INVALID_OPERATION)
943            reply_num (Iris::ERR_INVALID_OPERATION)
914944            return
915945    reply_num (0)
916946
917static void listitem_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
947static void listitem_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
918948    kListitem *item = (kListitemP)protected_data.l
919949    switch cmd:
920        case Kernel::Listitem::CLEAR & REQUEST_MASK:
950        case Iris::Listitem::CLEAR & REQUEST_MASK:
921951            // Disable linked capability.
922952            item->add (NULL)
923953            break
924        case Kernel::Listitem::SET_CAP & REQUEST_MASK:
954        case Iris::Listitem::SET_CAP & REQUEST_MASK:
925955            // Set linked capability.
926956            item->target.clone (0, c->arg, c->copy[1])
927957            break
928958        default:
929959            dpanic (0, "invalid listitem operation")
930            reply_num (Kernel::ERR_INVALID_OPERATION)
960            reply_num (Iris::ERR_INVALID_OPERATION)
931961            return
932962    reply_num (0)
933963
...... 
936966    while cap.valid ():
937967        kCapability *c = cap.deref ()
938968        cap = c->sibling_next
939        if (unsigned)c->target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY):
969        if (unsigned)c->target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY):
940970            c->invalidate ()
941971
942static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c):
972static void kernel_invoke (unsigned target, Iris::Num protected_data, kCapability::Context *c):
943973    // Kernel calling convention:
944974    // data[0].l is the request.
945975    // reply is the reply capability, or (for call capabilities) the target to call.
946976    // other parameters' meanings depend on the operation.
947    if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC):
977    if target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL_ASYNC):
948978        // This is a call capability. reply is the capability to call.
949979        kReceiver *owner = (kReceiver *)protected_data.l
950        owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
980        owner->protected_only = target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL)
951981        if must_wait:
952982            old_current->wait ()
953983        if !reply_target:
...... 
961991            // This is a user-implemented object. Create a real reply capability.
962992            kReceiver *call_target = reply_target
963993            c->reply = kCapRef (&reply_caps, 0)
964            c->reply.set ((kReceiver *)(CAPTYPE_RECEIVER | Kernel::Receiver::REPLY), protected_data, kCapRef (), &((kReceiver *)protected_data.l)->refs)
994            c->reply.set ((kReceiver *)(CAPTYPE_RECEIVER | Iris::Receiver::REPLY), protected_data, kCapRef (), &((kReceiver *)protected_data.l)->refs)
965995            c->copy[0] = true
966996            call_target->send_message (reply_protected, c)
967997            c->reply->invalidate ()
968        else if (unsigned)reply_target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY):
998        else if (unsigned)reply_target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY):
969999            // Reply capability: destroy all before invoke.
9701000            kReceiver *r = (kReceiver *)reply_protected.l
9711001            kill_reply (r)
...... 
9811011        return
9821012    if must_wait:
9831013        old_current->wait ()
984    if target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY):
1014    if target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY):
9851015        // This is a reply capability.
9861016        kReceiver *r = (kReceiver *)protected_data.l
9871017        kill_reply (r)
...... 
10261056            return
10271057    return
10281058
1029void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c):
1059void invoke (kReceiverP target, Iris::Num protected_data, kCapability::Context *c):
10301060    if dbg_code.l && old_current->id != 1:
10311061        log_message ("invoke", (unsigned)target, protected_data.l, c)
10321062    if (unsigned)target & ~KERNEL_MASK:
...... 
10461076        reply_protected = c->reply->protected_data
10471077    else:
10481078        reply_target = NULL
1079        reply_protected.l = 0
10491080    kernel_invoke ((unsigned)target, protected_data, c)
iris.hhp
5353// Master capabilities can create others.
5454#define CAP_MASTER_CREATE (1 << 31)
5555
56#define __receiver_num 0
57#define __thread_num 1
58#define __memory_num 2
59#define __call_num 3
60#define __parent_num 4
56#define __caps_num 0
57#define __receiver_num 1
58#define __thread_num 2
59#define __memory_num 3
60#define __call_num 4
61#define __parent_num 5
6162
6263// If this flag is set in a capability, it is copied instead of mapped.
6364// If it is set in the target capability, the Thread waits after the request.
...... 
6566// This constant signifies that no capability is passed.
6667#define CAP_NONE (~CAP_COPY)
6768
68struct Parent
69
70namespace Kernel:
69namespace Iris:
70    struct Parent
7171    enum Exception_code:
7272        NO_ERROR
7373        ERR_WRITE_DENIED
...... 
138138    Cap alloc_cap ()
139139    void free_slot (unsigned slot)
140140    void free_cap (Cap cap)
141    extern bool enable_debug
141142
142143    struct Cap:
143144        unsigned code
...... 
161162        Num protected_data
162163        Cap reply, arg
163164
165    extern Caps my_caps
164166    extern Receiver my_receiver
165167    extern Thread my_thread
166168    extern Memory my_memory
...... 
280282        Cap create_capability (Num protected_data):
281283            icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
282284            return get_arg ()
283        Num get_protected (Kernel::Cap target):
285        Num get_protected (Cap target):
284286            return ocall (target, CAP_MASTER_DIRECT | GET_PROTECTED)
285287        Num get_reply_protected_data ():
286288            return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
...... 
455457            PHYSICAL = 0x20
456458            // This is a read-only flag, saying if this is uncachable memory.
457459            UNCACHED = 0x40
458        void share (Cap target, unsigned flags):
459            ocall (target, Kernel::Num (CAP_MASTER_DIRECT | SHARE, flags))
460        void share (Cap target, unsigned flags = 0):
461            ocall (target, Num (CAP_MASTER_DIRECT | SHARE, flags))
460462        unsigned get_flags ():
461463            return call (CAP_MASTER_DIRECT | GET_FLAGS).l
462464        bool set_flags (unsigned new_flags, unsigned mask):
...... 
576578        Cap ().call ()
577579
578580// The start function has this prototype (there is no main function).
579Kernel::Num start ()
581Iris::Num start ()
580582
581583#ifndef __KERNEL__
582584#if 1
...... 
596598    for i = 0; i < digits; ++i:
597599        kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf])
598600
599namespace Kernel:
601namespace Iris:
600602    inline void panic (unsigned code, char const *message = NULL):
601603        if message:
602604            kdebug (message)
kernel.hhp
7575    kCapRef (kCapsP c, unsigned i) : caps (c), index (i):
7676    kCapRef () : caps (NULL), index (~0):
7777    inline void clone (kCapRef source, bool copy)
78    inline void set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
78    inline void set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
7979
8080struct kObject:
8181    kCapRef refs
...... 
9797
9898struct kCapability : public kObject:
9999    struct Context:
100        Kernel::Num data[2]
100        Iris::Num data[2]
101101        kCapRef reply
102102        kCapRef arg
103103        bool copy[2]
...... 
105105    kCapRef parent
106106    kCapRef children
107107    kCapRef sibling_prev, sibling_next
108    Kernel::Num protected_data
108    Iris::Num protected_data
109109    inline void invoke (kCapability::Context *c)
110110    void invalidate ()
111111
...... 
138138    void wait ()
139139    void unwait ()
140140    bool is_waiting ():
141        return flags & Kernel::Thread::WAITING
141        return flags & Iris::Thread::WAITING
142142    kCapRef find_capability (unsigned code, bool *copy)
143143
144144struct kReceiver : public kObject:
...... 
154154    // The message queue. kMessages are added at the tail, and removed at the front.
155155    kMessageP messages
156156    kMessageP last_message
157    Kernel::Num reply_protected_data
157    Iris::Num reply_protected_data
158158    bool protected_only
159159    // This limit is for messages stored in its address space. There is unlimited space if senders provide it.
160160    unsigned queue_limit, queue_use
161161    void own (kThreadP o)
162162    void orphan ()
163163    bool try_deliver ()
164    bool send_message (Kernel::Num protected_data, kCapability::Context *c)
164    bool send_message (Iris::Num protected_data, kCapability::Context *c)
165165    void check (unsigned line)
166166
167167struct kPage : public kObject:
...... 
177177    unsigned size
178178    kCapability caps[1]
179179    inline kCapability *cap (unsigned idx)
180    void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
180    void set (unsigned index, kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
181181    void clone (unsigned index, kCapRef source, bool copy)
182182    void init (unsigned size)
183183
...... 
185185#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1)
186186
187187struct kMessage : public kObject:
188    Kernel::Num protected_data
189    Kernel::Num data[2]
188    Iris::Num protected_data
189    Iris::Num data[2]
190190    // This is a real Caps of two elements, not a link.
191191    kCaps caps
192192
...... 
198198struct kListitem : public kObject:
199199    kListP list
200200    kListitemP prev_item, next_item
201    Kernel::Num info
201    Iris::Num info
202202    // This is a real Caps of one element, not a link.
203203    kCaps target
204204    void add (kList *l)
...... 
257257    #define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m))
258258    void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
259259    #ifndef NDEBUG
260    EXTERN Kernel::Num dbg_code
260    EXTERN Iris::Num dbg_code
261261    EXTERN unsigned dbg_buffer[32]
262262    EXTERN unsigned dbg_buffer_head
263263    static void dbg_push (unsigned n):
...... 
293293EXTERN bool do_schedule, must_wait
294294// reply_caps is the source of a receiver-generated reply capability.
295295// replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply.
296// reply_target is the target receiver for kernel replies.
297// reply_protected is the protected data for the kernel reply.
296298EXTERN kCaps reply_caps, replied_caps
299EXTERN kReceiver *reply_target
300EXTERN Iris::Num reply_protected
297301
298302// Defined in memory.ccp
299303unsigned init_memory (unsigned mem)
...... 
303307void phys_free (unsigned page, unsigned num)
304308
305309// Defind in invoke.ccp
306void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c)
310void invoke (kReceiverP target, Iris::Num protected_data, kCapability::Context *c)
307311
308312// Defined by architecture-specific files.
309313void kThread_arch_init (kThread *thread)
310void kThread_arch_receive (kThread *thread, Kernel::Num protected_data, Kernel::Num *data)
314void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data)
311315unsigned *kThread_arch_info (kThread *thread, unsigned num)
312316void kMemory_arch_init (kMemory *mem)
313317void kMemory_arch_free (kMemory *mem)
...... 
336340    return caps ? caps->cap (index) : NULL
337341void kCapRef::clone (kCapRef source, bool copy):
338342    caps->clone (index, source, copy)
339void kCapRef::set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr):
343void kCapRef::set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr):
340344    if valid ():
341345        deref ()->invalidate ()
342346    caps->set (index, target, pdata, parent, parent_ptr)
memory.ccp
172172    kFreePages *p
173173    for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
174174        // Do nothing.
175        if p == p->next:
176            dpanic (0, "page is its own next")
175177    // The new block should be inserted directly after p.
176178    if (unsigned)p->next == page + size:
177179        // It can be merged with the block after it: do that.
mips/arch.ccp
3838    page->arch.prev_mapped = NULL
3939    page->arch.next_mapped = NULL
4040
41void kThread_arch_receive (kThread *thread, Kernel::Num protected_data, Kernel::Num *data):
41void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data):
4242    thread->arch.a[0] = data[0].l
4343    thread->arch.a[1] = data[0].h
4444    thread->arch.a[2] = data[1].l
...... 
161161        //kdebug ("not mapping because there is no frame\n")
162162        return 0
163163    unsigned flags
164    if page->flags & Kernel::Page::UNCACHED:
164    if page->flags & Iris::Page::UNCACHED:
165165        flags = 0x10 | 0x2
166166    else:
167167        // 18 is write-back cache; 00 is write-through cache.
168168        flags = 0x18 | 0x2
169    if ~page->flags & Kernel::Page::MAPPED_READONLY:
169    if ~page->flags & Iris::Page::MAPPED_READONLY:
170170        flags |= 0x4
171171    return ((page->frame & ~0x80000000) >> 6) | flags
172172
mips/init.ccp
3333    idle.schedule_next = NULL
3434    idle.address_space = &idle_memory
3535    idle.refs.reset ()
36    idle.flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV
36    idle.flags = Iris::Thread::RUNNING | Iris::Thread::PRIV
3737    // initialize idle_memory.
3838    idle_memory.prev = NULL
3939    idle_memory.next = NULL
...... 
5252    idle_page.prev = NULL
5353    idle_page.next = NULL
5454    idle_page.frame = 0x80000000
55    idle_page.flags = Kernel::Page::PAYING | Kernel::Page::FRAME
55    idle_page.flags = Iris::Page::PAYING | Iris::Page::FRAME
5656    idle_page.refs.reset ()
5757    idle_page.address_space = NULL
5858    current = &idle
...... 
147147            return
148148        thread->pc = header->e_entry
149149        thread->sp = 0x80000000
150        unsigned *used = (unsigned *)mem->zalloc ()
150        kPage **used = (kPage **)mem->zalloc ()
151151        for unsigned section = 0; section < header->e_shnum; ++section:
152152            Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
153153            if ~shdr->sh_flags & SHF_ALLOC:
...... 
168168                            panic (0, "different pages mapped to one address in intitial file")
169169                            return
170170                        continue
171                    used[idx] = 1
172171                    page = mem->alloc_page ()
173172                    page->frame = thread_start[i] + (idx << PAGE_BITS)
174                    page->flags = Kernel::Page::PAYING | Kernel::Page::FRAME
173                    page->flags = Iris::Page::PAYING | Iris::Page::FRAME
174                    if used[idx]:
175                        page->share_next = used[idx]
176                        used[idx]->share_prev = page
177                        used[idx]->flags |= Iris::Page::SHARED
178                        used[idx] = page
179                        page->flags |= Iris::Page::SHARED
180                    else:
181                        used[idx] = page
175182                    if readonly:
176                        page->flags |= Kernel::Page::MAPPED_READONLY
183                        page->flags |= Iris::Page::MAPPED_READONLY
177184                    if !mem->map (page, p):
178185                        panic (0x22446688, "unable to map initial page")
179186                        return
...... 
200207                        if !page->frame:
201208                            panic (0x02220022, "out of memory");
202209                            return
203                        page->flags = Kernel::Page::PAYING | Kernel::Page::FRAME
210                        page->flags = Iris::Page::PAYING | Iris::Page::FRAME
204211                        if !mem->map (page, p):
205212                            panic (0x33557799, "unable to map initial bss page")
206213                            return
...... 
210217                        kdebug_num (i, 1)
211218                        kdebug ('\n')
212219                    else:
213                        if page->flags & Kernel::Page::MAPPED_READONLY:
220                        if page->flags & Iris::Page::MAPPED_READONLY:
214221                            panic (0x20203030, "bss section starts on read-only page")
215222                            return
216223                        for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
...... 
230237        mem->pfree ((unsigned)used)
231238        kPage *stackpage = mem->alloc_page ()
232239        stackpage->frame = mem->zalloc ()
233        stackpage->flags = Kernel::Page::PAYING | Kernel::Page::FRAME
240        stackpage->flags = Iris::Page::PAYING | Iris::Page::FRAME
234241        if !stackpage || !mem->map (stackpage, 0x7ffff000):
235242            panic (0x13151719, "unable to map initial stack page")
236243            return
...... 
242249        kReceiver *recv = mem->alloc_receiver ()
243250        recv->owner = thread
244251        thread->receivers = recv
245        thread->slot[0].caps->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
246        thread->slot[0].caps->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Kernel::Num ((unsigned)thread), kCapRef (), &thread->refs)
247        thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Kernel::Num ((unsigned)mem), kCapRef (), &mem->refs)
248        thread->slot[0].caps->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Kernel::Receiver::CALL), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
249        thread->flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV
252        thread->slot[0].caps->set (__caps_num, (kReceiverP)(CAPTYPE_CAPS | CAP_MASTER), Iris::Num ((unsigned)thread->slot[0].caps), kCapRef (), &thread->slot[0].caps->refs)
253        thread->slot[0].caps->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Iris::Num ((unsigned)recv), kCapRef (), &recv->refs)
254        thread->slot[0].caps->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Iris::Num ((unsigned)thread), kCapRef (), &thread->refs)
255        thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Iris::Num ((unsigned)mem), kCapRef (), &mem->refs)
256        thread->slot[0].caps->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Iris::Receiver::CALL), Iris::Num ((unsigned)recv), kCapRef (), &recv->refs)
257        thread->flags = Iris::Thread::RUNNING | Iris::Thread::PRIV
250258        if !i:
251259            first_scheduled = thread
252260            init_receiver = recv
mips/interrupts.ccp
3333        schedule ()
3434        if !current:
3535            current = &idle
36    if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING:
36    if (current->flags & (Iris::Thread::RUNNING | Iris::Thread::WAITING)) != Iris::Thread::RUNNING:
3737        panic (current->flags, "non-scheduled thread running")
3838    if old_current == current:
3939        return current
...... 
5454            asids[current->address_space->arch.asid] = (unsigned)current->address_space
5555    cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
5656    directory = current->address_space->arch.directory
57    if current->flags & Kernel::Thread::PRIV:
57    if current->flags & Iris::Thread::PRIV:
5858        cp0_set (CP0_STATUS, 0x1000ff13)
5959    else:
6060        cp0_set (CP0_STATUS, 0x0000ff13)
...... 
6969    if !directory:
7070        unsigned addr
7171        cp0_get (CP0_BAD_V_ADDR, addr)
72        current->raise (Kernel::ERR_NO_PAGE_DIRECTORY, addr)
72        current->raise (Iris::ERR_NO_PAGE_DIRECTORY, addr)
7373        return handle_exit ()
7474    unsigned EntryHi
7575    cp0_get (CP0_ENTRY_HI, EntryHi)
...... 
7777    if !t:
7878        unsigned addr
7979        cp0_get (CP0_BAD_V_ADDR, addr)
80        current->raise (Kernel::ERR_NO_PAGE_TABLE, addr)
80        current->raise (Iris::ERR_NO_PAGE_TABLE, addr)
8181    else:
8282        // - 2 instead of - 1 means reset bit 0
8383        unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
...... 
161161        return
162162    msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
163163    msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
164    msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1])
165    msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3])
164    msg.data[0] = Iris::Num (old_current->arch.a[0], old_current->arch.a[1])
165    msg.data[1] = Iris::Num (old_current->arch.a[2], old_current->arch.a[3])
166    dbg_push (old_current->arch.v[0])
167    dbg_push (old_current->arch.t[0])
168    dbg_push (old_current->arch.t[1])
169    dbg_push (old_current->arch.a[0])
170    dbg_push (old_current->arch.a[1])
171    dbg_push (old_current->arch.a[2])
172    dbg_push (old_current->arch.a[3])
173    dbg_push (0xdeadbeef)
166174    target->invoke (&msg)
175    dbg_push (0xfacebeef)
167176    if do_schedule && !must_wait:
168177        // If the call was to schedule without wait, it isn't done yet.
169178        schedule ()
170    else if old_current != current && (old_current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) == Kernel::Thread::RUNNING:
179    else if old_current != current && old_current && (old_current->flags & (Iris::Thread::RUNNING | Iris::Thread::WAITING)) == Iris::Thread::RUNNING:
171180        // If the caller received an immediate reply from the kernel, it is no longer set as current. Don't let it lose its timeslice.
172181        current = old_current
173182
...... 
186195            // TLB modification.
187196            unsigned addr
188197            cp0_get (CP0_BAD_V_ADDR, addr)
189            current->raise (Kernel::ERR_WRITE_DENIED, addr)
198            current->raise (Iris::ERR_WRITE_DENIED, addr)
190199            break
191200        case 2:
192201            // TLB load or instruction fetch.
193202            unsigned addr
194203            cp0_get (CP0_BAD_V_ADDR, addr)
195            current->raise (Kernel::ERR_UNMAPPED_READ, addr)
204            current->raise (Iris::ERR_UNMAPPED_READ, addr)
196205            break
197206        case 3:
198207            // TLB store.
199208            unsigned addr
200209            cp0_get (CP0_BAD_V_ADDR, addr)
201            current->raise (Kernel::ERR_UNMAPPED_WRITE, addr)
210            current->raise (Iris::ERR_UNMAPPED_WRITE, addr)
202211            break
203212        case 4:
204213            // Address error load or instruction fetch.
205214            unsigned addr
206215            cp0_get (CP0_BAD_V_ADDR, addr)
207            current->raise (Kernel::ERR_INVALID_ADDRESS_READ, addr)
216            current->raise (Iris::ERR_INVALID_ADDRESS_READ, addr)
208217            break
209218        case 5:
210219            // Address error store.
211220            unsigned addr
212221            cp0_get (CP0_BAD_V_ADDR, addr)
213            current->raise (Kernel::ERR_INVALID_ADDRESS_WRITE, addr)
222            current->raise (Iris::ERR_INVALID_ADDRESS_WRITE, addr)
214223            break
215224        case 6:
216225            // Bus error instruction fetch.
...... 
229238        case 9:
230239            // Breakpoint.
231240            #if 0 || defined (NDEBUG)
232            //current->raise (Kernel::ERR_BREAKPOINT, 0)
241            //current->raise (Iris::ERR_BREAKPOINT, 0)
233242            #ifndef NDEBUG
234243            current->pc += 4
235244            #endif
...... 
251260            break
252261        case 10:
253262            // Reserved instruction.
254            current->raise (Kernel::ERR_RESERVED_INSTRUCTION, 0)
263            current->raise (Iris::ERR_RESERVED_INSTRUCTION, 0)
255264            break
256265        case 11:
257266            // Coprocessor unusable.
258            current->raise (Kernel::ERR_COPROCESSOR_UNUSABLE, 0)
267            current->raise (Iris::ERR_COPROCESSOR_UNUSABLE, 0)
259268            break
260269        case 12:
261270            // Arithmetic overflow.
262            current->raise (Kernel::ERR_OVERFLOW, 0)
271            current->raise (Iris::ERR_OVERFLOW, 0)
263272            break
264273        case 13:
265274            // Trap.
266            current->raise (Kernel::ERR_TRAP, 0)
275            current->raise (Iris::ERR_TRAP, 0)
267276            break
268277        case 15:
269278            // Floating point exception.
...... 
272281        case 23:
273282            // Reference to WatchHi/WatchLo address.
274283            cp0_set0 (CP0_WATCH_LO)
275            current->raise (Kernel::ERR_WATCHPOINT, 0)
284            current->raise (Iris::ERR_WATCHPOINT, 0)
276285            break
277286        case 24:
278287            // Machine check.
mips/nanonote/Makefile.arch
2828arch_iris_sources = mips/interrupts.cc mips/arch.cc
2929boot_sources = mips/init.cc mips/nanonote/board.cc
3030arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh
31boot_threads = init udc
32programs = \#nanonote-gpio \#lcd display-emu bsquare display-emu2 ball \#buzzer metronome
31boot_threads = bootinit udc
32programs = init gpio lcd display-emu bsquare ball buzzer metronome elfrun
3333
3434all: test
3535
36test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs)))
36test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config
3737    echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050
3838
3939mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac devices.hh
...... 
5555mips/nanonote/threadlist.o: $(addsuffix .elf,$(boot_threads))
5656mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
5757mips/init.o: TARGET_FLAGS = -I/usr/include
58boot-programs/init.o: TARGET_FLAGS = -I/usr/include
58boot-programs/bootinit.o: TARGET_FLAGS = -I/usr/include
59source/elfrun.o: TARGET_FLAGS = -I/usr/include
60source/gpio.ccp: source/nanonote-gpio.ccp
61    ln -s $(subst source/,,$<) $@
5962$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
6063$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
6164$(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL
6265$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
63source/\#lcd.o: source/charset.data
66source/lcd.o: source/charset.data
6467
6568source/charset.data: source/charset
6669    $< > $@
mips/nanonote/jz4740.hhp
104104// Default lcd framebuffer mapping space.
105105#define LCD_FRAMEBUFFER_BASE ((unsigned *)0x00015000)
106106
107// Map IO memory (requires a priviledged Kernel::my_thread capability).
107// Map IO memory (requires a priviledged Iris::my_thread capability).
108108#include <iris.hh>
109109static void __map_io (unsigned physical, unsigned mapping):
110    Kernel::Page p = Kernel::my_memory.create_page ()
110    Iris::Page p = Iris::my_memory.create_page ()
111111    // false means not cachable; false means don't free when done.
112112    p.alloc_physical (physical, false, false)
113    Kernel::my_memory.map (p, mapping)
114    Kernel::free_cap (p)
113    Iris::my_memory.map (p, mapping)
114    Iris::free_cap (p)
115115
116116#define map_cpm() do { __map_io (CPM_PHYSICAL, CPM_BASE); } while (0)
117117#define map_intc() do { __map_io (INTC_PHYSICAL, INTC_BASE); } while (0)
...... 
135135
136136// udelay implementation
137137void cdelay (unsigned cs):
138    Kernel::my_receiver.set_alarm (cs + 1)
139    Kernel::Cap ().call ()
138    Iris::my_receiver.set_alarm (cs + 1)
139    Iris::Cap ().call ()
140140
141141#endif
142142
mips/nanonote/server/usb-server.ccp
105105            case ~1 & 0xffff:
106106                // No event.
107107                break
108            case Directory::GET_SIZE:
108            case Iris::Directory::GET_SIZE:
109109                unsigned long long size = dir.size ()
110110                std::cerr << "sending dir size\n"
111                std::cerr << Directory::GET_SIZE << '\n'
111                std::cerr << Iris::Directory::GET_SIZE << '\n'
112112                char *str = (char *)&size
113113                for unsigned i = 0; i < 8; ++i:
114114                    std::cerr << " " << (unsigned)(str[i] & 0xff)
115115                std::cerr << '\n'
116                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
116                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Iris::Directory::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
117117                    std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
118118                    usb_release_interface (handle, 0)
119119                    usb_close (handle)
120120                    handle = NULL
121121                    return
122122                continue
123            case Directory::GET_NAME:
123            case Iris::Directory::GET_NAME:
124124                if buffer[1] >= dir.size ():
125125                    std::cerr << "invalid file name requested" << std::endl;
126126                    usb_release_interface (handle, 0)
127127                    usb_close (handle)
128128                    handle = NULL
129129                    return
130                std::cerr << "sending filename\n"
131                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_NAME, 0, 0, dir[buffer[1]].name, 16, timeout) != 16:
130                std::cerr << "sending filename " << dir[buffer[1]].full << "\n"
131                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Iris::Directory::GET_NAME, 0, 0, dir[buffer[1]].name, 16, timeout) != 16:
132132                    std::cerr << "unable to send name to device: " << usb_strerror () << std::endl
133133                    usb_release_interface (handle, 0)
134134                    usb_close (handle)
135135                    handle = NULL
136136                    return
137137                continue
138            case Directory::LOCK_RO:
138            case Iris::Directory::LOCK_RO:
139139                std::cerr << "lock\n"
140140                lock++
141141                std::cerr << "freezing file list\n"
...... 
145145                    if !i->name.empty () && i->name[0] != '.':
146146                        dir.push_back (Name (i->name))
147147                continue
148            case Directory::UNLOCK_RO:
148            case Iris::Directory::UNLOCK_RO:
149149                std::cerr << "unlock\n"
150150                if !lock:
151151                    std::cerr << "unlocking without lock" << std::endl
...... 
156156                if !--lock:
157157                    dir.clear ()
158158                continue
159            case String::GET_PAGE:
159            case Iris::String::GET_PAGE:
160160                if buffer[1] >= dir.size ():
161161                    std::cerr << "reading invalid file" << std::endl
162162                    usb_release_interface (handle, 0)
...... 
178178                        handle = NULL
179179                        return
180180                continue
181            case String::GET_SIZE:
181            case Iris::String::GET_SIZE:
182182                if buffer[1] >= dir.size ():
183                    std::cerr << "reading invalid file size" << std::endl
183                    std::cerr << "reading invalid file size " << buffer[1] << " >= " << dir.size () << std::endl
184184                    usb_release_interface (handle, 0)
185185                    usb_close (handle)
186186                    handle = NULL
187187                    return
188188                unsigned long long size = dir[buffer[1]].content.size ()
189189                std::cerr << "sending file size " << size << "\n"
190                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, String::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
190                if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Iris::String::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8:
191191                    std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
192192                    usb_release_interface (handle, 0)
193193                    usb_close (handle)
...... 
312312    std::cerr << "(re)booted NanoNote\n"
313313
314314static void dump_devices ():
315    std::cerr << std::hex << "String: " << String::ID
316    std::cerr << "\nWString: " << WString::ID
317    std::cerr << "\nDevice: " << Device::ID
318    std::cerr << "\nParent: " << Parent::ID
319    std::cerr << "\nKeyboard: " << Keyboard::ID
320    std::cerr << "\nBuzzer: " << Buzzer::ID
321    std::cerr << "\nDisplay: " << Display::ID
322    std::cerr << "\nSetting: " << Setting::ID
323    std::cerr << "\nDirectory: " << Directory::ID
324    std::cerr << "\nWDirectory: " << WDirectory::ID
325    std::cerr << "\nFilesystem: " << Filesystem::ID
326    std::cerr << "\nStream: " << Stream::ID
315    std::cerr << std::hex << "String: " << Iris::String::ID
316    std::cerr << "\nWString: " << Iris::WString::ID
317    std::cerr << "\nDevice: " << Iris::Device::ID
318    std::cerr << "\nParent: " << Iris::Parent::ID
319    std::cerr << "\nKeyboard: " << Iris::Keyboard::ID
320    std::cerr << "\nBuzzer: " << Iris::Buzzer::ID
321    std::cerr << "\nDisplay: " << Iris::Display::ID
322    std::cerr << "\nSetting: " << Iris::Setting::ID
323    std::cerr << "\nDirectory: " << Iris::Directory::ID
324    std::cerr << "\nWDirectory: " << Iris::WDirectory::ID
325    std::cerr << "\nFilesystem: " << Iris::Filesystem::ID
326    std::cerr << "\nStream: " << Iris::Stream::ID
327327    std::cerr << "\n"
328328
329329int main (int argc, char **argv):
mips/nanonote/threadlist.S
2121
2222    .balign 0x1000
2323thread0:
24    .incbin "init.elf"
24    .incbin "bootinit.elf"
2525
2626    .balign 0x1000
2727thread1:
mips/trendtac/jz4730.hhp
137137// Default lcd framebuffer mapping space.
138138#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00021000)
139139
140// Map IO memory (requires a priviledged Kernel::my_thread capability).
140// Map IO memory (requires a priviledged Iris::my_thread capability).
141141#include <iris.hh>
142142static void __map_io (unsigned physical, unsigned mapping):
143    Kernel::Page p = Kernel::my_memory.create_page ()
143    Iris::Page p = Iris::my_memory.create_page ()
144144    // false means not cachable; false means don't free when done.
145145    p.alloc_physical (physical, false, false)
146    Kernel::my_memory.map (p, mapping)
147    Kernel::free_cap (p)
146    Iris::my_memory.map (p, mapping)
147    Iris::free_cap (p)
148148
149149#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
150150#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0)
...... 
23262326
23272327#ifndef __KERNEL__
23282328static __inline__ void cdelay (unsigned ds):
2329    Kernel::my_receiver.set_alarm (ds * (HZ / 100))
2330    Kernel::Cap ().call (~0)
2329    Iris::my_receiver.set_alarm (ds * (HZ / 100))
2330    Iris::Cap ().call (~0)
23312331#endif
23322332
23332333/***************************************************************************
panic.ccp
4848static void print_addr (char const *t, unsigned addr, bool last = false):
4949    kdebug (t)
5050    kdebug_num (addr)
51    #if 1
51    #if 0
5252    unsigned de = addr >> 21
5353    unsigned te = (addr >> 12) & ((1 << 9) - 1)
5454    if de < 0x400 && old_current && old_current->address_space->arch.directory && old_current->address_space->arch.directory[de]:
...... 
8383            kdebug_num (((unsigned *)addr)[i])
8484        kdebug ("\n")
8585    #else
86    kdebug (last ? '\n' : ';')
86    kdebug (last ? "\n" : "; ")
8787    #endif
8888
8989static void panic_message (unsigned n, const char *line, char const *name, char const *message):
...... 
118118    kdebug (':')
119119    kdebug_num (dbg_code.l)
120120    kdebug ('\n')
121    kdebug ("debug buffer:")
121    kdebug ("debug buffer (most recently pushed at end):")
122122    unsigned b = dbg_buffer_head
123    for unsigned i = 0; i < 16; ++i:
123    for unsigned i = 0; i < 8; ++i:
124124        kdebug ('\n')
125        for unsigned j = 0; j < 2; ++j:
125        for unsigned j = 0; j < 4; ++j:
126126            kdebug (' ')
127127            kdebug_num (dbg_buffer[b])
128128            ++b
plan
4242- start programma van filesystem
4343- nand driver
4444- filesystems met backing store
45
46Boot process:
47- bootinit and filesystem (and backing store) are started.
48- bootinit starts run.elf and loads init.elf.
49- run starts init.
50- init loads init.config and executes it.
51- during that process, the initial programs are killed.
52
53Order:
54run.elf
55init.elf
56init.config
57load.elf
58drivers
59emulations
60programs
61
62init.config is a script:
63
64    # load <name> = <filename> load a file into memory. Don't use this after killbootthreads.
65    load session = session.config
66    load driver_lcd = lcd.elf
67    load driver_buzzer = buzzer.elf
68    load driver_gpio = gpio.elf
69    load driver_audio = audio.elf
70    load driver_udc = udc.elf
71    load driver_nand = nand.elf
72
73    load emu_lcd = emu_display.elf
74    load emu_buzzer = emu_buzzer.elf
75    load emu_keyboard = emu_keyboard.elf
76    load emu_audio = emu_audio.elf
77    load emu_udc = emu_udc.elf
78
79    # killbootthreads destroy bootinit, bootfs and bootstore.
80    killbootthreads
81
82    # receive <cap> = <name> (<type> [, <index>]) prepare to accept a capability from a named program.
83    receive display = driver_lcd (display)
84    receive display_bright = driver_lcd (setting)
85    receive buzzer = driver_buzzer (buzzer)
86    receive keyboard = driver_gpio (keyboard, 0)
87    receive sysreq = driver_gpio (keyboard, 1)
88    receive audio = driver_audio (audio)
89    receive udc = driver_udc (udc)
90    receive nand = driver_nand (wstring)
91
92    # driver <name> run a previously loaded program priviledged.
93    driver driver_lcd
94    driver driver_buzzer
95    driver driver_gpio
96    driver driver_audio
97    driver driver_udc
98    driver driver_nand
99
100    # wait wait until all expected capabilities are received.
101    wait
102
103    # sysreq <cap> use a capability as the system request keyboard.
104    sysreq sysreq
105
106    # give <name> (<type> [, <index>]) = <cap> give this capability to this program when it requests it.
107    give emu_display (display) = display
108    give emu_display_bright (setting) = display_bright
109    give emu_buzzer (buzzer) = buzzer
110    give emu_keyboard (keyboard, 0) = keyboard
111    give emu_audio (audio) = audio
112    give emu_udc (udc) = udc
113
114    # run <name> run a previously loaded program (normally).
115    run emu_lcd
116    run emu_buzzer
117    run emu_keyboard
118    run emu_audio
119    run emu_udc
120
121    # include <name> include a loaded file as another config file.
122    include session
123
124    # loop sit and do nothing (respond to system request).
125    loop
schedule.ccp
3636        thread->schedule_next->schedule_prev = thread->schedule_prev
3737
3838void kThread::run ():
39    if flags & Kernel::Thread::RUNNING:
39    if flags & Iris::Thread::RUNNING:
4040        return
41    flags |= Kernel::Thread::RUNNING
41    flags |= Iris::Thread::RUNNING
4242    if is_waiting ():
4343        return
4444    run_thread (this)
4545
4646void kThread::unrun ():
47    if !(flags & Kernel::Thread::RUNNING):
47    if !(flags & Iris::Thread::RUNNING):
4848        return
49    flags &= ~Kernel::Thread::RUNNING
49    flags &= ~Iris::Thread::RUNNING
5050    if is_waiting ():
5151        return
5252    unrun_thread (this)
5353
5454void kThread::unwait ():
55    flags &= ~Kernel::Thread::WAITING
56    if flags & Kernel::Thread::RUNNING:
55    flags &= ~Iris::Thread::WAITING
56    if flags & Iris::Thread::RUNNING:
5757        run_thread (this)
5858
5959static void alarm_tick (kReceiver *recv):
...... 
7373    --recv->alarm_count
7474
7575void kThread::wait ():
76    if flags & Kernel::Thread::RUNNING:
76    if flags & Iris::Thread::RUNNING:
7777        unrun_thread (this)
78    flags |= Kernel::Thread::WAITING
78    flags |= Iris::Thread::WAITING
7979    // Try to receive a message from a kReceiver immediately.
8080    for kReceiver *r = receivers; r; r = r->next_owned:
8181        if r->try_deliver ():
source/#buzzer.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/buzzer.ccp: Piezo buzzer driver.
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#include "devices.hh"
20#define ARCH
21#include "arch.hh"
22
23class DevBuzzer:
24    static unsigned const pwm = 4
25    Kernel::Cap event
26    bool is_beeping
27    public:
28    DevBuzzer ():
29        is_beeping = false
30        tcu_stop_counter (pwm)
31        tcu_select_extalclk (pwm)
32        tcu_select_clk_div64 (pwm)
33        tcu_enable_pwm_output (pwm)
34    void stop ():
35        if !is_beeping:
36            return
37        tcu_stop_counter (pwm)
38        event.invoke ()
39        Kernel::free_cap (event)
40        is_beeping = false
41    void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
42        stop ()
43        event = cb
44        unsigned full = JZ_EXTAL / 64 / freq
45        tcu_set_full_data (pwm, full)
46        tcu_set_half_data (pwm, full / 2)
47        tcu_set_count (pwm, 0)
48        tcu_start_counter (pwm)
49        Kernel::my_receiver.set_alarm (ms * HZ / 1000)
50        is_beeping = true
51
52enum codes:
53    BUZZER = 32
54
55Kernel::Num start ():
56    map_tcu ()
57
58    DevBuzzer buzzer
59
60    Device dev = Kernel::my_receiver.create_capability (BUZZER)
61    Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
62    Kernel::free_cap (dev)
63    Kernel::my_parent.init_done ()
64    unsigned user (~0)
65    unsigned next_user (0)
66    while true:
67        Kernel::wait ()
68        switch Kernel::recv.protected_data.h:
69            case ~0:
70                // Alarm.
71                buzzer.stop ()
72                break
73            case 0:
74                switch Kernel::recv.protected_data.l:
75                    case BUZZER:
76                        // Buzzer device control request.
77                        Kernel::Cap reply = Kernel::get_reply ()
78                        Kernel::Cap arg = Kernel::get_arg ()
79                        Device::host (BUZZER, user, reply, arg)
80                        break
81                    default:
82                        kdebug ("invalid buzzer request\n")
83                        break
84                break
85            case BUZZER:
86                // Buzzer device user request.
87                if Kernel::recv.protected_data.l != user:
88                    kdebug ("invalid user requesting buzzer\n")
89                    Kernel::recv.reply.invoke ()
90                    break
91                switch Kernel::recv.data[0].l:
92                    case Buzzer::BEEP:
93                        // Volume is not used by this buzzer.
94                        Kernel::Cap arg = Kernel::get_arg ()
95                        Kernel::Cap reply = Kernel::get_reply ()
96                        buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
97                        reply.invoke ()
98                        Kernel::free_cap (reply)
99                        break
100                    case Buzzer::STOP:
101                        buzzer.stop ()
102                        Kernel::recv.reply.invoke ()
103                        break
104                    default:
105                        kdebug ("Buzzer: other\n")
106                        break
107                break
108            default:
109                kdebug ("Buzzer: unknown num: ")
110                kdebug_num (Kernel::recv.protected_data.h)
111                kdebug ("\n")
source/#gpio.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/gpio.ccp: GPIO driver, controlling all devices without special hardware.
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#include "devices.hh"
20#define ARCH
21#include "arch.hh"
22
23// Interval between polls for keyboard events (when keys are pressed)
24#define ALARM_INTERVAL (HZ / 50)
25
26// GPIO pins for the devices (port.pin)
27
28// keyboard
29// Cols = 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15, 3.29
30// Rows = 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7
31// For some reason, it only works if the rows are input and the columns are output.
32// interrupts: yes, with all columns set to output 0, the first key press can be detected as an interrupt; some other events also trigger interrupts.
33
34// touchpad buttons
35// Left: 0.16
36// Right: 0.13
37// interrupts: yes, for any change.
38
39// Lock leds
40// Num lock: 2.22
41// Caps lock: 0.27
42// Scroll lock: 0.9
43// interrupts: no, output only.
44
45// interrupt summary
46// Port 0: pin 0, 1, 2, 3, 4, 5, 6, 7: keyboard; 13, 16: touchpad
47// Port 1: None.
48// Port 2: None.
49// Port 3: None.
50
51enum event_type:
52    KEYBOARD_EVENT
53    TOUCHPAD_EVENT
54    NUM_EVENTS
55
56static Kernel::Cap events[NUM_EVENTS]
57
58static void event (event_type type, unsigned data):
59    events[type].invoke (data)
60
61static void set_cb (event_type type):
62    Kernel::free_cap (events[type])
63    events[type] = Kernel::get_arg ()
64
65class DevKeyboard:
66    static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
67    unsigned keys[GPIO_KBD_NUM_COLS]
68    bool scanning
69    void parse (unsigned col, unsigned data):
70        for unsigned row = 0; row < GPIO_KBD_NUM_ROWS; ++row:
71            if (data ^ keys[col]) & (1 << row):
72                unsigned code = encode[col][row]
73                if data & (1 << row):
74                    code |= Keyboard::RELEASE
75                event (KEYBOARD_EVENT, code)
76        keys[col] = data
77        // If any keys are pressed, scanning is required.
78        if data != GPIO_KBD_ROW_MASK:
79            scanning = true
80    public:
81    bool is_scanning ():
82        return scanning
83    void scan ():
84        // Disable interrupts during scan.
85        GPIO_GPIER (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
86        // All columns are input.
87        GPIO_GPDIR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
88        int const cols[GPIO_KBD_NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
89        unsigned dir = GPIO_GPDIR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
90        unsigned dat = GPIO_GPDR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
91        // Set scanning to false before first parse.
92        scanning = false
93        // Clear all pins. This is only required once, because it's done at the end of the loop as well.
94        GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
95        for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
96            // Set pin to output.
97            GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
98            // Delay for stabalization.
99            for unsigned i = 0; i < 100; ++i:
100                GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
101            // Read the result.
102            unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT) & GPIO_KBD_ROW_MASK
103            // Generate events.
104            parse (col, data)
105            // Set pin to get rid of capacitance effects.
106            GPIO_GPDR (GPIO_KBD_COL_PORT) = dat | (1 << cols[col])
107            // Delay to make the above trick work.
108            for unsigned i = 0; i < 100; ++i:
109                GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
110            // Pin is set to input at the start of the loop.
111        // set all to 0.
112        GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
113        // set all to output.
114        GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
115        // Delay for stabalization.
116        for unsigned i = 0; i < 100; ++i:
117            GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
118        // Set interrupts.
119        unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT)
120        for unsigned i = 0; i < 8; ++i:
121            if data & (1 << i):
122                gpio_irq_low (GPIO_KBD_ROW_PORT, i)
123            else:
124                gpio_irq_high (GPIO_KBD_ROW_PORT, i)
125        // Reenable interrupts.
126        GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
127    DevKeyboard ():
128        // Set all columns to output without pull-ups when set as input.
129        GPIO_GPPUR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
130        GPIO_GPDIR (GPIO_KBD_COL_PORT) |= GPIO_KBD_COL_MASK
131
132        // Set all rows to input and enable the pull-ups.
133        GPIO_GPPUR (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
134        GPIO_GPDIR (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
135        // Initialize things in the same way as when a new callback is set up.
136        send_initial ()
137    void send_initial ():
138        for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
139            keys[col] = 0xff
140        scan ()
141
142enum Keys:
143    N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
144    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
145    F1, F2, F3, F4, F5, F6, F7, F8, F9, F10
146    SPACE, TAB, ENTER, LBRACE, RBRACE, COMMA, PERIOD, MINUS, EQUAL, SLASH, BACKSLASH, SEMICOLON, EXTRA, BACKQUOTE, QUOTE
147    UP, DOWN, LEFT, RIGHT
148    ESC, INSERT, DELETE, BACKSPACE, PAUSE, FN, ZZZ, MENU, SYSRQ
149    LSHIFT, RSHIFT, CTRL, ALT
150    CAPS, NUM
151    NONE = ~Keyboard::RELEASE
152
153unsigned const DevKeyboard::encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] = {
154    { PAUSE, NONE, NONE, NONE, NONE, NONE, CTRL, F5 },
155    { Q, TAB, A, ESC, Z, NONE, BACKQUOTE, N1 },
156    { W, CAPS, S, EXTRA, X, NONE, NONE, N2 },
157    { E, F3, D, F4, C, NONE, NONE, N3 },
158    { R, T, F, G, V, B, N5, N4 },
159    { U, Y, J, H, M, N, N6, N7 },
160    { I, RBRACE, K, F6, COMMA, NONE, EQUAL, N8 },
161    { O, F7, L, NONE, PERIOD, MENU, F8, N9 },
162    { NONE, NONE, NONE, SPACE, NUM, NONE, DELETE, NONE },
163    { NONE, BACKSPACE, NONE, NONE, ENTER, NONE, F9, NONE },
164    { NONE, NONE, NONE, ALT, NONE, NONE, NONE, SYSRQ },
165    { P, LBRACE, SEMICOLON, QUOTE, BACKSLASH, SLASH, MINUS, N0 },
166    { NONE, ZZZ, NONE, NONE, NONE, NONE, NONE, F10 },
167    { NONE, NONE, NONE, NONE, NONE, NONE, F2, NONE },
168    { NONE, NONE, NONE, NONE, NONE, NONE, INSERT, NONE },
169    { NONE, NONE, UP, DOWN, LEFT, RIGHT, NONE, NONE },
170    { NONE, LSHIFT, RSHIFT, NONE, NONE, NONE, F1, FN }}
171
172class Touchpad:
173    unsigned old_state
174    public:
175    void check_events ():
176        unsigned state = GPIO_GPDR (GPIO_TP_LEFT_PORT)
177        if state & (1 << GPIO_TP_LEFT):
178            gpio_irq_low (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
179            if (state ^ old_state) & (1 << GPIO_TP_LEFT):
180                event (TOUCHPAD_EVENT, 0)
181        else:
182            gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
183            if (state ^ old_state) & (1 << GPIO_TP_LEFT):
184                event (TOUCHPAD_EVENT, 0 | Keyboard::RELEASE)
185        if state & (1 << GPIO_TP_RIGHT):
186            gpio_irq_low (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
187            if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
188                event (TOUCHPAD_EVENT, 1)
189        else:
190            gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
191            if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
192                event (TOUCHPAD_EVENT, 1 | Keyboard::RELEASE)
193        old_state = state
194        // Ack interrupts.
195        //GPIO_GPFR (GPIO_TP_LEFT_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
196    Touchpad ():
197        // Set pins to input with pull-ups.
198        gpio_as_input (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
199        gpio_as_input (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
200        GPIO_GPPUR (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
201        // See if they are already pressed. Also set up interrupts. This is done like when a new callback is registered.
202        send_initial ()
203    void send_initial ():
204        old_state = 0
205        check_events ()
206
207class Lockleds:
208    // Note that num lock is in port 2. The others are in port 0.
209    public:
210    Lockleds ():
211        gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
212        gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS)
213        gpio_as_output (GPIO_SCROLL_PORT, GPIO_SCROLL)
214        GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
215        GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
216        GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
217    void set (unsigned state):
218        if state & 4:
219            GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
220        else:
221            GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
222        if state & 2:
223            GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
224        else:
225            GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
226        if state & 1:
227            GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
228        else:
229            GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
230
231// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
232class Pwm:
233    public:
234    Pwm ():
235        GPIO_GPDIR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
236        PWM_PER (0) = 300
237    void set_backlight (unsigned level):
238        if level > 300:
239            level = 300
240        PWM_DUT (0) = level
241        if level:
242            PWM_CTR (0) = 0x80
243            GPIO_GPDR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
244        else:
245            PWM_CTR (0) = 0x00
246            GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
247    // TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
248
249enum codes:
250    KEYBOARD = 32
251    TOUCHPAD
252    LOCKLEDS
253    PWM
254
255Kernel::Num start ():
256    map_gpio ()
257    map_pwm0 ()
258
259    for unsigned i = 0; i < NUM_EVENTS; ++i:
260        events[i] = Kernel::alloc_cap ()
261
262    DevKeyboard kbd
263    Touchpad tp
264    Lockleds leds
265    Pwm pwm
266
267    Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
268    Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
269    Kernel::free_cap (c)
270    c = Kernel::my_receiver.create_capability (TOUCHPAD)
271    Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
272    Kernel::free_cap (c)
273    Kernel::my_parent.init_done ()
274
275    if kbd.is_scanning ():
276        Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
277
278    // Enable interrupts. All are in port 0.
279    GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
280    Kernel::register_interrupt (IRQ_GPIO0)
281
282    while true:
283        Kernel::schedule ()
284        Kernel::wait ()
285        switch Kernel::recv.protected_data.l:
286            case ~0:
287                // Alarm.
288                kbd.scan ()
289                if kbd.is_scanning ():
290                    Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
291                break
292            case IRQ_GPIO0:
293                // Always scan keyboard and touchpad on any interrupt.
294                kbd.scan ()
295                tp.check_events ()
296                // Reregister the interrupt.
297                Kernel::register_interrupt (IRQ_GPIO0)
298                break
299            case KEYBOARD:
300                set_cb (KEYBOARD_EVENT)
301                Kernel::recv.reply.invoke ()
302                kbd.send_initial ()
303                event (KEYBOARD_EVENT, ~0)
304                break
305            case TOUCHPAD:
306                set_cb (TOUCHPAD_EVENT)
307                Kernel::recv.reply.invoke ()
308                tp.send_initial ()
309                event (TOUCHPAD_EVENT, ~0)
310                break
311            case LOCKLEDS:
312                leds.set (Kernel::recv.data[0].l)
313                Kernel::recv.reply.invoke ()
314                break
315            case PWM:
316                pwm.set_backlight (Kernel::recv.data[0].l)
317                Kernel::recv.reply.invoke ()
318                break
319            default:
320                kdebug ("invalid gpio operation ")
321                kdebug_num (Kernel::recv.protected_data.l)
322                kdebug ("\n")
323                break
source/#lcd.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/lcd.ccp: Display driver.
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#include "devices.hh"
20#define ARCH
21#include "arch.hh"
22
23__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"source/charset.data\"\n.section .text")
24extern unsigned char const charset[127-32][8][6]
25
26#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
27
28#if defined (TRENDTAC)
29static unsigned h = 800, v = 480, fps = 60, Bpp = 2
30#define LOG_X_BASE 1
31#define LOG_Y_BASE 1
32#elif defined (NANONOTE)
33static unsigned h = 320, v = 240, fps = 60, Bpp = 4
34#define LOG_X_BASE 0
35#define LOG_Y_BASE 0
36#else
37#error unknown board
38#endif
39#define frame_size (v * h * Bpp)
40
41static unsigned physical_descriptor
42
43/**/struct Descriptor {
44    unsigned next;
45    unsigned frame;
46    unsigned id;
47    unsigned cmd;
48 } __attribute__ ((packed))
49
50#if defined (NANONOTE)
51#define SP_PORT 2
52#define SPEN 21
53#define SPDA 22
54#define SPCK 23
55
56static void udelay (unsigned num):
57    for unsigned i = 0; i < num * (JZ_EXTAL / 1000000); ++i:
58        // set 0 does nothing, but costs at least one clock pulse.
59        gpio_set (SP_PORT, 0)
60
61// Register names. The registers are not named in the datasheet, and in some cases the name only describes a part of the bits in it.
62// The registers with bit 6 set have bit 7 set instead, because of the transfer method.
63enum spi_reg:
64    AC = 0x00
65    DC = 0x01
66    BRIGHTNESS = 0x03
67    FORMAT = 0x04
68    BACKLIGHT1 = 0x05
69    VBLANK = 0x06
70    HBLANK = 0x07
71    BACKLIGHT2 = 0x08
72    SYNC = 0x0b
73    POLARITY = 0x0c
74    CONTRAST_RGB = 0x0d
75    SUB_CONTRAST_R = 0x0e
76    SUB_BRIGHTNESS_R= 0x0f
77    SUB_CONTRAST_B = 0x10
78    SUB_BRIGHTNESS_B= 0x11
79    TRIM = 0x12
80    COLOR = 0x13
81    GAMMA = 0x16
82    GAMMA1 = 0x17
83    GAMMA2 = 0x18
84    GAMMA3 = 0x19
85    GAMMA4 = 0x1a
86    INVERSION = 0xa5
87    HLEVEL = 0xa6
88    LLEVEL = 0xa7
89    FB = 0xb1
90
91static void write_reg (unsigned reg, unsigned val):
92    unsigned value = (reg << 8) | (val & 0xff)
93    gpio_clear (SP_PORT, 1 << SPEN)
94    udelay (1)
95    for unsigned i = 0; i < 16; ++i, value <<= 1:
96        gpio_clear (SP_PORT, 1 << SPCK)
97        if value & 0x8000:
98            gpio_set (SP_PORT, 1 << SPDA)
99        else:
100            gpio_clear (SP_PORT, 1 << SPDA)
101        udelay (4)
102        gpio_set (SP_PORT, 1 << SPCK)
103        udelay (4)
104    gpio_set (SP_PORT, 1 << SPEN)
105    udelay(4)
106#endif
107
108static void reset ():
109    #if defined (TRENDTAC)
110    // Note that the sync pulse is part of the pre-display region.
111    // Vertical timings.
112    unsigned vsync = 20, vpre = 20, vpost = 0
113    // Horizontal timings.
114    unsigned hsync = 80, hpre = 80, hpost = 0
115
116    // One clock pulse per pixel.
117    unsigned cpp = 1
118    // Bits per pixel.
119    unsigned bpp = LCD_CTRL_BPP_16
120    // Configuration.
121    #define MODE_TFT_GEN 0
122    #define VSYNC_N (1 << 8)
123    unsigned cfg = MODE_TFT_GEN | VSYNC_N
124    #elif defined (NANONOTE)
125    // Note that the sync pulse is part of the pre-display region.
126    // Horizontal timings.
127    unsigned hsync = 1, hpre = 70, hpost = 273
128    // Vertical timings.
129    unsigned vsync = 1, vpre = 21, vpost = 2
130    // 3 clocks per pixel.
131    unsigned cpp = 3
132    // Bits per pixel.
133    unsigned bpp = LCD_CTRL_BPP_18_24
134    // Configuration.
135    unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP | LCD_CFG_PCP
136    // Set up SPI pins.
137    gpio_as_output (SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
138    gpio_set (SP_PORT, (1 << SPEN) | (1 << SPCK))
139    #else
140    #error unknown board
141    #endif
142
143    // Note that the sync pulse is part of the pre-display region.
144    unsigned vpe = vsync, vds = vpre, vde = vds + v, vt = vde + vpost
145    unsigned hpe = hsync, hds = hpre, hde = hds + h, ht = hde + hpost
146
147    cpm_stop_lcd ()
148
149    unsigned pixclock = fps * ht * vt
150
151    #if defined (TRENDTAC)
152    unsigned pllout = cpm_get_pllout ()
153    CPM_CFCR2 = pllout / pixclock - 1
154
155    unsigned val = pllout / (pixclock * 4) - 1
156    assert (pllout / (val + 1) <= 150000000)
157    assert (val <= 0xf)
158    cpm_set_lcdclk_div (val)
159    CPM_CFCR |= CPM_CFCR_UPE
160    #elif defined (NANONOTE)
161    unsigned val = cpm_get_pllout2 () / pixclock - 1
162    //assert (val < 0x400)
163    //cpm_set_pixdiv (val)
164    //cpm_set_pixdiv (12)
165
166    val = cpm_get_pllout2 () / (pixclock * 3) - 1
167    assert (val < 0x20)
168    //cpm_set_ldiv (val)
169    // Update dividers.
170    //CPM_CPCCR |= CPM_CPCCR_CE
171    #else
172    #error "Unknown board"
173    #endif
174
175    cpm_start_lcd ()
176
177    #ifdef NANONOTE
178    // Reset the controller.
179    write_reg (BACKLIGHT1, 0x1e)
180    // Enable display.
181    write_reg (BACKLIGHT1, 0x5e)
182    // Set data to rgbrgbrgb input, with a delta color filter.
183    write_reg (COLOR, 0x01)
184    #endif
185
186    LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM
187    LCD_CFG = cfg
188    LCD_HSYNC = hpe
189    LCD_VSYNC = vpe
190    LCD_VAT = (ht << 16) | vt
191    LCD_DAH = (hds << 16) | hde
192    LCD_DAV = (vds << 16) | vde
193    LCD_DA0 = physical_descriptor
194    LCD_STATE = 0
195    LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM | LCD_CTRL_ENA
196
197static void putchar (unsigned x, unsigned y, unsigned ch):
198    if ch < 32 || ch > 126:
199        ch = 127
200    ch -= 32
201    for unsigned k = 0; k < 6; ++k:
202        for unsigned r = 0; r < 8; ++r:
203            LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = charset[ch][r][k] * 0x00010101
204
205
206static unsigned log_x = LOG_X_BASE, log_y = LOG_Y_BASE
207static void inc_logx ():
208    if ++log_x >= h / 6:
209        log_x = LOG_X_BASE
210        if ++log_y >= v / 8:
211            log_y = LOG_Y_BASE
212
213static void log_char (unsigned ch):
214    switch ch:
215        case '\n':
216            while log_x < h / 6:
217                putchar (log_x++, log_y, ' ')
218            inc_logx ()
219            break
220        default:
221            putchar (log_x, log_y, ch)
222            inc_logx ()
223
224static void log_str (char const *str):
225    while *str:
226        log_char (*str++)
227
228static void log_num (Kernel::Num n):
229    char const *encode = "0123456789abcdef"
230    log_char ('[')
231    for unsigned i = 0; i < 8; ++i:
232        log_char (encode[(n.h >> (4 * (7 - i))) & 0xf])
233    log_char (' ')
234    for unsigned i = 0; i < 8; ++i:
235        log_char (encode[(n.l >> (4 * (7 - i))) & 0xf])
236    log_char (']')
237
238static void log_msg ():
239    log_str ("prot:")
240    log_num (Kernel::recv.protected_data)
241    log_str ("data:")
242    for unsigned i = 0; i < 2; ++i:
243        log_num (Kernel::recv.data[i])
244    log_char ('\n')
245
246enum captype:
247    LOG = 32
248    BACKLIGHT
249    LCD
250
251static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
252    unsigned dx2 = (x - cx) * (x - cx)
253    unsigned dy2 = (y - cy) * (y - cy)
254    unsigned d2 = dx2 + dy2
255    unsigned l = 120
256    if d2 >= l * l:
257        return 0
258    return ((l * l - d2 - 1) << 8) / (l * l)
259
260static unsigned pages
261static Descriptor descriptor __attribute__ ((aligned (16)))
262static bool is_on
263
264static unsigned create (Kernel::Memory mem, Kernel::Caps caps):
265    unsigned physical = mem.alloc_range (pages)
266    unsigned address = 0x15000
267    if physical & ~PAGE_MASK:
268        Kernel::panic (0, "can't allocate framebuffer")
269    assert (physical & PAGE_MASK && ~physical)
270    for unsigned i = 0; i < pages; ++i:
271        Kernel::Page p = mem.create_page ()
272        p.alloc_physical (physical + (i << PAGE_BITS), false, true)
273        if address != ~0:
274            mem.map (p, address + (i << PAGE_BITS))
275        Kernel::free_cap (p)
276    return physical
277
278static void destroy (unsigned physical, Kernel::Caps caps):
279    unsigned address = 0x15000
280    Kernel::Memory mem = caps.get (1)
281    if physical == ~0:
282        Kernel::panic (0, "unable to destroy framebuffer with wrong cap0")
283    if descriptor.frame == physical && is_on:
284        lcd_clr_ena ()
285        #ifdef NANONOTE
286        write_reg (BACKLIGHT1, 0x5e)
287        #endif
288    if address != ~0:
289        for unsigned i = 0; i < pages; ++i:
290            Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS)))
291            mem.destroy (p)
292            Kernel::free_cap (p)
293
294static void use (unsigned physical, Kernel::Caps caps):
295    if physical == ~0:
296        Kernel::panic (0, "unable to use framebuffer with wrong cap0")
297    bool was_unused = descriptor.frame == 0
298    descriptor.frame = physical
299    unsigned dptr = (unsigned)&descriptor
300    __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
301    if was_unused && is_on:
302        lcd_set_ena ()
303        #ifdef NANONOTE:
304        write_reg (BACKLIGHT1, 0x5f)
305        #endif
306
307static void unuse (unsigned physical, Kernel::Caps caps):
308    if physical == ~0:
309        Kernel::panic (0, "unable to unuse framebuffer with wrong cap0")
310    if descriptor.frame == physical:
311        lcd_clr_ena ()
312        #ifdef NANONOTE
313        write_reg (BACKLIGHT1, 0x5e)
314        #endif
315        descriptor.frame = 0
316
317Kernel::Num start ():
318    Kernel::schedule ()
319    map_lcd ()
320    map_cpm ()
321    #ifdef NANONOTE
322    map_gpio ()
323    #endif
324
325    pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
326    #if 0
327    unsigned physical = Kernel::my_memory.alloc_range (pages)
328    assert (physical & PAGE_MASK && ~physical)
329    for unsigned i = 0; i < pages; ++i:
330        Kernel::Page p = Kernel::my_memory.create_page ()
331        p.alloc_physical (physical + (i << PAGE_BITS), false, true)
332        Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
333        Kernel::free_cap (p)
334    for unsigned y = 0; y < v; ++y:
335        for unsigned x = 0; x < h; ++x:
336            unsigned r = spot (x, y, 100, 160)
337            unsigned g = spot (x, y, 160, 60)
338            unsigned b = spot (x, y, 220, 160)
339            #if defined (TRENDTAC)
340            LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
341            #elif defined (NANONOTE)
342            LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 16) | (g << 8) | b
343            #else
344            #error "Define your framebuffer format."
345            #endif
346    #else
347    unsigned physical = 0
348    #endif
349    Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
350    unsigned paddr = p.physical_address ()
351    physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
352    Kernel::free_cap (p)
353    descriptor.next = physical_descriptor
354    descriptor.frame = physical
355    descriptor.id = 0xdeadbeef
356    descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
357    unsigned dptr = (unsigned)&descriptor
358    __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
359    reset ()
360
361    #if defined (TRENDTAC)
362    Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
363    __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
364    #endif
365
366    // Register the backlight device.
367    Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
368    Kernel::my_parent.provide_device <Setting> (backlight.copy ())
369    Kernel::free_cap (backlight)
370
371    // Register the display device.
372    Kernel::Cap display = Kernel::my_receiver.create_capability (LCD)
373    Kernel::my_parent.provide_device <Display> (display.copy ())
374    Kernel::free_cap (display)
375    Kernel::my_parent.init_done ()
376
377    Kernel::Cap eof_cb
378    bool have_eof = false
379    is_on = true
380    unsigned lcd_user = 0
381    unsigned current_backlight = 0
382    while true:
383        Kernel::wait ()
384        //log_msg ()
385        switch Kernel::recv.protected_data.h:
386            case 0:
387                switch Kernel::recv.protected_data.l:
388                    case IRQ_LCD:
389                        have_eof = false
390                        eof_cb.invoke ()
391                        Kernel::free_cap (eof_cb)
392                        break
393                    #if defined (TRENDTAC)
394                    case LOG:
395                        log_char (Kernel::recv.data[0].l)
396                        break
397                    #endif
398                    case BACKLIGHT:
399                        Kernel::Cap reply = Kernel::get_reply ()
400                        Kernel::Cap arg = Kernel::get_arg ()
401                        Device::host (BACKLIGHT, current_backlight, reply, arg)
402                        break
403                    case LCD:
404                        Kernel::Cap reply = Kernel::get_reply ()
405                        Kernel::Cap arg = Kernel::get_arg ()
406                        Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse)
407                        break
408                    default:
409                        Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd")
410                        break
411                break
412            case BACKLIGHT:
413                if current_backlight != Kernel::recv.protected_data.l:
414                    log_char ('&')
415                    log_num (current_backlight)
416                    log_num (Kernel::recv.protected_data)
417                    log_char ('\n')
418                    break
419                switch Kernel::recv.data[0].l:
420                    case Setting::SET:
421                        // TODO
422                        unsigned state = Kernel::recv.data[1].l
423                        if !state:
424                            #if defined (NANONOTE)
425                            if is_on:
426                                write_reg (BACKLIGHT1, 0x5e)
427                                is_on = false
428                            #else
429                            #endif
430                        else:
431                            #if defined (NANONOTE)
432                            if !is_on:
433                                write_reg (BACKLIGHT1, 0x5f)
434                                is_on = true
435                            #else
436                            #endif
437                        Kernel::recv.reply.invoke ()
438                        break
439                    case Setting::GET_RANGE:
440                        Kernel::recv.reply.invoke (~0)
441                        break
442                    default:
443                        Kernel::panic (0, "invalid operation for backlight")
444                        break
445                break
446            case LCD:
447                if descriptor.frame != Kernel::recv.protected_data.l:
448                    //Kernel::panic (0, "invalid user requesting lcd")
449                    Kernel::recv.reply.invoke (~0)
450                    break
451                switch Kernel::recv.data[0].l:
452                    case Display::SET_EOF_CB:
453                        Kernel::Cap reply = Kernel::get_reply ()
454                        Kernel::Cap arg = Kernel::get_arg ()
455                        if have_eof:
456                            Kernel::free_cap (eof_cb)
457                            Kernel::panic (0, "replacing eof_cb")
458                        else:
459                            lcd_clr_eof ()
460                            Kernel::register_interrupt (IRQ_LCD)
461                            have_eof = true
462                        eof_cb = arg
463                        reply.invoke ()
464                        Kernel::free_cap (reply)
465                        break
466                    case Display::GET_INFO:
467                        Kernel::panic (0, "get_info isn't defined yet.")
468                    default:
469                        Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd")
470                break
471            default:
472                Kernel::panic (0, "invalid master operation type for lcd")
473                break
source/#nanonote-gpio.ccp
1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/nanonote-gpio.ccp: gpio devices on the nanonote.
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#include "devices.hh"
20#define ARCH
21#include "arch.hh"
22#include "keys.hh"
23
24//#define QI
25#define SCAN_INTERVAL HZ / 50
26
27class DevKbd:
28    static unsigned const NUM_COLS = 8
29    static unsigned const NUM_ROWS = 8
30    static unsigned const COLS_PORT = 2
31    static unsigned const ROWS_PORT = 3
32    static unsigned const ALL_COLS = 0x0003fc00
33    static unsigned const ALL_ROWS = 0x05fc0000
34    static unsigned const COLS[NUM_COLS]
35    static unsigned const ROWS[NUM_ROWS]
36    static unsigned const encode[NUM_ROWS][NUM_COLS]
37    static unsigned const NUM_KEYS = 58
38    static unsigned const keys[NUM_KEYS]
39    unsigned state[NUM_COLS]
40    Kernel::Cap event
41    bool is_active
42    bool is_scanning
43    public:
44    unsigned size ():
45        return NUM_KEYS
46    void send_keys (unsigned first, Kernel::Cap target):
47        unsigned d[4]
48        unsigned i
49        for i = 0; first + i < NUM_KEYS && i < 4; ++i:
50            d[i] = keys[first + i]
51        for ; i < 4; ++i:
52            d[i] = ~0
53        target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
54    bool scanning ():
55        return is_scanning
56    void inactive ():
57        if is_active:
58            Kernel::free_cap (event)
59        is_active = false
60    void check (unsigned col, unsigned rowdata):
61        for unsigned r = 0; r < NUM_ROWS; ++r:
62            if !((rowdata ^ state[col]) & (1 << ROWS[r])):
63                continue
64            unsigned code = encode[r][col]
65            if rowdata & (1 << ROWS[r]):
66                code |= Keyboard::RELEASE
67            if is_active:
68                event.invoke (code)
69        state[col] = rowdata
70    void delay ():
71        for unsigned i = 0; i < 10000; ++i:
72            gpio_set (0, 0)
73    void scan ():
74        unsigned r
75        gpio_mask_irq (ROWS_PORT, ALL_ROWS)
76        is_scanning = false
77        if !is_active:
78            return
79        for unsigned c = 0; c < NUM_COLS; ++c:
80            gpio_as_input (COLS_PORT, ALL_COLS & ~(1 << COLS[c]))
81            gpio_as_output (COLS_PORT, 1 << COLS[c])
82            if c > 0:
83                check (c - 1, r)
84                delay ()
85            else:
86                check (0, state[0])
87                delay ()
88            r = gpio_get_port (ROWS_PORT) & ALL_ROWS
89            if r != ALL_ROWS:
90                is_scanning = true
91        gpio_as_output (COLS_PORT, ALL_COLS)
92        check (NUM_COLS - 1, r)
93        delay ()
94        r = gpio_get_port (ROWS_PORT) & ALL_ROWS
95        unsigned high = 0, low = 0
96        for unsigned i = 0; i < NUM_ROWS; ++i:
97            if r & (1 << ROWS[i]):
98                low |= 1 << ROWS[i]
99            else:
100                high |= 1 << ROWS[i]
101        gpio_as_interrupt (ROWS_PORT, high, true, true)
102        gpio_as_interrupt (ROWS_PORT, low, false, true)
103        gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
104   &