From 12bfb320f773347a3eb5335bdecfed61dec8e6b7 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Fri, 30 Apr 2010 23:13:49 +0200 Subject: [PATCH] make things work with unfinished new startup procedure --- .gitignore | 1 + Makefile | 3 + alloc.ccp | 58 +- boot-programs/bootinit.ccp | 344 +++++++++ boot-programs/crt0.ccp | 34 +- boot-programs/init.ccp | 592 -------------- boot-programs/udc.ccp | 248 +++--- devices.hhp | 724 +++++++++--------- init.config | 59 ++ invoke.ccp | 391 +++++----- iris.hhp | 28 +- kernel.hhp | 32 +- memory.ccp | 2 + mips/arch.ccp | 6 +- mips/init.ccp | 36 +- mips/interrupts.ccp | 45 +- mips/nanonote/Makefile.arch | 13 +- mips/nanonote/jz4740.hhp | 12 +- mips/nanonote/server/usb-server.ccp | 48 +- mips/nanonote/threadlist.S | 2 +- mips/trendtac/jz4730.hhp | 12 +- panic.ccp | 10 +- plan | 81 ++ schedule.ccp | 16 +- source/ball.ccp | 10 +- source/bsquare.ccp | 10 +- source/{#buzzer.ccp => buzzer.ccp} | 52 +- source/crt0.ccp | 60 +- source/display-emu.ccp | 78 +- source/display-emu2.ccp | 1 - source/elfrun.ccp | 286 +++++++ source/gpio.ccp | 1 + source/init.ccp | 412 ++++++++++ source/{#lcd.ccp => lcd.ccp} | 138 ++-- source/metronome.ccp | 22 +- .../{#nanonote-gpio.ccp => nanonote-gpio.ccp} | 104 +-- source/{#gpio.ccp => trendtac-gpio.ccp} | 52 +- 37 files changed, 2374 insertions(+), 1649 deletions(-) create mode 100644 boot-programs/bootinit.ccp delete mode 100644 boot-programs/init.ccp create mode 100644 init.config rename source/{#buzzer.ccp => buzzer.ccp} (67%) delete mode 120000 source/display-emu2.ccp create mode 100644 source/elfrun.ccp create mode 120000 source/gpio.ccp create mode 100644 source/init.ccp rename source/{#lcd.ccp => lcd.ccp} (76%) rename source/{#nanonote-gpio.ccp => nanonote-gpio.ccp} (78%) rename source/{#gpio.ccp => trendtac-gpio.ccp} (90%) diff --git a/.gitignore b/.gitignore index f4d612f..d2091cd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ mips/nanonote/server/depcomp mips/nanonote/server/install-sh mips/nanonote/server/missing mips/nanonote/server/usb-server +fs/ diff --git a/Makefile b/Makefile index 8ebd14d..0595de3 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,9 @@ fs/%.elf: source/crt0.o source/%.o $(LD) $(LDFLAGS) $(filter %.o,$^) -o $@ $(OBJCOPY) -S $(OBJCOPYFLAGS) $@ +fs/%: % + ln -s ../$< $@ + clean: rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES) diff --git a/alloc.ccp b/alloc.ccp index 29b9047..88fc14a 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -171,6 +171,9 @@ void kMemory::free_obj (kObject *obj, kPointer *first): ((kFree *)self->prev)->next = self->next else: frees = (kFree *)self->next + //kdebug ("freeing page: ") + //kdebug_num ((unsigned)self - SIZE) + //kdebug ("\n") pfree ((unsigned)self - SIZE) kPage *kMemory::alloc_page (): @@ -292,7 +295,7 @@ kMemory *kMemory::alloc_memory (): kMemory_arch_init (ret) return ret -void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr): +void kCaps::set (unsigned index, kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr): if index >= size: kdebug ("size: ") kdebug_num (size) @@ -300,11 +303,6 @@ void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef p dpanic (index, "index too large for kCaps") return kCapability *c = &caps[index] - if (unsigned)target == 0x81fdc350: - kdebug ("setting cap ") - kdebug_num (index) - kdebug (" old target: ") - kdebug_num ((unsigned)c->target) c->target = target c->protected_data = pdata c->parent = parent @@ -321,8 +319,6 @@ void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef p c->sibling_next.reset () if c->sibling_next.valid (): c->sibling_next->sibling_prev = kCapRef (this, index) - if (unsigned)target == 0x81fdc350: - kdebug (" done\n") void kCaps::clone (unsigned index, kCapRef source, bool copy): cap (index)->invalidate () @@ -341,10 +337,9 @@ void kCaps::clone (unsigned index, kCapRef source, bool copy): void kMemory::free_page (kPage *page): if page->mapping != ~0: page->address_space->unmap (page) - if page->flags & Kernel::Page::PAYING: + page->forget () + if page->flags & Iris::Page::PAYING: unuse () - if page->frame: - pfree (page->frame) free_obj (page, (kPointer *)&pages) void kThread::unset_slot (unsigned s): @@ -367,6 +362,8 @@ void kMemory::free_thread (kThread *thread): for unsigned i = 0; i < thread->slots; ++i: thread->unset_slot (i) free_obj (thread, (void **)&threads) + if old_current == thread: + old_current = NULL void kMemory::free_message (kReceiver *owner, kMessage *message): for unsigned i = 0; i < 2; ++i: @@ -382,11 +379,15 @@ void kMemory::free_receiver (kReceiver *receiver): while receiver->messages: free_message (receiver, receiver->messages) free_obj (receiver, (void **)&receivers) + if receiver == reply_target: + reply_target = NULL + // Signal that it is correct to not reply here. + reply_protected.l = 1 void kReceiver::orphan (): if prev_owned: prev_owned->next_owned = next_owned - else: + else if owner: owner->receivers = next_owned if next_owned: next_owned->prev_owned = prev_owned @@ -404,10 +405,14 @@ void kReceiver::own (kThread *o): void kCapability::invalidate (): if !target: return + //kdebug_num ((unsigned)this) + //kdebug ("\n") //kdebug_num ((unsigned)target) //kdebug (":") //kdebug_num ((unsigned)protected_data.l) //kdebug ("\n") + if (unsigned)this == dbg_code.h: + dpanic (0, "invalidating watched capability") if sibling_prev.valid (): sibling_prev->sibling_next = sibling_next else if parent.valid (): @@ -429,6 +434,8 @@ void kCapability::invalidate (): if !next: next = c->parent.deref () c->target = NULL + if c->parent.valid (): + c->parent->children = c->sibling_next c->parent.reset () c->children.reset () c->sibling_prev.reset () @@ -492,19 +499,24 @@ void kMemory::free_list (kList *l): void kMemory::free_memory (kMemory *mem): while mem->pages: - free_page (mem->pages) + //kdebug ("freeing page ") + //kdebug_num ((unsigned)mem->pages) + //kdebug (", next = ") + //kdebug_num ((unsigned)mem->pages->next) + //kdebug ("\n") + mem->free_page (mem->pages) while mem->capses: - free_caps (mem->capses) + mem->free_caps (mem->capses) while mem->threads: - free_thread (mem->threads) + mem->free_thread (mem->threads) while mem->memories: - free_memory (mem->memories) + mem->free_memory (mem->memories) while mem->receivers: - free_receiver (mem->receivers) + mem->free_receiver (mem->receivers) while mem->lists: - free_list (mem->lists) + mem->free_list (mem->lists) while mem->listitems: - free_listitem (mem->listitems) + mem->free_listitem (mem->listitems) if mem->frees: panic (0, "kernel memory leak: memory still in use") free_obj (mem, (void **)&memories) @@ -519,10 +531,10 @@ void kPage::forget (): share_next = NULL else: // If the page has a frame and should be freed, free it. - if !((flags ^ Kernel::Page::FRAME) & (Kernel::Page::PHYSICAL | Kernel::Page::FRAME)): + if !((flags ^ Iris::Page::FRAME) & (Iris::Page::PHYSICAL | Iris::Page::FRAME)): raw_pfree (frame) frame = 0 - flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED) + flags &= ~(Iris::Page::FRAME | Iris::Page::SHARED | Iris::Page::PHYSICAL | Iris::Page::UNCACHED) kPage_arch_update_mapping (this) static void check_receiver (kReceiver *r, kCapRef cap, unsigned line): @@ -546,6 +558,8 @@ static void check_receiver (kReceiver *r, kCapRef cap, unsigned line): kdebug ("!= receiver\n") dpanic (line, "consistency bug in kernel capabilities") for kCapRef c = cap->children; c.valid (); c = c->sibling_next: + if c->protected_data.value () != cap->protected_data.value () || c->target != cap->target: + dpanic (line, "capability db bug") check_receiver (r, c, line) void kReceiver::check (unsigned line): @@ -556,7 +570,7 @@ void kMemory::check (unsigned line): for kReceiver *r = receivers; r; r = (kReceiver *)r->next: r->check (line) for kThread *t = threads; t; t = (kThread *)t->next: - if t->flags & Kernel::Thread::RUNNING && t->pc == 0: + if t->flags & Iris::Thread::RUNNING && t->pc == 0: kdebug_num ((unsigned)t) kdebug ("\n") panic (line, "pc is 0") diff --git a/boot-programs/bootinit.ccp b/boot-programs/bootinit.ccp new file mode 100644 index 0000000..cbd0943 --- /dev/null +++ b/boot-programs/bootinit.ccp @@ -0,0 +1,344 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// boot-programs/bootinit.ccp: Bootstrapping code. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "devices.hh" +#include "iris.hh" +#include + +#define ELFRUN_NAME "elfrun.elf" +#define INIT_NAME "init.elf" +#define NUM_SLOTS 8 +#define NUM_CAPS 32 + +static unsigned _free +extern unsigned _end + +void init_alloc (): + _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK + +char *alloc_space (unsigned pages): + unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK + _free = ret + (pages << PAGE_BITS) + return (char *)ret + +void *operator new[] (unsigned size): + //kdebug ("new ") + void *ret = (void *)_free + size = (size + 3) & ~3 + unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1) + if rest < size: + unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS + for unsigned p = 0; p < pages; ++p: + Iris::Page page = Iris::my_memory.create_page () + page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) + Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS)) + Iris::free_cap (page) + _free += size + //kdebug_num ((unsigned)ret) + //kdebug ("+") + //kdebug_num (size) + //kdebug ("\n") + return ret + +void *operator new (unsigned size): + return new char[size] + +static bool have_data_mem, have_fs_mem +static Iris::Memory data_mem, fs_mem + +// Get the initial block device and filesystem. +static Iris::Directory receive_devices (): + Iris::Caps data, fs + bool have_data = false, have_fs = false + Iris::Device fs_dev, data_dev + for unsigned i = 0; i < 2; ++i: + Iris::wait () + if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE: + Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.") + switch Iris::recv.data[1].l: + case Iris::String::ID: + if have_data: + Iris::panic (0, "duplicate device.") + data_dev = Iris::get_arg () + Iris::recv.reply.invoke () + have_data = true + break + case Iris::Filesystem::ID: + if have_fs: + Iris::panic (0, "duplicate filesystem.") + fs_dev = Iris::get_arg () + Iris::recv.reply.invoke () + have_fs = true + break + default: + Iris::panic (Iris::recv.data[1].l, "unexpected device") + // Initialize the root file system. + data = data_dev.create_user (Iris::my_memory) + data_dev.use (data) + fs = fs_dev.create_user (Iris::my_memory) + fs_dev.use (fs) + Iris::Filesystem fs_cap = fs.get (0) + Iris::Directory root = fs_cap.use_device_ro (data.copy ()) + have_data_mem = data_dev.call (0).l + if have_data_mem: + data_mem = Iris::get_arg () + have_fs_mem = fs_dev.call (0).l + if have_fs_mem: + fs_mem = Iris::get_arg () + Iris::free_cap (data) + Iris::free_cap (fs) + Iris::free_cap (fs_cap) + Iris::free_cap (data_dev) + Iris::free_cap (fs_dev) + return root + +static bool stringcmp (char const *s1, char const *s2, unsigned size): + for unsigned t = 0; t < size; ++t: + if s1[t] != s2[t]: + return false + return true + +static Iris::String find (Iris::Directory root, char const *name): + unsigned size = 0 + while name[size]: + ++size + Iris::Num num_files = root.get_size () + for Iris::Num i = 0; i.value () < num_files.value (); i = i.value () + 1: + Iris::String n = root.get_name (i) + char current_name[16] + n.get_chars (0, current_name) + Iris::free_cap (n) + if !stringcmp (current_name, name, size): + continue + // Found elfrun. + Iris::String ret = root.get_file_ro (i) + return ret + Iris::panic (0, "bootfile not found") + +static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent): + // Get the size. + Iris::Num size = data.get_size () + if size.value () == 0: + Iris::panic (0, "elfrun is empty") + // Allocate a caps with all the pages. + unsigned pages = (size.value () + PAGE_SIZE - 1) >> PAGE_BITS + Iris::Caps pages_caps = Iris::my_memory.create_caps (pages) + unsigned slot = pages_caps.use () + // Map them into the address space as well. + char *mapping = alloc_space (pages) + // Create a memory for the program. + Iris::Memory mem = parent_memory.create_memory () + // Load the file into memory and map it. + for unsigned p = 0; p < pages; ++p: + //kdebug_num (p) + //kdebug ("/") + //kdebug_num (pages) + //kdebug ("\n") + Iris::set_recv_arg (Iris::Cap (slot, p)) + Iris::my_memory.create_page () + Iris::Page (slot, p).set_flags (Iris::Page::PAYING, Iris::Page::PAYING) + data.get_page (p << PAGE_BITS, Iris::Cap (slot, p)) + Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS]) + Iris::Thread thread = mem.create_thread (NUM_SLOTS) + Elf32_Ehdr *header = (Elf32_Ehdr *)mapping + for unsigned j = 0; j < SELFMAG; ++j: + if header->e_ident[j] != ELFMAG[j]: + Iris::panic (header->e_ident[j], "invalid ELF magic") + return + if header->e_ident[EI_CLASS] != ELFCLASS32: + kdebug ("invalid ELF class:") + kdebug_num (header->e_ident[EI_CLASS]) + kdebug (" != ") + kdebug_num (ELFCLASS32) + kdebug ("\n") + Iris::panic (0) + return + if header->e_ident[EI_DATA] != ELFDATA2LSB: + Iris::panic (header->e_ident[EI_DATA], "invalid ELF data") + if header->e_ident[EI_VERSION] != EV_CURRENT: + Iris::panic (header->e_ident[EI_VERSION], "invalid ELF version") + if header->e_type != ET_EXEC: + Iris::panic (header->e_type, "invalid ELF type") + if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS: + Iris::panic (header->e_machine, "invalid ELF machine") + thread.set_pc (header->e_entry) + thread.set_sp (0x80000000) + for unsigned section = 0; section < header->e_shnum; ++section: + Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize) + if ~shdr->sh_flags & SHF_ALLOC: + continue + bool readonly = !(shdr->sh_flags & SHF_WRITE) + //bool executable = shdr->sh_flags & SHF_EXEC_INSTR + if shdr->sh_type != SHT_NOBITS: + unsigned file_offset = shdr->sh_offset >> PAGE_BITS + if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2): + Iris::panic (shdr->sh_size, "thread too large") + return + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS + unsigned idx = file_offset + section_offset + Iris::Page page = mem.mapping ((void *)p) + if Iris::recv.data[0].l == Iris::NO_ERROR: + // The address already has a mapping; assume that it is correct. + Iris::free_cap (page) + continue + Iris::free_cap (page) + page = mem.create_page () + unsigned f + if readonly: + f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY + else: + f = Iris::Page::PAYING + page.set_flags (f, f) + Iris::Page (slot, idx).share (page, 0) + //kdebug ("mapping at ") + //kdebug_num (p) + //if readonly: + // kdebug (" (readonly)") + //kdebug ("\n") + if !mem.map (page, p): + Iris::panic (0, "unable to map page") + return + Iris::free_cap (page) + else: + if readonly: + Iris::panic (0, "unwritable bss section") + return + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + Iris::Page page = mem.mapping ((void *)p) + if Iris::recv.data[0].l == Iris::NO_ERROR: + // No error means there is a mapping. + Iris::free_cap (page) + for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4: + if a >= shdr->sh_addr + shdr->sh_size: + break + if a < shdr->sh_addr: + continue + ((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0 + else: + Iris::free_cap (page) + page = mem.create_page () + if Iris::recv.data[0].l != Iris::NO_ERROR: + Iris::panic (Iris::recv.data[0].l, "out of memory") + if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME): + Iris::panic (0, "out of memory") + if !mem.map (page, p): + Iris::panic (0, "unable to map bss page") + Iris::free_cap (page) + for unsigned p = 0; p < pages; ++p: + Iris::my_memory.destroy (Iris::Page (slot, p)) + Iris::my_memory.destroy (pages_caps) + Iris::free_slot (slot) + Iris::Page stackpage = mem.create_page () + stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) + if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000): + Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page") + Iris::free_cap (stackpage) + Iris::Caps caps = mem.create_caps (NUM_CAPS) + thread.use (caps, 0) + thread.set_info (Iris::Thread::A0, NUM_SLOTS) + thread.set_info (Iris::Thread::A1, NUM_CAPS) + Iris::Receiver receiver = mem.create_receiver () + receiver.set_owner (thread.copy ()) + Iris::Cap call = receiver.create_call_capability () + caps.set (__caps_num, caps.copy ()) + caps.set (__receiver_num, receiver.copy ()) + caps.set (__thread_num, thread.copy ()) + caps.set (__memory_num, mem.copy ()) + caps.set (__call_num, call.copy ()) + caps.set (__parent_num, parent) + thread.run () + Iris::free_cap (receiver) + Iris::free_cap (thread) + Iris::free_cap (call) + Iris::free_cap (caps) + +Iris::Num start (): + // Wait for the debugging device to be active, in case there is one. + Iris::schedule () + kdebug ("Starting bootinit\n") + init_alloc () + Iris::Memory top_memory = Iris::get_top_memory () + Iris::Directory root = receive_devices () + root.lock_ro () + Iris::String run_string = find (root, ELFRUN_NAME) + Iris::Cap parent_cap = Iris::my_receiver.create_capability (0) + run (run_string, top_memory, parent_cap) + Iris::wait () + if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE || Iris::recv.data[1].l != Iris::Elfrun::ID: + Iris::panic (0, "elfrun doesn't provide correct capability") + Iris::Cap reply = Iris::get_reply () + Iris::Device elfrun_dev = Iris::get_arg () + Iris::my_caps.set (parent_cap.idx (), Iris::Cap (CAP_NONE)) + Iris::free_cap (parent_cap) + reply.invoke () + Iris::free_cap (reply) + + parent_cap = Iris::my_receiver.create_capability (0) + Iris::Caps elfrun = elfrun_dev.create_user (Iris::my_memory) + elfrun_dev.use (elfrun) + Iris::Elfrun elfrun_cap = elfrun.get (0) + Iris::free_cap (elfrun) + Iris::String init_string = find (root, INIT_NAME) + Iris::Caps init_caps = elfrun_cap.run_string (top_memory.copy (), init_string.copy (), parent_cap.copy ()) + + Iris::Thread init = init_caps.get (__thread_num) + init.make_priv () + init.run () + Iris::free_cap (init) + Iris::free_cap (init_caps) + + bool have_root = false + bool have_elfrun = false + while true: + Iris::wait () + switch Iris::recv.data[0].l: + case Iris::Parent::GET_DEVICE: + switch Iris::recv.data[1].l: + case Iris::Directory::ID: + if have_root: + Iris::panic (0, "Init requests root directory twice") + Iris::recv.reply.invoke (0, 0, root.copy ()) + have_root = true + break + case Iris::Elfrun::ID: + if have_elfrun: + Iris::panic (0, "Init requests elfrun twice") + Iris::recv.reply.invoke (0, 0, elfrun_cap.copy ()) + have_elfrun = true + break + default: + Iris::panic (0, "Invalid device requested by init") + break + case Iris::Parent::INIT_DONE: + if Iris::recv.data[1].value () != 0: + Iris::recv.reply.invoke () + break + // Special response: kill boot threads. + Iris::Cap reply = Iris::get_reply () + root.unlock_ro () + if have_data_mem: + top_memory.destroy (data_mem) + if have_fs_mem: + top_memory.destroy (fs_mem) + reply.invoke () + Iris::free_cap (reply) + top_memory.destroy (Iris::my_memory) + Iris::panic (0, "bootinit should be destroyed") + default: + Iris::panic (Iris::recv.data[0].l, "invalid operation from init") diff --git a/boot-programs/crt0.ccp b/boot-programs/crt0.ccp index c0d91bc..0befa90 100644 --- a/boot-programs/crt0.ccp +++ b/boot-programs/crt0.ccp @@ -29,7 +29,8 @@ static unsigned __slots, __caps static list *__slot_admin, *__cap_admin static list *__first_free_slot, *__first_free_cap -namespace Kernel: +namespace Iris: + Caps my_caps Receiver my_receiver Thread my_thread Memory my_memory @@ -77,7 +78,7 @@ namespace Kernel: if !__first_free_slot: // Out of slots... Probably best to raise an exception. For now, just return NO_SLOT. kdebug ("out of slots!\n") - Kernel::panic (0) + Iris::panic (0) return ~0 list *ret = __first_free_slot __first_free_slot = ret->next @@ -90,7 +91,7 @@ namespace Kernel: if !__first_free_cap: // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE kdebug ("out of capabilities!\n") - Kernel::panic (0) + Iris::panic (0) return Cap (0, CAP_NONE) list *ret = __first_free_cap __first_free_cap = ret->next @@ -106,20 +107,21 @@ extern "C": __cap_admin = cap_admin __first_free_slot = NULL for unsigned i = 1; i < __slots; ++i: - Kernel::free_slot (i) + Iris::free_slot (i) __first_free_cap = NULL - for unsigned i = 7; i < __caps; ++i: - Kernel::free_cap (Kernel::Cap (0, i)) - Kernel::my_receiver = Kernel::Cap (0, __receiver_num) - Kernel::my_thread = Kernel::Cap (0, __thread_num) - Kernel::my_memory = Kernel::Cap (0, __memory_num) - Kernel::my_call = Kernel::Cap (0, __call_num) - Kernel::my_parent = Kernel::Cap (0, __parent_num) - Kernel::recv.reply = Kernel::alloc_cap () - Kernel::recv.arg = Kernel::alloc_cap () - Kernel::Num ret = start () - Kernel::my_parent.exit (ret) - Kernel::my_memory.destroy (Kernel::my_thread) + for unsigned i = 6; i < __caps; ++i: + Iris::free_cap (Iris::Cap (0, i)) + Iris::my_caps = Iris::Cap (0, __caps_num) + Iris::my_receiver = Iris::Cap (0, __receiver_num) + Iris::my_thread = Iris::Cap (0, __thread_num) + Iris::my_memory = Iris::Cap (0, __memory_num) + Iris::my_call = Iris::Cap (0, __call_num) + Iris::my_parent = Iris::Cap (0, __parent_num) + Iris::recv.reply = Iris::alloc_cap () + Iris::recv.arg = Iris::alloc_cap () + Iris::Num ret = start () + Iris::my_parent.exit (ret) + Iris::my_memory.destroy (Iris::my_thread) // The program no longer exists. If it somehow does, generate an address fault. while true: *(volatile unsigned *)~0 diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp deleted file mode 100644 index c9a8cb2..0000000 --- a/boot-programs/init.ccp +++ /dev/null @@ -1,592 +0,0 @@ -#pypp 0 -// Iris: micro-kernel for a capability-based operating system. -// bootstrap/init.ccp: Bootstrapping code. -// Copyright 2009 Bas Wijnen -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "devices.hh" -#include "iris.hh" -#include "keys.hh" -#include - -#define NUM_SLOTS 8 -#define NUM_CAPS 32 - -enum Cap_codes: - SYSREQ = 1 << 16 - THREAD - KEYBOARD - -static unsigned _free -extern unsigned _end - -void init_alloc (): - _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK - -char *alloc_space (unsigned pages): - unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK - _free = ret + (pages << PAGE_BITS) - return (char *)ret - -void *operator new[] (unsigned size): - //kdebug ("new ") - void *ret = (void *)_free - size = (size + 3) & ~3 - unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1) - if rest < size: - unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS - for unsigned p = 0; p < pages; ++p: - Kernel::Page page = Kernel::my_memory.create_page () - page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME) - Kernel::my_memory.map (page, _free + rest + (p << PAGE_BITS)) - Kernel::free_cap (page) - _free += size - //kdebug_num ((unsigned)ret) - //kdebug ("+") - //kdebug_num (size) - //kdebug ("\n") - return ret - -void *operator new (unsigned size): - return new char[size] - -struct file: - unsigned size - // Only the first 16 characters of the name are used, because that's much easier. - // This means that file names must be different in the first 16 characters if sort order matters. - char name[16] - String string - -static unsigned num_files -static file *files -static unsigned *index -static Kernel::Memory top_memory -static unsigned slot -static unsigned max_pages -static char *mapping -static unsigned current_thread -static Kernel::Caps terminals -static unsigned terminal_slot -static Kernel::Caps memories -static unsigned memory_slot -static unsigned *inuse - -// Get the initial block device and filesystem. -static Directory receive_devices (): - Kernel::Caps data, fs - bool have_data = false, have_fs = false - Device fs_dev, data_dev - for unsigned i = 0; i < 2; ++i: - Kernel::wait () - if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE: - Kernel::panic (Kernel::recv.data[0].l, "Invalid bootstrap request.") - switch Kernel::recv.data[1].l: - case String::ID: - if have_data: - Kernel::panic (0, "duplicate device.") - data_dev = Kernel::get_arg () - Kernel::recv.reply.invoke () - have_data = true - break - case Filesystem::ID: - if have_fs: - Kernel::panic (0, "duplicate filesystem.") - fs_dev = Kernel::get_arg () - Kernel::recv.reply.invoke () - have_fs = true - break - default: - Kernel::panic (Kernel::recv.data[1].l, "unexpected device") - // Initialize the root file system. - data = data_dev.create_user (Kernel::my_memory) - data_dev.use (data) - fs = fs_dev.create_user (Kernel::my_memory) - fs_dev.use (fs) - Filesystem fs_cap = fs.get (0) - Directory root = fs_cap.use_device_ro (data.copy ()) - Kernel::free_cap (data) - Kernel::free_cap (fs) - Kernel::free_cap (fs_cap) - Kernel::free_cap (data_dev) - Kernel::free_cap (fs_dev) - return root - -// Make a list of all files. -static void list_files (Directory root): - Kernel::Num fullsize = root.get_size () - if fullsize.h != 0: - kdebug ("Too many files in bootstrap directory:") - kdebug_num (fullsize.h) - kdebug (":") - kdebug_num (fullsize.l) - kdebug ("\n") - Kernel::panic (0) - num_files = fullsize.l - files = new file[num_files] - Kernel::Caps caps = Kernel::my_memory.create_caps (num_files) - unsigned slot = Kernel::alloc_slot () - caps.use (slot) - Kernel::free_cap (caps) - for unsigned i = 0; i < num_files; ++i: - String n = root.get_name (i) - n.get_chars (0, files[i].name) - Kernel::free_cap (n) - Kernel::set_recv_arg (Kernel::Cap (slot, i)) - files[i].string = root.get_file_ro (i) - Kernel::Num fullsize = files[i].string.get_size () - if fullsize.h != 0: - kdebug ("initial file size too large: ") - kdebug_num (fullsize.h) - kdebug (":") - kdebug_num (fullsize.l) - kdebug (".\n") - Kernel::panic (0) - files[i].size = fullsize.l - if max_pages < (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS: - max_pages = (fullsize.l + PAGE_SIZE - 1) >> PAGE_BITS - -// Sort the list of files. -static bool is_less (file *f1, file *f2): - for unsigned i = 0; i < 16; ++i: - if f1->name[i] < f2->name[i]: - return true - if f1->name[i] > f2->name[i]: - return false - return false - -// Bubble sort. -static void sort (): - index = new unsigned[num_files] - index[0] = 0 - // Invariant: index[0...f-1] is sorted. - for unsigned f = 1; f < num_files; ++f: - // Bubble up until top. Test for less-than, because it wraps to maxunsigned. - unsigned i - // Invariant: index[0...f] \ index[i+1] is sorted and index[i+1...f] is sorted. - for i = f - 1; i < f; --i: - if is_less (&files[index[i]], &files[f]): - break - index[i + 1] = index[i] - index[i + 1] = f - -static void run (file *f, bool priv, int id): - Kernel::Memory mem = Kernel::Cap (memory_slot, id) - Kernel::set_recv_arg (mem) - top_memory.create_memory () - unsigned num_pages = (f->size + PAGE_SIZE - 1) >> PAGE_BITS - for unsigned p = 0; p < num_pages; ++p: - //kdebug_num (p) - //kdebug ("/") - //kdebug_num (num_pages) - //kdebug ("\n") - Kernel::set_recv_arg (Kernel::Cap (slot, p)) - Kernel::my_memory.create_page () - Kernel::Page (slot, p).set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING) - f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p)) - Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS]) - Kernel::Thread thread = mem.create_thread (NUM_SLOTS) - if priv: - thread.make_priv () - Elf32_Ehdr *header = (Elf32_Ehdr *)mapping - for unsigned j = 0; j < SELFMAG; ++j: - if header->e_ident[j] != ELFMAG[j]: - Kernel::panic (header->e_ident[j], "invalid ELF magic") - return - if header->e_ident[EI_CLASS] != ELFCLASS32: - kdebug ("invalid ELF class:") - kdebug_num (header->e_ident[EI_CLASS]) - kdebug (" != ") - kdebug_num (ELFCLASS32) - kdebug ("\n") - Kernel::panic (0) - return - if header->e_ident[EI_DATA] != ELFDATA2LSB: - Kernel::panic (header->e_ident[EI_DATA], "invalid ELF data") - if header->e_ident[EI_VERSION] != EV_CURRENT: - Kernel::panic (header->e_ident[EI_VERSION], "invalid ELF version") - if header->e_type != ET_EXEC: - Kernel::panic (header->e_type, "invalid ELF type") - if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS: - Kernel::panic (header->e_machine, "invalid ELF machine") - thread.set_pc (header->e_entry) - thread.set_sp (0x80000000) - for unsigned section = 0; section < header->e_shnum; ++section: - Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize) - if ~shdr->sh_flags & SHF_ALLOC: - continue - bool readonly = !(shdr->sh_flags & SHF_WRITE) - //bool executable = shdr->sh_flags & SHF_EXEC_INSTR - if shdr->sh_type != SHT_NOBITS: - unsigned file_offset = shdr->sh_offset >> PAGE_BITS - if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2): - Kernel::panic (shdr->sh_size, "thread too large") - return - for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: - unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS - unsigned idx = file_offset + section_offset - Kernel::Page page = mem.mapping ((void *)p) - if Kernel::recv.data[0].l == Kernel::NO_ERROR: - // The address already has a mapping; assume that it is correct. - Kernel::free_cap (page) - continue - Kernel::free_cap (page) - page = mem.create_page () - unsigned f - if readonly: - f = Kernel::Page::PAYING | Kernel::Page::MAPPED_READONLY - else: - f = Kernel::Page::PAYING - page.set_flags (f, f) - Kernel::Page (slot, idx).share (page, 0) - //kdebug ("mapping at ") - //kdebug_num (p) - //if readonly: - // kdebug (" (readonly)") - //kdebug ("\n") - if !mem.map (page, p): - Kernel::panic (0, "unable to map page") - return - Kernel::free_cap (page) - else: - if readonly: - Kernel::panic (0, "unwritable bss section") - return - for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: - Kernel::Page page = mem.mapping ((void *)p) - if Kernel::recv.data[0].l == Kernel::NO_ERROR: - // No error means there is a mapping. - Kernel::free_cap (page) - for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4: - if a >= shdr->sh_addr + shdr->sh_size: - break - if a < shdr->sh_addr: - continue - ((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0 - else: - Kernel::free_cap (page) - page = mem.create_page () - if Kernel::recv.data[0].l != Kernel::NO_ERROR: - Kernel::panic (Kernel::recv.data[0].l, "out of memory") - if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME): - Kernel::panic (0, "out of memory") - if !mem.map (page, p): - Kernel::panic (0, "unable to map bss page") - Kernel::free_cap (page) - for unsigned p = 0; p < num_pages; ++p: - Kernel::my_memory.destroy (Kernel::Page (slot, p)) - Kernel::Page stackpage = mem.create_page () - stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME) - if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000): - Kernel::panic (Kernel::recv.data[0].l, "unable to map initial stack page") - Kernel::free_cap (stackpage) - Kernel::Caps caps = mem.create_caps (NUM_CAPS) - thread.use (caps, 0) - thread.set_info (Kernel::Thread::A0, NUM_SLOTS) - thread.set_info (Kernel::Thread::A1, NUM_CAPS) - Kernel::Receiver receiver = mem.create_receiver () - receiver.set_owner (thread.copy ()) - Kernel::Cap call = receiver.create_call_capability () - Kernel::Cap parent = Kernel::my_receiver.create_capability (Kernel::Num (current_thread++, THREAD)) - caps.set (__receiver_num, receiver.copy ()) - caps.set (__thread_num, thread.copy ()) - caps.set (__memory_num, mem.copy ()) - caps.set (__call_num, call.copy ()) - caps.set (__parent_num, parent.copy ()) - thread.run () - Kernel::free_cap (receiver) - Kernel::free_cap (thread) - Kernel::free_cap (call) - Kernel::free_cap (parent) - Kernel::free_cap (caps) - -static void kdebug_name (char const *t, file *f): - kdebug (t) - for unsigned j = 0; j < 16; ++j: - if f->name[j] != 0: - kdebug_char (f->name[j]) - kdebug ("...") - -static Device sysreq_dev - -struct Dev: - static Dev *devs - static unsigned num_devs - Dev *next - unsigned code, idx, id - Device dev - static Dev *find (unsigned c, unsigned i): - for Dev *d = devs; d; d = d->next: - if d->code == c && d->idx == i: - return d - return NULL - static void add (unsigned c, unsigned i, Kernel::Cap cap): - if c == Keyboard::ID && i == 1: - sysreq_dev = cap - return - while find (c, i): - ++i - Dev *d = new Dev () - d->next = devs - d->code = c - d->idx = i - d->dev = cap - devs = d - d->id = num_devs++ - static void kdebug_list (): - for Dev *d = devs; d; d = d->next: - kdebug (">") - kdebug_num (d->code) - kdebug (":") - kdebug_num (d->idx) - -Dev *Dev::devs -unsigned Dev::num_devs - -static void handle_init (unsigned id): - while true: - Kernel::wait () - switch Kernel::recv.data[0].l: - case Parent::PROVIDE_DEVICE: - kdebug ("adding dev ") - kdebug_num (Kernel::recv.data[1].l) - kdebug (":") - kdebug_num (Kernel::recv.data[0].h) - kdebug (" as ") - kdebug_num (Dev::num_devs) - kdebug ("\n") - Kernel::Cap reply = Kernel::get_reply () - Dev::add (Kernel::recv.data[1].l, Kernel::recv.data[0].h, Kernel::get_arg ()) - reply.invoke () - Kernel::free_cap (reply) - break - case Parent::INIT_DONE: - Kernel::Cap reply = Kernel::get_reply () - memories.set (id + num_files, reply.copy ()) - Kernel::free_cap (reply) - return - default: - kdebug ("unknown init request\n") - Kernel::panic (Kernel::recv.data[0].l) - -static void get_device (): - Kernel::Cap reply = Kernel::get_reply () - unsigned id = Kernel::recv.protected_data.l - Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h) - if d: - if inuse[id * Dev::num_devs + d->id] > 0: - Kernel::panic (id, "requesting device twice") - kdebug ("giving dev ") - kdebug_num (Kernel::recv.data[1].l) - kdebug (":") - kdebug_num (Kernel::recv.data[0].h) - kdebug (" = ") - kdebug_num (d->id) - kdebug (" to ") - kdebug_num (id) - kdebug ("\n") - Kernel::Caps cap = d->dev.create_user (Kernel::Memory (memory_slot, id), 0, 0x15000) - Kernel::Caps (terminal_slot, id).set (d->id, cap.copy ()) - for unsigned i = 0; i < num_files; ++i: - if inuse[i * Dev::num_devs + d->id] == 2: - inuse[i * Dev::num_devs + d->id] = 1 - inuse[id * Dev::num_devs + d->id] = 2 - d->dev.use (cap) - Kernel::Cap ret = cap.get (0) - reply.invoke (0, 0, ret.copy ()) - Kernel::free_cap (ret) - Kernel::free_cap (cap) - else: - kdebug ("device not found: ") - kdebug_num (Kernel::recv.data[1].l) - kdebug (":") - kdebug_num (Kernel::recv.data[0].h) - Dev::kdebug_list () - kdebug ("\n") - reply.invoke (~0, ~0) - Kernel::panic (0) - Kernel::free_cap (reply) - -static void draw_ball (): - int const r = 50 - for int y = -r; y < r; ++y: - for int x = -r; x < r; ++x: - if x * x + y * y > r * r: - ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0x000000 - else: - ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0x3f30ff - -static void draw_square (): - int const r = 50 - for int y = -r; y < r; ++y: - for int x = -r; x < r; ++x: - ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0xffff00 - -Kernel::Num start (): - // Wait for the debugging device to be active, in case there is one. - Kernel::schedule () - Dev::devs = NULL - Dev::num_devs = 0 - init_alloc () - top_memory = Kernel::get_top_memory () - Directory root = receive_devices () - root.lock_ro () - list_files (root) - sort () - Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages) - slot = caps.use () - mapping = alloc_space (max_pages) - terminals = Kernel::my_memory.create_caps (num_files) - terminal_slot = terminals.use () - // Two times, because it holds the memory and the init_done reply for each task. - memories = Kernel::my_memory.create_caps (num_files * 2) - memory_slot = memories.use () - for unsigned i = 0; i < num_files; ++i: - kdebug_name ("loading ", &files[index[i]]) - run (&files[index[i]], files[index[i]].name[0] == '#', i) - kdebug ("running\n") - handle_init (i) - inuse = new unsigned[num_files * Dev::num_devs] - for unsigned f = 0; f < num_files; ++f: - for unsigned d = 0; d < Dev::num_devs; ++d: - inuse[f * Dev::num_devs + d] = 0 - // Notify all programs that they may start. - for unsigned i = 0; i < num_files; ++i: - Kernel::Cap (memory_slot, i + num_files).invoke () - // create terminals. - for unsigned i = 0; i < num_files; ++i: - Kernel::Caps term (terminal_slot, i) - Kernel::Memory mem (memory_slot, i) - Kernel::set_recv_arg (term) - mem.create_caps (Dev::num_devs) - // set up system request. - Kernel::Caps sysreq_caps = sysreq_dev.create_user (Kernel::my_memory) - sysreq_dev.use (sysreq_caps) - Keyboard sysreq = sysreq_caps.get (0) - Kernel::free_cap (sysreq_dev) - Kernel::free_cap (sysreq_caps) - Kernel::Cap cap = Kernel::my_receiver.create_capability (Kernel::Num (0, SYSREQ)) - sysreq.set_cb (cap.copy ()) - Kernel::free_cap (sysreq) - Kernel::free_cap (cap) - // set up own capabilities. - Dev *display_dev = Dev::find (Display::ID, 0) - if !display_dev: - Kernel::panic (0, "no display") - Kernel::Caps display_caps = display_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) - Display display = display_caps.get (0) - draw_ball () - Dev *keyboard_dev = Dev::find (Keyboard::ID, 0) - if !keyboard_dev: - Kernel::panic (0, "no keyboard") - Kernel::Caps keyboard_caps = keyboard_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) - Keyboard keyboard = keyboard_caps.get (0) - kdebug ("init done\n") - root.unlock_ro () - Kernel::free_slot (slot) - Kernel::my_memory.destroy (caps) - Dev **waiter = new Dev *[num_files] - Kernel::Cap keyboard_cb = Kernel::my_receiver.create_capability (Kernel::Num (0, KEYBOARD)) - bool in_system = false - while true: - Kernel::wait () - switch Kernel::recv.protected_data.h: - case SYSREQ: - // System request. - if Kernel::recv.data[0].l & Keyboard::RELEASE: - continue - keyboard_dev->dev.use (keyboard_caps) - display_dev->dev.use (display_caps) - keyboard.set_cb (keyboard_cb) - in_system = true - continue - case THREAD: - // Request for something from a child thread. - switch Kernel::recv.data[0].l: - case Parent::INIT_DONE: - Kernel::panic (Kernel::recv.protected_data.l, "double init_done") - case Parent::PROVIDE_DEVICE: - Kernel::panic (Kernel::recv.protected_data.l, "too late now for provide") - case Parent::GET_DEVICE: - get_device () - break - case Parent::WAIT: - unsigned id = Kernel::recv.protected_data.l - Dev *dev = Dev::find (Kernel::recv.data[1].l, 0) - if id >= num_files: - Kernel::panic (0, "invalid id") - if !dev: - Kernel::panic (0, "invalid dev") - switch inuse[id * Dev::num_devs + dev->id]: - case 0: - Kernel::panic (0, "waiting for non-owned device") - case 2: - if !in_system: - Kernel::recv.reply.invoke () - break - // fall through. - case 1: - Kernel::Cap reply = Kernel::get_reply () - memories.set (id + num_files, reply.copy ()) - Kernel::free_cap (reply) - waiter[id] = dev - break - break - case Parent::EXIT: - Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported") - default: - Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child") - break - case KEYBOARD: - if !in_system: - break - if Kernel::recv.data[0].l == (Key::ENTER | Keyboard::RELEASE): - for Dev *d = Dev::devs; d; d = d->next: - if d->idx != 0: - continue - for unsigned i = 0; i < num_files; ++i: - if inuse[i * Dev::num_devs + d->id] == 2: - Kernel::Cap c = Kernel::Caps (terminal_slot, i).get (d->id) - d->dev.use (c) - Kernel::free_cap (c) - if waiter[i] == d: - Kernel::Cap (memory_slot, i + num_files).invoke () - waiter[i] = NULL - in_system = false - break - if Kernel::recv.data[0].l & Keyboard::RELEASE: - continue - unsigned which = 0 - switch Kernel::recv.data[0].l: - case Key::VOLUME_DOWN: - // Set ball. - draw_ball () - which = 2 - break - case Key::VOLUME_UP: - // Set square. - draw_square () - which = 1 - break - if which != 0: - for Dev *d = Dev::devs; d; d = d->next: - if d->code != Display::ID || d->idx != 0: - continue - for unsigned f = 0; f < num_files; ++f: - if inuse[f * Dev::num_devs + d->id] == 0: - continue - inuse[f * Dev::num_devs + d->id] = (--which ? 2 : 1) - break - default: - Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request") diff --git a/boot-programs/udc.ccp b/boot-programs/udc.ccp index 26c67ec..c94f8ec 100644 --- a/boot-programs/udc.ccp +++ b/boot-programs/udc.ccp @@ -162,16 +162,16 @@ class Udc: char log_buffer[1000] unsigned log_buffer_size unsigned log_buffer_start - Kernel::Cap caller, caller_arg + Iris::Cap caller, caller_arg bool have_caller unsigned *page unsigned *p - Kernel::Page buffer_page + Iris::Page buffer_page public: void init () void log (unsigned c) void interrupt (unsigned cmd) - void send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg) + void send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg) Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 } Udc::my_config Udc::config_descriptor = { @@ -217,9 +217,9 @@ void Udc::init (): // Normally a normal new page should be allocated here, but new isn't implemented at this point. page = (unsigned *)LCD_FRAMEBUFFER_BASE p = page - buffer_page = Kernel::my_memory.create_page () - buffer_page.set_flags (Kernel::Page::FRAME | Kernel::Page::PAYING, Kernel::Page::FRAME | Kernel::Page::PAYING) - Kernel::my_memory.map (buffer_page, (unsigned)page) + buffer_page = Iris::my_memory.create_page () + buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING, Iris::Page::FRAME | Iris::Page::PAYING) + Iris::my_memory.map (buffer_page, (unsigned)page) // Disconnect from the bus and don't try to get high-speed. UDC_POWER = 0 @@ -242,14 +242,14 @@ void Udc::init (): UDC_INTROUTE = 1 << 1 // Wait a while. for unsigned w = 0; w < 10000; ++w: - Kernel::schedule () + Iris::schedule () // Connect to the host. UDC_POWER = UDC_POWER_SOFTCONN bool Udc::vendor (Setup *s, unsigned cmd): if !(s->request_type & 0x80): kdebug ("data to device without size\n") - Kernel::panic (0) + Iris::panic (0) return true if s->request == 10: static unsigned b[2] @@ -258,10 +258,10 @@ bool Udc::vendor (Setup *s, unsigned cmd): if cmd_code != ~0: b[0] = cmd_code b[1] = cmd_arg - if cmd_code == Directory::LOCK_RO || cmd_code == Directory::UNLOCK_RO: + if cmd_code == Iris::Directory::LOCK_RO || cmd_code == Iris::Directory::UNLOCK_RO: caller.invoke () - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) have_caller = false //kdebug ("(un)lock response\n") cmd_code = ~0 @@ -283,10 +283,10 @@ bool Udc::vendor (Setup *s, unsigned cmd): state = TX return true -void Udc::send (unsigned code, unsigned narg, Kernel::Cap reply, Kernel::Cap arg): +void Udc::send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg): if cmd_code != ~0: kdebug ("new code sent while old one wasn't finished.\n") - Kernel::panic (0) + Iris::panic (0) cmd_code = code cmd_arg = narg caller = reply @@ -404,7 +404,7 @@ void Udc::irq_in (unsigned cmd): switch state: case IDLE: if rebooting: - Kernel::reboot () + Iris::reboot () if !(csr & UDC_CSR0_OUTPKTRDY): return union { unsigned d[2]; Setup s; } packet @@ -439,53 +439,53 @@ void Udc::irq_in (unsigned cmd): case RX: // The protocol that is used doesn't allow large packets, so being here always means the entire packet is received. switch rx_request & 0xff: - case Directory::GET_SIZE & 0xff: + case Iris::Directory::GET_SIZE & 0xff: if !have_caller: kdebug ("received dir size from server without a caller waiting\n") - Kernel::panic (0) + Iris::panic (0) unsigned size_l = UDC_FIFO (0) unsigned size_h = UDC_FIFO (0) - caller.invoke (Kernel::Num (size_l, size_h)) - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + caller.invoke (Iris::Num (size_l, size_h)) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) have_caller = false //kdebug ("get_size response\n") break - case Directory::GET_NAME & 0xff: + case Iris::Directory::GET_NAME & 0xff: if !have_caller: kdebug ("received filename from server without a caller waiting\n") - Kernel::panic (0) + Iris::panic (0) unsigned n[4] for unsigned i = 0; i < 4; ++i: n[i] = UDC_FIFO (0) - caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3])) - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3])) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) //kdebug ("get_name response\n") have_caller = false break - case ::String::GET_SIZE & 0xff: + case Iris::String::GET_SIZE & 0xff: if !have_caller: kdebug ("received string size from server without a caller waiting\n") - Kernel::panic (0) + Iris::panic (0) unsigned size_l = UDC_FIFO (0) unsigned size_h = UDC_FIFO (0) - caller.invoke (Kernel::Num (size_l, size_h)) - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + caller.invoke (Iris::Num (size_l, size_h)) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) have_caller = false //kdebug ("get_filesize response\n") break - case ::String::GET_CHARS & 0xff: + case Iris::String::GET_CHARS & 0xff: if !have_caller: kdebug ("received string char data from server without a caller waiting\n") - Kernel::panic (0) + Iris::panic (0) unsigned n[4] for unsigned i = 0; i < 4; ++i: n[i] = UDC_FIFO (0) - caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3])) - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3])) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) have_caller = false //kdebug ("get_chars response\n") break @@ -493,7 +493,7 @@ void Udc::irq_in (unsigned cmd): kdebug ("invalid vendor request: ") kdebug_num (rx_request) kdebug ("\n") - Kernel::panic (0) + Iris::panic (0) UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY state = IDLE break @@ -504,7 +504,7 @@ void Udc::irq_out (unsigned cmd): UDC_INDEX = 1 if !have_caller: kdebug ("received bulk data from server without a caller waiting\n") - Kernel::panic (0) + Iris::panic (0) unsigned size = UDC_OUTCOUNT unsigned csr = UDC_OUTCSR //kdebug ("handling bulk interrupt for ") @@ -516,11 +516,11 @@ void Udc::irq_out (unsigned cmd): for unsigned i = 0; i < size; i += 4: *p++ = UDC_FIFO (1) if p - page == PAGE_SIZE >> 2: - buffer_page.share (caller_arg, Kernel::Page::FORGET) - buffer_page.set_flags (Kernel::Page::FRAME, Kernel::Page::FRAME) + buffer_page.share (caller_arg, Iris::Page::FORGET) + buffer_page.set_flags (Iris::Page::FRAME, Iris::Page::FRAME) caller.invoke () - Kernel::free_cap (caller) - Kernel::free_cap (caller_arg) + Iris::free_cap (caller) + Iris::free_cap (caller_arg) have_caller = false //kdebug ("bulk response\n") p = page @@ -561,153 +561,153 @@ enum pdata: FILE NAME -Kernel::Num start (): +Iris::Num start (): map_udc () map_gpio () map_cpm () Udc udc - Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG) + Iris::Cap logcap = Iris::my_receiver.create_capability (LOG) __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") udc.init () - Kernel::register_interrupt (IRQ_UDC) - Device fs_dev = Kernel::my_receiver.create_capability (FS) - Device data_dev = Kernel::my_receiver.create_capability (DATA) - Kernel::my_parent.provide_device (fs_dev.copy ()) - Kernel::my_parent.provide_device (data_dev.copy ()) - Kernel::free_cap (fs_dev) - Kernel::free_cap (data_dev) + Iris::register_interrupt (IRQ_UDC) + Iris::Device fs_dev = Iris::my_receiver.create_capability (FS) + Iris::Device data_dev = Iris::my_receiver.create_capability (DATA) + Iris::my_parent.provide_device (fs_dev.copy ()) + Iris::my_parent.provide_device (data_dev.copy ()) + Iris::free_cap (fs_dev) + Iris::free_cap (data_dev) unsigned data_current_user = 0, fs_current_user = 0 unsigned next_user unsigned state = 0 while true: - Kernel::wait () - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - switch Kernel::recv.protected_data.h: + Iris::wait () + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + switch Iris::recv.protected_data.h: case 0: - switch Kernel::recv.protected_data.l: + switch Iris::recv.protected_data.l: case IRQ_UDC: udc.interrupt (state) - Kernel::register_interrupt (IRQ_UDC) + Iris::register_interrupt (IRQ_UDC) break case LOG: - udc.log (Kernel::recv.data[0].l) + udc.log (Iris::recv.data[0].l) break case FS: - Device::host (FS, fs_current_user, reply, arg) + Iris::Device::host (FS, fs_current_user, reply, arg) continue case DATA: - Device::host (DATA, data_current_user, reply, arg) + Iris::Device::host (DATA, data_current_user, reply, arg) continue default: udc.log ('~') char digit[] = "0123456789abcdef" for unsigned i = 0; i < 8; ++i: - udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf]) + udc.log (digit[(Iris::recv.protected_data.l >> (4 * (7 - i))) & 0xf]) udc.log ('\n') break break case DATA: - if data_current_user != Kernel::recv.protected_data.l: + if data_current_user != Iris::recv.protected_data.l: break - switch Kernel::recv.data[0].l: - case ::String::GET_SIZE: - case ::String::GET_CHARS: + switch Iris::recv.data[0].l: + case Iris::String::GET_SIZE: + case Iris::String::GET_CHARS: reply.invoke (0) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (reply) + Iris::free_cap (arg) continue - case ::String::GET_PAGE: + case Iris::String::GET_PAGE: default: - reply.invoke (Kernel::ERR_INVALID_OPERATION) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + reply.invoke (Iris::ERR_INVALID_OPERATION) + Iris::free_cap (reply) + Iris::free_cap (arg) continue break case FS: - if fs_current_user != Kernel::recv.protected_data.l: + if fs_current_user != Iris::recv.protected_data.l: break - switch Kernel::recv.data[0].l: - case Filesystem::USE_DEVICE: - case Filesystem::USE_DEVICE_RO: - Directory dir = Kernel::my_receiver.create_capability (Kernel::Num (0, DIRECTORY)) + switch Iris::recv.data[0].l: + case Iris::Filesystem::USE_DEVICE: + case Iris::Filesystem::USE_DEVICE_RO: + Iris::Directory dir = Iris::my_receiver.create_capability (Iris::Num (0, DIRECTORY)) reply.invoke (0, 0, dir.copy ()) - Kernel::free_cap (dir) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (dir) + Iris::free_cap (reply) + Iris::free_cap (arg) continue default: - reply.invoke (Kernel::ERR_INVALID_OPERATION) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + reply.invoke (Iris::ERR_INVALID_OPERATION) + Iris::free_cap (reply) + Iris::free_cap (arg) continue break case DIRECTORY: - switch Kernel::recv.data[0].l: - case Directory::GET_NAME: - Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, NAME)) + switch Iris::recv.data[0].l: + case Iris::Directory::GET_NAME: + Iris::Cap name = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, NAME)) reply.invoke (0, 0, name.copy ()) - Kernel::free_cap (name) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (name) + Iris::free_cap (reply) + Iris::free_cap (arg) continue - case Directory::GET_SIZE: - case Directory::LOCK_RO: - case Directory::UNLOCK_RO: - state = Kernel::recv.data[0].l - if Kernel::recv.data[1].h != 0: + case Iris::Directory::GET_SIZE: + case Iris::Directory::LOCK_RO: + case Iris::Directory::UNLOCK_RO: + state = Iris::recv.data[0].l + if Iris::recv.data[1].h != 0: kdebug ("index out of supported range\n") - Kernel::panic (0) - udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l, reply, arg) + Iris::panic (0) + udc.send (Iris::recv.data[0].l, Iris::recv.data[1].l, reply, arg) continue - case Directory::GET_FILE_RO: - if Kernel::recv.data[1].h != 0: + case Iris::Directory::GET_FILE_RO: + if Iris::recv.data[1].h != 0: kdebug ("index out of supported range\n") - Kernel::panic (0) + Iris::panic (0) //kdebug ("sending file\n") - Kernel::Cap file = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, FILE)) + Iris::Cap file = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, FILE)) reply.invoke (0, 0, file.copy ()) - Kernel::free_cap (file) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (file) + Iris::free_cap (reply) + Iris::free_cap (arg) continue - case Directory::GET_FILE_INFO: + case Iris::Directory::GET_FILE_INFO: default: - reply.invoke (Kernel::ERR_INVALID_OPERATION) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + reply.invoke (Iris::ERR_INVALID_OPERATION) + Iris::free_cap (reply) + Iris::free_cap (arg) continue break case FILE: - switch Kernel::recv.data[0].l: - case ::String::GET_SIZE: - case ::String::GET_CHARS: - case ::String::GET_PAGE: - udc.send (Kernel::recv.data[0].l | ((Kernel::recv.data[1].l >> PAGE_BITS) << 16), Kernel::recv.protected_data.l, reply, arg) + switch Iris::recv.data[0].l: + case Iris::String::GET_SIZE: + case Iris::String::GET_CHARS: + case Iris::String::GET_PAGE: + udc.send (Iris::recv.data[0].l | ((Iris::recv.data[1].l >> PAGE_BITS) << 16), Iris::recv.protected_data.l, reply, arg) continue default: - reply.invoke (Kernel::ERR_INVALID_OPERATION) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + reply.invoke (Iris::ERR_INVALID_OPERATION) + Iris::free_cap (reply) + Iris::free_cap (arg) continue break case NAME: - switch Kernel::recv.data[0].l: - case ::String::GET_SIZE: + switch Iris::recv.data[0].l: + case Iris::String::GET_SIZE: reply.invoke (16) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (reply) + Iris::free_cap (arg) continue - case ::String::GET_CHARS: - state = Kernel::recv.data[0].l - udc.send (Directory::GET_NAME, Kernel::recv.protected_data.l, reply, arg) + case Iris::String::GET_CHARS: + state = Iris::recv.data[0].l + udc.send (Iris::Directory::GET_NAME, Iris::recv.protected_data.l, reply, arg) continue default: - reply.invoke (Kernel::ERR_INVALID_OPERATION) - Kernel::free_cap (reply) - Kernel::free_cap (arg) + reply.invoke (Iris::ERR_INVALID_OPERATION) + Iris::free_cap (reply) + Iris::free_cap (arg) continue reply.invoke () - Kernel::free_cap (reply) - Kernel::free_cap (arg) + Iris::free_cap (reply) + Iris::free_cap (arg) diff --git a/devices.hhp b/devices.hhp index b500aee..fcb0072 100644 --- a/devices.hhp +++ b/devices.hhp @@ -21,363 +21,405 @@ #include "iris.hh" -// List interface. -template // -struct List : public Kernel::Caps: - List (Kernel::Caps c = Kernel::Cap ()) : Kernel::Caps (c): - List <_T> create (unsigned size, Kernel::Memory mem = Kernel::my_memory): - return List <_T> (mem.create_caps (size)) - void set (unsigned idx, _T value): - return Kernel::Caps::set (idx, value) - _T get (unsigned idx): - return _T (Kernel::Caps::get (idx)) +namespace Iris: + // Caplist interface. + template // + struct Caplist : public Iris::Caps: + Caplist (Iris::Caps c = Iris::Cap ()) : Iris::Caps (c): + Caplist <_T> create (unsigned size, Iris::Memory mem = Iris::my_memory): + return Caplist <_T> (mem.create_caps (size)) + void set (unsigned idx, _T value): + return Iris::Caps::set (idx, value) + _T get (unsigned idx): + return _T (Iris::Caps::get (idx)) -/// A block of data with a size and content. Any character can be stored in it (including '\0'). -struct String : public Kernel::Cap: - String (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - GET_SIZE = 0x2001 - GET_CHARS - GET_PAGE - ID - /// Get the size of the string. - Kernel::Num get_size (): - return call (CAP_MASTER_DIRECT | GET_SIZE) - /// Get exactly 16 characters. The index must be word-aligned. - char *get_chars (Kernel::Num idx, char buffer[16]): - call (CAP_MASTER_DIRECT | GET_CHARS, idx) - unsigned *b = (unsigned *)buffer - b[0] = Kernel::recv.data[0].l - b[1] = Kernel::recv.data[0].h - b[2] = Kernel::recv.data[1].l - b[3] = Kernel::recv.data[1].h - return buffer - /// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. - Cap get_page (Kernel::Num idx, Kernel::Page ret = Kernel::my_memory.create_page ()): - ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx) - return ret + /// A block of data with a size and content. Any character can be stored in it (including '\0'). + struct String : public Iris::Cap: + String (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + GET_SIZE = 0x2001 + GET_CHARS + GET_PAGE + ID + /// Get the size of the string. + Iris::Num get_size (): + return call (CAP_MASTER_DIRECT | GET_SIZE) + /// Get exactly 16 characters. The index must be word-aligned. + char *get_chars (Iris::Num idx, char buffer[16]): + call (CAP_MASTER_DIRECT | GET_CHARS, idx) + unsigned *b = (unsigned *)buffer + b[0] = Iris::recv.data[0].l + b[1] = Iris::recv.data[0].h + b[2] = Iris::recv.data[1].l + b[3] = Iris::recv.data[1].h + return buffer + /// Helper function for get_page. + static Iris::Page _create_paying_page (): + Iris::Page ret = Iris::my_memory.create_page () + ret.set_flags (Iris::Page::PAYING, Iris::Page::PAYING) + return ret + /// Get a page from the string. This need not be implemented for strings smaller than PAGE_SIZE. The index must be page-aligned. + Cap get_page (Iris::Num idx, Iris::Page ret = _create_paying_page ()): + ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx) + return ret -/// A writable String. -struct WString : public String: - WString (Kernel::Cap c = Kernel::Cap ()) : String (c): - enum request: - TRUNCATE = String::ID - SET_CHARS - SET_PAGE - ID - /// Set the size of the string. Strings may have a limit to this setting. - void truncate (Kernel::Num size): - call (CAP_MASTER_DIRECT | TRUNCATE, size) - /// Set exactly 4 characters. The index must be word-aligned. - void set_chars (Kernel::Num idx, char buffer[4]): - call (Kernel::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx) - /// 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. - void set_page (Kernel::Num idx, Kernel::Page page): - ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx) + /// A writable String. + struct WString : public String: + WString (Iris::Cap c = Iris::Cap ()) : String (c): + enum request: + TRUNCATE = String::ID + SET_CHARS + SET_PAGE + ID + /// Set the size of the string. Strings may have a limit to this setting. + void truncate (Iris::Num size): + call (CAP_MASTER_DIRECT | TRUNCATE, size) + /// Set exactly 4 characters. The index must be word-aligned. + void set_chars (Iris::Num idx, char buffer[4]): + call (Iris::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx) + /// 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. + void set_page (Iris::Num idx, Iris::Page page): + ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx) -// Every process which wants to be switchable through a terminal must implement this interface. -struct Device : public Kernel::Cap: - Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - CREATE_USER = WString::ID - DESTROY_USER - UNUSE - USE - ID - // Create a new user for this device. It will not be the active user. - // The provided storage must allow object creation; no other actions may be used by the terminal. - Kernel::Cap create_user (Kernel::Memory storage, unsigned arg1 = 0, Kernel::Num arg2 = 0): - iocall (storage, Kernel::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2) - return Kernel::get_arg () - // Destroy a user. It is made inactive if it was active. - void destroy_user (Kernel::Cap user): - ocall (user, CAP_MASTER_DIRECT | DESTROY_USER) - // Make user inactive. - void unuse (Kernel::Cap user): - ocall (user, CAP_MASTER_DIRECT | UNUSE) - // Make user active. It makes the previous active user inactive. - void use (Kernel::Cap user): - ocall (user, CAP_MASTER_DIRECT | USE) - // Convenience function for threads implementing a device. - static void host (unsigned id, unsigned ¤t_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): - static unsigned last_user - switch Kernel::recv.data[0].l: - case Device::CREATE_USER: - Kernel::Memory mem (arg) - Kernel::Caps caps = mem.create_caps (capssize) - unsigned user - if create: - user = create (mem, caps) - else: - // Increment last_user; skip 0. - // FIXME: if this really wraps, it is possible that two users share their id. - if !++last_user: - ++last_user - user = last_user - Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (user, id)) - caps.set (0, c.copy ()) - caps.set (1, mem.copy ()) - reply.invoke (0, 0, caps.copy ()) - Kernel::free_cap (c) - Kernel::free_cap (caps) - Kernel::free_cap (reply) - Kernel::free_cap (arg) - break - case Device::DESTROY_USER: - Kernel::Caps caps (arg) - Kernel::Cap c = caps.get (0) - Kernel::Num user = Kernel::my_receiver.get_protected (c) - Kernel::free_cap (c) - if user.h != id: - Kernel::panic (user.h, "invalid id for destroy") - // TODO: unuse. - if destroy: - destroy (user.l, caps) - reply.invoke () - Kernel::free_cap (reply) - Kernel::free_cap (arg) - break - case Device::USE: - Kernel::Caps caps (arg) - Kernel::Cap c = caps.get (0) - Kernel::Num user = Kernel::my_receiver.get_protected (c) - Kernel::free_cap (c) - if user.h != id: - Kernel::panic (user.h, "invalid id for use") - // TODO: send unuse signal. - current_user = user.l - if use: - use (user.l, caps) - c = caps.get (2) - c.invoke (1) - Kernel::free_cap (c) - reply.invoke () - Kernel::free_cap (reply) - Kernel::free_cap (arg) - break - case Device::UNUSE: - Kernel::Caps caps (arg) - Kernel::Cap c = caps.get (0) - Kernel::Num user = Kernel::my_receiver.get_protected (c) - Kernel::free_cap (c) - if user.h != id: - Kernel::panic (user.h, "invalid id for unuse") - if unuse: - unuse (user.l, caps) - if user.l == current_user: + // Every process which wants to be switchable through a terminal must implement this interface. + struct Device : public Iris::Cap: + Device (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + CREATE_USER = WString::ID + DESTROY_USER + UNUSE + USE + ID + // Create a new user for this device. It will not be the active user. + // The provided storage must allow object creation; no other actions may be used by the terminal. + Iris::Cap create_user (Iris::Memory storage, unsigned arg1 = 0, Iris::Num arg2 = 0): + iocall (storage, Iris::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2) + return Iris::get_arg () + // Destroy a user. It is made inactive if it was active. + void destroy_user (Iris::Cap user): + ocall (user, CAP_MASTER_DIRECT | DESTROY_USER) + // Make user inactive. + void unuse (Iris::Cap user): + ocall (user, CAP_MASTER_DIRECT | UNUSE) + // Make user active. It makes the previous active user inactive. + void use (Iris::Cap user): + ocall (user, CAP_MASTER_DIRECT | USE) + // Convenience function for threads implementing a device. + static void host (unsigned id, unsigned ¤t_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): + static unsigned last_user + switch Iris::recv.data[0].l: + case Device::CREATE_USER: + Iris::Memory mem (arg) + Iris::Caps caps = mem.create_caps (capssize) + unsigned user + if create: + user = create (mem, caps) + else: + // Increment last_user; skip 0. + // FIXME: if this really wraps, it is possible that two users share their id. + if !++last_user: + ++last_user + user = last_user + Iris::Cap c = Iris::my_receiver.create_capability (Iris::Num (user, id)) + caps.set (0, c.copy ()) + caps.set (1, mem.copy ()) + reply.invoke (0, 0, caps.copy ()) + Iris::free_cap (c) + Iris::free_cap (caps) + Iris::free_cap (reply) + Iris::free_cap (arg) + break + case Device::DESTROY_USER: + Iris::Caps caps (arg) + Iris::Cap c = caps.get (0) + Iris::Num user = Iris::my_receiver.get_protected (c) + Iris::free_cap (c) + if user.h != id: + Iris::panic (user.h, "invalid id for destroy") + // TODO: unuse. + if destroy: + destroy (user.l, caps) + reply.invoke () + Iris::free_cap (reply) + Iris::free_cap (arg) + break + case Device::USE: + Iris::Caps caps (arg) + Iris::Cap c = caps.get (0) + Iris::Num user = Iris::my_receiver.get_protected (c) + Iris::free_cap (c) + if user.h != id: + Iris::panic (user.h, "invalid id for use") + // TODO: send unuse signal. + current_user = user.l + if use: + use (user.l, caps) c = caps.get (2) - c.invoke (0) - Kernel::free_cap (c) - current_user = 0 - reply.invoke () - Kernel::free_cap (reply) - Kernel::free_cap (arg) - break + c.invoke (1) + Iris::free_cap (c) + reply.invoke () + Iris::free_cap (reply) + Iris::free_cap (arg) + break + case Device::UNUSE: + Iris::Caps caps (arg) + Iris::Cap c = caps.get (0) + Iris::Num user = Iris::my_receiver.get_protected (c) + Iris::free_cap (c) + if user.h != id: + Iris::panic (user.h, "invalid id for unuse") + if unuse: + unuse (user.l, caps) + if user.l == current_user: + c = caps.get (2) + c.invoke (0) + Iris::free_cap (c) + current_user = 0 + reply.invoke () + Iris::free_cap (reply) + Iris::free_cap (arg) + break + default: + kdebug ("invalid request\n") + reply.invoke (~0) + Iris::free_cap (reply) + Iris::free_cap (arg) + break -// Interface for talking to the parent process. -struct Parent : public Kernel::Cap: - Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - GET_DEVICE = Device::ID - PROVIDE_DEVICE - WAIT - GET_MEMORY - PROVIDE_MEMORY - INIT_DONE - EXIT - ID - // Get a device handle. - template _T get_device (unsigned num = 0): - icall (Kernel::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID) - return Kernel::get_arg () - // Provide a device handle. - template void provide_device (Device dev, unsigned num = 0): - ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID) - // Wait until a device is used by the caller again. - template void wait (unsigned num = 0): - call (Kernel::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID) - // 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. - Kernel::Memory get_memory (Kernel::Cap target): - iocall (target, CAP_MASTER_DIRECT | GET_MEMORY) - return Kernel::get_arg () - // 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). - Kernel::Cap provide_memory (unsigned limit): - icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit) - return Kernel::get_arg () - // Signal the parent that the initialisation phase is over. - void init_done (): - call (CAP_MASTER_DIRECT | INIT_DONE) - // Exit the program. The parent does not reply, but kills the process. - void exit (Kernel::Num code): - call (CAP_MASTER_DIRECT | EXIT, code) + struct Elfrun : public Iris::Cap: + Elfrun (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + RUN_STRING = Device::ID + RUN_CAPS + ID + enum arg_pos: + PARENT_MEMORY + DATA + PARENT + Iris::Caps run_string (Memory parent_memory, String data, Cap parent, unsigned num_slots = 8, unsigned num_caps = 32): + Iris::Caps caps = Iris::my_memory.create_caps (3) + caps.set (PARENT_MEMORY, parent_memory) + caps.set (DATA, data) + caps.set (PARENT, parent) + iocall (caps.copy (), CAP_MASTER_DIRECT | RUN_STRING, Iris::Num (num_slots, num_caps)) + Iris::Caps ret = Iris::get_arg () + Iris::my_memory.destroy (caps) + Iris::free_cap (caps) + return ret + Iris::Caps run_caps (Memory parent_memory, Caps data, Cap parent, unsigned pages, unsigned num_slots = 8, unsigned num_caps = 32): + Iris::Caps caps = Iris::my_memory.create_caps (3) + caps.set (PARENT_MEMORY, parent_memory) + caps.set (DATA, data) + caps.set (PARENT, parent) + iocall (caps.copy (), Iris::Num (CAP_MASTER_DIRECT | RUN_CAPS, pages), Iris::Num (num_slots, num_caps)) + Iris::Caps ret = Iris::get_arg () + Iris::my_memory.destroy (caps) + Iris::free_cap (caps) + return ret -// Keyboard interface. -struct Keyboard : public Kernel::Cap: - Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - SET_CB = Parent::ID - GET_NUM_KEYS - GET_KEYS - ID - // At event: the callback is called with a keycode. One bit defines if it's a press or release event. - enum constant: - RELEASE = 1 << 31 - // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately. - void set_cb (Kernel::Cap cb): - ocall (cb, CAP_MASTER_DIRECT | SET_CB) - // Get the number of keys on the keyboard. - unsigned get_num_keys (): - return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l - // Get the keycodes for the keys. The reply sends 4 key codes (32 bit each). - void get_keys (unsigned first): - call (CAP_MASTER_DIRECT | GET_KEYS, first) + // Interface for talking to the parent process. + struct Parent : public Iris::Cap: + Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + GET_DEVICE = Elfrun::ID + PROVIDE_DEVICE + WAIT + GET_MEMORY + PROVIDE_MEMORY + INIT_DONE + EXIT + ID + // Get a device handle. + template _T get_device (unsigned num = 0): + icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID) + return Iris::get_arg () + // Provide a device handle. + template void provide_device (Device dev, unsigned num = 0): + ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID) + // Wait until a device is used by the caller again. + template void wait (unsigned num = 0): + call (Iris::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID) + // 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. + Iris::Memory get_memory (Iris::Cap target): + iocall (target, CAP_MASTER_DIRECT | GET_MEMORY) + return Iris::get_arg () + // 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). + Iris::Cap provide_memory (unsigned limit): + icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit) + return Iris::get_arg () + // Signal the parent that the initialisation phase is over. + void init_done (Iris::Num stage = 0): + call (CAP_MASTER_DIRECT | INIT_DONE, stage) + // Exit the program. The parent does not reply, but kills the process. + void exit (Iris::Num code): + call (CAP_MASTER_DIRECT | EXIT, code) -// Buzzer interface. -struct Buzzer : public Kernel::Cap: - Buzzer (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - BEEP = Keyboard::ID - STOP - ID - // Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted. - void beep (unsigned freq, unsigned ms, unsigned volume, Kernel::Cap cb = Kernel::Cap ()): - ocall (cb, Kernel::Num (CAP_MASTER_DIRECT | BEEP, volume), Kernel::Num (freq, ms)) - // Abort current beep, if any. - void stop (): - call (CAP_MASTER_DIRECT | STOP) + // Keyboard interface. + struct Keyboard : public Iris::Cap: + Keyboard (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + SET_CB = Parent::ID + GET_NUM_KEYS + GET_KEYS + ID + // At event: the callback is called with a keycode. One bit defines if it's a press or release event. + enum constant: + RELEASE = 1 << 31 + // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately. + void set_cb (Iris::Cap cb): + ocall (cb, CAP_MASTER_DIRECT | SET_CB) + // Get the number of keys on the keyboard. + unsigned get_num_keys (): + return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l + // Get the keycodes for the keys. The reply sends 4 key codes (32 bit each). + void get_keys (unsigned first): + call (CAP_MASTER_DIRECT | GET_KEYS, first) -// Display interface. -struct Display : public Kernel::Cap: - Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - SET_EOF_CB = Buzzer::ID - MAP_FB - GET_INFO - ID - // Register an end-of-frame callback. - // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events. - void set_eof_cb (Kernel::Cap cb): - ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB) - // Map the framebuffer into memory. - void map_fb (unsigned address): - call (CAP_MASTER_DIRECT | MAP_FB, address) - // Get information about the display. - void get_info (): - // TODO: Interface is to be designed. - kdebug ("using undefined interface Display::get_info ()\n") - Kernel::panic (0) + // Buzzer interface. + struct Buzzer : public Iris::Cap: + Buzzer (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + BEEP = Keyboard::ID + STOP + ID + // Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted. + void beep (unsigned freq, unsigned ms, unsigned volume, Iris::Cap cb = Iris::Cap ()): + ocall (cb, Iris::Num (CAP_MASTER_DIRECT | BEEP, volume), Iris::Num (freq, ms)) + // Abort current beep, if any. + void stop (): + call (CAP_MASTER_DIRECT | STOP) -// Numerical setting, such as a display backlight. -struct Setting : public Kernel::Cap: - Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - SET = Display::ID - GET_RANGE - ID - // Set a new value. - void set (unsigned value): - call (CAP_MASTER_DIRECT | SET, value) - // Get the maximum value for this setting. Using a higher value with SET gives undefined results. - unsigned get_range (): - return call (CAP_MASTER_DIRECT | GET_RANGE).l + // Display interface. + struct Display : public Iris::Cap: + Display (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + SET_EOF_CB = Buzzer::ID + MAP_FB + GET_INFO + ID + // Register an end-of-frame callback. + // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events. + void set_eof_cb (Iris::Cap cb): + ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB) + // Map the framebuffer into memory. + void map_fb (unsigned address): + call (CAP_MASTER_DIRECT | MAP_FB, address) + // Get information about the display. + void get_info (): + // TODO: Interface is to be designed. + Iris::panic (0, "using undefined interface Display::get_info ()") -// File system interface. -// filesystem-related interfaces: directory, stream, seekable. -// Normal files implement stream and/or seekable. Directories implement directory. -// Seekable is not a class, it is identical to [W]String. + // Numerical setting, such as a display backlight. + struct Setting : public Iris::Cap: + Setting (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + SET = Display::ID + GET_RANGE + ID + // Set a new value. + void set (unsigned value): + call (CAP_MASTER_DIRECT | SET, value) + // Get the maximum value for this setting. Using a higher value with SET gives undefined results. + unsigned get_range (): + return call (CAP_MASTER_DIRECT | GET_RANGE).l -// Directory interface. -struct Directory : public Kernel::Cap: - Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - GET_SIZE = Setting::ID - GET_NAME - GET_FILE_RO - GET_FILE_INFO - LOCK_RO - UNLOCK_RO - ID - // Get the number of entries in this directory. - Kernel::Num get_size (): - return call (CAP_MASTER_DIRECT | GET_SIZE) - // Get the filename. - String get_name (Kernel::Num idx): - icall (CAP_MASTER_DIRECT | GET_NAME, idx) - return Kernel::get_arg () - // Get the file. - Kernel::Cap get_file_ro (Kernel::Num idx): - icall (CAP_MASTER_DIRECT | GET_FILE_RO, idx) - return Kernel::get_arg () - // Get file info. TODO: define possible types. - Kernel::Num get_file_info (Kernel::Num idx, unsigned type): - return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx) - // Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present. - void lock_ro (): - call (CAP_MASTER_DIRECT | LOCK_RO) - // Release a read-only lock. Write operations can only be done when the directory is locked. - void unlock_ro (): - call (CAP_MASTER_DIRECT | UNLOCK_RO) -struct WDirectory : public Directory: - WDirectory (Kernel::Cap c = Kernel::Cap ()) : Directory (c): - enum request: - GET_FILE = Directory::ID - CREATE_FILE - DELETE_FILE - LOCK - UNLOCK - ID - // Get the file. - Kernel::Cap get_file (Kernel::Num idx): - icall (CAP_MASTER_DIRECT | GET_FILE, idx) - return Kernel::get_arg () - // Create a new file. After this, any index may map to a different file. - Kernel::Cap create_file (String name): - icall (CAP_MASTER_DIRECT | CREATE_FILE) - return Kernel::get_arg () - // Delete a file. After this, any index may map to a different file. - void delete_file (Kernel::Num idx): - call (CAP_MASTER_DIRECT | DELETE_FILE, idx) - // Lock the directory. Write operations can only be done when the directory is locked. - void lock (): - call (CAP_MASTER_DIRECT | LOCK) - // Unlock the directory. Write operations can only be done when the directory is locked. - void unlock (): - call (CAP_MASTER_DIRECT | UNLOCK) + // File system interface. + // filesystem-related interfaces: directory, stream, seekable. + // Normal files implement stream and/or seekable. Directories implement directory. + // Seekable is not a class, it is identical to [W]String. -// A filesystem turns a String into a Directory. -struct Filesystem : public Device: - Filesystem (Kernel::Cap c = Kernel::Cap ()) : Device (c): - enum request: - USE_DEVICE = WDirectory::ID - USE_DEVICE_RO - ID - WDirectory use_device (WString dev): - ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE) - return Kernel::get_arg () - Directory use_device_ro (String dev): - ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO) - return Kernel::get_arg () + // Directory interface. + struct Directory : public Iris::Cap: + Directory (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + GET_SIZE = Setting::ID + GET_NAME + GET_FILE_RO + GET_FILE_INFO + LOCK_RO + UNLOCK_RO + ID + // Get the number of entries in this directory. + Iris::Num get_size (): + return call (CAP_MASTER_DIRECT | GET_SIZE) + // Get the filename. + String get_name (Iris::Num idx): + icall (CAP_MASTER_DIRECT | GET_NAME, idx) + return Iris::get_arg () + // Get the file. + Iris::Cap get_file_ro (Iris::Num idx): + icall (CAP_MASTER_DIRECT | GET_FILE_RO, idx) + return Iris::get_arg () + // Get file info. TODO: define possible types. + Iris::Num get_file_info (Iris::Num idx, unsigned type): + return icall (Iris::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx) + // Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present. + void lock_ro (): + call (CAP_MASTER_DIRECT | LOCK_RO) + // Release a read-only lock. Write operations can only be done when the directory is locked. + void unlock_ro (): + call (CAP_MASTER_DIRECT | UNLOCK_RO) + struct WDirectory : public Directory: + WDirectory (Iris::Cap c = Iris::Cap ()) : Directory (c): + enum request: + GET_FILE = Directory::ID + CREATE_FILE + DELETE_FILE + LOCK + UNLOCK + ID + // Get the file. + Iris::Cap get_file (Iris::Num idx): + icall (CAP_MASTER_DIRECT | GET_FILE, idx) + return Iris::get_arg () + // Create a new file. After this, any index may map to a different file. + Iris::Cap create_file (String name): + icall (CAP_MASTER_DIRECT | CREATE_FILE) + return Iris::get_arg () + // Delete a file. After this, any index may map to a different file. + void delete_file (Iris::Num idx): + call (CAP_MASTER_DIRECT | DELETE_FILE, idx) + // Lock the directory. Write operations can only be done when the directory is locked. + void lock (): + call (CAP_MASTER_DIRECT | LOCK) + // Unlock the directory. Write operations can only be done when the directory is locked. + void unlock (): + call (CAP_MASTER_DIRECT | UNLOCK) -// Stream interface. -struct Stream : public Kernel::Cap: - Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): - enum request: - READ = Filesystem::ID - WRITE - ID - // Try to read size bytes. Returns the number of bytes successfully read. - Kernel::Num read (Kernel::Num size, bool block): - return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, block), size) - // Try to write size bytes. Returns the number of bytes successfully written. - Kernel::Num write (String s, Kernel::Num size): - return ocall (s, CAP_MASTER_DIRECT | WRITE, size) + // A filesystem turns a String into a Directory. + struct Filesystem : public Device: + Filesystem (Iris::Cap c = Iris::Cap ()) : Device (c): + enum request: + USE_DEVICE = WDirectory::ID + USE_DEVICE_RO + ID + WDirectory use_device (WString dev): + ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE) + return Iris::get_arg () + Directory use_device_ro (String dev): + ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO) + return Iris::get_arg () + + // Stream interface. + struct Stream : public Iris::Cap: + Stream (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c): + enum request: + READ = Filesystem::ID + WRITE + ID + // Try to read size bytes. Returns the number of bytes successfully read. + Iris::Num read (Iris::Num size, bool block): + return icall (Iris::Num (CAP_MASTER_DIRECT | READ, block), size) + // Try to write size bytes. Returns the number of bytes successfully written. + Iris::Num write (String s, Iris::Num size): + return ocall (s, CAP_MASTER_DIRECT | WRITE, size) -// Block device interface. -struct Block_device : public WString: - Block_device (Kernel::Cap c = Kernel::Cap ()) : WString (c): - // TODO: to be designed. + // Block device interface. + struct Block_device : public WString: + Block_device (Iris::Cap c = Iris::Cap ()) : WString (c): + // TODO: to be designed. // TODO. diff --git a/init.config b/init.config new file mode 100644 index 0000000..928cd14 --- /dev/null +++ b/init.config @@ -0,0 +1,59 @@ + # load = '' load a file into memory. Don't use this after killbootthreads. + load session = "session.config" + load driver_lcd = "lcd.elf" + load driver_buzzer = "buzzer.elf" + load driver_gpio = "gpio.elf" +# load driver_audio = "audio.elf" +# load driver_udc = "udc.elf" +# load driver_nand = "nand.elf" + +# load emu_lcd = "emu_display.elf" +# load emu_buzzer = "emu_buzzer.elf" +# load emu_keyboard = "emu_keyboard.elf" +# load emu_audio = "emu_audio.elf" +# load emu_udc = "emu_udc.elf" + + # killbootthreads destroy bootinit, bootfs and bootstore. + killbootthreads + + # receive / [, ] = prepare to accept a capability from a named program. + receive driver_lcd / Display = display + receive driver_lcd / Setting = display_bright + receive driver_buzzer / Buzzer = buzzer + receive driver_gpio / Keyboard , 0 = keyboard + receive driver_gpio / Keyboard , 1 = sysreq +# receive driver_audio / Audio = audio +# receive driver_udc / Udc = udc +# receive driver_nand / WString = nand + + # driver run a previously loaded program priviledged. + driver driver_lcd + driver driver_buzzer + driver driver_gpio +# driver driver_audio +# driver driver_udc +# driver driver_nand + + # wait wait until all expected capabilities are received. + wait + + # sysreq use a capability as the system request keyboard. + sysreq sysreq + + # give ( [, ]) = give this capability to this program when it requests it. +# give emu_display (display) = display +# give emu_display_bright (setting) = display_bright +# give emu_buzzer (buzzer) = buzzer +# give emu_keyboard (keyboard, 0) = keyboard +# give emu_audio (audio) = audio +# give emu_udc (udc) = udc + + # run run a previously loaded program (normally). +# run emu_lcd +# run emu_buzzer +# run emu_keyboard +# run emu_audio +# run emu_udc + + # include include a loaded file as another config file. + include session diff --git a/invoke.ccp b/invoke.ccp index cd65e4a..850be16 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -60,8 +60,8 @@ void kThread::raise (unsigned code, unsigned data): kdebug (':') kdebug_num ((unsigned)old_current) kdebug ('/') - if code < Kernel::NUM_EXCEPTION_CODES: - kdebug (Kernel::exception_name[code]) + if code < Iris::NUM_EXCEPTION_CODES: + kdebug (Iris::exception_name[code]) else: kdebug ("invalid code:") kdebug_num (code) @@ -73,7 +73,7 @@ void kThread::raise (unsigned code, unsigned data): if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target: return kCapability::Context c - c.data[0] = Kernel::Num (code, data) + c.data[0] = Iris::Num (code, data) slot[0].caps->cap (0)->invoke (&c) // From user-provided, thus untrusted, data, find a capability. @@ -128,7 +128,7 @@ bool kReceiver::try_deliver (): return true // Send a message to a receiver; try to deliver it immediately. -bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c): +bool kReceiver::send_message (Iris::Num protected_data, kCapability::Context *c): //log_message ("send_message", (unsigned)this, protected_data.l, c) if owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()): if protected_only: @@ -161,59 +161,64 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context * return true static kCapability::Context *context -static kReceiver *reply_target -static Kernel::Num reply_protected -static void reply_num (Kernel::Num num): +static void reply_num (Iris::Num num): kCapability::Context c c.data[0] = num c.data[1] = 0 if reply_target: reply_target->send_message (reply_protected, &c) - else: + else if reply_protected.l == 0: dpanic (0, "nothing to reply to") + else: + kdebug ("not replying, because receiver was destroyed in the operation\n") static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0): kCapability::Context c - c.data[0] = Kernel::Num (num1, num2) + c.data[0] = Iris::Num (num1, num2) c.data[1] = num3 if reply_target: reply_target->send_message (reply_protected, &c) + else if reply_protected.l == 0: + dpanic (0, "nothing to reply to") else: - dpanic (0, "nothing to reply to") + kdebug ("not replying, because receiver was destroyed in the operation\n") -static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref, unsigned num = 0): +static void reply_cap (unsigned target, Iris::Num protected_data, kCapRef *ref, unsigned num = 0): if !reply_target: - dpanic (0, "nothing to reply to") + if reply_protected.l == 0: + dpanic (0, "nothing to reply to") + else: + kdebug ("not replying, because receiver was destroyed in the operation\n") return replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref) kCapability::Context c c.arg = kCapRef (&replied_caps, 0) c.copy[1] = true - c.data[0] = Kernel::Num (num, 0) + c.data[0] = Iris::Num (num, 0) reply_target->send_message (reply_protected, &c) c.arg->invalidate () -static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void receiver_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kReceiver *receiver = (kReceiver *)protected_data.l switch cmd: - case Kernel::Receiver::SET_OWNER & REQUEST_MASK: + case Iris::Receiver::SET_OWNER & REQUEST_MASK: if !c->arg.valid (): - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return unsigned cap = (unsigned)c->arg->target - if cap != (CAPTYPE_THREAD | CAP_MASTER) && cap != (CAPTYPE_THREAD | Kernel::Thread::SET_OWNER): + if cap != (CAPTYPE_THREAD | CAP_MASTER) && cap != (CAPTYPE_THREAD | Iris::Thread::SET_OWNER): // FIXME: This makes it impossible to use a fake kThread capability. return receiver->own ((kThread *)c->arg->protected_data.l) break - case Kernel::Receiver::CREATE_CAPABILITY & REQUEST_MASK: + case Iris::Receiver::CREATE_CAPABILITY & REQUEST_MASK: reply_cap ((unsigned)receiver, c->data[1], &receiver->capabilities) return - case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK: - reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Kernel::Receiver::CALL_ASYNC : Kernel::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs) + case Iris::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK: + reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Iris::Receiver::CALL_ASYNC : Iris::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs) return - case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK: + case Iris::Receiver::GET_PROTECTED & REQUEST_MASK: if !c->arg.valid () || c->arg->target != receiver: if !c->arg.valid (): kdebug ("invalid arg\n") @@ -226,23 +231,23 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte kdebug_num ((unsigned)c->arg->protected_data.l) kdebug ("\n") dpanic (0, "wrong argument for get_protected") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return reply_num (c->arg->protected_data) return - case Kernel::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK: + case Iris::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK: reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0) return - case Kernel::Receiver::SET_REPLY_PROTECTED_DATA & REQUEST_MASK: + case Iris::Receiver::SET_REPLY_PROTECTED_DATA & REQUEST_MASK: receiver->reply_protected_data = c->data[1] break - case Kernel::Receiver::GET_ALARM & REQUEST_MASK: + case Iris::Receiver::GET_ALARM & REQUEST_MASK: reply_num (receiver->alarm_count) return - case Kernel::Receiver::SET_ALARM & REQUEST_MASK: - case Kernel::Receiver::ADD_ALARM & REQUEST_MASK: + case Iris::Receiver::SET_ALARM & REQUEST_MASK: + case Iris::Receiver::ADD_ALARM & REQUEST_MASK: unsigned old = receiver->alarm_count - if cmd == (Kernel::Receiver::SET_ALARM & REQUEST_MASK): + if cmd == (Iris::Receiver::SET_ALARM & REQUEST_MASK): receiver->alarm_count = c->data[1].l else: receiver->alarm_count += c->data[1].l @@ -267,14 +272,14 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte return default: dpanic (cmd, "invalid receiver operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return reply_num (0) -static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kMemory *mem = (kMemory *)protected_data.l switch cmd: - case Kernel::Memory::CREATE & REQUEST_MASK: + case Iris::Memory::CREATE & REQUEST_MASK: switch c->data[0].h: case CAPTYPE_RECEIVER: kReceiver *ret = mem->alloc_receiver () @@ -282,7 +287,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ reply_cap (CAPTYPE_RECEIVER | CAP_MASTER, (unsigned)ret, &ret->refs) else: dpanic (0x03311992, "out of memory creating receiver") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return case CAPTYPE_MEMORY: kMemory *ret = mem->alloc_memory () @@ -290,7 +295,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)ret, &ret->refs) else: dpanic (0x13311992, "out of memory creating memory") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return case CAPTYPE_THREAD: kThread *ret = mem->alloc_thread (c->data[1].l) @@ -301,7 +306,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ kdebug (")") else: dpanic (0x23311992, "out of memory creating thread") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return case CAPTYPE_PAGE: kPage *ret = mem->alloc_page () @@ -309,7 +314,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs) else: dpanic (0x33311992, "out of memory creating page") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return case CAPTYPE_CAPS: kCaps *ret = mem->alloc_caps (c->data[1].l) @@ -317,16 +322,16 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)ret, &ret->refs) else: dpanic (0x43311992, "out of memory creating caps") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return default: dpanic (0, "invalid create type") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return break - case Kernel::Memory::DESTROY & REQUEST_MASK: + case Iris::Memory::DESTROY & REQUEST_MASK: if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || !c->arg->target || ((kObject *)c->arg->protected_data.l)->address_space != mem: - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return switch (unsigned)c->arg->target & CAPTYPE_MASK: case CAPTYPE_RECEIVER: @@ -348,87 +353,88 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ panic (0x55228930, "invalid case") return break - case Kernel::Memory::LIST & REQUEST_MASK: + case Iris::Memory::LIST & REQUEST_MASK: // TODO break - case Kernel::Memory::MAP & REQUEST_MASK: + case Iris::Memory::MAP & REQUEST_MASK: // FIXME: this should work for fake pages as well. if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || ((unsigned)c->arg->target & CAPTYPE_MASK) != CAPTYPE_PAGE: dpanic (0x22993341, "Trying to map non-page") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kPage *page = (kPage *)c->arg->protected_data.l if page->address_space != mem: dpanic (0x52993341, "Trying to map foreign page") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return - if c->data[1].l & (unsigned)c->arg->target & Kernel::Page::READONLY: + if c->data[1].l & (unsigned)c->arg->target & Iris::Page::READONLY: kdebug ("Mapping readonly because capability is readonly\n") - page->flags |= Kernel::Page::MAPPED_READONLY + page->flags |= Iris::Page::MAPPED_READONLY mem->map (page, c->data[1].l & PAGE_MASK) break - case Kernel::Memory::MAPPING & REQUEST_MASK: + case Iris::Memory::MAPPING & REQUEST_MASK: kPage *page = mem->get_mapping (c->data[1].l) if !page: - reply_num (Kernel::ERR_UNMAPPED_READ) + reply_num (Iris::ERR_UNMAPPED_READ) return unsigned t = CAPTYPE_PAGE | CAP_MASTER - if page->flags & Kernel::Page::MAPPED_READONLY: - t |= Kernel::Page::READONLY + if page->flags & Iris::Page::MAPPED_READONLY: + t |= Iris::Page::READONLY reply_cap (t, (unsigned)page, &page->refs) return - case Kernel::Memory::GET_LIMIT & REQUEST_MASK: + case Iris::Memory::GET_LIMIT & REQUEST_MASK: reply_num (mem->limit) return - case Kernel::Memory::SET_LIMIT & REQUEST_MASK: + case Iris::Memory::SET_LIMIT & REQUEST_MASK: mem->limit = c->data[1].l break default: dpanic (0, "invalid memory operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return reply_num (0) -static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): + dbg_push (__LINE__) kThread *thread = (kThread *)protected_data.l switch cmd: - case Kernel::Thread::GET_INFO & REQUEST_MASK: + case Iris::Thread::GET_INFO & REQUEST_MASK: switch c->data[0].h: - case Kernel::Thread::PC: + case Iris::Thread::PC: reply_num (thread->pc) return - case Kernel::Thread::SP: + case Iris::Thread::SP: reply_num (thread->sp) return - case Kernel::Thread::FLAGS: + case Iris::Thread::FLAGS: reply_num (thread->flags) return default: reply_num (*kThread_arch_info (thread, c->data[0].h)) return - case Kernel::Thread::SET_INFO & REQUEST_MASK: + case Iris::Thread::SET_INFO & REQUEST_MASK: unsigned *value switch c->data[0].h: - case Kernel::Thread::PC: + case Iris::Thread::PC: value = &thread->pc break - case Kernel::Thread::SP: + case Iris::Thread::SP: value = &thread->sp break - case Kernel::Thread::FLAGS: + case Iris::Thread::FLAGS: // It is not possible to set the PRIV flag (but it can be reset). - if c->data[1].l & Kernel::Thread::PRIV: - c->data[1].h &= ~Kernel::Thread::PRIV + if c->data[1].l & Iris::Thread::PRIV: + c->data[1].h &= ~Iris::Thread::PRIV value = &thread->flags - if c->data[1].h & ~Kernel::Thread::USER_FLAGS: + if c->data[1].h & ~Iris::Thread::USER_FLAGS: unsigned v = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h) - if (v & Kernel::Thread::WAITING) != (*value & Kernel::Thread::WAITING): - if v & Kernel::Thread::WAITING: + if (v & Iris::Thread::WAITING) != (*value & Iris::Thread::WAITING): + if v & Iris::Thread::WAITING: thread->wait () else thread->unwait () - if (v & Kernel::Thread::RUNNING) != (*value & Kernel::Thread::RUNNING): - if v & Kernel::Thread::RUNNING: + if (v & Iris::Thread::RUNNING) != (*value & Iris::Thread::RUNNING): + if v & Iris::Thread::RUNNING: thread->run () else: thread->unrun () @@ -439,140 +445,155 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ if value: *value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h) break - case Kernel::Thread::USE_SLOT & REQUEST_MASK: + case Iris::Thread::USE_SLOT & REQUEST_MASK: + dbg_push (__LINE__) if c->data[1].l >= thread->slots || !c->arg.valid (): + if c->data[1].l == 0xdeadbeef: + bool dummy + dbg_code.h = (unsigned)c->arg.deref () + break dbg_send (5, 3) dpanic (c->data[1].l, "no argument given for USE_SLOT") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return // FIXME: This doesn't allow using a fake caps. - if (unsigned)c->arg->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->arg->target != (CAPTYPE_CAPS | Kernel::Caps::USE): - dpanic (0, "argument for USE_SLOT is not a caps") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + if (unsigned)c->arg->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->arg->target != (CAPTYPE_CAPS | Iris::Caps::USE): + dpanic ((unsigned)c->arg->target, "argument for USE_SLOT is not a caps") + reply_num (Iris::ERR_INVALID_ARGUMENT) return + dbg_push (__LINE__) unsigned slot = c->data[1].l + dbg_push (__LINE__) kCaps *new_caps = (kCaps *)c->arg->protected_data.l + dbg_push (__LINE__) if slot >= thread->slots: dpanic (0, "using invalid slot") return + dbg_push (__LINE__) thread->unset_slot (slot) + dbg_push (__LINE__) thread->slot[slot].caps = new_caps + dbg_push (__LINE__) if new_caps: + dbg_push (__LINE__) thread->slot[slot].next = new_caps->first_slot thread->slot[slot].caps = new_caps new_caps->first_slot.thread = thread new_caps->first_slot.index = slot + dbg_push (__LINE__) break - case Kernel::Thread::GET_CAPS & REQUEST_MASK: + case Iris::Thread::GET_CAPS & REQUEST_MASK: unsigned slot = c->data[1].l if slot < thread->slots: reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->slot[slot].caps, &thread->slot[slot].caps->refs, thread->slots) else: reply_num (thread->slots) return - case Kernel::Thread::SCHEDULE & REQUEST_MASK: + case Iris::Thread::SCHEDULE & REQUEST_MASK: do_schedule = true return default: - if !(thread->flags & Kernel::Thread::PRIV): + if !(thread->flags & Iris::Thread::PRIV): dpanic (0, "invalid thread operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return switch cmd: - case Kernel::Thread::PRIV_REGISTER_INTERRUPT & REQUEST_MASK: + case Iris::Thread::PRIV_REGISTER_INTERRUPT & REQUEST_MASK: 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) break - case Kernel::Thread::PRIV_GET_TOP_MEMORY & REQUEST_MASK: + case Iris::Thread::PRIV_GET_TOP_MEMORY & REQUEST_MASK: reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)&top_memory, &top_memory.refs) return - case Kernel::Thread::PRIV_MAKE_PRIV & REQUEST_MASK: + case Iris::Thread::PRIV_MAKE_PRIV & REQUEST_MASK: if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_THREAD: dpanic (0, "not a thread argument for make priv") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return - ((kThread *)c->arg->protected_data.l)->flags |= Kernel::Thread::PRIV + ((kThread *)c->arg->protected_data.l)->flags |= Iris::Thread::PRIV break - case Kernel::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK: + case Iris::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK: if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY: panic (0x54365435, "non-memory argument to alloc_range") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kMemory *mem = (kMemory *)c->arg->protected_data.l if !mem->use (c->data[1].l): dpanic (0x34365435, "out of memory during alloc_range") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return unsigned data = phys_alloc (c->data[1].l) if !data: mem->unuse (c->data[1].l) dpanic (0x14365435, "out of memory during alloc_range") - reply_num (Kernel::ERR_OUT_OF_MEMORY) + reply_num (Iris::ERR_OUT_OF_MEMORY) return reply_num (data & ~0xc0000000) return - case Kernel::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK: + case Iris::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK: if !c->arg.valid (): panic (0x71342134, "no argument provided for alloc physical") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE: panic (0x21342134, "no page provided for alloc physical") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kPage *page = (kPage *)c->arg->protected_data.l page->forget () if !(c->data[1].l & 2): - if page->flags & Kernel::Page::PAYING: - page->flags &= ~Kernel::Page::PAYING + if page->flags & Iris::Page::PAYING: + page->flags &= ~Iris::Page::PAYING page->address_space->unuse () else: // This is for mapping allocated ranges. They are already paid for. Record that. - if page->flags & Kernel::Page::PAYING: + if page->flags & Iris::Page::PAYING: page->address_space->unuse () else: - page->flags |= Kernel::Page::PAYING + page->flags |= Iris::Page::PAYING page->frame = (c->data[1].l & PAGE_MASK) | 0x80000000 - page->flags |= Kernel::Page::FRAME + page->flags |= Iris::Page::FRAME if !(c->data[1].l & 1): - page->flags |= Kernel::Page::UNCACHED + page->flags |= Iris::Page::UNCACHED if !(c->data[1].l & 2): - page->flags |= Kernel::Page::PHYSICAL + page->flags |= Iris::Page::PHYSICAL kPage_arch_update_mapping (page) break - case Kernel::Thread::PRIV_PHYSICAL_ADDRESS & REQUEST_MASK: + case Iris::Thread::PRIV_PHYSICAL_ADDRESS & REQUEST_MASK: if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_PAGE: dpanic (0x99049380, "invalid page for physical address") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kPage *page = (kPage *)c->arg->protected_data.l reply_num (page->frame & ~0xc0000000) return - case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK: + case Iris::Thread::PRIV_REBOOT & REQUEST_MASK: arch_reboot () - case Kernel::Thread::PRIV_PANIC & REQUEST_MASK: + case Iris::Thread::PRIV_PANIC & REQUEST_MASK: if c->data[1].l == 0xdeaddead: dbg_code.l = 1 break panic (c->data[1].l, "panic requested by thread") reply_num (~0) return - case Kernel::Thread::DBG_SEND & REQUEST_MASK: + case Iris::Thread::DBG_SEND & REQUEST_MASK: dbg_send (c->data[1].l, c->data[1].h) break default: dpanic (0, "invalid priv thread operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return + dbg_push (__LINE__) reply_num (0) + dbg_push (__LINE__) return static void page_check_payment (kPage *page): kPage *p for p = page; p; p = p->share_prev: - if p->flags & Kernel::Page::PAYING: + if p->flags & Iris::Page::PAYING: return for p = page->share_next; p; p = p->share_next: - if p->flags & Kernel::Page::PAYING: + if p->flags & Iris::Page::PAYING: return // No kPage is paying for this frame anymore. raw_pfree (page->frame) @@ -581,46 +602,55 @@ static void page_check_payment (kPage *page): p->frame = NULL p->share_prev = NULL p->share_next = NULL - p->flags &= ~(Kernel::Page::SHARED | Kernel::Page::FRAME) + p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME) kPage_arch_update_mapping (p) for p = page, next = p->share_next; p; p = next, next = p->share_next: p->frame = NULL p->share_prev = NULL p->share_next = NULL - p->flags &= ~(Kernel::Page::SHARED | Kernel::Page::FRAME) + p->flags &= ~(Iris::Page::SHARED | Iris::Page::FRAME) kPage_arch_update_mapping (p) -static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void page_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kPage *page = (kPage *)protected_data.l - switch cmd & ~Kernel::Page::READONLY: - case Kernel::Page::SHARE & REQUEST_MASK: + switch cmd & ~Iris::Page::READONLY: + case Iris::Page::SHARE & REQUEST_MASK: if !c->arg.valid (): // Cannot share without a target page. dpanic (0, "no target page for share") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE: // FIXME: This makes it impossible to use a fake kPage capability. dpanic (0, "share target is no page") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kPage *t = (kPage *)c->arg->protected_data.l + //kdebug ("sharing from ") + //kdebug_num ((unsigned)page) + //kdebug (" (frame ") + //kdebug_num (page->frame) + //kdebug (") to ") + //kdebug_num ((unsigned)t) + //kdebug (" (frame ") + //kdebug_num (t->frame) + //kdebug (")\n") if t != page: t->forget () - if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY: - t->flags |= Kernel::Page::READONLY - if !(page->flags & Kernel::Page::FRAME): + if c->data[0].h & Iris::Page::READONLY || cmd & Iris::Page::READONLY: + t->flags |= Iris::Page::READONLY + if !(page->flags & Iris::Page::FRAME): kdebug ("share problem: ") kdebug_num (page->flags) kdebug ("\n") dpanic (0, "sharing nothing results in lost page") kPage_arch_update_mapping (t) break - if c->data[0].h & Kernel::Page::COPY: - if ~t->flags & Kernel::Page::PAYING: + if c->data[0].h & Iris::Page::COPY: + if ~t->flags & Iris::Page::PAYING: kPage_arch_update_mapping (t) break - if !(c->data[0].h & Kernel::Page::FORGET) || page->flags & Kernel::Page::SHARED: + if !(c->data[0].h & Iris::Page::FORGET) || page->flags & Iris::Page::SHARED: unsigned *d = (unsigned *)page->frame if t == page: kPage *other = page->share_next ? page->share_next : page->share_prev @@ -635,20 +665,20 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da page->share_prev = NULL page_check_payment (other) else: - t->flags |= Kernel::Page::FRAME + t->flags |= Iris::Page::FRAME t->frame = raw_zalloc () for unsigned i = 0; i < PAGE_SIZE; i += 4: ((unsigned *)t->frame)[i >> 2] = d[i >> 2] - if c->data[0].h & Kernel::Page::FORGET: + if c->data[0].h & Iris::Page::FORGET: page->frame = NULL - page->flags &= ~Kernel::Page::FRAME + page->flags &= ~Iris::Page::FRAME kPage_arch_update_mapping (page) else: if t != page: t->frame = page->frame - t->flags |= Kernel::Page::FRAME + t->flags |= Iris::Page::FRAME page->frame = NULL - page->flags &= ~Kernel::Page::FRAME + page->flags &= ~Iris::Page::FRAME kPage_arch_update_mapping (page) else: dpanic (0, "sharing page with itself...") @@ -657,15 +687,15 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da dpanic (0, "sharing page with itself") kPage_arch_update_mapping (t) break - if c->data[0].h & Kernel::Page::FORGET: - if ~page->flags & Kernel::Page::SHARED: - if t->flags & Kernel::Page::PAYING: + if c->data[0].h & Iris::Page::FORGET: + if ~page->flags & Iris::Page::SHARED: + if t->flags & Iris::Page::PAYING: t->frame = page->frame - t->flags |= Kernel::Page::FRAME + t->flags |= Iris::Page::FRAME else: dpanic (0, "move page failed because target is not paying") page->frame = NULL - page->flags &= ~Kernel::Page::FRAME + page->flags &= ~Iris::Page::FRAME kPage_arch_update_mapping (page) else: t->share_prev = page->share_prev @@ -685,49 +715,49 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da if t->share_prev: t->share_prev->share_next = t t->frame = page->frame - t->flags |= Kernel::Page::FRAME + t->flags |= Iris::Page::FRAME kPage_arch_update_mapping (t) break - case Kernel::Page::SET_FLAGS & REQUEST_MASK: - if cmd & Kernel::Page::READONLY: + case Iris::Page::SET_FLAGS & REQUEST_MASK: + if cmd & Iris::Page::READONLY: dpanic (0, "setting page flags denied") - reply_num (Kernel::ERR_WRITE_DENIED) + reply_num (Iris::ERR_WRITE_DENIED) return // Always refuse to set reserved flags. - c->data[1].h &= ~(Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED) + c->data[1].h &= ~(Iris::Page::PHYSICAL | Iris::Page::UNCACHED) // Remember the old flags. unsigned old = page->flags // Compute the new flags. page->flags = (page->flags & ~c->data[1].h) | (c->data[1].l & c->data[1].h) // If we stop paying, see if the frame is still paid for. If not, free it. - if ~page->flags & old & Kernel::Page::PAYING: + if ~page->flags & old & Iris::Page::PAYING: // Decrease the use counter in any case. page->address_space->unuse () page_check_payment (page) // If we start paying, increase the use counter. - if page->flags & ~old & Kernel::Page::PAYING: + if page->flags & ~old & Iris::Page::PAYING: if !page->address_space->use(): dpanic (0, "cannot pay for frame") // If it doesn't work, refuse to set the flag, and refuse to allocate a frame. - page->flags &= ~(Kernel::Page::PAYING | Kernel::Page::FRAME) + page->flags &= ~(Iris::Page::PAYING | Iris::Page::FRAME) // However, if there already was a frame, keep it. - if old & Kernel::Page::FRAME: - page->flags |= Kernel::Page::FRAME + if old & Iris::Page::FRAME: + page->flags |= Iris::Page::FRAME // If we want a frame, see if we can get it. - if ~old & page->flags & Kernel::Page::FRAME: - if ~page->flags & Kernel::Page::PAYING: + if ~old & page->flags & Iris::Page::FRAME: + if ~page->flags & Iris::Page::PAYING: dpanic (0, "cannot have frame without paying") - page->flags &= ~Kernel::Page::FRAME + page->flags &= ~Iris::Page::FRAME else: page->frame = page->address_space->zalloc () kPage_arch_update_mapping (page) break default: dpanic (0, "invalid page operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return if page->flags > 0x7f: dpanic (page->flags, "weird output from page operation") @@ -755,12 +785,12 @@ static void print_cap (kCapRef cap, kCapRef self): else: kdebug (']') -static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void caps_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kCaps *caps = (kCapsP)protected_data.l switch cmd: - case Kernel::Caps::GET & REQUEST_MASK: + case Iris::Caps::GET & REQUEST_MASK: if c->data[1].l >= caps->size: - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) kdebug_num ((unsigned)caps) kdebug (" size: ") kdebug_num (caps->size) @@ -782,10 +812,10 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da #endif reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities) return - case Kernel::Caps::GET_SIZE & REQUEST_MASK: + case Iris::Caps::GET_SIZE & REQUEST_MASK: reply_num (caps->size) return - case Kernel::Caps::SET & REQUEST_MASK: + case Iris::Caps::SET & REQUEST_MASK: if c->data[1].l >= caps->size: dpanic (0, "invalid index for set caps") return @@ -802,10 +832,10 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da //kdebug_num (caps->caps[c->data[1].l].protected_data.l) //kdebug ("\n") return - case Kernel::Caps::TRUNCATE & REQUEST_MASK: + case Iris::Caps::TRUNCATE & REQUEST_MASK: dpanic (0, "truncate caps is not implemented yet.") return - case Kernel::Caps::PRINT & REQUEST_MASK: + case Iris::Caps::PRINT & REQUEST_MASK: if c->data[1].l >= caps->size: dpanic (0, "invalid caps for print") return @@ -839,12 +869,12 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da return default: dpanic (cmd, "invalid caps operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return -static void list_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void list_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kList *list = (kListP)protected_data.l - if cmd == Kernel::List::SET_CB & REQUEST_MASK: + if cmd == Iris::List::SET_CB & REQUEST_MASK: list->owner.clone (0, c->arg, c->copy[1]) return kListitem *item @@ -853,81 +883,81 @@ static void list_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da else: if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_LISTITEM: dpanic (0, "invalid request for list: arg is no listitem") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return item = (kListitem *)c->arg->protected_data.l if item->list != list: dpanic (0, "item list is not equal to called object") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return switch cmd: - case Kernel::List::GET_NEXT & REQUEST_MASK: + case Iris::List::GET_NEXT & REQUEST_MASK: if !item: item = list->first_listitem else: - if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::LIST: + if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Iris::Listitem::LIST: dpanic (0, "trying to get next listitem with insufficient rights") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return item = item->next_item if !item: reply_num (0) return - reply_cap (CAPTYPE_LISTITEM | Kernel::Listitem::LIST, (unsigned)item, &item->refs) + reply_cap (CAPTYPE_LISTITEM | Iris::Listitem::LIST, (unsigned)item, &item->refs) return - case Kernel::List::ADD_ITEM & REQUEST_MASK: + case Iris::List::ADD_ITEM & REQUEST_MASK: if !item: dpanic (0, "invalid request: no listitem for List::ADD_ITEM") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return - if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::ADD: + if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Iris::Listitem::ADD: dpanic (0, "trying to add listitem with insufficient rights") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return ((kListitem *)c->arg->protected_data.l)->add (list) break - case Kernel::List::GET_INFO & REQUEST_MASK: + case Iris::List::GET_INFO & REQUEST_MASK: if !item: dpanic (0, "no item for List::GET_INFO") - reply_num (Kernel::ERR_INVALID_ARGUMENT, ~0, ~0) + reply_num (Iris::ERR_INVALID_ARGUMENT, ~0, ~0) return reply_num (item->info) return - case Kernel::List::SET_INFO & REQUEST_MASK: + case Iris::List::SET_INFO & REQUEST_MASK: if !item: dpanic (0, "no item for List::SET_INFO") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return item->info = c->data[1] break - case Kernel::List::GET_CAP & REQUEST_MASK: + case Iris::List::GET_CAP & REQUEST_MASK: if !item: dpanic (0, "no item for List::GET_CAP") - reply_num (Kernel::ERR_INVALID_ARGUMENT) + reply_num (Iris::ERR_INVALID_ARGUMENT) return kCapability *cap = item->target.cap (0) reply_cap ((unsigned)cap->target, cap->protected_data, ((unsigned)cap->target & ~KERNEL_MASK) == 0 ? &((kObject *)cap->target)->refs : &cap->target->capabilities) return default: dpanic (0, "invalid list operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return reply_num (0) -static void listitem_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void listitem_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c): kListitem *item = (kListitemP)protected_data.l switch cmd: - case Kernel::Listitem::CLEAR & REQUEST_MASK: + case Iris::Listitem::CLEAR & REQUEST_MASK: // Disable linked capability. item->add (NULL) break - case Kernel::Listitem::SET_CAP & REQUEST_MASK: + case Iris::Listitem::SET_CAP & REQUEST_MASK: // Set linked capability. item->target.clone (0, c->arg, c->copy[1]) break default: dpanic (0, "invalid listitem operation") - reply_num (Kernel::ERR_INVALID_OPERATION) + reply_num (Iris::ERR_INVALID_OPERATION) return reply_num (0) @@ -936,18 +966,18 @@ static void kill_reply (kReceiver *r): while cap.valid (): kCapability *c = cap.deref () cap = c->sibling_next - if (unsigned)c->target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY): + if (unsigned)c->target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY): c->invalidate () -static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c): +static void kernel_invoke (unsigned target, Iris::Num protected_data, kCapability::Context *c): // Kernel calling convention: // data[0].l is the request. // reply is the reply capability, or (for call capabilities) the target to call. // other parameters' meanings depend on the operation. - if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC): + if target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL_ASYNC): // This is a call capability. reply is the capability to call. kReceiver *owner = (kReceiver *)protected_data.l - owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) + owner->protected_only = target == (CAPTYPE_RECEIVER | Iris::Receiver::CALL) if must_wait: old_current->wait () if !reply_target: @@ -961,11 +991,11 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil // This is a user-implemented object. Create a real reply capability. kReceiver *call_target = reply_target c->reply = kCapRef (&reply_caps, 0) - c->reply.set ((kReceiver *)(CAPTYPE_RECEIVER | Kernel::Receiver::REPLY), protected_data, kCapRef (), &((kReceiver *)protected_data.l)->refs) + c->reply.set ((kReceiver *)(CAPTYPE_RECEIVER | Iris::Receiver::REPLY), protected_data, kCapRef (), &((kReceiver *)protected_data.l)->refs) c->copy[0] = true call_target->send_message (reply_protected, c) c->reply->invalidate () - else if (unsigned)reply_target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY): + else if (unsigned)reply_target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY): // Reply capability: destroy all before invoke. kReceiver *r = (kReceiver *)reply_protected.l kill_reply (r) @@ -981,7 +1011,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil return if must_wait: old_current->wait () - if target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY): + if target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY): // This is a reply capability. kReceiver *r = (kReceiver *)protected_data.l kill_reply (r) @@ -1026,7 +1056,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil return return -void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c): +void invoke (kReceiverP target, Iris::Num protected_data, kCapability::Context *c): if dbg_code.l && old_current->id != 1: log_message ("invoke", (unsigned)target, protected_data.l, c) if (unsigned)target & ~KERNEL_MASK: @@ -1046,4 +1076,5 @@ void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context reply_protected = c->reply->protected_data else: reply_target = NULL + reply_protected.l = 0 kernel_invoke ((unsigned)target, protected_data, c) diff --git a/iris.hhp b/iris.hhp index 49dc340..ab5ca88 100644 --- a/iris.hhp +++ b/iris.hhp @@ -53,11 +53,12 @@ // Master capabilities can create others. #define CAP_MASTER_CREATE (1 << 31) -#define __receiver_num 0 -#define __thread_num 1 -#define __memory_num 2 -#define __call_num 3 -#define __parent_num 4 +#define __caps_num 0 +#define __receiver_num 1 +#define __thread_num 2 +#define __memory_num 3 +#define __call_num 4 +#define __parent_num 5 // If this flag is set in a capability, it is copied instead of mapped. // If it is set in the target capability, the Thread waits after the request. @@ -65,9 +66,8 @@ // This constant signifies that no capability is passed. #define CAP_NONE (~CAP_COPY) -struct Parent - -namespace Kernel: +namespace Iris: + struct Parent enum Exception_code: NO_ERROR ERR_WRITE_DENIED @@ -138,6 +138,7 @@ namespace Kernel: Cap alloc_cap () void free_slot (unsigned slot) void free_cap (Cap cap) + extern bool enable_debug struct Cap: unsigned code @@ -161,6 +162,7 @@ namespace Kernel: Num protected_data Cap reply, arg + extern Caps my_caps extern Receiver my_receiver extern Thread my_thread extern Memory my_memory @@ -280,7 +282,7 @@ namespace Kernel: Cap create_capability (Num protected_data): icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data) return get_arg () - Num get_protected (Kernel::Cap target): + Num get_protected (Cap target): return ocall (target, CAP_MASTER_DIRECT | GET_PROTECTED) Num get_reply_protected_data (): return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA) @@ -455,8 +457,8 @@ namespace Kernel: PHYSICAL = 0x20 // This is a read-only flag, saying if this is uncachable memory. UNCACHED = 0x40 - void share (Cap target, unsigned flags): - ocall (target, Kernel::Num (CAP_MASTER_DIRECT | SHARE, flags)) + void share (Cap target, unsigned flags = 0): + ocall (target, Num (CAP_MASTER_DIRECT | SHARE, flags)) unsigned get_flags (): return call (CAP_MASTER_DIRECT | GET_FLAGS).l bool set_flags (unsigned new_flags, unsigned mask): @@ -576,7 +578,7 @@ namespace Kernel: Cap ().call () // The start function has this prototype (there is no main function). -Kernel::Num start () +Iris::Num start () #ifndef __KERNEL__ #if 1 @@ -596,7 +598,7 @@ static void kdebug_num (unsigned n, unsigned digits = 8): for i = 0; i < digits; ++i: kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf]) -namespace Kernel: +namespace Iris: inline void panic (unsigned code, char const *message = NULL): if message: kdebug (message) diff --git a/kernel.hhp b/kernel.hhp index f23d324..0c7d039 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -75,7 +75,7 @@ struct kCapRef: kCapRef (kCapsP c, unsigned i) : caps (c), index (i): kCapRef () : caps (NULL), index (~0): inline void clone (kCapRef source, bool copy) - inline void set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) + inline void set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) struct kObject: kCapRef refs @@ -97,7 +97,7 @@ bool kObject::is_free (): struct kCapability : public kObject: struct Context: - Kernel::Num data[2] + Iris::Num data[2] kCapRef reply kCapRef arg bool copy[2] @@ -105,7 +105,7 @@ struct kCapability : public kObject: kCapRef parent kCapRef children kCapRef sibling_prev, sibling_next - Kernel::Num protected_data + Iris::Num protected_data inline void invoke (kCapability::Context *c) void invalidate () @@ -138,7 +138,7 @@ struct kThread : public kObject: void wait () void unwait () bool is_waiting (): - return flags & Kernel::Thread::WAITING + return flags & Iris::Thread::WAITING kCapRef find_capability (unsigned code, bool *copy) struct kReceiver : public kObject: @@ -154,14 +154,14 @@ struct kReceiver : public kObject: // The message queue. kMessages are added at the tail, and removed at the front. kMessageP messages kMessageP last_message - Kernel::Num reply_protected_data + Iris::Num reply_protected_data bool protected_only // This limit is for messages stored in its address space. There is unlimited space if senders provide it. unsigned queue_limit, queue_use void own (kThreadP o) void orphan () bool try_deliver () - bool send_message (Kernel::Num protected_data, kCapability::Context *c) + bool send_message (Iris::Num protected_data, kCapability::Context *c) void check (unsigned line) struct kPage : public kObject: @@ -177,7 +177,7 @@ struct kCaps : public kObject: unsigned size kCapability caps[1] inline kCapability *cap (unsigned idx) - void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) + void set (unsigned index, kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) void clone (unsigned index, kCapRef source, bool copy) void init (unsigned size) @@ -185,8 +185,8 @@ struct kCaps : public kObject: #define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1) struct kMessage : public kObject: - Kernel::Num protected_data - Kernel::Num data[2] + Iris::Num protected_data + Iris::Num data[2] // This is a real Caps of two elements, not a link. kCaps caps @@ -198,7 +198,7 @@ struct kList : public kObject: struct kListitem : public kObject: kListP list kListitemP prev_item, next_item - Kernel::Num info + Iris::Num info // This is a real Caps of one element, not a link. kCaps target void add (kList *l) @@ -257,7 +257,7 @@ extern "C": #define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m)) void panic_impl (unsigned n, char const *line, char const *name, char const *message = "") #ifndef NDEBUG - EXTERN Kernel::Num dbg_code + EXTERN Iris::Num dbg_code EXTERN unsigned dbg_buffer[32] EXTERN unsigned dbg_buffer_head static void dbg_push (unsigned n): @@ -293,7 +293,11 @@ EXTERN kThreadP current, old_current EXTERN bool do_schedule, must_wait // reply_caps is the source of a receiver-generated reply capability. // replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply. +// reply_target is the target receiver for kernel replies. +// reply_protected is the protected data for the kernel reply. EXTERN kCaps reply_caps, replied_caps +EXTERN kReceiver *reply_target +EXTERN Iris::Num reply_protected // Defined in memory.ccp unsigned init_memory (unsigned mem) @@ -303,11 +307,11 @@ unsigned phys_alloc (unsigned num) void phys_free (unsigned page, unsigned num) // Defind in invoke.ccp -void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c) +void invoke (kReceiverP target, Iris::Num protected_data, kCapability::Context *c) // Defined by architecture-specific files. void kThread_arch_init (kThread *thread) -void kThread_arch_receive (kThread *thread, Kernel::Num protected_data, Kernel::Num *data) +void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data) unsigned *kThread_arch_info (kThread *thread, unsigned num) void kMemory_arch_init (kMemory *mem) void kMemory_arch_free (kMemory *mem) @@ -336,7 +340,7 @@ kCapability *kCapRef::deref (): return caps ? caps->cap (index) : NULL void kCapRef::clone (kCapRef source, bool copy): caps->clone (index, source, copy) -void kCapRef::set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr): +void kCapRef::set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr): if valid (): deref ()->invalidate () caps->set (index, target, pdata, parent, parent_ptr) diff --git a/memory.ccp b/memory.ccp index 989877f..cc2f43e 100644 --- a/memory.ccp +++ b/memory.ccp @@ -172,6 +172,8 @@ void phys_free (unsigned page, unsigned num): kFreePages *p for p = first_free; p->next && (unsigned)p->next < page; p = p->next: // Do nothing. + if p == p->next: + dpanic (0, "page is its own next") // The new block should be inserted directly after p. if (unsigned)p->next == page + size: // It can be merged with the block after it: do that. diff --git a/mips/arch.ccp b/mips/arch.ccp index e9a36de..cdd9ff8 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -38,7 +38,7 @@ void kPage_arch_init (kPage *page): page->arch.prev_mapped = NULL page->arch.next_mapped = NULL -void kThread_arch_receive (kThread *thread, Kernel::Num protected_data, Kernel::Num *data): +void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data): thread->arch.a[0] = data[0].l thread->arch.a[1] = data[0].h thread->arch.a[2] = data[1].l @@ -161,12 +161,12 @@ static unsigned make_entry_lo (kPage *page): //kdebug ("not mapping because there is no frame\n") return 0 unsigned flags - if page->flags & Kernel::Page::UNCACHED: + if page->flags & Iris::Page::UNCACHED: flags = 0x10 | 0x2 else: // 18 is write-back cache; 00 is write-through cache. flags = 0x18 | 0x2 - if ~page->flags & Kernel::Page::MAPPED_READONLY: + if ~page->flags & Iris::Page::MAPPED_READONLY: flags |= 0x4 return ((page->frame & ~0x80000000) >> 6) | flags diff --git a/mips/init.ccp b/mips/init.ccp index 3461ce2..5074187 100644 --- a/mips/init.ccp +++ b/mips/init.ccp @@ -33,7 +33,7 @@ static void init_idle (): idle.schedule_next = NULL idle.address_space = &idle_memory idle.refs.reset () - idle.flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV + idle.flags = Iris::Thread::RUNNING | Iris::Thread::PRIV // initialize idle_memory. idle_memory.prev = NULL idle_memory.next = NULL @@ -52,7 +52,7 @@ static void init_idle (): idle_page.prev = NULL idle_page.next = NULL idle_page.frame = 0x80000000 - idle_page.flags = Kernel::Page::PAYING | Kernel::Page::FRAME + idle_page.flags = Iris::Page::PAYING | Iris::Page::FRAME idle_page.refs.reset () idle_page.address_space = NULL current = &idle @@ -147,7 +147,7 @@ static void init_threads (): return thread->pc = header->e_entry thread->sp = 0x80000000 - unsigned *used = (unsigned *)mem->zalloc () + kPage **used = (kPage **)mem->zalloc () for unsigned section = 0; section < header->e_shnum; ++section: Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize) if ~shdr->sh_flags & SHF_ALLOC: @@ -168,12 +168,19 @@ static void init_threads (): panic (0, "different pages mapped to one address in intitial file") return continue - used[idx] = 1 page = mem->alloc_page () page->frame = thread_start[i] + (idx << PAGE_BITS) - page->flags = Kernel::Page::PAYING | Kernel::Page::FRAME + page->flags = Iris::Page::PAYING | Iris::Page::FRAME + if used[idx]: + page->share_next = used[idx] + used[idx]->share_prev = page + used[idx]->flags |= Iris::Page::SHARED + used[idx] = page + page->flags |= Iris::Page::SHARED + else: + used[idx] = page if readonly: - page->flags |= Kernel::Page::MAPPED_READONLY + page->flags |= Iris::Page::MAPPED_READONLY if !mem->map (page, p): panic (0x22446688, "unable to map initial page") return @@ -200,7 +207,7 @@ static void init_threads (): if !page->frame: panic (0x02220022, "out of memory"); return - page->flags = Kernel::Page::PAYING | Kernel::Page::FRAME + page->flags = Iris::Page::PAYING | Iris::Page::FRAME if !mem->map (page, p): panic (0x33557799, "unable to map initial bss page") return @@ -210,7 +217,7 @@ static void init_threads (): kdebug_num (i, 1) kdebug ('\n') else: - if page->flags & Kernel::Page::MAPPED_READONLY: + if page->flags & Iris::Page::MAPPED_READONLY: panic (0x20203030, "bss section starts on read-only page") return for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4: @@ -230,7 +237,7 @@ static void init_threads (): mem->pfree ((unsigned)used) kPage *stackpage = mem->alloc_page () stackpage->frame = mem->zalloc () - stackpage->flags = Kernel::Page::PAYING | Kernel::Page::FRAME + stackpage->flags = Iris::Page::PAYING | Iris::Page::FRAME if !stackpage || !mem->map (stackpage, 0x7ffff000): panic (0x13151719, "unable to map initial stack page") return @@ -242,11 +249,12 @@ static void init_threads (): kReceiver *recv = mem->alloc_receiver () recv->owner = thread thread->receivers = recv - thread->slot[0].caps->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs) - thread->slot[0].caps->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Kernel::Num ((unsigned)thread), kCapRef (), &thread->refs) - thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Kernel::Num ((unsigned)mem), kCapRef (), &mem->refs) - thread->slot[0].caps->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Kernel::Receiver::CALL), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs) - thread->flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV + 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) + thread->slot[0].caps->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Iris::Num ((unsigned)recv), kCapRef (), &recv->refs) + thread->slot[0].caps->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Iris::Num ((unsigned)thread), kCapRef (), &thread->refs) + thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Iris::Num ((unsigned)mem), kCapRef (), &mem->refs) + thread->slot[0].caps->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Iris::Receiver::CALL), Iris::Num ((unsigned)recv), kCapRef (), &recv->refs) + thread->flags = Iris::Thread::RUNNING | Iris::Thread::PRIV if !i: first_scheduled = thread init_receiver = recv diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index f0ce225..cade086 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -33,7 +33,7 @@ static kThread *handle_exit (): schedule () if !current: current = &idle - if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING: + if (current->flags & (Iris::Thread::RUNNING | Iris::Thread::WAITING)) != Iris::Thread::RUNNING: panic (current->flags, "non-scheduled thread running") if old_current == current: return current @@ -54,7 +54,7 @@ static kThread *handle_exit (): asids[current->address_space->arch.asid] = (unsigned)current->address_space cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid) directory = current->address_space->arch.directory - if current->flags & Kernel::Thread::PRIV: + if current->flags & Iris::Thread::PRIV: cp0_set (CP0_STATUS, 0x1000ff13) else: cp0_set (CP0_STATUS, 0x0000ff13) @@ -69,7 +69,7 @@ kThread *tlb_refill (): if !directory: unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_NO_PAGE_DIRECTORY, addr) + current->raise (Iris::ERR_NO_PAGE_DIRECTORY, addr) return handle_exit () unsigned EntryHi cp0_get (CP0_ENTRY_HI, EntryHi) @@ -77,7 +77,7 @@ kThread *tlb_refill (): if !t: unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_NO_PAGE_TABLE, addr) + current->raise (Iris::ERR_NO_PAGE_TABLE, addr) else: // - 2 instead of - 1 means reset bit 0 unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2) @@ -161,13 +161,22 @@ static void arch_invoke (): return msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0]) msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1]) - msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1]) - msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3]) + msg.data[0] = Iris::Num (old_current->arch.a[0], old_current->arch.a[1]) + msg.data[1] = Iris::Num (old_current->arch.a[2], old_current->arch.a[3]) + dbg_push (old_current->arch.v[0]) + dbg_push (old_current->arch.t[0]) + dbg_push (old_current->arch.t[1]) + dbg_push (old_current->arch.a[0]) + dbg_push (old_current->arch.a[1]) + dbg_push (old_current->arch.a[2]) + dbg_push (old_current->arch.a[3]) + dbg_push (0xdeadbeef) target->invoke (&msg) + dbg_push (0xfacebeef) if do_schedule && !must_wait: // If the call was to schedule without wait, it isn't done yet. schedule () - else if old_current != current && (old_current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) == Kernel::Thread::RUNNING: + else if old_current != current && old_current && (old_current->flags & (Iris::Thread::RUNNING | Iris::Thread::WAITING)) == Iris::Thread::RUNNING: // If the caller received an immediate reply from the kernel, it is no longer set as current. Don't let it lose its timeslice. current = old_current @@ -186,31 +195,31 @@ kThread *exception (): // TLB modification. unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_WRITE_DENIED, addr) + current->raise (Iris::ERR_WRITE_DENIED, addr) break case 2: // TLB load or instruction fetch. unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_UNMAPPED_READ, addr) + current->raise (Iris::ERR_UNMAPPED_READ, addr) break case 3: // TLB store. unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_UNMAPPED_WRITE, addr) + current->raise (Iris::ERR_UNMAPPED_WRITE, addr) break case 4: // Address error load or instruction fetch. unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_INVALID_ADDRESS_READ, addr) + current->raise (Iris::ERR_INVALID_ADDRESS_READ, addr) break case 5: // Address error store. unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) - current->raise (Kernel::ERR_INVALID_ADDRESS_WRITE, addr) + current->raise (Iris::ERR_INVALID_ADDRESS_WRITE, addr) break case 6: // Bus error instruction fetch. @@ -229,7 +238,7 @@ kThread *exception (): case 9: // Breakpoint. #if 0 || defined (NDEBUG) - //current->raise (Kernel::ERR_BREAKPOINT, 0) + //current->raise (Iris::ERR_BREAKPOINT, 0) #ifndef NDEBUG current->pc += 4 #endif @@ -251,19 +260,19 @@ kThread *exception (): break case 10: // Reserved instruction. - current->raise (Kernel::ERR_RESERVED_INSTRUCTION, 0) + current->raise (Iris::ERR_RESERVED_INSTRUCTION, 0) break case 11: // Coprocessor unusable. - current->raise (Kernel::ERR_COPROCESSOR_UNUSABLE, 0) + current->raise (Iris::ERR_COPROCESSOR_UNUSABLE, 0) break case 12: // Arithmetic overflow. - current->raise (Kernel::ERR_OVERFLOW, 0) + current->raise (Iris::ERR_OVERFLOW, 0) break case 13: // Trap. - current->raise (Kernel::ERR_TRAP, 0) + current->raise (Iris::ERR_TRAP, 0) break case 15: // Floating point exception. @@ -272,7 +281,7 @@ kThread *exception (): case 23: // Reference to WatchHi/WatchLo address. cp0_set0 (CP0_WATCH_LO) - current->raise (Kernel::ERR_WATCHPOINT, 0) + current->raise (Iris::ERR_WATCHPOINT, 0) break case 24: // Machine check. diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index e830130..189aa04 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -28,12 +28,12 @@ LDFLAGS = --omagic -Ttext $(load) arch_iris_sources = mips/interrupts.cc mips/arch.cc boot_sources = mips/init.cc mips/nanonote/board.cc arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh -boot_threads = init udc -programs = \#nanonote-gpio \#lcd display-emu bsquare display-emu2 ball \#buzzer metronome +boot_threads = bootinit udc +programs = init gpio lcd display-emu bsquare ball buzzer metronome elfrun all: test -test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) +test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050 mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac devices.hh @@ -55,12 +55,15 @@ mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T mips/nanonote/sdram-setup.l mips/nanonote/threadlist.o: $(addsuffix .elf,$(boot_threads)) mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20" mips/init.o: TARGET_FLAGS = -I/usr/include -boot-programs/init.o: TARGET_FLAGS = -I/usr/include +boot-programs/bootinit.o: TARGET_FLAGS = -I/usr/include +source/elfrun.o: TARGET_FLAGS = -I/usr/include +source/gpio.ccp: source/nanonote-gpio.ccp + ln -s $(subst source/,,$<) $@ $(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I. $(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL $(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL $(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh -source/\#lcd.o: source/charset.data +source/lcd.o: source/charset.data source/charset.data: source/charset $< > $@ diff --git a/mips/nanonote/jz4740.hhp b/mips/nanonote/jz4740.hhp index 1dbec69..dbad377 100644 --- a/mips/nanonote/jz4740.hhp +++ b/mips/nanonote/jz4740.hhp @@ -104,14 +104,14 @@ // Default lcd framebuffer mapping space. #define LCD_FRAMEBUFFER_BASE ((unsigned *)0x00015000) -// Map IO memory (requires a priviledged Kernel::my_thread capability). +// Map IO memory (requires a priviledged Iris::my_thread capability). #include static void __map_io (unsigned physical, unsigned mapping): - Kernel::Page p = Kernel::my_memory.create_page () + Iris::Page p = Iris::my_memory.create_page () // false means not cachable; false means don't free when done. p.alloc_physical (physical, false, false) - Kernel::my_memory.map (p, mapping) - Kernel::free_cap (p) + Iris::my_memory.map (p, mapping) + Iris::free_cap (p) #define map_cpm() do { __map_io (CPM_PHYSICAL, CPM_BASE); } while (0) #define map_intc() do { __map_io (INTC_PHYSICAL, INTC_BASE); } while (0) @@ -135,8 +135,8 @@ static void __map_io (unsigned physical, unsigned mapping): // udelay implementation void cdelay (unsigned cs): - Kernel::my_receiver.set_alarm (cs + 1) - Kernel::Cap ().call () + Iris::my_receiver.set_alarm (cs + 1) + Iris::Cap ().call () #endif diff --git a/mips/nanonote/server/usb-server.ccp b/mips/nanonote/server/usb-server.ccp index 0988a66..ba4aafb 100644 --- a/mips/nanonote/server/usb-server.ccp +++ b/mips/nanonote/server/usb-server.ccp @@ -105,37 +105,37 @@ void data::poll (): case ~1 & 0xffff: // No event. break - case Directory::GET_SIZE: + case Iris::Directory::GET_SIZE: unsigned long long size = dir.size () std::cerr << "sending dir size\n" - std::cerr << Directory::GET_SIZE << '\n' + std::cerr << Iris::Directory::GET_SIZE << '\n' char *str = (char *)&size for unsigned i = 0; i < 8; ++i: std::cerr << " " << (unsigned)(str[i] & 0xff) std::cerr << '\n' - if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, Directory::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8: + 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: std::cerr << "unable to send size to device: " << usb_strerror () << std::endl usb_release_interface (handle, 0) usb_close (handle) handle = NULL return continue - case Directory::GET_NAME: + case Iris::Directory::GET_NAME: if buffer[1] >= dir.size (): std::cerr << "invalid file name requested" << std::endl; usb_release_interface (handle, 0) usb_close (handle) handle = NULL return - std::cerr << "sending filename\n" - 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: + std::cerr << "sending filename " << dir[buffer[1]].full << "\n" + 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: std::cerr << "unable to send name to device: " << usb_strerror () << std::endl usb_release_interface (handle, 0) usb_close (handle) handle = NULL return continue - case Directory::LOCK_RO: + case Iris::Directory::LOCK_RO: std::cerr << "lock\n" lock++ std::cerr << "freezing file list\n" @@ -145,7 +145,7 @@ void data::poll (): if !i->name.empty () && i->name[0] != '.': dir.push_back (Name (i->name)) continue - case Directory::UNLOCK_RO: + case Iris::Directory::UNLOCK_RO: std::cerr << "unlock\n" if !lock: std::cerr << "unlocking without lock" << std::endl @@ -156,7 +156,7 @@ void data::poll (): if !--lock: dir.clear () continue - case String::GET_PAGE: + case Iris::String::GET_PAGE: if buffer[1] >= dir.size (): std::cerr << "reading invalid file" << std::endl usb_release_interface (handle, 0) @@ -178,16 +178,16 @@ void data::poll (): handle = NULL return continue - case String::GET_SIZE: + case Iris::String::GET_SIZE: if buffer[1] >= dir.size (): - std::cerr << "reading invalid file size" << std::endl + std::cerr << "reading invalid file size " << buffer[1] << " >= " << dir.size () << std::endl usb_release_interface (handle, 0) usb_close (handle) handle = NULL return unsigned long long size = dir[buffer[1]].content.size () std::cerr << "sending file size " << size << "\n" - if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, String::GET_SIZE, 0, 0, (char *)&size, 8, timeout) != 8: + 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: std::cerr << "unable to send size to device: " << usb_strerror () << std::endl usb_release_interface (handle, 0) usb_close (handle) @@ -312,18 +312,18 @@ void data::boot (unsigned entry): std::cerr << "(re)booted NanoNote\n" static void dump_devices (): - std::cerr << std::hex << "String: " << String::ID - std::cerr << "\nWString: " << WString::ID - std::cerr << "\nDevice: " << Device::ID - std::cerr << "\nParent: " << Parent::ID - std::cerr << "\nKeyboard: " << Keyboard::ID - std::cerr << "\nBuzzer: " << Buzzer::ID - std::cerr << "\nDisplay: " << Display::ID - std::cerr << "\nSetting: " << Setting::ID - std::cerr << "\nDirectory: " << Directory::ID - std::cerr << "\nWDirectory: " << WDirectory::ID - std::cerr << "\nFilesystem: " << Filesystem::ID - std::cerr << "\nStream: " << Stream::ID + std::cerr << std::hex << "String: " << Iris::String::ID + std::cerr << "\nWString: " << Iris::WString::ID + std::cerr << "\nDevice: " << Iris::Device::ID + std::cerr << "\nParent: " << Iris::Parent::ID + std::cerr << "\nKeyboard: " << Iris::Keyboard::ID + std::cerr << "\nBuzzer: " << Iris::Buzzer::ID + std::cerr << "\nDisplay: " << Iris::Display::ID + std::cerr << "\nSetting: " << Iris::Setting::ID + std::cerr << "\nDirectory: " << Iris::Directory::ID + std::cerr << "\nWDirectory: " << Iris::WDirectory::ID + std::cerr << "\nFilesystem: " << Iris::Filesystem::ID + std::cerr << "\nStream: " << Iris::Stream::ID std::cerr << "\n" int main (int argc, char **argv): diff --git a/mips/nanonote/threadlist.S b/mips/nanonote/threadlist.S index 45ab1fa..1270282 100644 --- a/mips/nanonote/threadlist.S +++ b/mips/nanonote/threadlist.S @@ -21,7 +21,7 @@ .balign 0x1000 thread0: - .incbin "init.elf" + .incbin "bootinit.elf" .balign 0x1000 thread1: diff --git a/mips/trendtac/jz4730.hhp b/mips/trendtac/jz4730.hhp index b7b7c5c..20d9f95 100644 --- a/mips/trendtac/jz4730.hhp +++ b/mips/trendtac/jz4730.hhp @@ -137,14 +137,14 @@ // Default lcd framebuffer mapping space. #define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00021000) -// Map IO memory (requires a priviledged Kernel::my_thread capability). +// Map IO memory (requires a priviledged Iris::my_thread capability). #include static void __map_io (unsigned physical, unsigned mapping): - Kernel::Page p = Kernel::my_memory.create_page () + Iris::Page p = Iris::my_memory.create_page () // false means not cachable; false means don't free when done. p.alloc_physical (physical, false, false) - Kernel::my_memory.map (p, mapping) - Kernel::free_cap (p) + Iris::my_memory.map (p, mapping) + Iris::free_cap (p) #define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0) #define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0) @@ -2326,8 +2326,8 @@ static __inline__ void udelay (unsigned us): #ifndef __KERNEL__ static __inline__ void cdelay (unsigned ds): - Kernel::my_receiver.set_alarm (ds * (HZ / 100)) - Kernel::Cap ().call (~0) + Iris::my_receiver.set_alarm (ds * (HZ / 100)) + Iris::Cap ().call (~0) #endif /*************************************************************************** diff --git a/panic.ccp b/panic.ccp index f058cf9..a1c05bd 100644 --- a/panic.ccp +++ b/panic.ccp @@ -48,7 +48,7 @@ void kdebug_num (unsigned num, unsigned digits): static void print_addr (char const *t, unsigned addr, bool last = false): kdebug (t) kdebug_num (addr) - #if 1 + #if 0 unsigned de = addr >> 21 unsigned te = (addr >> 12) & ((1 << 9) - 1) if de < 0x400 && old_current && old_current->address_space->arch.directory && old_current->address_space->arch.directory[de]: @@ -83,7 +83,7 @@ static void print_addr (char const *t, unsigned addr, bool last = false): kdebug_num (((unsigned *)addr)[i]) kdebug ("\n") #else - kdebug (last ? '\n' : ';') + kdebug (last ? "\n" : "; ") #endif static void panic_message (unsigned n, const char *line, char const *name, char const *message): @@ -118,11 +118,11 @@ static void panic_message (unsigned n, const char *line, char const *name, char kdebug (':') kdebug_num (dbg_code.l) kdebug ('\n') - kdebug ("debug buffer:") + kdebug ("debug buffer (most recently pushed at end):") unsigned b = dbg_buffer_head - for unsigned i = 0; i < 16; ++i: + for unsigned i = 0; i < 8; ++i: kdebug ('\n') - for unsigned j = 0; j < 2; ++j: + for unsigned j = 0; j < 4; ++j: kdebug (' ') kdebug_num (dbg_buffer[b]) ++b diff --git a/plan b/plan index ff7d078..b82c0d1 100644 --- a/plan +++ b/plan @@ -42,3 +42,84 @@ te doen: - start programma van filesystem - nand driver - filesystems met backing store + +Boot process: +- bootinit and filesystem (and backing store) are started. +- bootinit starts run.elf and loads init.elf. +- run starts init. +- init loads init.config and executes it. +- during that process, the initial programs are killed. + +Order: +run.elf +init.elf +init.config +load.elf +drivers +emulations +programs + +init.config is a script: + + # load = load a file into memory. Don't use this after killbootthreads. + load session = session.config + load driver_lcd = lcd.elf + load driver_buzzer = buzzer.elf + load driver_gpio = gpio.elf + load driver_audio = audio.elf + load driver_udc = udc.elf + load driver_nand = nand.elf + + load emu_lcd = emu_display.elf + load emu_buzzer = emu_buzzer.elf + load emu_keyboard = emu_keyboard.elf + load emu_audio = emu_audio.elf + load emu_udc = emu_udc.elf + + # killbootthreads destroy bootinit, bootfs and bootstore. + killbootthreads + + # receive = ( [, ]) prepare to accept a capability from a named program. + receive display = driver_lcd (display) + receive display_bright = driver_lcd (setting) + receive buzzer = driver_buzzer (buzzer) + receive keyboard = driver_gpio (keyboard, 0) + receive sysreq = driver_gpio (keyboard, 1) + receive audio = driver_audio (audio) + receive udc = driver_udc (udc) + receive nand = driver_nand (wstring) + + # driver run a previously loaded program priviledged. + driver driver_lcd + driver driver_buzzer + driver driver_gpio + driver driver_audio + driver driver_udc + driver driver_nand + + # wait wait until all expected capabilities are received. + wait + + # sysreq use a capability as the system request keyboard. + sysreq sysreq + + # give ( [, ]) = give this capability to this program when it requests it. + give emu_display (display) = display + give emu_display_bright (setting) = display_bright + give emu_buzzer (buzzer) = buzzer + give emu_keyboard (keyboard, 0) = keyboard + give emu_audio (audio) = audio + give emu_udc (udc) = udc + + # run run a previously loaded program (normally). + run emu_lcd + run emu_buzzer + run emu_keyboard + run emu_audio + run emu_udc + + # include include a loaded file as another config file. + include session + + # loop sit and do nothing (respond to system request). + loop diff --git a/schedule.ccp b/schedule.ccp index 2357472..6fdf97f 100644 --- a/schedule.ccp +++ b/schedule.ccp @@ -36,24 +36,24 @@ static void unrun_thread (kThread *thread): thread->schedule_next->schedule_prev = thread->schedule_prev void kThread::run (): - if flags & Kernel::Thread::RUNNING: + if flags & Iris::Thread::RUNNING: return - flags |= Kernel::Thread::RUNNING + flags |= Iris::Thread::RUNNING if is_waiting (): return run_thread (this) void kThread::unrun (): - if !(flags & Kernel::Thread::RUNNING): + if !(flags & Iris::Thread::RUNNING): return - flags &= ~Kernel::Thread::RUNNING + flags &= ~Iris::Thread::RUNNING if is_waiting (): return unrun_thread (this) void kThread::unwait (): - flags &= ~Kernel::Thread::WAITING - if flags & Kernel::Thread::RUNNING: + flags &= ~Iris::Thread::WAITING + if flags & Iris::Thread::RUNNING: run_thread (this) static void alarm_tick (kReceiver *recv): @@ -73,9 +73,9 @@ static void alarm_tick (kReceiver *recv): --recv->alarm_count void kThread::wait (): - if flags & Kernel::Thread::RUNNING: + if flags & Iris::Thread::RUNNING: unrun_thread (this) - flags |= Kernel::Thread::WAITING + flags |= Iris::Thread::WAITING // Try to receive a message from a kReceiver immediately. for kReceiver *r = receivers; r; r = r->next_owned: if r->try_deliver (): diff --git a/source/ball.ccp b/source/ball.ccp index 1c0ad36..76d22bd 100644 --- a/source/ball.ccp +++ b/source/ball.ccp @@ -33,16 +33,16 @@ void ball (int x, int y, unsigned colour): continue framebuffer[ty * 320 + tx] = (colour) -Kernel::Num start (): - Kernel::my_parent.init_done () +Iris::Num start (): + Iris::my_parent.init_done () int colour = 0x3f30ff framebuffer = (unsigned *)0x15000 - Display display = Kernel::my_parent.get_device (0x10000) + Iris::Display display = Iris::my_parent.get_device (0x10000) int x = r, y = r, dx = 3, dy = 0 - Kernel::Cap eof = Kernel::my_receiver.create_capability (0) + Iris::Cap eof = Iris::my_receiver.create_capability (0) while true: display.set_eof_cb (eof) - Kernel::wait () + Iris::wait () ball (x, y, 0) x += dx y += dy diff --git a/source/bsquare.ccp b/source/bsquare.ccp index b374bc1..53c9c2f 100644 --- a/source/bsquare.ccp +++ b/source/bsquare.ccp @@ -32,16 +32,16 @@ void square (int x, int y, bool print): continue framebuffer[ty * 320 + tx] = (print ? colour : 0) -Kernel::Num start (): - Kernel::my_parent.init_done () +Iris::Num start (): + Iris::my_parent.init_done () colour = 0xffff00 framebuffer = (unsigned *)0x15000 - Display display = Kernel::my_parent.get_device (0x10001) + Iris::Display display = Iris::my_parent.get_device (0x10001) int x = r, y = r, dx = 3, dy = 3 - Kernel::Cap eof = Kernel::my_receiver.create_capability (0) + Iris::Cap eof = Iris::my_receiver.create_capability (0) while true: display.set_eof_cb (eof) - Kernel::wait () + Iris::wait () square (x, y, false) x += dx y += dy diff --git a/source/#buzzer.ccp b/source/buzzer.ccp similarity index 67% rename from source/#buzzer.ccp rename to source/buzzer.ccp index f18c5fa..b3963b6 100644 --- a/source/#buzzer.ccp +++ b/source/buzzer.ccp @@ -22,7 +22,7 @@ class DevBuzzer: static unsigned const pwm = 4 - Kernel::Cap event + Iris::Cap event bool is_beeping public: DevBuzzer (): @@ -36,9 +36,9 @@ class DevBuzzer: return tcu_stop_counter (pwm) event.invoke () - Kernel::free_cap (event) + Iris::free_cap (event) is_beeping = false - void beep (unsigned freq, unsigned ms, Kernel::Cap cb): + void beep (unsigned freq, unsigned ms, Iris::Cap cb): stop () event = cb unsigned full = JZ_EXTAL / 64 / freq @@ -46,37 +46,37 @@ class DevBuzzer: tcu_set_half_data (pwm, full / 2) tcu_set_count (pwm, 0) tcu_start_counter (pwm) - Kernel::my_receiver.set_alarm (ms * HZ / 1000) + Iris::my_receiver.set_alarm (ms * HZ / 1000) is_beeping = true enum codes: BUZZER = 32 -Kernel::Num start (): +Iris::Num start (): map_tcu () DevBuzzer buzzer - Device dev = Kernel::my_receiver.create_capability (BUZZER) - Kernel::my_parent.provide_device (dev.copy ()) - Kernel::free_cap (dev) - Kernel::my_parent.init_done () + Iris::Device dev = Iris::my_receiver.create_capability (BUZZER) + Iris::my_parent.provide_device (dev.copy ()) + Iris::free_cap (dev) + Iris::my_parent.init_done () unsigned user (~0) unsigned next_user (0) while true: - Kernel::wait () - switch Kernel::recv.protected_data.h: + Iris::wait () + switch Iris::recv.protected_data.h: case ~0: // Alarm. buzzer.stop () break case 0: - switch Kernel::recv.protected_data.l: + switch Iris::recv.protected_data.l: case BUZZER: // Buzzer device control request. - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - Device::host (BUZZER, user, reply, arg) + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::Device::host (BUZZER, user, reply, arg) break default: kdebug ("invalid buzzer request\n") @@ -84,22 +84,22 @@ Kernel::Num start (): break case BUZZER: // Buzzer device user request. - if Kernel::recv.protected_data.l != user: + if Iris::recv.protected_data.l != user: kdebug ("invalid user requesting buzzer\n") - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () break - switch Kernel::recv.data[0].l: - case Buzzer::BEEP: + switch Iris::recv.data[0].l: + case Iris::Buzzer::BEEP: // Volume is not used by this buzzer. - Kernel::Cap arg = Kernel::get_arg () - Kernel::Cap reply = Kernel::get_reply () - buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg) + Iris::Cap arg = Iris::get_arg () + Iris::Cap reply = Iris::get_reply () + buzzer.beep (Iris::recv.data[1].l, Iris::recv.data[1].h, arg) reply.invoke () - Kernel::free_cap (reply) + Iris::free_cap (reply) break - case Buzzer::STOP: + case Iris::Buzzer::STOP: buzzer.stop () - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () break default: kdebug ("Buzzer: other\n") @@ -107,5 +107,5 @@ Kernel::Num start (): break default: kdebug ("Buzzer: unknown num: ") - kdebug_num (Kernel::recv.protected_data.h) + kdebug_num (Iris::recv.protected_data.h) kdebug ("\n") diff --git a/source/crt0.ccp b/source/crt0.ccp index 92f3868..66dbb6b 100644 --- a/source/crt0.ccp +++ b/source/crt0.ccp @@ -29,7 +29,9 @@ static unsigned __slots, __caps static list *__slot_admin, *__cap_admin static list *__first_free_slot, *__first_free_cap -namespace Kernel: +namespace Iris: + bool enable_debug + Caps my_caps Receiver my_receiver Thread my_thread Memory my_memory @@ -44,6 +46,8 @@ namespace Kernel: used[i] = true unsigned num = 0 for list *i = __first_free_cap; i; i = i->next: + if used[i - __cap_admin] == false: + panic (0, "inconsistent userspace cap db") used[i - __cap_admin] = false ++num kdebug_num (num, 2) @@ -54,6 +58,9 @@ namespace Kernel: void free_slot (unsigned slot): //kdebug ("free slot\n") + for list *i = __first_free_slot; i; i = i->next: + if slot == i - __slot_admin: + panic (0, "double free of userspace slot") __slot_admin[slot].prev = NULL __slot_admin[slot].next = __first_free_slot if __slot_admin[slot].next: @@ -61,12 +68,16 @@ namespace Kernel: __first_free_slot = &__slot_admin[slot] void free_cap (Cap cap): - //kdebug ("free cap ") - //kdebug_num (cap.idx (), 2) - //kdebug ("\n") + if enable_debug: + kdebug ("free cap ") + kdebug_num (cap.idx (), 2) + kdebug ("\n") + for list *i = __first_free_cap; i; i = i->next: + if cap.idx () == i - __cap_admin: + panic (0, "double free of userspace cap") if cap.slot () != 0: kdebug ("trying to free capability from non-0 slot\n") - Kernel::panic (0) + Iris::panic (0) return list *l = &__cap_admin[cap.idx ()] l->prev = NULL @@ -80,7 +91,7 @@ namespace Kernel: if !__first_free_slot: // Out of slots... Probably best to raise an exception. For now, just return NO_SLOT. kdebug ("out of slots!\n") - Kernel::panic (0) + Iris::panic (0) return ~0 list *ret = __first_free_slot __first_free_slot = ret->next @@ -89,42 +100,45 @@ namespace Kernel: return ret - __slot_admin Cap alloc_cap (): - //kdebug ("alloc cap ") if !__first_free_cap: // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE kdebug ("out of capabilities!\n") - Kernel::panic (0) + Iris::panic (0) return Cap (0, CAP_NONE) list *ret = __first_free_cap __first_free_cap = ret->next if ret->next: ret->next->prev = NULL - //kdebug_num (ret - __cap_admin, 2) - //kdebug ("\n") + if enable_debug: + kdebug ("alloc cap ") + kdebug_num (ret - __cap_admin, 2) + kdebug ("\n") return Cap (0, ret - __cap_admin) extern "C": void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin): + Iris::enable_debug = false __slots = slots __caps = caps __slot_admin = slot_admin __cap_admin = cap_admin __first_free_slot = NULL for unsigned i = 1; i < __slots; ++i: - Kernel::free_slot (i) + Iris::free_slot (i) __first_free_cap = NULL - for unsigned i = 7; i < __caps; ++i: - Kernel::free_cap (Kernel::Cap (0, i)) - Kernel::my_receiver = Kernel::Cap (0, __receiver_num) - Kernel::my_thread = Kernel::Cap (0, __thread_num) - Kernel::my_memory = Kernel::Cap (0, __memory_num) - Kernel::my_call = Kernel::Cap (0, __call_num) - Kernel::my_parent = Kernel::Cap (0, __parent_num) - Kernel::recv.reply = Kernel::alloc_cap () - Kernel::recv.arg = Kernel::alloc_cap () - Kernel::Num ret = start () - Kernel::my_parent.invoke (~0, ret) - Kernel::my_memory.destroy (Kernel::my_thread) + for unsigned i = 6; i < __caps; ++i: + Iris::free_cap (Iris::Cap (0, i)) + Iris::my_caps = Iris::Cap (0, __caps_num) + Iris::my_receiver = Iris::Cap (0, __receiver_num) + Iris::my_thread = Iris::Cap (0, __thread_num) + Iris::my_memory = Iris::Cap (0, __memory_num) + Iris::my_call = Iris::Cap (0, __call_num) + Iris::my_parent = Iris::Cap (0, __parent_num) + Iris::recv.reply = Iris::alloc_cap () + Iris::recv.arg = Iris::alloc_cap () + Iris::Num ret = start () + Iris::my_parent.invoke (~0, ret) + Iris::my_memory.destroy (Iris::my_thread) // The program no longer exists. If it somehow does, generate an address fault. while true: *(volatile unsigned *)~0 diff --git a/source/display-emu.ccp b/source/display-emu.ccp index 3236d26..95e4931 100644 --- a/source/display-emu.ccp +++ b/source/display-emu.ccp @@ -19,64 +19,64 @@ #include #include -Kernel::Num start (): - Device d = Kernel::my_receiver.create_capability (0) - Kernel::my_parent.provide_device (d.copy (), 0x10000) - Kernel::free_cap (d) - Kernel::my_parent.init_done () - Display real = Kernel::my_parent.get_device (0) +Iris::Num start (): + Iris::Device d = Iris::my_receiver.create_capability (0) + Iris::my_parent.provide_device (d.copy (), 0x10000) + Iris::free_cap (d) + Iris::my_parent.init_done () + Iris::Display real = Iris::my_parent.get_device (0) while true: - Kernel::wait () - Kernel::Cap arg = Kernel::get_arg () - Kernel::Cap reply = Kernel::get_reply () - switch Kernel::recv.protected_data.h: + Iris::wait () + Iris::Cap arg = Iris::get_arg () + Iris::Cap reply = Iris::get_reply () + switch Iris::recv.protected_data.h: case 0: - switch Kernel::recv.data[0].l: - case Device::CREATE_USER: - Kernel::Memory mem (arg) - Kernel::Caps ret = mem.create_caps (3) - Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1)) + switch Iris::recv.data[0].l: + case Iris::Device::CREATE_USER: + Iris::Memory mem (arg) + Iris::Caps ret = mem.create_caps (3) + Iris::Cap target = Iris::my_receiver.create_capability (Iris::Num (0, 1)) ret.set (0, target.copy ()) ret.set (1, mem) - Kernel::free_cap (target) + Iris::free_cap (target) for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE: - Kernel::Page p = Kernel::my_memory.mapping ((void *)(0x15000 + i)) - Kernel::Page t = mem.create_page () - t.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING) - p.share (t, Kernel::Page::FORGET) + Iris::Page p = Iris::my_memory.mapping ((void *)(0x15000 + i)) + Iris::Page t = mem.create_page () + t.set_flags (Iris::Page::PAYING, Iris::Page::PAYING) + p.share (t, Iris::Page::FORGET) mem.map (t, 0x15000 + i) - Kernel::my_memory.destroy (t) - Kernel::free_cap (t) - Kernel::free_cap (p) + Iris::my_memory.destroy (t) + Iris::free_cap (t) + Iris::free_cap (p) reply.invoke (0, 0, ret.copy ()) - Kernel::free_cap (ret) + Iris::free_cap (ret) break - case Device::DESTROY_USER: - Kernel::panic (0, "destroying emulation user") - case Device::USE: - case Device::UNUSE: + case Iris::Device::DESTROY_USER: + Iris::panic (0, "destroying emulation user") + case Iris::Device::USE: + case Iris::Device::UNUSE: reply.invoke () break default: - kdebug_num (Kernel::recv.data[0].l) + kdebug_num (Iris::recv.data[0].l) kdebug ("\n") - Kernel::panic (0, "invalid emulation command") + Iris::panic (0, "invalid emulation command") break case 1: - switch Kernel::recv.data[0].l: - case Display::SET_EOF_CB: + switch Iris::recv.data[0].l: + case Iris::Display::SET_EOF_CB: real.set_eof_cb (arg.copy ()) - while Kernel::recv.data[0].l != 0: - Kernel::my_parent.wait (0) + while Iris::recv.data[0].l != 0: + Iris::my_parent.wait (0) real.set_eof_cb (arg.copy ()) reply.invoke () break default: - kdebug_num (Kernel::recv.data[0].l) + kdebug_num (Iris::recv.data[0].l) kdebug_char ('\n') - Kernel::panic (Kernel::recv.data[0].l, "invalid operation on display emulation") + Iris::panic (Iris::recv.data[0].l, "invalid operation on display emulation") break default: - Kernel::panic (0, "bug in display emulation") - Kernel::free_cap (arg) - Kernel::free_cap (reply) + Iris::panic (0, "bug in display emulation") + Iris::free_cap (arg) + Iris::free_cap (reply) diff --git a/source/display-emu2.ccp b/source/display-emu2.ccp deleted file mode 120000 index c7f93ff..0000000 --- a/source/display-emu2.ccp +++ /dev/null @@ -1 +0,0 @@ -display-emu.ccp \ No newline at end of file diff --git a/source/elfrun.ccp b/source/elfrun.ccp new file mode 100644 index 0000000..c7124d8 --- /dev/null +++ b/source/elfrun.ccp @@ -0,0 +1,286 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// source/elfrun.ccp: Process creation server. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "devices.hh" +#include "iris.hh" +#include + +static unsigned _free +extern unsigned _end + +void init_alloc (): + _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK + +char *alloc_space (unsigned pages): + unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK + _free = ret + (pages << PAGE_BITS) + return (char *)ret + +void *operator new[] (unsigned size): + //kdebug ("new ") + void *ret = (void *)_free + size = (size + 3) & ~3 + unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1) + if rest < size: + unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS + for unsigned p = 0; p < pages; ++p: + Iris::Page page = Iris::my_memory.create_page () + page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) + Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS)) + Iris::free_cap (page) + _free += size + //kdebug_num ((unsigned)ret) + //kdebug ("+") + //kdebug_num (size) + //kdebug ("\n") + return ret + +void *operator new (unsigned size): + return new char[size] + +static Iris::Memory parent_memory +static Iris::Cap parent +static unsigned slot +static char *mapping +static unsigned pages +static Iris::Caps pages_caps +static Iris::Memory mem + +static Iris::Caps map_string (Iris::String data): + // Get the size. + Iris::Num size = data.get_size () + if size.value () == 0: + Iris::panic (0, "data string is empty") + // Allocate a caps with all the pages. + pages = (size.value () + PAGE_SIZE - 1) >> PAGE_BITS + pages_caps = Iris::my_memory.create_caps (pages) + slot = pages_caps.use () + // Map them into the address space as well. + mapping = alloc_space (pages) + // Create a memory for the program. + mem = parent_memory.create_memory () + // Load the file into memory and map it. + for unsigned p = 0; p < pages; ++p: + //kdebug_num (p) + //kdebug ("/") + //kdebug_num (pages) + //kdebug ("\n") + Iris::set_recv_arg (Iris::Cap (slot, p)) + data.get_page (p << PAGE_BITS) + Iris::my_memory.map (Iris::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS]) + +static Iris::Caps map_caps (Iris::Caps data, unsigned p): + // Get the size. + if p == 0: + Iris::panic (0, "data caps is empty") + // Allocate a new caps with all the pages for mapping locally. + pages = p + pages_caps = Iris::my_memory.create_caps (pages) + slot = pages_caps.use () + unsigned src_slot = data.use () + // Map them into the address space as well. + mapping = alloc_space (pages) + // Create a memory for the program. + mem = parent_memory.create_memory () + // Load the file into memory and map it. + for unsigned p = 0; p < pages; ++p: + //kdebug_num (p) + //kdebug ("/") + //kdebug_num (pages) + //kdebug ("\n") + Iris::Page page = Iris::Cap (slot, p) + Iris::set_recv_arg (page) + Iris::my_memory.create_page () + Iris::Page (Iris::Cap (src_slot, p)).share (page) + Iris::my_memory.map (page, (unsigned)&mapping[p << PAGE_BITS]) + Iris::free_slot (src_slot) + +static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap parent, unsigned num_slots, unsigned num_caps): + Iris::Thread thread = mem.create_thread (num_slots) + Elf32_Ehdr *header = (Elf32_Ehdr *)mapping + for unsigned j = 0; j < SELFMAG; ++j: + if header->e_ident[j] != ELFMAG[j]: + Iris::panic (header->e_ident[j], "invalid ELF magic") + return Iris::Caps () + if header->e_ident[EI_CLASS] != ELFCLASS32: + kdebug ("invalid ELF class:") + kdebug_num (header->e_ident[EI_CLASS]) + kdebug (" != ") + kdebug_num (ELFCLASS32) + kdebug ("\n") + Iris::panic (0) + return Iris::Caps () + if header->e_ident[EI_DATA] != ELFDATA2LSB: + Iris::panic (header->e_ident[EI_DATA], "invalid ELF data") + if header->e_ident[EI_VERSION] != EV_CURRENT: + Iris::panic (header->e_ident[EI_VERSION], "invalid ELF version") + if header->e_type != ET_EXEC: + Iris::panic (header->e_type, "invalid ELF type") + if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS: + Iris::panic (header->e_machine, "invalid ELF machine") + thread.set_pc (header->e_entry) + thread.set_sp (0x80000000) + for unsigned section = 0; section < header->e_shnum; ++section: + Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize) + if ~shdr->sh_flags & SHF_ALLOC: + continue + bool readonly = !(shdr->sh_flags & SHF_WRITE) + //bool executable = shdr->sh_flags & SHF_EXEC_INSTR + if shdr->sh_type != SHT_NOBITS: + unsigned file_offset = shdr->sh_offset >> PAGE_BITS + if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2): + kdebug ("thread size: ") + kdebug_num (file_offset) + kdebug (",") + kdebug_num (shdr->sh_size) + kdebug ("\n") + Iris::panic (shdr->sh_size, "thread too large") + return Iris::Caps () + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS + unsigned idx = file_offset + section_offset + Iris::Page page = mem.mapping ((void *)p) + if Iris::recv.data[0].l == Iris::NO_ERROR: + // The address already has a mapping; assume that it is correct. + Iris::free_cap (page) + continue + Iris::free_cap (page) + page = mem.create_page () + unsigned f + if readonly: + f = Iris::Page::PAYING | Iris::Page::MAPPED_READONLY + else: + f = Iris::Page::PAYING + page.set_flags (f, f) + Iris::Page (slot, idx).share (page, 0) + //kdebug ("mapping at ") + //kdebug_num (p) + //if readonly: + // kdebug (" (readonly)") + //kdebug ("\n") + if !mem.map (page, p): + Iris::panic (0, "unable to map page") + return Iris::Caps () + Iris::free_cap (page) + else: + if readonly: + Iris::panic (0, "unwritable bss section") + return Iris::Caps () + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + Iris::Page page = mem.mapping ((void *)p) + if Iris::recv.data[0].l == Iris::NO_ERROR: + // No error means there is a mapping. + Iris::free_cap (page) + for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4: + if a >= shdr->sh_addr + shdr->sh_size: + break + if a < shdr->sh_addr: + continue + ((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0 + else: + Iris::free_cap (page) + page = mem.create_page () + if Iris::recv.data[0].l != Iris::NO_ERROR: + Iris::panic (Iris::recv.data[0].l, "out of memory") + if !page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME): + Iris::panic (0, "out of memory") + if !mem.map (page, p): + Iris::panic (0, "unable to map bss page") + Iris::free_cap (page) + for unsigned p = 0; p < pages; ++p: + Iris::my_memory.destroy (Iris::Page (slot, p)) + Iris::my_memory.destroy (pages_caps) + Iris::free_slot (slot) + Iris::free_cap (pages_caps) + Iris::Page stackpage = mem.create_page () + stackpage.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) + if Iris::recv.data[0].l != Iris::NO_ERROR || !mem.map (stackpage, 0x7ffff000): + Iris::panic (Iris::recv.data[0].l, "unable to map initial stack page") + Iris::free_cap (stackpage) + Iris::Caps caps = mem.create_caps (num_caps) + thread.use (caps, 0) + thread.set_info (Iris::Thread::A0, num_slots) + thread.set_info (Iris::Thread::A1, num_caps) + Iris::Receiver receiver = mem.create_receiver () + receiver.set_owner (thread.copy ()) + Iris::Cap call = receiver.create_call_capability () + caps.set (__caps_num, caps.copy ()) + caps.set (__receiver_num, receiver.copy ()) + caps.set (__thread_num, thread.copy ()) + caps.set (__memory_num, mem.copy ()) + caps.set (__call_num, call.copy ()) + caps.set (__parent_num, parent.copy ()) + Iris::free_cap (receiver) + Iris::free_cap (thread) + Iris::free_cap (mem) + Iris::free_cap (call) + return caps + +Iris::Num start (): + kdebug ("elfrun started.\n") + init_alloc () + Iris::Device dev = Iris::my_receiver.create_capability (0) + Iris::my_parent.provide_device (dev.copy ()) + + unsigned user = ~0 + while true: + Iris::wait () + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::print_caps () + switch Iris::recv.protected_data.h: + case 0: + Iris::Device::host (1, user, reply, arg) + break + case 1: + switch Iris::recv.data[0].l: + case Iris::Elfrun::RUN_STRING: + unsigned num_slots = Iris::recv.data[1].l + unsigned num_caps = Iris::recv.data[1].h + parent_memory = Iris::Caps (arg).get (Iris::Elfrun::PARENT_MEMORY) + parent = Iris::Caps (arg).get (Iris::Elfrun::PARENT) + Iris::String data = Iris::Caps (arg).get (Iris::Elfrun::DATA) + map_string (data) + Iris::Caps ret = run (data, parent_memory, parent, num_slots, num_caps) + reply.invoke (0, 0, ret.copy ()) + free_cap (ret) + free_cap (parent_memory) + free_cap (parent) + free_cap (data) + break + case Iris::Elfrun::RUN_CAPS: + unsigned num_slots = Iris::recv.data[1].l + unsigned num_caps = Iris::recv.data[1].h + unsigned p = Iris::recv.data[0].h + parent_memory = Iris::Caps (arg).get (Iris::Elfrun::PARENT_MEMORY) + parent = Iris::Caps (arg).get (Iris::Elfrun::PARENT) + Iris::Caps data = Iris::Caps (arg).get (Iris::Elfrun::DATA) + map_caps (data, p) + Iris::Caps ret = run (data, parent_memory, parent, num_slots, num_caps) + reply.invoke (0, 0, ret.copy ()) + free_cap (ret) + free_cap (parent_memory) + free_cap (parent) + free_cap (data) + break + default: + Iris::panic (0, "invalid operation for elfrun") + reply.invoke (~0) + break + Iris::free_cap (arg) + Iris::free_cap (reply) diff --git a/source/gpio.ccp b/source/gpio.ccp new file mode 120000 index 0000000..9448fe4 --- /dev/null +++ b/source/gpio.ccp @@ -0,0 +1 @@ +nanonote-gpio.ccp \ No newline at end of file diff --git a/source/init.ccp b/source/init.ccp new file mode 100644 index 0000000..dc02c6a --- /dev/null +++ b/source/init.ccp @@ -0,0 +1,412 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// bootstrap/init.ccp: Bootstrapping code. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "devices.hh" +#include "iris.hh" +#include "keys.hh" + +#define NUM_SLOTS 8 +#define NUM_CAPS 32 + +static unsigned _free +extern unsigned _end + +void init_alloc (): + _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK + +char *alloc_space (unsigned pages): + unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK + _free = ret + (pages << PAGE_BITS) + return (char *)ret + +void *operator new[] (unsigned size): + //kdebug ("new ") + void *ret = (void *)_free + size = (size + 3) & ~3 + unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1) + if rest < size: + unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS + for unsigned p = 0; p < pages; ++p: + Iris::Page page = Iris::my_memory.create_page () + page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME, Iris::Page::PAYING | Iris::Page::FRAME) + Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS)) + Iris::free_cap (page) + _free += size + //kdebug_num ((unsigned)ret) + //kdebug ("+") + //kdebug_num (size) + //kdebug ("\n") + return ret + +void *operator new (unsigned size): + return new char[size] + +template // +struct List: + struct Item: + Item *prev, *next + _T value + _T &operator* (): + return value + _T *operator-> (): + return &value + Item *first + Item *begin (): + return first + void erase (Item *i): + if i->prev: + i->prev->next = i->next + else: + first = i->next + if i->next: + i->next->prev = i->prev + delete i + Item *insert (Item *after = NULL): + Item *ret = new Item + if after: + ret->prev = after->prev + ret->next = after + if ret->prev: + ret->prev->next = ret + else: + first = ret + after->prev = ret + else: + ret->prev = NULL + ret->next = first + first = ret + if ret->next: + ret->next->prev = ret + return ret + void init (): + first = NULL + List () : first (NULL): + +struct Program + +struct Device: + char *name + unsigned name_len + unsigned type, index + Iris::Cap cap + Program *server + Program *client + +struct Program: + char *name + unsigned name_len + unsigned size + Iris::Caps pages + Iris::Memory memory + Iris::Thread thread + List devices + +static Iris::Memory top_memory +static Iris::Directory root +static Iris::Elfrun elfrun +static List programs + +static bool name_match (char const *name, unsigned name_len, Iris::String n): + char nm[16] + n.get_chars (0, nm) + for unsigned t = 0; t < 16 && t < name_len; ++t: + if nm[t] != name[t]: + return false + return true + +static Iris::Caps load (char const *name, unsigned name_len, unsigned &size, Iris::Caps target = Iris::alloc_cap ()): + kdebug ("loading ") + for unsigned i = 0; i < name_len; ++i: + kdebug_char (name[i]) + kdebug ("\n") + root.lock_ro () + Iris::Num sz = root.get_size () + if sz.h: + Iris::panic (sz.h, "too many files") + for unsigned i = 0; i < sz.l; ++i: + Iris::String n = root.get_name (i) + if !name_match (name, name_len, n): + Iris::free_cap (n) + continue + Iris::free_cap (n) + Iris::String file = root.get_file_ro (i) + Iris::Num s = file.get_size () + if s.h: + Iris::panic (s.h, "file is too large to load") + size = s.l + unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS + if pages > 0: + Iris::set_recv_arg (target) + Iris::my_memory.create_caps (pages) + unsigned slot = target.use () + for unsigned p = 0; p < pages; ++p: + Iris::set_recv_arg (Iris::Cap (slot, p)) + file.get_page (p << PAGE_BITS) + Iris::free_slot (slot) + Iris::free_cap (file) + root.unlock_ro () + return target + Iris::panic (0, "file not found for init") + return target + +static void delspace (char *&line, unsigned &maxlen): + while maxlen && (*line == ' ' || *line == '\t'): + ++line + --maxlen + if maxlen && *line == '#': + line += maxlen + maxlen = 0 + +static bool match (char *&line, unsigned &maxlen, char const *word): + delspace (line, maxlen) + char const *w = word + char *l = line + unsigned len = 0 + while *word: + if *l++ != *word++: + return false + ++len + line = l + maxlen -= len + delspace (line, maxlen) + //kdebug ("match: ") + //kdebug (w) + //kdebug ("\n") + return true + +static bool isnamechar (char c): + if c >= 'a' && c <= 'z': + return true + if c >= 'A' && c <= 'Z': + return true + if c >= '0' && c <= '9': + return true + if c == '_': + return true + return false + +static bool get_name (char *&line, unsigned &len, char *&name, unsigned &name_len): + delspace (line, len) + if !len: + return false + name_len = 0 + while name_len < len && isnamechar (line[name_len]): + ++name_len + name = new char[name_len] + for unsigned i = 0; i < name_len; ++i: + name[i] = line[i] + line += name_len + len -= name_len + delspace (line, len) + return true + +static bool string_match (char const *s1, unsigned l1, char const *s2, unsigned l2): + if l1 != l2: + return false + for unsigned i = 0; i < l1; ++i: + if s1[i] != s2[i]: + return false + return true + +struct Type: + char const *name + unsigned len + unsigned type + +static unsigned read_num (char *&line, unsigned &len): + delspace (line, len) + unsigned num = 0 + while len && *line >= '0' && *line <= '9': + num *= 10 + num += *line - '0' + ++line + --len + delspace (line, len) + return num + +static Type types[] = { + { "String", 6, Iris::String::ID }, + { "WString", 7, Iris::WString::ID }, + { "Device", 6, Iris::Device::ID }, + { "Parent", 6, Iris::Parent::ID }, + { "Keyboard", 8, Iris::Keyboard::ID }, + { "Buzzer", 6, Iris::Buzzer::ID }, + { "Display", 7, Iris::Display::ID }, + { "Setting", 7, Iris::Setting::ID }, + { "Directory", 9, Iris::Directory::ID }, + { "WDirectory", 10, Iris::WDirectory::ID }, + { "Filesystem", 10, Iris::Filesystem::ID }, + { "Stream", 6, Iris::Stream::ID }, + { NULL, 0, 0 } + } + +static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &index): + char *n + unsigned l + if !get_name (line, len, n, l) || !len: + Iris::panic (0, "no name for type") + for unsigned t = 0; types[t].len != 0; ++t: + if string_match (types[t].name, types[t].len, n, l): + type = types[t].type + if len && *line == ',': + ++line + --len + index = read_num (line, len) + else: + index = 0 + return + Iris::panic (0, "no valid type found") + +static void parse_line (char *&line, unsigned maxlen): + char *start = line + while maxlen && *line != '\n': + ++line + --maxlen + // The line to execute is from start to line. + maxlen = line - start + if *line == '\n': + ++line + delspace (start, maxlen) + if !maxlen: + return + if match (start, maxlen, "load"): + Program *p = &**programs.insert () + if !get_name (start, maxlen, p->name, p->name_len) || !match (start, maxlen, "=") || !maxlen: + Iris::panic (0, "syntax error in init.config (load)") + char q = *start++ + --maxlen + unsigned len = 0 + while maxlen && *start != q: + ++start + --maxlen + ++len + if !maxlen: + Iris::panic (0, "no closing quote in init.config") + p->pages = load (start - len, len, p->size) + ++start + --maxlen + else if match (start, maxlen, "killbootthreads"): + Iris::my_parent.init_done () + else if match (start, maxlen, "receive"): + // receive / [, ] = + char *n + unsigned l + if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen: + Iris::panic (0, "syntax error in init.config (receive)") + List ::Item *p + for p = programs.begin (); p; p = p->next: + if string_match ((*p)->name, (*p)->name_len, n, l): + break + if !p: + Iris::panic (0, "program not found for receive") + List ::Item *dev = (*p)->devices.insert () + find_type (start, maxlen, (*dev)->type, (*dev)->index) + if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len): + Iris::panic (1, "syntax error in init.config (receive)") + else if match (start, maxlen, "driver"): + char *n + unsigned l + if !get_name (start, maxlen, n, l): + Iris::panic (0, "syntax error in init.config (driver)") + List ::Item *p + for p = programs.begin (); p; p = p->next: + if string_match ((*p)->name, (*p)->name_len, n, l): + break + if !p: + Iris::panic (0, "program not found for driver") + Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p) + kdebug ("running ") + for unsigned i = 0; i < (*p)->name_len; ++i: + kdebug_char ((*p)->name[i]) + kdebug ("\n") + Iris::Caps caps = elfrun.run_caps (top_memory, (*p)->pages, cap.copy (), ((*p)->size + PAGE_SIZE - 1) >> PAGE_BITS) + Iris::free_cap (cap) + (*p)->thread = caps.get (__thread_num) + (*p)->memory = caps.get (__memory_num) + (*p)->thread.make_priv () + (*p)->thread.run () + // TODO: pass arguments. + start += maxlen + maxlen = 0 + else if match (start, maxlen, "wait"): + // TODO + start += maxlen + maxlen = 0 + else if match (start, maxlen, "sysreq"): + // TODO + start += maxlen + maxlen = 0 + else if match (start, maxlen, "give"): + // TODO + start += maxlen + maxlen = 0 + else if match (start, maxlen, "run"): + // TODO + start += maxlen + maxlen = 0 + else if match (start, maxlen, "include"): + // TODO + start += maxlen + maxlen = 0 + else: + Iris::panic (0, "invalid line in init.config") + delspace (start, maxlen) + if maxlen: + kdebug ("Junk: ") + for unsigned i = 0; i < maxlen; ++i: + kdebug_char (start[i]) + kdebug_char ('\n') + Iris::panic (0, "junk at end of line in init.config") + +Iris::Num start (): + init_alloc () + programs.init () + root = Iris::my_parent.get_device () + elfrun = Iris::my_parent.get_device () + top_memory = Iris::get_top_memory () + unsigned config_size + Iris::Caps config_pages = load ("init.config", 12, config_size) + unsigned pages = (config_size + PAGE_SIZE - 1) >> PAGE_BITS + char *config = alloc_space (pages) + unsigned pages_slot = config_pages.use () + for unsigned p = 0; p < pages; ++p: + Iris::Page page (pages_slot, p) + Iris::my_memory.map (page, (unsigned)&config[p << PAGE_BITS]) + char *ptr = config + kdebug ("parsing config\n") + while ptr - config < config_size: + parse_line (ptr, config + config_size - ptr) + kdebug ("destroying pages\n") + for unsigned p = 0; p < pages; ++p: + Iris::my_memory.destroy (Iris::Cap (pages_slot, p)) + Iris::my_memory.destroy (config_pages) + Iris::free_cap (config_pages) + Iris::free_slot (pages_slot) + kdebug ("waiting for events.\n") + while true: + Iris::wait () + Program *caller = (Program *)Iris::recv.protected_data.l + if !caller: + // System request. + // TODO. + kdebug ("system request\n") + continue + switch Iris::recv.data[0].l: + default: + // TODO. + kdebug ("child request\n") diff --git a/source/#lcd.ccp b/source/lcd.ccp similarity index 76% rename from source/#lcd.ccp rename to source/lcd.ccp index 9925cab..2340f71 100644 --- a/source/#lcd.ccp +++ b/source/lcd.ccp @@ -225,7 +225,7 @@ static void log_str (char const *str): while *str: log_char (*str++) -static void log_num (Kernel::Num n): +static void log_num (Iris::Num n): char const *encode = "0123456789abcdef" log_char ('[') for unsigned i = 0; i < 8; ++i: @@ -237,10 +237,10 @@ static void log_num (Kernel::Num n): static void log_msg (): log_str ("prot:") - log_num (Kernel::recv.protected_data) + log_num (Iris::recv.protected_data) log_str ("data:") for unsigned i = 0; i < 2; ++i: - log_num (Kernel::recv.data[i]) + log_num (Iris::recv.data[i]) log_char ('\n') enum captype: @@ -261,25 +261,25 @@ static unsigned pages static Descriptor descriptor __attribute__ ((aligned (16))) static bool is_on -static unsigned create (Kernel::Memory mem, Kernel::Caps caps): +static unsigned create (Iris::Memory mem, Iris::Caps caps): unsigned physical = mem.alloc_range (pages) unsigned address = 0x15000 if physical & ~PAGE_MASK: - Kernel::panic (0, "can't allocate framebuffer") + Iris::panic (0, "can't allocate framebuffer") assert (physical & PAGE_MASK && ~physical) for unsigned i = 0; i < pages; ++i: - Kernel::Page p = mem.create_page () + Iris::Page p = mem.create_page () p.alloc_physical (physical + (i << PAGE_BITS), false, true) if address != ~0: mem.map (p, address + (i << PAGE_BITS)) - Kernel::free_cap (p) + Iris::free_cap (p) return physical -static void destroy (unsigned physical, Kernel::Caps caps): +static void destroy (unsigned physical, Iris::Caps caps): unsigned address = 0x15000 - Kernel::Memory mem = caps.get (1) + Iris::Memory mem = caps.get (1) if physical == ~0: - Kernel::panic (0, "unable to destroy framebuffer with wrong cap0") + Iris::panic (0, "unable to destroy framebuffer with wrong cap0") if descriptor.frame == physical && is_on: lcd_clr_ena () #ifdef NANONOTE @@ -287,13 +287,13 @@ static void destroy (unsigned physical, Kernel::Caps caps): #endif if address != ~0: for unsigned i = 0; i < pages; ++i: - Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS))) + Iris::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS))) mem.destroy (p) - Kernel::free_cap (p) + Iris::free_cap (p) -static void use (unsigned physical, Kernel::Caps caps): +static void use (unsigned physical, Iris::Caps caps): if physical == ~0: - Kernel::panic (0, "unable to use framebuffer with wrong cap0") + Iris::panic (0, "unable to use framebuffer with wrong cap0") bool was_unused = descriptor.frame == 0 descriptor.frame = physical unsigned dptr = (unsigned)&descriptor @@ -304,9 +304,9 @@ static void use (unsigned physical, Kernel::Caps caps): write_reg (BACKLIGHT1, 0x5f) #endif -static void unuse (unsigned physical, Kernel::Caps caps): +static void unuse (unsigned physical, Iris::Caps caps): if physical == ~0: - Kernel::panic (0, "unable to unuse framebuffer with wrong cap0") + Iris::panic (0, "unable to unuse framebuffer with wrong cap0") if descriptor.frame == physical: lcd_clr_ena () #ifdef NANONOTE @@ -314,8 +314,8 @@ static void unuse (unsigned physical, Kernel::Caps caps): #endif descriptor.frame = 0 -Kernel::Num start (): - Kernel::schedule () +Iris::Num start (): + Iris::schedule () map_lcd () map_cpm () #ifdef NANONOTE @@ -324,13 +324,13 @@ Kernel::Num start (): pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS #if 0 - unsigned physical = Kernel::my_memory.alloc_range (pages) + unsigned physical = Iris::my_memory.alloc_range (pages) assert (physical & PAGE_MASK && ~physical) for unsigned i = 0; i < pages; ++i: - Kernel::Page p = Kernel::my_memory.create_page () + Iris::Page p = Iris::my_memory.create_page () p.alloc_physical (physical + (i << PAGE_BITS), false, true) - Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS)) - Kernel::free_cap (p) + Iris::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS)) + Iris::free_cap (p) for unsigned y = 0; y < v; ++y: for unsigned x = 0; x < h; ++x: unsigned r = spot (x, y, 100, 160) @@ -346,10 +346,10 @@ Kernel::Num start (): #else unsigned physical = 0 #endif - Kernel::Page p = Kernel::my_memory.mapping (&descriptor) + Iris::Page p = Iris::my_memory.mapping (&descriptor) unsigned paddr = p.physical_address () physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK) - Kernel::free_cap (p) + Iris::free_cap (p) descriptor.next = physical_descriptor descriptor.frame = physical descriptor.id = 0xdeadbeef @@ -359,67 +359,67 @@ Kernel::Num start (): reset () #if defined (TRENDTAC) - Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG) + Iris::Cap logcap = Iris::my_receiver.create_capability (LOG) __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") #endif // Register the backlight device. - Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT) - Kernel::my_parent.provide_device (backlight.copy ()) - Kernel::free_cap (backlight) + Iris::Cap backlight = Iris::my_receiver.create_capability (BACKLIGHT) + Iris::my_parent.provide_device (backlight.copy ()) + Iris::free_cap (backlight) // Register the display device. - Kernel::Cap display = Kernel::my_receiver.create_capability (LCD) - Kernel::my_parent.provide_device (display.copy ()) - Kernel::free_cap (display) - Kernel::my_parent.init_done () + Iris::Cap display = Iris::my_receiver.create_capability (LCD) + Iris::my_parent.provide_device (display.copy ()) + Iris::free_cap (display) + Iris::my_parent.init_done () - Kernel::Cap eof_cb + Iris::Cap eof_cb bool have_eof = false is_on = true unsigned lcd_user = 0 unsigned current_backlight = 0 while true: - Kernel::wait () + Iris::wait () //log_msg () - switch Kernel::recv.protected_data.h: + switch Iris::recv.protected_data.h: case 0: - switch Kernel::recv.protected_data.l: + switch Iris::recv.protected_data.l: case IRQ_LCD: have_eof = false eof_cb.invoke () - Kernel::free_cap (eof_cb) + Iris::free_cap (eof_cb) break #if defined (TRENDTAC) case LOG: - log_char (Kernel::recv.data[0].l) + log_char (Iris::recv.data[0].l) break #endif case BACKLIGHT: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - Device::host (BACKLIGHT, current_backlight, reply, arg) + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::Device::host (BACKLIGHT, current_backlight, reply, arg) break case LCD: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse) + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse) break default: - Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd") + Iris::panic (Iris::recv.protected_data.l, "invalid operation for master lcd") break break case BACKLIGHT: - if current_backlight != Kernel::recv.protected_data.l: + if current_backlight != Iris::recv.protected_data.l: log_char ('&') log_num (current_backlight) - log_num (Kernel::recv.protected_data) + log_num (Iris::recv.protected_data) log_char ('\n') break - switch Kernel::recv.data[0].l: - case Setting::SET: + switch Iris::recv.data[0].l: + case Iris::Setting::SET: // TODO - unsigned state = Kernel::recv.data[1].l + unsigned state = Iris::recv.data[1].l if !state: #if defined (NANONOTE) if is_on: @@ -434,40 +434,40 @@ Kernel::Num start (): is_on = true #else #endif - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () break - case Setting::GET_RANGE: - Kernel::recv.reply.invoke (~0) + case Iris::Setting::GET_RANGE: + Iris::recv.reply.invoke (~0) break default: - Kernel::panic (0, "invalid operation for backlight") + Iris::panic (0, "invalid operation for backlight") break break case LCD: - if descriptor.frame != Kernel::recv.protected_data.l: - //Kernel::panic (0, "invalid user requesting lcd") - Kernel::recv.reply.invoke (~0) + if descriptor.frame != Iris::recv.protected_data.l: + //Iris::panic (0, "invalid user requesting lcd") + Iris::recv.reply.invoke (~0) break - switch Kernel::recv.data[0].l: - case Display::SET_EOF_CB: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () + switch Iris::recv.data[0].l: + case Iris::Display::SET_EOF_CB: + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () if have_eof: - Kernel::free_cap (eof_cb) - Kernel::panic (0, "replacing eof_cb") + Iris::free_cap (eof_cb) + Iris::panic (0, "replacing eof_cb") else: lcd_clr_eof () - Kernel::register_interrupt (IRQ_LCD) + Iris::register_interrupt (IRQ_LCD) have_eof = true eof_cb = arg reply.invoke () - Kernel::free_cap (reply) + Iris::free_cap (reply) break - case Display::GET_INFO: - Kernel::panic (0, "get_info isn't defined yet.") + case Iris::Display::GET_INFO: + Iris::panic (0, "get_info isn't defined yet.") default: - Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd") + Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd") break default: - Kernel::panic (0, "invalid master operation type for lcd") + Iris::panic (0, "invalid master operation type for lcd") break diff --git a/source/metronome.ccp b/source/metronome.ccp index f09cb87..b665c61 100644 --- a/source/metronome.ccp +++ b/source/metronome.ccp @@ -19,11 +19,11 @@ #include "devices.hh" #include "keys.hh" -Kernel::Num start (): - Kernel::my_parent.init_done () - Buzzer buzzer = Kernel::my_parent.get_device () - Keyboard kbd = Kernel::my_parent.get_device () - Kernel::Cap key = Kernel::my_receiver.create_capability (0) +Iris::Num start (): + Iris::my_parent.init_done () + Iris::Buzzer buzzer = Iris::my_parent.get_device () + Iris::Keyboard kbd = Iris::my_parent.get_device () + Iris::Cap key = Iris::my_receiver.create_capability (0) kbd.set_cb (key) // Frequency of the pulse train in millihertz. unsigned mHz = 1000 @@ -31,17 +31,17 @@ Kernel::Num start (): unsigned freq = 1000 bool running (false) while true: - Kernel::wait () - switch Kernel::recv.protected_data.l: + Iris::wait () + switch Iris::recv.protected_data.l: case ~0: if running: buzzer.beep (freq, 10, ~0) - Kernel::my_receiver.set_alarm (HZ * 1000 / mHz) + Iris::my_receiver.set_alarm (HZ * 1000 / mHz) break case 0: - if Kernel::recv.data[0].l & Keyboard::RELEASE: + if Iris::recv.data[0].l & Iris::Keyboard::RELEASE: break - switch Kernel::recv.data[0].l: + switch Iris::recv.data[0].l: case Key::VOLUME_UP: freq = freq * 11 / 10 break @@ -63,7 +63,7 @@ Kernel::Num start (): case Key::P: running = !running if running: - Kernel::my_receiver.set_alarm (0) + Iris::my_receiver.set_alarm (0) break break default: diff --git a/source/#nanonote-gpio.ccp b/source/nanonote-gpio.ccp similarity index 78% rename from source/#nanonote-gpio.ccp rename to source/nanonote-gpio.ccp index 1d4de5f..c323520 100644 --- a/source/#nanonote-gpio.ccp +++ b/source/nanonote-gpio.ccp @@ -37,25 +37,25 @@ class DevKbd: static unsigned const NUM_KEYS = 58 static unsigned const keys[NUM_KEYS] unsigned state[NUM_COLS] - Kernel::Cap event + Iris::Cap event bool is_active bool is_scanning public: unsigned size (): return NUM_KEYS - void send_keys (unsigned first, Kernel::Cap target): + void send_keys (unsigned first, Iris::Cap target): unsigned d[4] unsigned i for i = 0; first + i < NUM_KEYS && i < 4; ++i: d[i] = keys[first + i] for ; i < 4; ++i: d[i] = ~0 - target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3])) + target.invoke (Iris::Num (d[0], d[1]), Iris::Num (d[2], d[3])) bool scanning (): return is_scanning void inactive (): if is_active: - Kernel::free_cap (event) + Iris::free_cap (event) is_active = false void check (unsigned col, unsigned rowdata): for unsigned r = 0; r < NUM_ROWS; ++r: @@ -63,7 +63,7 @@ class DevKbd: continue unsigned code = encode[r][col] if rowdata & (1 << ROWS[r]): - code |= Keyboard::RELEASE + code |= Iris::Keyboard::RELEASE if is_active: event.invoke (code) state[col] = rowdata @@ -101,7 +101,7 @@ class DevKbd: gpio_as_interrupt (ROWS_PORT, high, true, true) gpio_as_interrupt (ROWS_PORT, low, false, true) gpio_unmask_irq (ROWS_PORT, ALL_ROWS) - void active (Kernel::Cap cb): + void active (Iris::Cap cb): inactive () event = cb is_active = true @@ -167,7 +167,7 @@ unsigned const DevKbd::keys[NUM_KEYS] = { class PowerButton: bool state, started - Kernel::Cap cb + Iris::Cap cb public: void scan (): if !started: @@ -176,16 +176,16 @@ class PowerButton: bool s = gpio_get_port (3) & (1 << 29) if s != state: state = s - cb.invoke (state ? Keyboard::RELEASE : 0) + cb.invoke (state ? Iris::Keyboard::RELEASE : 0) gpio_as_interrupt (3, 1 << 29, !state, true) gpio_unmask_irq (3, 1 << 29) PowerButton (): gpio_as_gpio (3, 29) state = true started = false - void set_cb (Kernel::Cap c): + void set_cb (Iris::Cap c): if started: - Kernel::free_cap (cb) + Iris::free_cap (cb) else: started = true cb = c @@ -196,100 +196,100 @@ enum codes: KBD_DEV = 32 PWR -Kernel::Num start (): +Iris::Num start (): map_gpio () DevKbd kbd PowerButton pwr - Device dev = Kernel::my_receiver.create_capability (KBD_DEV) - Keyboard pw = Kernel::my_receiver.create_capability (PWR) - Kernel::my_parent.provide_device (dev.copy (), 0) - Kernel::my_parent.provide_device (pw.copy (), 1) - Kernel::free_cap (dev) - Kernel::free_cap (pw) - Kernel::my_parent.init_done () + Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV) + Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR) + Iris::my_parent.provide_device (dev.copy (), 0) + Iris::my_parent.provide_device (pw.copy (), 1) + Iris::free_cap (dev) + Iris::free_cap (pw) + Iris::my_parent.init_done () if kbd.scanning (): - Kernel::my_receiver.set_alarm (SCAN_INTERVAL) + Iris::my_receiver.set_alarm (SCAN_INTERVAL) unsigned user (0), power_user (0) unsigned next_user (0) - Kernel::register_interrupt (IRQ_GPIO3) + Iris::register_interrupt (IRQ_GPIO3) while true: - Kernel::wait () - switch Kernel::recv.protected_data.h: + Iris::wait () + switch Iris::recv.protected_data.h: case ~0: // Alarm. kbd.scan () if kbd.scanning (): - Kernel::my_receiver.set_alarm (SCAN_INTERVAL) + Iris::my_receiver.set_alarm (SCAN_INTERVAL) break case 0: - switch Kernel::recv.protected_data.l: + switch Iris::recv.protected_data.l: case IRQ_GPIO3: // Interrupt. pwr.scan () kbd.scan () if kbd.scanning (): - Kernel::my_receiver.set_alarm (SCAN_INTERVAL) - Kernel::register_interrupt (IRQ_GPIO3) + Iris::my_receiver.set_alarm (SCAN_INTERVAL) + Iris::register_interrupt (IRQ_GPIO3) break case PWR: // Power button request. - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - Device::host (PWR, power_user, reply, arg) + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::Device::host (PWR, power_user, reply, arg) break case KBD_DEV: // Keyboard device control request. - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - Device::host (KBD_DEV, user, reply, arg) + Iris::Cap reply = Iris::get_reply () + Iris::Cap arg = Iris::get_arg () + Iris::Device::host (KBD_DEV, user, reply, arg) break default: break break case KBD_DEV: // Keyboard device user request. - if Kernel::recv.protected_data.l != user: + if Iris::recv.protected_data.l != user: kdebug ("invalid user requesting keyboard\n") - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () break - switch Kernel::recv.data[0].l: - case Keyboard::SET_CB: - Kernel::Cap reply = Kernel::get_reply () - kbd.active (Kernel::get_arg ()) + switch Iris::recv.data[0].l: + case Iris::Keyboard::SET_CB: + Iris::Cap reply = Iris::get_reply () + kbd.active (Iris::get_arg ()) reply.invoke () - Kernel::free_cap (reply) + Iris::free_cap (reply) break - case Keyboard::GET_NUM_KEYS: - Kernel::recv.reply.invoke (kbd.size ()) + case Iris::Keyboard::GET_NUM_KEYS: + Iris::recv.reply.invoke (kbd.size ()) break - case Keyboard::GET_KEYS: - kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply) + case Iris::Keyboard::GET_KEYS: + kbd.send_keys (Iris::recv.data[0].l, Iris::recv.reply) break default: kdebug ("keyboard other\n") break break case PWR: - if Kernel::recv.protected_data.l != power_user: + if Iris::recv.protected_data.l != power_user: kdebug ("invalid user requesting power\n") - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () break - switch Kernel::recv.data[0].l: - case Keyboard::SET_CB: - Kernel::Cap reply = Kernel::get_reply () - pwr.set_cb (Kernel::get_arg ()) + switch Iris::recv.data[0].l: + case Iris::Keyboard::SET_CB: + Iris::Cap reply = Iris::get_reply () + pwr.set_cb (Iris::get_arg ()) reply.invoke () - Kernel::free_cap (reply) + Iris::free_cap (reply) break default: kdebug ("Power button invalid request\n") - kdebug_num (Kernel::recv.data[0].l) + kdebug_num (Iris::recv.data[0].l) kdebug ("\n") break break default: kdebug ("keyboard unknown num: ") - kdebug_num (Kernel::recv.protected_data.h) + kdebug_num (Iris::recv.protected_data.h) kdebug ("\n") diff --git a/source/#gpio.ccp b/source/trendtac-gpio.ccp similarity index 90% rename from source/#gpio.ccp rename to source/trendtac-gpio.ccp index 66f6da4..7ff2d01 100644 --- a/source/#gpio.ccp +++ b/source/trendtac-gpio.ccp @@ -53,14 +53,14 @@ enum event_type: TOUCHPAD_EVENT NUM_EVENTS -static Kernel::Cap events[NUM_EVENTS] +static Iris::Cap events[NUM_EVENTS] static void event (event_type type, unsigned data): events[type].invoke (data) static void set_cb (event_type type): - Kernel::free_cap (events[type]) - events[type] = Kernel::get_arg () + Iris::free_cap (events[type]) + events[type] = Iris::get_arg () class DevKeyboard: static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] @@ -252,72 +252,72 @@ enum codes: LOCKLEDS PWM -Kernel::Num start (): +Iris::Num start (): map_gpio () map_pwm0 () for unsigned i = 0; i < NUM_EVENTS; ++i: - events[i] = Kernel::alloc_cap () + events[i] = Iris::alloc_cap () DevKeyboard kbd Touchpad tp Lockleds leds Pwm pwm - Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD) - Kernel::my_parent.provide_device (c.copy (), 0) - Kernel::free_cap (c) - c = Kernel::my_receiver.create_capability (TOUCHPAD) - Kernel::my_parent.provide_device (c.copy (), 1) - Kernel::free_cap (c) - Kernel::my_parent.init_done () + Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD) + Iris::my_parent.provide_device (c.copy (), 0) + Iris::free_cap (c) + c = Iris::my_receiver.create_capability (TOUCHPAD) + Iris::my_parent.provide_device (c.copy (), 1) + Iris::free_cap (c) + Iris::my_parent.init_done () if kbd.is_scanning (): - Kernel::my_receiver.set_alarm (ALARM_INTERVAL) + Iris::my_receiver.set_alarm (ALARM_INTERVAL) // Enable interrupts. All are in port 0. GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK - Kernel::register_interrupt (IRQ_GPIO0) + Iris::register_interrupt (IRQ_GPIO0) while true: - Kernel::schedule () - Kernel::wait () - switch Kernel::recv.protected_data.l: + Iris::schedule () + Iris::wait () + switch Iris::recv.protected_data.l: case ~0: // Alarm. kbd.scan () if kbd.is_scanning (): - Kernel::my_receiver.set_alarm (ALARM_INTERVAL) + Iris::my_receiver.set_alarm (ALARM_INTERVAL) break case IRQ_GPIO0: // Always scan keyboard and touchpad on any interrupt. kbd.scan () tp.check_events () // Reregister the interrupt. - Kernel::register_interrupt (IRQ_GPIO0) + Iris::register_interrupt (IRQ_GPIO0) break case KEYBOARD: set_cb (KEYBOARD_EVENT) - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () kbd.send_initial () event (KEYBOARD_EVENT, ~0) break case TOUCHPAD: set_cb (TOUCHPAD_EVENT) - Kernel::recv.reply.invoke () + Iris::recv.reply.invoke () tp.send_initial () event (TOUCHPAD_EVENT, ~0) break case LOCKLEDS: - leds.set (Kernel::recv.data[0].l) - Kernel::recv.reply.invoke () + leds.set (Iris::recv.data[0].l) + Iris::recv.reply.invoke () break case PWM: - pwm.set_backlight (Kernel::recv.data[0].l) - Kernel::recv.reply.invoke () + pwm.set_backlight (Iris::recv.data[0].l) + Iris::recv.reply.invoke () break default: kdebug ("invalid gpio operation ") - kdebug_num (Kernel::recv.protected_data.l) + kdebug_num (Iris::recv.protected_data.l) kdebug ("\n") break