mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 21:06:27 +02:00
make things work with unfinished new startup procedure
This commit is contained in:
parent
7c43204a7e
commit
12bfb320f7
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ mips/nanonote/server/depcomp
|
|||||||
mips/nanonote/server/install-sh
|
mips/nanonote/server/install-sh
|
||||||
mips/nanonote/server/missing
|
mips/nanonote/server/missing
|
||||||
mips/nanonote/server/usb-server
|
mips/nanonote/server/usb-server
|
||||||
|
fs/
|
||||||
|
3
Makefile
3
Makefile
@ -51,6 +51,9 @@ fs/%.elf: source/crt0.o source/%.o
|
|||||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||||
|
|
||||||
|
fs/%: %
|
||||||
|
ln -s ../$< $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
||||||
|
|
||||||
|
58
alloc.ccp
58
alloc.ccp
@ -171,6 +171,9 @@ void kMemory::free_obj (kObject *obj, kPointer *first):
|
|||||||
((kFree *)self->prev)->next = self->next
|
((kFree *)self->prev)->next = self->next
|
||||||
else:
|
else:
|
||||||
frees = (kFree *)self->next
|
frees = (kFree *)self->next
|
||||||
|
//kdebug ("freeing page: ")
|
||||||
|
//kdebug_num ((unsigned)self - SIZE)
|
||||||
|
//kdebug ("\n")
|
||||||
pfree ((unsigned)self - SIZE)
|
pfree ((unsigned)self - SIZE)
|
||||||
|
|
||||||
kPage *kMemory::alloc_page ():
|
kPage *kMemory::alloc_page ():
|
||||||
@ -292,7 +295,7 @@ kMemory *kMemory::alloc_memory ():
|
|||||||
kMemory_arch_init (ret)
|
kMemory_arch_init (ret)
|
||||||
return 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:
|
if index >= size:
|
||||||
kdebug ("size: ")
|
kdebug ("size: ")
|
||||||
kdebug_num (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")
|
dpanic (index, "index too large for kCaps")
|
||||||
return
|
return
|
||||||
kCapability *c = &caps[index]
|
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->target = target
|
||||||
c->protected_data = pdata
|
c->protected_data = pdata
|
||||||
c->parent = parent
|
c->parent = parent
|
||||||
@ -321,8 +319,6 @@ void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef p
|
|||||||
c->sibling_next.reset ()
|
c->sibling_next.reset ()
|
||||||
if c->sibling_next.valid ():
|
if c->sibling_next.valid ():
|
||||||
c->sibling_next->sibling_prev = kCapRef (this, index)
|
c->sibling_next->sibling_prev = kCapRef (this, index)
|
||||||
if (unsigned)target == 0x81fdc350:
|
|
||||||
kdebug (" done\n")
|
|
||||||
|
|
||||||
void kCaps::clone (unsigned index, kCapRef source, bool copy):
|
void kCaps::clone (unsigned index, kCapRef source, bool copy):
|
||||||
cap (index)->invalidate ()
|
cap (index)->invalidate ()
|
||||||
@ -341,10 +337,9 @@ void kCaps::clone (unsigned index, kCapRef source, bool copy):
|
|||||||
void kMemory::free_page (kPage *page):
|
void kMemory::free_page (kPage *page):
|
||||||
if page->mapping != ~0:
|
if page->mapping != ~0:
|
||||||
page->address_space->unmap (page)
|
page->address_space->unmap (page)
|
||||||
if page->flags & Kernel::Page::PAYING:
|
page->forget ()
|
||||||
|
if page->flags & Iris::Page::PAYING:
|
||||||
unuse ()
|
unuse ()
|
||||||
if page->frame:
|
|
||||||
pfree (page->frame)
|
|
||||||
free_obj (page, (kPointer *)&pages)
|
free_obj (page, (kPointer *)&pages)
|
||||||
|
|
||||||
void kThread::unset_slot (unsigned s):
|
void kThread::unset_slot (unsigned s):
|
||||||
@ -367,6 +362,8 @@ void kMemory::free_thread (kThread *thread):
|
|||||||
for unsigned i = 0; i < thread->slots; ++i:
|
for unsigned i = 0; i < thread->slots; ++i:
|
||||||
thread->unset_slot (i)
|
thread->unset_slot (i)
|
||||||
free_obj (thread, (void **)&threads)
|
free_obj (thread, (void **)&threads)
|
||||||
|
if old_current == thread:
|
||||||
|
old_current = NULL
|
||||||
|
|
||||||
void kMemory::free_message (kReceiver *owner, kMessage *message):
|
void kMemory::free_message (kReceiver *owner, kMessage *message):
|
||||||
for unsigned i = 0; i < 2; ++i:
|
for unsigned i = 0; i < 2; ++i:
|
||||||
@ -382,11 +379,15 @@ void kMemory::free_receiver (kReceiver *receiver):
|
|||||||
while receiver->messages:
|
while receiver->messages:
|
||||||
free_message (receiver, receiver->messages)
|
free_message (receiver, receiver->messages)
|
||||||
free_obj (receiver, (void **)&receivers)
|
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 ():
|
void kReceiver::orphan ():
|
||||||
if prev_owned:
|
if prev_owned:
|
||||||
prev_owned->next_owned = next_owned
|
prev_owned->next_owned = next_owned
|
||||||
else:
|
else if owner:
|
||||||
owner->receivers = next_owned
|
owner->receivers = next_owned
|
||||||
if next_owned:
|
if next_owned:
|
||||||
next_owned->prev_owned = prev_owned
|
next_owned->prev_owned = prev_owned
|
||||||
@ -404,10 +405,14 @@ void kReceiver::own (kThread *o):
|
|||||||
void kCapability::invalidate ():
|
void kCapability::invalidate ():
|
||||||
if !target:
|
if !target:
|
||||||
return
|
return
|
||||||
|
//kdebug_num ((unsigned)this)
|
||||||
|
//kdebug ("\n")
|
||||||
//kdebug_num ((unsigned)target)
|
//kdebug_num ((unsigned)target)
|
||||||
//kdebug (":")
|
//kdebug (":")
|
||||||
//kdebug_num ((unsigned)protected_data.l)
|
//kdebug_num ((unsigned)protected_data.l)
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
|
if (unsigned)this == dbg_code.h:
|
||||||
|
dpanic (0, "invalidating watched capability")
|
||||||
if sibling_prev.valid ():
|
if sibling_prev.valid ():
|
||||||
sibling_prev->sibling_next = sibling_next
|
sibling_prev->sibling_next = sibling_next
|
||||||
else if parent.valid ():
|
else if parent.valid ():
|
||||||
@ -429,6 +434,8 @@ void kCapability::invalidate ():
|
|||||||
if !next:
|
if !next:
|
||||||
next = c->parent.deref ()
|
next = c->parent.deref ()
|
||||||
c->target = NULL
|
c->target = NULL
|
||||||
|
if c->parent.valid ():
|
||||||
|
c->parent->children = c->sibling_next
|
||||||
c->parent.reset ()
|
c->parent.reset ()
|
||||||
c->children.reset ()
|
c->children.reset ()
|
||||||
c->sibling_prev.reset ()
|
c->sibling_prev.reset ()
|
||||||
@ -492,19 +499,24 @@ void kMemory::free_list (kList *l):
|
|||||||
|
|
||||||
void kMemory::free_memory (kMemory *mem):
|
void kMemory::free_memory (kMemory *mem):
|
||||||
while mem->pages:
|
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:
|
while mem->capses:
|
||||||
free_caps (mem->capses)
|
mem->free_caps (mem->capses)
|
||||||
while mem->threads:
|
while mem->threads:
|
||||||
free_thread (mem->threads)
|
mem->free_thread (mem->threads)
|
||||||
while mem->memories:
|
while mem->memories:
|
||||||
free_memory (mem->memories)
|
mem->free_memory (mem->memories)
|
||||||
while mem->receivers:
|
while mem->receivers:
|
||||||
free_receiver (mem->receivers)
|
mem->free_receiver (mem->receivers)
|
||||||
while mem->lists:
|
while mem->lists:
|
||||||
free_list (mem->lists)
|
mem->free_list (mem->lists)
|
||||||
while mem->listitems:
|
while mem->listitems:
|
||||||
free_listitem (mem->listitems)
|
mem->free_listitem (mem->listitems)
|
||||||
if mem->frees:
|
if mem->frees:
|
||||||
panic (0, "kernel memory leak: memory still in use")
|
panic (0, "kernel memory leak: memory still in use")
|
||||||
free_obj (mem, (void **)&memories)
|
free_obj (mem, (void **)&memories)
|
||||||
@ -519,10 +531,10 @@ void kPage::forget ():
|
|||||||
share_next = NULL
|
share_next = NULL
|
||||||
else:
|
else:
|
||||||
// If the page has a frame and should be freed, free it.
|
// 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)
|
raw_pfree (frame)
|
||||||
frame = 0
|
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)
|
kPage_arch_update_mapping (this)
|
||||||
|
|
||||||
static void check_receiver (kReceiver *r, kCapRef cap, unsigned line):
|
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")
|
kdebug ("!= receiver\n")
|
||||||
dpanic (line, "consistency bug in kernel capabilities")
|
dpanic (line, "consistency bug in kernel capabilities")
|
||||||
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
|
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)
|
check_receiver (r, c, line)
|
||||||
|
|
||||||
void kReceiver::check (unsigned line):
|
void kReceiver::check (unsigned line):
|
||||||
@ -556,7 +570,7 @@ void kMemory::check (unsigned line):
|
|||||||
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
|
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
|
||||||
r->check (line)
|
r->check (line)
|
||||||
for kThread *t = threads; t; t = (kThread *)t->next:
|
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_num ((unsigned)t)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
panic (line, "pc is 0")
|
panic (line, "pc is 0")
|
||||||
|
344
boot-programs/bootinit.ccp
Normal file
344
boot-programs/bootinit.ccp
Normal file
@ -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 <wijnen@debian.org>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "devices.hh"
|
||||||
|
#include "iris.hh"
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
#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")
|
@ -29,7 +29,8 @@ static unsigned __slots, __caps
|
|||||||
static list *__slot_admin, *__cap_admin
|
static list *__slot_admin, *__cap_admin
|
||||||
static list *__first_free_slot, *__first_free_cap
|
static list *__first_free_slot, *__first_free_cap
|
||||||
|
|
||||||
namespace Kernel:
|
namespace Iris:
|
||||||
|
Caps my_caps
|
||||||
Receiver my_receiver
|
Receiver my_receiver
|
||||||
Thread my_thread
|
Thread my_thread
|
||||||
Memory my_memory
|
Memory my_memory
|
||||||
@ -77,7 +78,7 @@ namespace Kernel:
|
|||||||
if !__first_free_slot:
|
if !__first_free_slot:
|
||||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||||
kdebug ("out of slots!\n")
|
kdebug ("out of slots!\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return ~0
|
return ~0
|
||||||
list *ret = __first_free_slot
|
list *ret = __first_free_slot
|
||||||
__first_free_slot = ret->next
|
__first_free_slot = ret->next
|
||||||
@ -90,7 +91,7 @@ namespace Kernel:
|
|||||||
if !__first_free_cap:
|
if !__first_free_cap:
|
||||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||||
kdebug ("out of capabilities!\n")
|
kdebug ("out of capabilities!\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return Cap (0, CAP_NONE)
|
return Cap (0, CAP_NONE)
|
||||||
list *ret = __first_free_cap
|
list *ret = __first_free_cap
|
||||||
__first_free_cap = ret->next
|
__first_free_cap = ret->next
|
||||||
@ -106,20 +107,21 @@ extern "C":
|
|||||||
__cap_admin = cap_admin
|
__cap_admin = cap_admin
|
||||||
__first_free_slot = NULL
|
__first_free_slot = NULL
|
||||||
for unsigned i = 1; i < __slots; ++i:
|
for unsigned i = 1; i < __slots; ++i:
|
||||||
Kernel::free_slot (i)
|
Iris::free_slot (i)
|
||||||
__first_free_cap = NULL
|
__first_free_cap = NULL
|
||||||
for unsigned i = 7; i < __caps; ++i:
|
for unsigned i = 6; i < __caps; ++i:
|
||||||
Kernel::free_cap (Kernel::Cap (0, i))
|
Iris::free_cap (Iris::Cap (0, i))
|
||||||
Kernel::my_receiver = Kernel::Cap (0, __receiver_num)
|
Iris::my_caps = Iris::Cap (0, __caps_num)
|
||||||
Kernel::my_thread = Kernel::Cap (0, __thread_num)
|
Iris::my_receiver = Iris::Cap (0, __receiver_num)
|
||||||
Kernel::my_memory = Kernel::Cap (0, __memory_num)
|
Iris::my_thread = Iris::Cap (0, __thread_num)
|
||||||
Kernel::my_call = Kernel::Cap (0, __call_num)
|
Iris::my_memory = Iris::Cap (0, __memory_num)
|
||||||
Kernel::my_parent = Kernel::Cap (0, __parent_num)
|
Iris::my_call = Iris::Cap (0, __call_num)
|
||||||
Kernel::recv.reply = Kernel::alloc_cap ()
|
Iris::my_parent = Iris::Cap (0, __parent_num)
|
||||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
Iris::recv.reply = Iris::alloc_cap ()
|
||||||
Kernel::Num ret = start ()
|
Iris::recv.arg = Iris::alloc_cap ()
|
||||||
Kernel::my_parent.exit (ret)
|
Iris::Num ret = start ()
|
||||||
Kernel::my_memory.destroy (Kernel::my_thread)
|
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.
|
// The program no longer exists. If it somehow does, generate an address fault.
|
||||||
while true:
|
while true:
|
||||||
*(volatile unsigned *)~0
|
*(volatile unsigned *)~0
|
||||||
|
@ -1,592 +0,0 @@
|
|||||||
#pypp 0
|
|
||||||
// Iris: micro-kernel for a capability-based operating system.
|
|
||||||
// bootstrap/init.ccp: Bootstrapping code.
|
|
||||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
|
||||||
//
|
|
||||||
// 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#include "devices.hh"
|
|
||||||
#include "iris.hh"
|
|
||||||
#include "keys.hh"
|
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
#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")
|
|
@ -162,16 +162,16 @@ class Udc:
|
|||||||
char log_buffer[1000]
|
char log_buffer[1000]
|
||||||
unsigned log_buffer_size
|
unsigned log_buffer_size
|
||||||
unsigned log_buffer_start
|
unsigned log_buffer_start
|
||||||
Kernel::Cap caller, caller_arg
|
Iris::Cap caller, caller_arg
|
||||||
bool have_caller
|
bool have_caller
|
||||||
unsigned *page
|
unsigned *page
|
||||||
unsigned *p
|
unsigned *p
|
||||||
Kernel::Page buffer_page
|
Iris::Page buffer_page
|
||||||
public:
|
public:
|
||||||
void init ()
|
void init ()
|
||||||
void log (unsigned c)
|
void log (unsigned c)
|
||||||
void interrupt (unsigned cmd)
|
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::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 = {
|
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.
|
// Normally a normal new page should be allocated here, but new isn't implemented at this point.
|
||||||
page = (unsigned *)LCD_FRAMEBUFFER_BASE
|
page = (unsigned *)LCD_FRAMEBUFFER_BASE
|
||||||
p = page
|
p = page
|
||||||
buffer_page = Kernel::my_memory.create_page ()
|
buffer_page = Iris::my_memory.create_page ()
|
||||||
buffer_page.set_flags (Kernel::Page::FRAME | Kernel::Page::PAYING, Kernel::Page::FRAME | Kernel::Page::PAYING)
|
buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING, Iris::Page::FRAME | Iris::Page::PAYING)
|
||||||
Kernel::my_memory.map (buffer_page, (unsigned)page)
|
Iris::my_memory.map (buffer_page, (unsigned)page)
|
||||||
|
|
||||||
// Disconnect from the bus and don't try to get high-speed.
|
// Disconnect from the bus and don't try to get high-speed.
|
||||||
UDC_POWER = 0
|
UDC_POWER = 0
|
||||||
@ -242,14 +242,14 @@ void Udc::init ():
|
|||||||
UDC_INTROUTE = 1 << 1
|
UDC_INTROUTE = 1 << 1
|
||||||
// Wait a while.
|
// Wait a while.
|
||||||
for unsigned w = 0; w < 10000; ++w:
|
for unsigned w = 0; w < 10000; ++w:
|
||||||
Kernel::schedule ()
|
Iris::schedule ()
|
||||||
// Connect to the host.
|
// Connect to the host.
|
||||||
UDC_POWER = UDC_POWER_SOFTCONN
|
UDC_POWER = UDC_POWER_SOFTCONN
|
||||||
|
|
||||||
bool Udc::vendor (Setup *s, unsigned cmd):
|
bool Udc::vendor (Setup *s, unsigned cmd):
|
||||||
if !(s->request_type & 0x80):
|
if !(s->request_type & 0x80):
|
||||||
kdebug ("data to device without size\n")
|
kdebug ("data to device without size\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return true
|
return true
|
||||||
if s->request == 10:
|
if s->request == 10:
|
||||||
static unsigned b[2]
|
static unsigned b[2]
|
||||||
@ -258,10 +258,10 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
|||||||
if cmd_code != ~0:
|
if cmd_code != ~0:
|
||||||
b[0] = cmd_code
|
b[0] = cmd_code
|
||||||
b[1] = cmd_arg
|
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 ()
|
caller.invoke ()
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
have_caller = false
|
have_caller = false
|
||||||
//kdebug ("(un)lock response\n")
|
//kdebug ("(un)lock response\n")
|
||||||
cmd_code = ~0
|
cmd_code = ~0
|
||||||
@ -283,10 +283,10 @@ bool Udc::vendor (Setup *s, unsigned cmd):
|
|||||||
state = TX
|
state = TX
|
||||||
return true
|
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:
|
if cmd_code != ~0:
|
||||||
kdebug ("new code sent while old one wasn't finished.\n")
|
kdebug ("new code sent while old one wasn't finished.\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
cmd_code = code
|
cmd_code = code
|
||||||
cmd_arg = narg
|
cmd_arg = narg
|
||||||
caller = reply
|
caller = reply
|
||||||
@ -404,7 +404,7 @@ void Udc::irq_in (unsigned cmd):
|
|||||||
switch state:
|
switch state:
|
||||||
case IDLE:
|
case IDLE:
|
||||||
if rebooting:
|
if rebooting:
|
||||||
Kernel::reboot ()
|
Iris::reboot ()
|
||||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||||
return
|
return
|
||||||
union { unsigned d[2]; Setup s; } packet
|
union { unsigned d[2]; Setup s; } packet
|
||||||
@ -439,53 +439,53 @@ void Udc::irq_in (unsigned cmd):
|
|||||||
case RX:
|
case RX:
|
||||||
// The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
|
// The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
|
||||||
switch rx_request & 0xff:
|
switch rx_request & 0xff:
|
||||||
case Directory::GET_SIZE & 0xff:
|
case Iris::Directory::GET_SIZE & 0xff:
|
||||||
if !have_caller:
|
if !have_caller:
|
||||||
kdebug ("received dir size from server without a caller waiting\n")
|
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_l = UDC_FIFO (0)
|
||||||
unsigned size_h = UDC_FIFO (0)
|
unsigned size_h = UDC_FIFO (0)
|
||||||
caller.invoke (Kernel::Num (size_l, size_h))
|
caller.invoke (Iris::Num (size_l, size_h))
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
have_caller = false
|
have_caller = false
|
||||||
//kdebug ("get_size response\n")
|
//kdebug ("get_size response\n")
|
||||||
break
|
break
|
||||||
case Directory::GET_NAME & 0xff:
|
case Iris::Directory::GET_NAME & 0xff:
|
||||||
if !have_caller:
|
if !have_caller:
|
||||||
kdebug ("received filename from server without a caller waiting\n")
|
kdebug ("received filename from server without a caller waiting\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
unsigned n[4]
|
unsigned n[4]
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
n[i] = UDC_FIFO (0)
|
n[i] = UDC_FIFO (0)
|
||||||
caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
|
caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
//kdebug ("get_name response\n")
|
//kdebug ("get_name response\n")
|
||||||
have_caller = false
|
have_caller = false
|
||||||
break
|
break
|
||||||
case ::String::GET_SIZE & 0xff:
|
case Iris::String::GET_SIZE & 0xff:
|
||||||
if !have_caller:
|
if !have_caller:
|
||||||
kdebug ("received string size from server without a caller waiting\n")
|
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_l = UDC_FIFO (0)
|
||||||
unsigned size_h = UDC_FIFO (0)
|
unsigned size_h = UDC_FIFO (0)
|
||||||
caller.invoke (Kernel::Num (size_l, size_h))
|
caller.invoke (Iris::Num (size_l, size_h))
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
have_caller = false
|
have_caller = false
|
||||||
//kdebug ("get_filesize response\n")
|
//kdebug ("get_filesize response\n")
|
||||||
break
|
break
|
||||||
case ::String::GET_CHARS & 0xff:
|
case Iris::String::GET_CHARS & 0xff:
|
||||||
if !have_caller:
|
if !have_caller:
|
||||||
kdebug ("received string char data from server without a caller waiting\n")
|
kdebug ("received string char data from server without a caller waiting\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
unsigned n[4]
|
unsigned n[4]
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
n[i] = UDC_FIFO (0)
|
n[i] = UDC_FIFO (0)
|
||||||
caller.invoke (Kernel::Num (n[0], n[1]), Kernel::Num (n[2], n[3]))
|
caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
have_caller = false
|
have_caller = false
|
||||||
//kdebug ("get_chars response\n")
|
//kdebug ("get_chars response\n")
|
||||||
break
|
break
|
||||||
@ -493,7 +493,7 @@ void Udc::irq_in (unsigned cmd):
|
|||||||
kdebug ("invalid vendor request: ")
|
kdebug ("invalid vendor request: ")
|
||||||
kdebug_num (rx_request)
|
kdebug_num (rx_request)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||||
state = IDLE
|
state = IDLE
|
||||||
break
|
break
|
||||||
@ -504,7 +504,7 @@ void Udc::irq_out (unsigned cmd):
|
|||||||
UDC_INDEX = 1
|
UDC_INDEX = 1
|
||||||
if !have_caller:
|
if !have_caller:
|
||||||
kdebug ("received bulk data from server without a caller waiting\n")
|
kdebug ("received bulk data from server without a caller waiting\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
unsigned size = UDC_OUTCOUNT
|
unsigned size = UDC_OUTCOUNT
|
||||||
unsigned csr = UDC_OUTCSR
|
unsigned csr = UDC_OUTCSR
|
||||||
//kdebug ("handling bulk interrupt for ")
|
//kdebug ("handling bulk interrupt for ")
|
||||||
@ -516,11 +516,11 @@ void Udc::irq_out (unsigned cmd):
|
|||||||
for unsigned i = 0; i < size; i += 4:
|
for unsigned i = 0; i < size; i += 4:
|
||||||
*p++ = UDC_FIFO (1)
|
*p++ = UDC_FIFO (1)
|
||||||
if p - page == PAGE_SIZE >> 2:
|
if p - page == PAGE_SIZE >> 2:
|
||||||
buffer_page.share (caller_arg, Kernel::Page::FORGET)
|
buffer_page.share (caller_arg, Iris::Page::FORGET)
|
||||||
buffer_page.set_flags (Kernel::Page::FRAME, Kernel::Page::FRAME)
|
buffer_page.set_flags (Iris::Page::FRAME, Iris::Page::FRAME)
|
||||||
caller.invoke ()
|
caller.invoke ()
|
||||||
Kernel::free_cap (caller)
|
Iris::free_cap (caller)
|
||||||
Kernel::free_cap (caller_arg)
|
Iris::free_cap (caller_arg)
|
||||||
have_caller = false
|
have_caller = false
|
||||||
//kdebug ("bulk response\n")
|
//kdebug ("bulk response\n")
|
||||||
p = page
|
p = page
|
||||||
@ -561,153 +561,153 @@ enum pdata:
|
|||||||
FILE
|
FILE
|
||||||
NAME
|
NAME
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
map_udc ()
|
map_udc ()
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
map_cpm ()
|
map_cpm ()
|
||||||
Udc udc
|
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")
|
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||||
udc.init ()
|
udc.init ()
|
||||||
Kernel::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Device fs_dev = Kernel::my_receiver.create_capability (FS)
|
Iris::Device fs_dev = Iris::my_receiver.create_capability (FS)
|
||||||
Device data_dev = Kernel::my_receiver.create_capability (DATA)
|
Iris::Device data_dev = Iris::my_receiver.create_capability (DATA)
|
||||||
Kernel::my_parent.provide_device <Filesystem> (fs_dev.copy ())
|
Iris::my_parent.provide_device <Iris::Filesystem> (fs_dev.copy ())
|
||||||
Kernel::my_parent.provide_device <String> (data_dev.copy ())
|
Iris::my_parent.provide_device <Iris::String> (data_dev.copy ())
|
||||||
Kernel::free_cap (fs_dev)
|
Iris::free_cap (fs_dev)
|
||||||
Kernel::free_cap (data_dev)
|
Iris::free_cap (data_dev)
|
||||||
unsigned data_current_user = 0, fs_current_user = 0
|
unsigned data_current_user = 0, fs_current_user = 0
|
||||||
unsigned next_user
|
unsigned next_user
|
||||||
unsigned state = 0
|
unsigned state = 0
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Iris::recv.protected_data.h:
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case IRQ_UDC:
|
case IRQ_UDC:
|
||||||
udc.interrupt (state)
|
udc.interrupt (state)
|
||||||
Kernel::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
break
|
break
|
||||||
case LOG:
|
case LOG:
|
||||||
udc.log (Kernel::recv.data[0].l)
|
udc.log (Iris::recv.data[0].l)
|
||||||
break
|
break
|
||||||
case FS:
|
case FS:
|
||||||
Device::host (FS, fs_current_user, reply, arg)
|
Iris::Device::host (FS, fs_current_user, reply, arg)
|
||||||
continue
|
continue
|
||||||
case DATA:
|
case DATA:
|
||||||
Device::host (DATA, data_current_user, reply, arg)
|
Iris::Device::host (DATA, data_current_user, reply, arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
udc.log ('~')
|
udc.log ('~')
|
||||||
char digit[] = "0123456789abcdef"
|
char digit[] = "0123456789abcdef"
|
||||||
for unsigned i = 0; i < 8; ++i:
|
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')
|
udc.log ('\n')
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
case DATA:
|
case DATA:
|
||||||
if data_current_user != Kernel::recv.protected_data.l:
|
if data_current_user != Iris::recv.protected_data.l:
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case ::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
case ::String::GET_CHARS:
|
case Iris::String::GET_CHARS:
|
||||||
reply.invoke (0)
|
reply.invoke (0)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
case ::String::GET_PAGE:
|
case Iris::String::GET_PAGE:
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
case FS:
|
case FS:
|
||||||
if fs_current_user != Kernel::recv.protected_data.l:
|
if fs_current_user != Iris::recv.protected_data.l:
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Filesystem::USE_DEVICE:
|
case Iris::Filesystem::USE_DEVICE:
|
||||||
case Filesystem::USE_DEVICE_RO:
|
case Iris::Filesystem::USE_DEVICE_RO:
|
||||||
Directory dir = Kernel::my_receiver.create_capability (Kernel::Num (0, DIRECTORY))
|
Iris::Directory dir = Iris::my_receiver.create_capability (Iris::Num (0, DIRECTORY))
|
||||||
reply.invoke (0, 0, dir.copy ())
|
reply.invoke (0, 0, dir.copy ())
|
||||||
Kernel::free_cap (dir)
|
Iris::free_cap (dir)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
case DIRECTORY:
|
case DIRECTORY:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Directory::GET_NAME:
|
case Iris::Directory::GET_NAME:
|
||||||
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (Kernel::recv.data[1].l, NAME))
|
Iris::Cap name = Iris::my_receiver.create_capability (Iris::Num (Iris::recv.data[1].l, NAME))
|
||||||
reply.invoke (0, 0, name.copy ())
|
reply.invoke (0, 0, name.copy ())
|
||||||
Kernel::free_cap (name)
|
Iris::free_cap (name)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
case Directory::GET_SIZE:
|
case Iris::Directory::GET_SIZE:
|
||||||
case Directory::LOCK_RO:
|
case Iris::Directory::LOCK_RO:
|
||||||
case Directory::UNLOCK_RO:
|
case Iris::Directory::UNLOCK_RO:
|
||||||
state = Kernel::recv.data[0].l
|
state = Iris::recv.data[0].l
|
||||||
if Kernel::recv.data[1].h != 0:
|
if Iris::recv.data[1].h != 0:
|
||||||
kdebug ("index out of supported range\n")
|
kdebug ("index out of supported range\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l, reply, arg)
|
udc.send (Iris::recv.data[0].l, Iris::recv.data[1].l, reply, arg)
|
||||||
continue
|
continue
|
||||||
case Directory::GET_FILE_RO:
|
case Iris::Directory::GET_FILE_RO:
|
||||||
if Kernel::recv.data[1].h != 0:
|
if Iris::recv.data[1].h != 0:
|
||||||
kdebug ("index out of supported range\n")
|
kdebug ("index out of supported range\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
//kdebug ("sending file\n")
|
//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 ())
|
reply.invoke (0, 0, file.copy ())
|
||||||
Kernel::free_cap (file)
|
Iris::free_cap (file)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
case Directory::GET_FILE_INFO:
|
case Iris::Directory::GET_FILE_INFO:
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
case FILE:
|
case FILE:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case ::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
case ::String::GET_CHARS:
|
case Iris::String::GET_CHARS:
|
||||||
case ::String::GET_PAGE:
|
case Iris::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)
|
udc.send (Iris::recv.data[0].l | ((Iris::recv.data[1].l >> PAGE_BITS) << 16), Iris::recv.protected_data.l, reply, arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
case NAME:
|
case NAME:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case ::String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
reply.invoke (16)
|
reply.invoke (16)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
case ::String::GET_CHARS:
|
case Iris::String::GET_CHARS:
|
||||||
state = Kernel::recv.data[0].l
|
state = Iris::recv.data[0].l
|
||||||
udc.send (Directory::GET_NAME, Kernel::recv.protected_data.l, reply, arg)
|
udc.send (Iris::Directory::GET_NAME, Iris::recv.protected_data.l, reply, arg)
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
reply.invoke (Kernel::ERR_INVALID_OPERATION)
|
reply.invoke (Iris::ERR_INVALID_OPERATION)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
continue
|
continue
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
|
724
devices.hhp
724
devices.hhp
@ -21,363 +21,405 @@
|
|||||||
|
|
||||||
#include "iris.hh"
|
#include "iris.hh"
|
||||||
|
|
||||||
// List interface.
|
namespace Iris:
|
||||||
template <typename _T> //
|
// Caplist interface.
|
||||||
struct List : public Kernel::Caps:
|
template <typename _T> //
|
||||||
List (Kernel::Caps c = Kernel::Cap ()) : Kernel::Caps (c):
|
struct Caplist : public Iris::Caps:
|
||||||
List <_T> create (unsigned size, Kernel::Memory mem = Kernel::my_memory):
|
Caplist (Iris::Caps c = Iris::Cap ()) : Iris::Caps (c):
|
||||||
return List <_T> (mem.create_caps (size))
|
Caplist <_T> create (unsigned size, Iris::Memory mem = Iris::my_memory):
|
||||||
void set (unsigned idx, _T value):
|
return Caplist <_T> (mem.create_caps (size))
|
||||||
return Kernel::Caps::set (idx, value)
|
void set (unsigned idx, _T value):
|
||||||
_T get (unsigned idx):
|
return Iris::Caps::set (idx, value)
|
||||||
return _T (Kernel::Caps::get (idx))
|
_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').
|
/// A block of data with a size and content. Any character can be stored in it (including '\0').
|
||||||
struct String : public Kernel::Cap:
|
struct String : public Iris::Cap:
|
||||||
String (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
String (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
GET_SIZE = 0x2001
|
GET_SIZE = 0x2001
|
||||||
GET_CHARS
|
GET_CHARS
|
||||||
GET_PAGE
|
GET_PAGE
|
||||||
ID
|
ID
|
||||||
/// Get the size of the string.
|
/// Get the size of the string.
|
||||||
Kernel::Num get_size ():
|
Iris::Num get_size ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||||
/// Get exactly 16 characters. The index must be word-aligned.
|
/// Get exactly 16 characters. The index must be word-aligned.
|
||||||
char *get_chars (Kernel::Num idx, char buffer[16]):
|
char *get_chars (Iris::Num idx, char buffer[16]):
|
||||||
call (CAP_MASTER_DIRECT | GET_CHARS, idx)
|
call (CAP_MASTER_DIRECT | GET_CHARS, idx)
|
||||||
unsigned *b = (unsigned *)buffer
|
unsigned *b = (unsigned *)buffer
|
||||||
b[0] = Kernel::recv.data[0].l
|
b[0] = Iris::recv.data[0].l
|
||||||
b[1] = Kernel::recv.data[0].h
|
b[1] = Iris::recv.data[0].h
|
||||||
b[2] = Kernel::recv.data[1].l
|
b[2] = Iris::recv.data[1].l
|
||||||
b[3] = Kernel::recv.data[1].h
|
b[3] = Iris::recv.data[1].h
|
||||||
return buffer
|
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.
|
/// Helper function for get_page.
|
||||||
Cap get_page (Kernel::Num idx, Kernel::Page ret = Kernel::my_memory.create_page ()):
|
static Iris::Page _create_paying_page ():
|
||||||
ocall (ret, CAP_MASTER_DIRECT | GET_PAGE, idx)
|
Iris::Page ret = Iris::my_memory.create_page ()
|
||||||
return ret
|
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.
|
/// A writable String.
|
||||||
struct WString : public String:
|
struct WString : public String:
|
||||||
WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
|
WString (Iris::Cap c = Iris::Cap ()) : String (c):
|
||||||
enum request:
|
enum request:
|
||||||
TRUNCATE = String::ID
|
TRUNCATE = String::ID
|
||||||
SET_CHARS
|
SET_CHARS
|
||||||
SET_PAGE
|
SET_PAGE
|
||||||
ID
|
ID
|
||||||
/// Set the size of the string. Strings may have a limit to this setting.
|
/// Set the size of the string. Strings may have a limit to this setting.
|
||||||
void truncate (Kernel::Num size):
|
void truncate (Iris::Num size):
|
||||||
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
||||||
/// Set exactly 4 characters. The index must be word-aligned.
|
/// Set exactly 4 characters. The index must be word-aligned.
|
||||||
void set_chars (Kernel::Num idx, char buffer[4]):
|
void set_chars (Iris::Num idx, char buffer[4]):
|
||||||
call (Kernel::Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx)
|
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.
|
/// 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):
|
void set_page (Iris::Num idx, Iris::Page page):
|
||||||
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
||||||
|
|
||||||
// Every process which wants to be switchable through a terminal must implement this interface.
|
// Every process which wants to be switchable through a terminal must implement this interface.
|
||||||
struct Device : public Kernel::Cap:
|
struct Device : public Iris::Cap:
|
||||||
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Device (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
CREATE_USER = WString::ID
|
CREATE_USER = WString::ID
|
||||||
DESTROY_USER
|
DESTROY_USER
|
||||||
UNUSE
|
UNUSE
|
||||||
USE
|
USE
|
||||||
ID
|
ID
|
||||||
// Create a new user for this device. It will not be the active user.
|
// 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.
|
// 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):
|
Iris::Cap create_user (Iris::Memory storage, unsigned arg1 = 0, Iris::Num arg2 = 0):
|
||||||
iocall (storage, Kernel::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2)
|
iocall (storage, Iris::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2)
|
||||||
return Kernel::get_arg ()
|
return Iris::get_arg ()
|
||||||
// Destroy a user. It is made inactive if it was active.
|
// Destroy a user. It is made inactive if it was active.
|
||||||
void destroy_user (Kernel::Cap user):
|
void destroy_user (Iris::Cap user):
|
||||||
ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
|
ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
|
||||||
// Make user inactive.
|
// Make user inactive.
|
||||||
void unuse (Kernel::Cap user):
|
void unuse (Iris::Cap user):
|
||||||
ocall (user, CAP_MASTER_DIRECT | UNUSE)
|
ocall (user, CAP_MASTER_DIRECT | UNUSE)
|
||||||
// Make user active. It makes the previous active user inactive.
|
// Make user active. It makes the previous active user inactive.
|
||||||
void use (Kernel::Cap user):
|
void use (Iris::Cap user):
|
||||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||||
// Convenience function for threads implementing a device.
|
// 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 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
|
static unsigned last_user
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Device::CREATE_USER:
|
case Device::CREATE_USER:
|
||||||
Kernel::Memory mem (arg)
|
Iris::Memory mem (arg)
|
||||||
Kernel::Caps caps = mem.create_caps (capssize)
|
Iris::Caps caps = mem.create_caps (capssize)
|
||||||
unsigned user
|
unsigned user
|
||||||
if create:
|
if create:
|
||||||
user = create (mem, caps)
|
user = create (mem, caps)
|
||||||
else:
|
else:
|
||||||
// Increment last_user; skip 0.
|
// Increment last_user; skip 0.
|
||||||
// FIXME: if this really wraps, it is possible that two users share their id.
|
// FIXME: if this really wraps, it is possible that two users share their id.
|
||||||
if !++last_user:
|
if !++last_user:
|
||||||
++last_user
|
++last_user
|
||||||
user = last_user
|
user = last_user
|
||||||
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (user, id))
|
Iris::Cap c = Iris::my_receiver.create_capability (Iris::Num (user, id))
|
||||||
caps.set (0, c.copy ())
|
caps.set (0, c.copy ())
|
||||||
caps.set (1, mem.copy ())
|
caps.set (1, mem.copy ())
|
||||||
reply.invoke (0, 0, caps.copy ())
|
reply.invoke (0, 0, caps.copy ())
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
Kernel::free_cap (caps)
|
Iris::free_cap (caps)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
break
|
break
|
||||||
case Device::DESTROY_USER:
|
case Device::DESTROY_USER:
|
||||||
Kernel::Caps caps (arg)
|
Iris::Caps caps (arg)
|
||||||
Kernel::Cap c = caps.get (0)
|
Iris::Cap c = caps.get (0)
|
||||||
Kernel::Num user = Kernel::my_receiver.get_protected (c)
|
Iris::Num user = Iris::my_receiver.get_protected (c)
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
if user.h != id:
|
if user.h != id:
|
||||||
Kernel::panic (user.h, "invalid id for destroy")
|
Iris::panic (user.h, "invalid id for destroy")
|
||||||
// TODO: unuse.
|
// TODO: unuse.
|
||||||
if destroy:
|
if destroy:
|
||||||
destroy (user.l, caps)
|
destroy (user.l, caps)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
break
|
break
|
||||||
case Device::USE:
|
case Device::USE:
|
||||||
Kernel::Caps caps (arg)
|
Iris::Caps caps (arg)
|
||||||
Kernel::Cap c = caps.get (0)
|
Iris::Cap c = caps.get (0)
|
||||||
Kernel::Num user = Kernel::my_receiver.get_protected (c)
|
Iris::Num user = Iris::my_receiver.get_protected (c)
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
if user.h != id:
|
if user.h != id:
|
||||||
Kernel::panic (user.h, "invalid id for use")
|
Iris::panic (user.h, "invalid id for use")
|
||||||
// TODO: send unuse signal.
|
// TODO: send unuse signal.
|
||||||
current_user = user.l
|
current_user = user.l
|
||||||
if use:
|
if use:
|
||||||
use (user.l, caps)
|
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:
|
|
||||||
c = caps.get (2)
|
c = caps.get (2)
|
||||||
c.invoke (0)
|
c.invoke (1)
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
current_user = 0
|
reply.invoke ()
|
||||||
reply.invoke ()
|
Iris::free_cap (reply)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (arg)
|
||||||
Kernel::free_cap (arg)
|
break
|
||||||
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 Elfrun : public Iris::Cap:
|
||||||
struct Parent : public Kernel::Cap:
|
Elfrun (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
enum request:
|
||||||
enum request:
|
RUN_STRING = Device::ID
|
||||||
GET_DEVICE = Device::ID
|
RUN_CAPS
|
||||||
PROVIDE_DEVICE
|
ID
|
||||||
WAIT
|
enum arg_pos:
|
||||||
GET_MEMORY
|
PARENT_MEMORY
|
||||||
PROVIDE_MEMORY
|
DATA
|
||||||
INIT_DONE
|
PARENT
|
||||||
EXIT
|
Iris::Caps run_string (Memory parent_memory, String data, Cap parent, unsigned num_slots = 8, unsigned num_caps = 32):
|
||||||
ID
|
Iris::Caps caps = Iris::my_memory.create_caps (3)
|
||||||
// Get a device handle.
|
caps.set (PARENT_MEMORY, parent_memory)
|
||||||
template <typename _T> _T get_device (unsigned num = 0):
|
caps.set (DATA, data)
|
||||||
icall (Kernel::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
|
caps.set (PARENT, parent)
|
||||||
return Kernel::get_arg ()
|
iocall (caps.copy (), CAP_MASTER_DIRECT | RUN_STRING, Iris::Num (num_slots, num_caps))
|
||||||
// Provide a device handle.
|
Iris::Caps ret = Iris::get_arg ()
|
||||||
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
Iris::my_memory.destroy (caps)
|
||||||
ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
Iris::free_cap (caps)
|
||||||
// Wait until a device is used by the caller again.
|
return ret
|
||||||
template <typename _T> void wait (unsigned num = 0):
|
Iris::Caps run_caps (Memory parent_memory, Caps data, Cap parent, unsigned pages, unsigned num_slots = 8, unsigned num_caps = 32):
|
||||||
call (Kernel::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
|
Iris::Caps caps = Iris::my_memory.create_caps (3)
|
||||||
// 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.
|
caps.set (PARENT_MEMORY, parent_memory)
|
||||||
Kernel::Memory get_memory (Kernel::Cap target):
|
caps.set (DATA, data)
|
||||||
iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
|
caps.set (PARENT, parent)
|
||||||
return Kernel::get_arg ()
|
iocall (caps.copy (), Iris::Num (CAP_MASTER_DIRECT | RUN_CAPS, pages), Iris::Num (num_slots, num_caps))
|
||||||
// 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::Caps ret = Iris::get_arg ()
|
||||||
Kernel::Cap provide_memory (unsigned limit):
|
Iris::my_memory.destroy (caps)
|
||||||
icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
|
Iris::free_cap (caps)
|
||||||
return Kernel::get_arg ()
|
return ret
|
||||||
// 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)
|
|
||||||
|
|
||||||
// Keyboard interface.
|
// Interface for talking to the parent process.
|
||||||
struct Keyboard : public Kernel::Cap:
|
struct Parent : public Iris::Cap:
|
||||||
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
SET_CB = Parent::ID
|
GET_DEVICE = Elfrun::ID
|
||||||
GET_NUM_KEYS
|
PROVIDE_DEVICE
|
||||||
GET_KEYS
|
WAIT
|
||||||
ID
|
GET_MEMORY
|
||||||
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
|
PROVIDE_MEMORY
|
||||||
enum constant:
|
INIT_DONE
|
||||||
RELEASE = 1 << 31
|
EXIT
|
||||||
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
|
ID
|
||||||
void set_cb (Kernel::Cap cb):
|
// Get a device handle.
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
template <typename _T> _T get_device (unsigned num = 0):
|
||||||
// Get the number of keys on the keyboard.
|
icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
|
||||||
unsigned get_num_keys ():
|
return Iris::get_arg ()
|
||||||
return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
|
// Provide a device handle.
|
||||||
// Get the keycodes for the keys. The reply sends 4 key codes (32 bit each).
|
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
||||||
void get_keys (unsigned first):
|
ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
||||||
call (CAP_MASTER_DIRECT | GET_KEYS, first)
|
// Wait until a device is used by the caller again.
|
||||||
|
template <typename _T> 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.
|
// Keyboard interface.
|
||||||
struct Buzzer : public Kernel::Cap:
|
struct Keyboard : public Iris::Cap:
|
||||||
Buzzer (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Keyboard (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
BEEP = Keyboard::ID
|
SET_CB = Parent::ID
|
||||||
STOP
|
GET_NUM_KEYS
|
||||||
ID
|
GET_KEYS
|
||||||
// Emit a beep of specified frequency, time and volume. Volume may not be supported. If an other beep is in progress, it is aborted.
|
ID
|
||||||
void beep (unsigned freq, unsigned ms, unsigned volume, Kernel::Cap cb = Kernel::Cap ()):
|
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
|
||||||
ocall (cb, Kernel::Num (CAP_MASTER_DIRECT | BEEP, volume), Kernel::Num (freq, ms))
|
enum constant:
|
||||||
// Abort current beep, if any.
|
RELEASE = 1 << 31
|
||||||
void stop ():
|
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
|
||||||
call (CAP_MASTER_DIRECT | STOP)
|
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.
|
// Buzzer interface.
|
||||||
struct Display : public Kernel::Cap:
|
struct Buzzer : public Iris::Cap:
|
||||||
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Buzzer (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
SET_EOF_CB = Buzzer::ID
|
BEEP = Keyboard::ID
|
||||||
MAP_FB
|
STOP
|
||||||
GET_INFO
|
ID
|
||||||
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.
|
||||||
// Register an end-of-frame callback.
|
void beep (unsigned freq, unsigned ms, unsigned volume, Iris::Cap cb = Iris::Cap ()):
|
||||||
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
|
ocall (cb, Iris::Num (CAP_MASTER_DIRECT | BEEP, volume), Iris::Num (freq, ms))
|
||||||
void set_eof_cb (Kernel::Cap cb):
|
// Abort current beep, if any.
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
|
void stop ():
|
||||||
// Map the framebuffer into memory.
|
call (CAP_MASTER_DIRECT | STOP)
|
||||||
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)
|
|
||||||
|
|
||||||
// Numerical setting, such as a display backlight.
|
// Display interface.
|
||||||
struct Setting : public Kernel::Cap:
|
struct Display : public Iris::Cap:
|
||||||
Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Display (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
SET = Display::ID
|
SET_EOF_CB = Buzzer::ID
|
||||||
GET_RANGE
|
MAP_FB
|
||||||
ID
|
GET_INFO
|
||||||
// Set a new value.
|
ID
|
||||||
void set (unsigned value):
|
// Register an end-of-frame callback.
|
||||||
call (CAP_MASTER_DIRECT | SET, value)
|
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
|
||||||
// Get the maximum value for this setting. Using a higher value with SET gives undefined results.
|
void set_eof_cb (Iris::Cap cb):
|
||||||
unsigned get_range ():
|
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
|
||||||
return call (CAP_MASTER_DIRECT | GET_RANGE).l
|
// 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.
|
// Numerical setting, such as a display backlight.
|
||||||
// filesystem-related interfaces: directory, stream, seekable.
|
struct Setting : public Iris::Cap:
|
||||||
// Normal files implement stream and/or seekable. Directories implement directory.
|
Setting (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
// Seekable is not a class, it is identical to [W]String.
|
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.
|
// File system interface.
|
||||||
struct Directory : public Kernel::Cap:
|
// filesystem-related interfaces: directory, stream, seekable.
|
||||||
Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
// Normal files implement stream and/or seekable. Directories implement directory.
|
||||||
enum request:
|
// Seekable is not a class, it is identical to [W]String.
|
||||||
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)
|
|
||||||
|
|
||||||
// A filesystem turns a String into a Directory.
|
// Directory interface.
|
||||||
struct Filesystem : public Device:
|
struct Directory : public Iris::Cap:
|
||||||
Filesystem (Kernel::Cap c = Kernel::Cap ()) : Device (c):
|
Directory (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
USE_DEVICE = WDirectory::ID
|
GET_SIZE = Setting::ID
|
||||||
USE_DEVICE_RO
|
GET_NAME
|
||||||
ID
|
GET_FILE_RO
|
||||||
WDirectory use_device (WString dev):
|
GET_FILE_INFO
|
||||||
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE)
|
LOCK_RO
|
||||||
return Kernel::get_arg ()
|
UNLOCK_RO
|
||||||
Directory use_device_ro (String dev):
|
ID
|
||||||
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO)
|
// Get the number of entries in this directory.
|
||||||
return Kernel::get_arg ()
|
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.
|
// A filesystem turns a String into a Directory.
|
||||||
struct Stream : public Kernel::Cap:
|
struct Filesystem : public Device:
|
||||||
Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Filesystem (Iris::Cap c = Iris::Cap ()) : Device (c):
|
||||||
enum request:
|
enum request:
|
||||||
READ = Filesystem::ID
|
USE_DEVICE = WDirectory::ID
|
||||||
WRITE
|
USE_DEVICE_RO
|
||||||
ID
|
ID
|
||||||
// Try to read size bytes. Returns the number of bytes successfully read.
|
WDirectory use_device (WString dev):
|
||||||
Kernel::Num read (Kernel::Num size, bool block):
|
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE)
|
||||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, block), size)
|
return Iris::get_arg ()
|
||||||
// Try to write size bytes. Returns the number of bytes successfully written.
|
Directory use_device_ro (String dev):
|
||||||
Kernel::Num write (String s, Kernel::Num size):
|
ocall (dev, CAP_MASTER_DIRECT | USE_DEVICE_RO)
|
||||||
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
|
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.
|
// Block device interface.
|
||||||
struct Block_device : public WString:
|
struct Block_device : public WString:
|
||||||
Block_device (Kernel::Cap c = Kernel::Cap ()) : WString (c):
|
Block_device (Iris::Cap c = Iris::Cap ()) : WString (c):
|
||||||
// TODO: to be designed.
|
// TODO: to be designed.
|
||||||
|
|
||||||
|
|
||||||
// TODO.
|
// TODO.
|
||||||
|
59
init.config
Normal file
59
init.config
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# load <name> = '<filename>' 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 <name> / <type> [, <index>] = <cap> 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 <name> 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 <cap> use a capability as the system request keyboard.
|
||||||
|
sysreq sysreq
|
||||||
|
|
||||||
|
# give <name> (<type> [, <index>]) = <cap> 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 <name> run a previously loaded program (normally).
|
||||||
|
# run emu_lcd
|
||||||
|
# run emu_buzzer
|
||||||
|
# run emu_keyboard
|
||||||
|
# run emu_audio
|
||||||
|
# run emu_udc
|
||||||
|
|
||||||
|
# include <name> include a loaded file as another config file.
|
||||||
|
include session
|
391
invoke.ccp
391
invoke.ccp
@ -60,8 +60,8 @@ void kThread::raise (unsigned code, unsigned data):
|
|||||||
kdebug (':')
|
kdebug (':')
|
||||||
kdebug_num ((unsigned)old_current)
|
kdebug_num ((unsigned)old_current)
|
||||||
kdebug ('/')
|
kdebug ('/')
|
||||||
if code < Kernel::NUM_EXCEPTION_CODES:
|
if code < Iris::NUM_EXCEPTION_CODES:
|
||||||
kdebug (Kernel::exception_name[code])
|
kdebug (Iris::exception_name[code])
|
||||||
else:
|
else:
|
||||||
kdebug ("invalid code:")
|
kdebug ("invalid code:")
|
||||||
kdebug_num (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:
|
if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target:
|
||||||
return
|
return
|
||||||
kCapability::Context c
|
kCapability::Context c
|
||||||
c.data[0] = Kernel::Num (code, data)
|
c.data[0] = Iris::Num (code, data)
|
||||||
slot[0].caps->cap (0)->invoke (&c)
|
slot[0].caps->cap (0)->invoke (&c)
|
||||||
|
|
||||||
// From user-provided, thus untrusted, data, find a capability.
|
// From user-provided, thus untrusted, data, find a capability.
|
||||||
@ -128,7 +128,7 @@ bool kReceiver::try_deliver ():
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
// Send a message to a receiver; try to deliver it immediately.
|
// 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)
|
//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 owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()):
|
||||||
if protected_only:
|
if protected_only:
|
||||||
@ -161,59 +161,64 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
static kCapability::Context *context
|
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
|
kCapability::Context c
|
||||||
c.data[0] = num
|
c.data[0] = num
|
||||||
c.data[1] = 0
|
c.data[1] = 0
|
||||||
if reply_target:
|
if reply_target:
|
||||||
reply_target->send_message (reply_protected, &c)
|
reply_target->send_message (reply_protected, &c)
|
||||||
else:
|
else if reply_protected.l == 0:
|
||||||
dpanic (0, "nothing to reply to")
|
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):
|
static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
||||||
kCapability::Context c
|
kCapability::Context c
|
||||||
c.data[0] = Kernel::Num (num1, num2)
|
c.data[0] = Iris::Num (num1, num2)
|
||||||
c.data[1] = num3
|
c.data[1] = num3
|
||||||
if reply_target:
|
if reply_target:
|
||||||
reply_target->send_message (reply_protected, &c)
|
reply_target->send_message (reply_protected, &c)
|
||||||
|
else if reply_protected.l == 0:
|
||||||
|
dpanic (0, "nothing to reply to")
|
||||||
else:
|
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:
|
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
|
return
|
||||||
replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
|
replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
|
||||||
kCapability::Context c
|
kCapability::Context c
|
||||||
c.arg = kCapRef (&replied_caps, 0)
|
c.arg = kCapRef (&replied_caps, 0)
|
||||||
c.copy[1] = true
|
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)
|
reply_target->send_message (reply_protected, &c)
|
||||||
c.arg->invalidate ()
|
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
|
kReceiver *receiver = (kReceiver *)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::Receiver::SET_OWNER & REQUEST_MASK:
|
case Iris::Receiver::SET_OWNER & REQUEST_MASK:
|
||||||
if !c->arg.valid ():
|
if !c->arg.valid ():
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
unsigned cap = (unsigned)c->arg->target
|
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.
|
// FIXME: This makes it impossible to use a fake kThread capability.
|
||||||
return
|
return
|
||||||
receiver->own ((kThread *)c->arg->protected_data.l)
|
receiver->own ((kThread *)c->arg->protected_data.l)
|
||||||
break
|
break
|
||||||
case Kernel::Receiver::CREATE_CAPABILITY & REQUEST_MASK:
|
case Iris::Receiver::CREATE_CAPABILITY & REQUEST_MASK:
|
||||||
reply_cap ((unsigned)receiver, c->data[1], &receiver->capabilities)
|
reply_cap ((unsigned)receiver, c->data[1], &receiver->capabilities)
|
||||||
return
|
return
|
||||||
case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
|
case Iris::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)
|
reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Iris::Receiver::CALL_ASYNC : Iris::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
|
||||||
return
|
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 () || c->arg->target != receiver:
|
||||||
if !c->arg.valid ():
|
if !c->arg.valid ():
|
||||||
kdebug ("invalid arg\n")
|
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_num ((unsigned)c->arg->protected_data.l)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
dpanic (0, "wrong argument for get_protected")
|
dpanic (0, "wrong argument for get_protected")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
reply_num (c->arg->protected_data)
|
reply_num (c->arg->protected_data)
|
||||||
return
|
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)
|
reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0)
|
||||||
return
|
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]
|
receiver->reply_protected_data = c->data[1]
|
||||||
break
|
break
|
||||||
case Kernel::Receiver::GET_ALARM & REQUEST_MASK:
|
case Iris::Receiver::GET_ALARM & REQUEST_MASK:
|
||||||
reply_num (receiver->alarm_count)
|
reply_num (receiver->alarm_count)
|
||||||
return
|
return
|
||||||
case Kernel::Receiver::SET_ALARM & REQUEST_MASK:
|
case Iris::Receiver::SET_ALARM & REQUEST_MASK:
|
||||||
case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
|
case Iris::Receiver::ADD_ALARM & REQUEST_MASK:
|
||||||
unsigned old = receiver->alarm_count
|
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
|
receiver->alarm_count = c->data[1].l
|
||||||
else:
|
else:
|
||||||
receiver->alarm_count += c->data[1].l
|
receiver->alarm_count += c->data[1].l
|
||||||
@ -267,14 +272,14 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (cmd, "invalid receiver operation")
|
dpanic (cmd, "invalid receiver operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
reply_num (0)
|
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
|
kMemory *mem = (kMemory *)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::Memory::CREATE & REQUEST_MASK:
|
case Iris::Memory::CREATE & REQUEST_MASK:
|
||||||
switch c->data[0].h:
|
switch c->data[0].h:
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
kReceiver *ret = mem->alloc_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)
|
reply_cap (CAPTYPE_RECEIVER | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
else:
|
else:
|
||||||
dpanic (0x03311992, "out of memory creating receiver")
|
dpanic (0x03311992, "out of memory creating receiver")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
case CAPTYPE_MEMORY:
|
case CAPTYPE_MEMORY:
|
||||||
kMemory *ret = mem->alloc_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)
|
reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
else:
|
else:
|
||||||
dpanic (0x13311992, "out of memory creating memory")
|
dpanic (0x13311992, "out of memory creating memory")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
case CAPTYPE_THREAD:
|
case CAPTYPE_THREAD:
|
||||||
kThread *ret = mem->alloc_thread (c->data[1].l)
|
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 (")")
|
kdebug (")")
|
||||||
else:
|
else:
|
||||||
dpanic (0x23311992, "out of memory creating thread")
|
dpanic (0x23311992, "out of memory creating thread")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
case CAPTYPE_PAGE:
|
case CAPTYPE_PAGE:
|
||||||
kPage *ret = mem->alloc_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)
|
reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
else:
|
else:
|
||||||
dpanic (0x33311992, "out of memory creating page")
|
dpanic (0x33311992, "out of memory creating page")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
case CAPTYPE_CAPS:
|
case CAPTYPE_CAPS:
|
||||||
kCaps *ret = mem->alloc_caps (c->data[1].l)
|
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)
|
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||||
else:
|
else:
|
||||||
dpanic (0x43311992, "out of memory creating caps")
|
dpanic (0x43311992, "out of memory creating caps")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid create type")
|
dpanic (0, "invalid create type")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
break
|
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:
|
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
|
return
|
||||||
switch (unsigned)c->arg->target & CAPTYPE_MASK:
|
switch (unsigned)c->arg->target & CAPTYPE_MASK:
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
@ -348,87 +353,88 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
|||||||
panic (0x55228930, "invalid case")
|
panic (0x55228930, "invalid case")
|
||||||
return
|
return
|
||||||
break
|
break
|
||||||
case Kernel::Memory::LIST & REQUEST_MASK:
|
case Iris::Memory::LIST & REQUEST_MASK:
|
||||||
// TODO
|
// TODO
|
||||||
break
|
break
|
||||||
case Kernel::Memory::MAP & REQUEST_MASK:
|
case Iris::Memory::MAP & REQUEST_MASK:
|
||||||
// FIXME: this should work for fake pages as well.
|
// 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:
|
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")
|
dpanic (0x22993341, "Trying to map non-page")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kPage *page = (kPage *)c->arg->protected_data.l
|
kPage *page = (kPage *)c->arg->protected_data.l
|
||||||
if page->address_space != mem:
|
if page->address_space != mem:
|
||||||
dpanic (0x52993341, "Trying to map foreign page")
|
dpanic (0x52993341, "Trying to map foreign page")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
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")
|
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)
|
mem->map (page, c->data[1].l & PAGE_MASK)
|
||||||
break
|
break
|
||||||
case Kernel::Memory::MAPPING & REQUEST_MASK:
|
case Iris::Memory::MAPPING & REQUEST_MASK:
|
||||||
kPage *page = mem->get_mapping (c->data[1].l)
|
kPage *page = mem->get_mapping (c->data[1].l)
|
||||||
if !page:
|
if !page:
|
||||||
reply_num (Kernel::ERR_UNMAPPED_READ)
|
reply_num (Iris::ERR_UNMAPPED_READ)
|
||||||
return
|
return
|
||||||
unsigned t = CAPTYPE_PAGE | CAP_MASTER
|
unsigned t = CAPTYPE_PAGE | CAP_MASTER
|
||||||
if page->flags & Kernel::Page::MAPPED_READONLY:
|
if page->flags & Iris::Page::MAPPED_READONLY:
|
||||||
t |= Kernel::Page::READONLY
|
t |= Iris::Page::READONLY
|
||||||
reply_cap (t, (unsigned)page, &page->refs)
|
reply_cap (t, (unsigned)page, &page->refs)
|
||||||
return
|
return
|
||||||
case Kernel::Memory::GET_LIMIT & REQUEST_MASK:
|
case Iris::Memory::GET_LIMIT & REQUEST_MASK:
|
||||||
reply_num (mem->limit)
|
reply_num (mem->limit)
|
||||||
return
|
return
|
||||||
case Kernel::Memory::SET_LIMIT & REQUEST_MASK:
|
case Iris::Memory::SET_LIMIT & REQUEST_MASK:
|
||||||
mem->limit = c->data[1].l
|
mem->limit = c->data[1].l
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid memory operation")
|
dpanic (0, "invalid memory operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
reply_num (0)
|
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
|
kThread *thread = (kThread *)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::Thread::GET_INFO & REQUEST_MASK:
|
case Iris::Thread::GET_INFO & REQUEST_MASK:
|
||||||
switch c->data[0].h:
|
switch c->data[0].h:
|
||||||
case Kernel::Thread::PC:
|
case Iris::Thread::PC:
|
||||||
reply_num (thread->pc)
|
reply_num (thread->pc)
|
||||||
return
|
return
|
||||||
case Kernel::Thread::SP:
|
case Iris::Thread::SP:
|
||||||
reply_num (thread->sp)
|
reply_num (thread->sp)
|
||||||
return
|
return
|
||||||
case Kernel::Thread::FLAGS:
|
case Iris::Thread::FLAGS:
|
||||||
reply_num (thread->flags)
|
reply_num (thread->flags)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
reply_num (*kThread_arch_info (thread, c->data[0].h))
|
reply_num (*kThread_arch_info (thread, c->data[0].h))
|
||||||
return
|
return
|
||||||
case Kernel::Thread::SET_INFO & REQUEST_MASK:
|
case Iris::Thread::SET_INFO & REQUEST_MASK:
|
||||||
unsigned *value
|
unsigned *value
|
||||||
switch c->data[0].h:
|
switch c->data[0].h:
|
||||||
case Kernel::Thread::PC:
|
case Iris::Thread::PC:
|
||||||
value = &thread->pc
|
value = &thread->pc
|
||||||
break
|
break
|
||||||
case Kernel::Thread::SP:
|
case Iris::Thread::SP:
|
||||||
value = &thread->sp
|
value = &thread->sp
|
||||||
break
|
break
|
||||||
case Kernel::Thread::FLAGS:
|
case Iris::Thread::FLAGS:
|
||||||
// It is not possible to set the PRIV flag (but it can be reset).
|
// It is not possible to set the PRIV flag (but it can be reset).
|
||||||
if c->data[1].l & Kernel::Thread::PRIV:
|
if c->data[1].l & Iris::Thread::PRIV:
|
||||||
c->data[1].h &= ~Kernel::Thread::PRIV
|
c->data[1].h &= ~Iris::Thread::PRIV
|
||||||
value = &thread->flags
|
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)
|
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 & Iris::Thread::WAITING) != (*value & Iris::Thread::WAITING):
|
||||||
if v & Kernel::Thread::WAITING:
|
if v & Iris::Thread::WAITING:
|
||||||
thread->wait ()
|
thread->wait ()
|
||||||
else
|
else
|
||||||
thread->unwait ()
|
thread->unwait ()
|
||||||
if (v & Kernel::Thread::RUNNING) != (*value & Kernel::Thread::RUNNING):
|
if (v & Iris::Thread::RUNNING) != (*value & Iris::Thread::RUNNING):
|
||||||
if v & Kernel::Thread::RUNNING:
|
if v & Iris::Thread::RUNNING:
|
||||||
thread->run ()
|
thread->run ()
|
||||||
else:
|
else:
|
||||||
thread->unrun ()
|
thread->unrun ()
|
||||||
@ -439,140 +445,155 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
|||||||
if value:
|
if value:
|
||||||
*value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
*value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
||||||
break
|
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 >= 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)
|
dbg_send (5, 3)
|
||||||
dpanic (c->data[1].l, "no argument given for USE_SLOT")
|
dpanic (c->data[1].l, "no argument given for USE_SLOT")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
// FIXME: This doesn't allow using a fake caps.
|
// 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):
|
if (unsigned)c->arg->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->arg->target != (CAPTYPE_CAPS | Iris::Caps::USE):
|
||||||
dpanic (0, "argument for USE_SLOT is not a caps")
|
dpanic ((unsigned)c->arg->target, "argument for USE_SLOT is not a caps")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
|
dbg_push (__LINE__)
|
||||||
unsigned slot = c->data[1].l
|
unsigned slot = c->data[1].l
|
||||||
|
dbg_push (__LINE__)
|
||||||
kCaps *new_caps = (kCaps *)c->arg->protected_data.l
|
kCaps *new_caps = (kCaps *)c->arg->protected_data.l
|
||||||
|
dbg_push (__LINE__)
|
||||||
if slot >= thread->slots:
|
if slot >= thread->slots:
|
||||||
dpanic (0, "using invalid slot")
|
dpanic (0, "using invalid slot")
|
||||||
return
|
return
|
||||||
|
dbg_push (__LINE__)
|
||||||
thread->unset_slot (slot)
|
thread->unset_slot (slot)
|
||||||
|
dbg_push (__LINE__)
|
||||||
thread->slot[slot].caps = new_caps
|
thread->slot[slot].caps = new_caps
|
||||||
|
dbg_push (__LINE__)
|
||||||
if new_caps:
|
if new_caps:
|
||||||
|
dbg_push (__LINE__)
|
||||||
thread->slot[slot].next = new_caps->first_slot
|
thread->slot[slot].next = new_caps->first_slot
|
||||||
thread->slot[slot].caps = new_caps
|
thread->slot[slot].caps = new_caps
|
||||||
new_caps->first_slot.thread = thread
|
new_caps->first_slot.thread = thread
|
||||||
new_caps->first_slot.index = slot
|
new_caps->first_slot.index = slot
|
||||||
|
dbg_push (__LINE__)
|
||||||
break
|
break
|
||||||
case Kernel::Thread::GET_CAPS & REQUEST_MASK:
|
case Iris::Thread::GET_CAPS & REQUEST_MASK:
|
||||||
unsigned slot = c->data[1].l
|
unsigned slot = c->data[1].l
|
||||||
if slot < thread->slots:
|
if slot < thread->slots:
|
||||||
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->slot[slot].caps, &thread->slot[slot].caps->refs, thread->slots)
|
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->slot[slot].caps, &thread->slot[slot].caps->refs, thread->slots)
|
||||||
else:
|
else:
|
||||||
reply_num (thread->slots)
|
reply_num (thread->slots)
|
||||||
return
|
return
|
||||||
case Kernel::Thread::SCHEDULE & REQUEST_MASK:
|
case Iris::Thread::SCHEDULE & REQUEST_MASK:
|
||||||
do_schedule = true
|
do_schedule = true
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
if !(thread->flags & Kernel::Thread::PRIV):
|
if !(thread->flags & Iris::Thread::PRIV):
|
||||||
dpanic (0, "invalid thread operation")
|
dpanic (0, "invalid thread operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
switch cmd:
|
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)
|
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
|
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)
|
reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)&top_memory, &top_memory.refs)
|
||||||
return
|
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:
|
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_THREAD:
|
||||||
dpanic (0, "not a thread argument for make priv")
|
dpanic (0, "not a thread argument for make priv")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
((kThread *)c->arg->protected_data.l)->flags |= Kernel::Thread::PRIV
|
((kThread *)c->arg->protected_data.l)->flags |= Iris::Thread::PRIV
|
||||||
break
|
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:
|
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
|
||||||
panic (0x54365435, "non-memory argument to alloc_range")
|
panic (0x54365435, "non-memory argument to alloc_range")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kMemory *mem = (kMemory *)c->arg->protected_data.l
|
kMemory *mem = (kMemory *)c->arg->protected_data.l
|
||||||
if !mem->use (c->data[1].l):
|
if !mem->use (c->data[1].l):
|
||||||
dpanic (0x34365435, "out of memory during alloc_range")
|
dpanic (0x34365435, "out of memory during alloc_range")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
unsigned data = phys_alloc (c->data[1].l)
|
unsigned data = phys_alloc (c->data[1].l)
|
||||||
if !data:
|
if !data:
|
||||||
mem->unuse (c->data[1].l)
|
mem->unuse (c->data[1].l)
|
||||||
dpanic (0x14365435, "out of memory during alloc_range")
|
dpanic (0x14365435, "out of memory during alloc_range")
|
||||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
reply_num (Iris::ERR_OUT_OF_MEMORY)
|
||||||
return
|
return
|
||||||
reply_num (data & ~0xc0000000)
|
reply_num (data & ~0xc0000000)
|
||||||
return
|
return
|
||||||
case Kernel::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK:
|
case Iris::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK:
|
||||||
if !c->arg.valid ():
|
if !c->arg.valid ():
|
||||||
panic (0x71342134, "no argument provided for alloc physical")
|
panic (0x71342134, "no argument provided for alloc physical")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
||||||
panic (0x21342134, "no page provided for alloc physical")
|
panic (0x21342134, "no page provided for alloc physical")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kPage *page = (kPage *)c->arg->protected_data.l
|
kPage *page = (kPage *)c->arg->protected_data.l
|
||||||
page->forget ()
|
page->forget ()
|
||||||
if !(c->data[1].l & 2):
|
if !(c->data[1].l & 2):
|
||||||
if page->flags & Kernel::Page::PAYING:
|
if page->flags & Iris::Page::PAYING:
|
||||||
page->flags &= ~Kernel::Page::PAYING
|
page->flags &= ~Iris::Page::PAYING
|
||||||
page->address_space->unuse ()
|
page->address_space->unuse ()
|
||||||
else:
|
else:
|
||||||
// This is for mapping allocated ranges. They are already paid for. Record that.
|
// 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 ()
|
page->address_space->unuse ()
|
||||||
else:
|
else:
|
||||||
page->flags |= Kernel::Page::PAYING
|
page->flags |= Iris::Page::PAYING
|
||||||
page->frame = (c->data[1].l & PAGE_MASK) | 0x80000000
|
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):
|
if !(c->data[1].l & 1):
|
||||||
page->flags |= Kernel::Page::UNCACHED
|
page->flags |= Iris::Page::UNCACHED
|
||||||
if !(c->data[1].l & 2):
|
if !(c->data[1].l & 2):
|
||||||
page->flags |= Kernel::Page::PHYSICAL
|
page->flags |= Iris::Page::PHYSICAL
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
break
|
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:
|
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_PAGE:
|
||||||
dpanic (0x99049380, "invalid page for physical address")
|
dpanic (0x99049380, "invalid page for physical address")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kPage *page = (kPage *)c->arg->protected_data.l
|
kPage *page = (kPage *)c->arg->protected_data.l
|
||||||
reply_num (page->frame & ~0xc0000000)
|
reply_num (page->frame & ~0xc0000000)
|
||||||
return
|
return
|
||||||
case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK:
|
case Iris::Thread::PRIV_REBOOT & REQUEST_MASK:
|
||||||
arch_reboot ()
|
arch_reboot ()
|
||||||
case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
|
case Iris::Thread::PRIV_PANIC & REQUEST_MASK:
|
||||||
if c->data[1].l == 0xdeaddead:
|
if c->data[1].l == 0xdeaddead:
|
||||||
dbg_code.l = 1
|
dbg_code.l = 1
|
||||||
break
|
break
|
||||||
panic (c->data[1].l, "panic requested by thread")
|
panic (c->data[1].l, "panic requested by thread")
|
||||||
reply_num (~0)
|
reply_num (~0)
|
||||||
return
|
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)
|
dbg_send (c->data[1].l, c->data[1].h)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid priv thread operation")
|
dpanic (0, "invalid priv thread operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
|
dbg_push (__LINE__)
|
||||||
reply_num (0)
|
reply_num (0)
|
||||||
|
dbg_push (__LINE__)
|
||||||
return
|
return
|
||||||
|
|
||||||
static void page_check_payment (kPage *page):
|
static void page_check_payment (kPage *page):
|
||||||
kPage *p
|
kPage *p
|
||||||
for p = page; p; p = p->share_prev:
|
for p = page; p; p = p->share_prev:
|
||||||
if p->flags & Kernel::Page::PAYING:
|
if p->flags & Iris::Page::PAYING:
|
||||||
return
|
return
|
||||||
for p = page->share_next; p; p = p->share_next:
|
for p = page->share_next; p; p = p->share_next:
|
||||||
if p->flags & Kernel::Page::PAYING:
|
if p->flags & Iris::Page::PAYING:
|
||||||
return
|
return
|
||||||
// No kPage is paying for this frame anymore.
|
// No kPage is paying for this frame anymore.
|
||||||
raw_pfree (page->frame)
|
raw_pfree (page->frame)
|
||||||
@ -581,46 +602,55 @@ static void page_check_payment (kPage *page):
|
|||||||
p->frame = NULL
|
p->frame = NULL
|
||||||
p->share_prev = NULL
|
p->share_prev = NULL
|
||||||
p->share_next = 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)
|
kPage_arch_update_mapping (p)
|
||||||
for p = page, next = p->share_next; p; p = next, next = p->share_next:
|
for p = page, next = p->share_next; p; p = next, next = p->share_next:
|
||||||
p->frame = NULL
|
p->frame = NULL
|
||||||
p->share_prev = NULL
|
p->share_prev = NULL
|
||||||
p->share_next = 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)
|
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
|
kPage *page = (kPage *)protected_data.l
|
||||||
switch cmd & ~Kernel::Page::READONLY:
|
switch cmd & ~Iris::Page::READONLY:
|
||||||
case Kernel::Page::SHARE & REQUEST_MASK:
|
case Iris::Page::SHARE & REQUEST_MASK:
|
||||||
if !c->arg.valid ():
|
if !c->arg.valid ():
|
||||||
// Cannot share without a target page.
|
// Cannot share without a target page.
|
||||||
dpanic (0, "no target page for share")
|
dpanic (0, "no target page for share")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
|
||||||
// FIXME: This makes it impossible to use a fake kPage capability.
|
// FIXME: This makes it impossible to use a fake kPage capability.
|
||||||
dpanic (0, "share target is no page")
|
dpanic (0, "share target is no page")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kPage *t = (kPage *)c->arg->protected_data.l
|
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:
|
if t != page:
|
||||||
t->forget ()
|
t->forget ()
|
||||||
if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY:
|
if c->data[0].h & Iris::Page::READONLY || cmd & Iris::Page::READONLY:
|
||||||
t->flags |= Kernel::Page::READONLY
|
t->flags |= Iris::Page::READONLY
|
||||||
if !(page->flags & Kernel::Page::FRAME):
|
if !(page->flags & Iris::Page::FRAME):
|
||||||
kdebug ("share problem: ")
|
kdebug ("share problem: ")
|
||||||
kdebug_num (page->flags)
|
kdebug_num (page->flags)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
dpanic (0, "sharing nothing results in lost page")
|
dpanic (0, "sharing nothing results in lost page")
|
||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
break
|
break
|
||||||
if c->data[0].h & Kernel::Page::COPY:
|
if c->data[0].h & Iris::Page::COPY:
|
||||||
if ~t->flags & Kernel::Page::PAYING:
|
if ~t->flags & Iris::Page::PAYING:
|
||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
break
|
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
|
unsigned *d = (unsigned *)page->frame
|
||||||
if t == page:
|
if t == page:
|
||||||
kPage *other = page->share_next ? page->share_next : page->share_prev
|
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->share_prev = NULL
|
||||||
page_check_payment (other)
|
page_check_payment (other)
|
||||||
else:
|
else:
|
||||||
t->flags |= Kernel::Page::FRAME
|
t->flags |= Iris::Page::FRAME
|
||||||
t->frame = raw_zalloc ()
|
t->frame = raw_zalloc ()
|
||||||
for unsigned i = 0; i < PAGE_SIZE; i += 4:
|
for unsigned i = 0; i < PAGE_SIZE; i += 4:
|
||||||
((unsigned *)t->frame)[i >> 2] = d[i >> 2]
|
((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->frame = NULL
|
||||||
page->flags &= ~Kernel::Page::FRAME
|
page->flags &= ~Iris::Page::FRAME
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
else:
|
else:
|
||||||
if t != page:
|
if t != page:
|
||||||
t->frame = page->frame
|
t->frame = page->frame
|
||||||
t->flags |= Kernel::Page::FRAME
|
t->flags |= Iris::Page::FRAME
|
||||||
page->frame = NULL
|
page->frame = NULL
|
||||||
page->flags &= ~Kernel::Page::FRAME
|
page->flags &= ~Iris::Page::FRAME
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
else:
|
else:
|
||||||
dpanic (0, "sharing page with itself...")
|
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")
|
dpanic (0, "sharing page with itself")
|
||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
break
|
break
|
||||||
if c->data[0].h & Kernel::Page::FORGET:
|
if c->data[0].h & Iris::Page::FORGET:
|
||||||
if ~page->flags & Kernel::Page::SHARED:
|
if ~page->flags & Iris::Page::SHARED:
|
||||||
if t->flags & Kernel::Page::PAYING:
|
if t->flags & Iris::Page::PAYING:
|
||||||
t->frame = page->frame
|
t->frame = page->frame
|
||||||
t->flags |= Kernel::Page::FRAME
|
t->flags |= Iris::Page::FRAME
|
||||||
else:
|
else:
|
||||||
dpanic (0, "move page failed because target is not paying")
|
dpanic (0, "move page failed because target is not paying")
|
||||||
page->frame = NULL
|
page->frame = NULL
|
||||||
page->flags &= ~Kernel::Page::FRAME
|
page->flags &= ~Iris::Page::FRAME
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
else:
|
else:
|
||||||
t->share_prev = page->share_prev
|
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:
|
if t->share_prev:
|
||||||
t->share_prev->share_next = t
|
t->share_prev->share_next = t
|
||||||
t->frame = page->frame
|
t->frame = page->frame
|
||||||
t->flags |= Kernel::Page::FRAME
|
t->flags |= Iris::Page::FRAME
|
||||||
kPage_arch_update_mapping (t)
|
kPage_arch_update_mapping (t)
|
||||||
break
|
break
|
||||||
case Kernel::Page::SET_FLAGS & REQUEST_MASK:
|
case Iris::Page::SET_FLAGS & REQUEST_MASK:
|
||||||
if cmd & Kernel::Page::READONLY:
|
if cmd & Iris::Page::READONLY:
|
||||||
dpanic (0, "setting page flags denied")
|
dpanic (0, "setting page flags denied")
|
||||||
reply_num (Kernel::ERR_WRITE_DENIED)
|
reply_num (Iris::ERR_WRITE_DENIED)
|
||||||
return
|
return
|
||||||
// Always refuse to set reserved flags.
|
// 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.
|
// Remember the old flags.
|
||||||
unsigned old = page->flags
|
unsigned old = page->flags
|
||||||
// Compute the new flags.
|
// Compute the new flags.
|
||||||
page->flags = (page->flags & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
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 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.
|
// Decrease the use counter in any case.
|
||||||
page->address_space->unuse ()
|
page->address_space->unuse ()
|
||||||
page_check_payment (page)
|
page_check_payment (page)
|
||||||
|
|
||||||
// If we start paying, increase the use counter.
|
// 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():
|
if !page->address_space->use():
|
||||||
dpanic (0, "cannot pay for frame")
|
dpanic (0, "cannot pay for frame")
|
||||||
// If it doesn't work, refuse to set the flag, and refuse to allocate a 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.
|
// However, if there already was a frame, keep it.
|
||||||
if old & Kernel::Page::FRAME:
|
if old & Iris::Page::FRAME:
|
||||||
page->flags |= Kernel::Page::FRAME
|
page->flags |= Iris::Page::FRAME
|
||||||
|
|
||||||
// If we want a frame, see if we can get it.
|
// If we want a frame, see if we can get it.
|
||||||
if ~old & page->flags & Kernel::Page::FRAME:
|
if ~old & page->flags & Iris::Page::FRAME:
|
||||||
if ~page->flags & Kernel::Page::PAYING:
|
if ~page->flags & Iris::Page::PAYING:
|
||||||
dpanic (0, "cannot have frame without paying")
|
dpanic (0, "cannot have frame without paying")
|
||||||
page->flags &= ~Kernel::Page::FRAME
|
page->flags &= ~Iris::Page::FRAME
|
||||||
else:
|
else:
|
||||||
page->frame = page->address_space->zalloc ()
|
page->frame = page->address_space->zalloc ()
|
||||||
kPage_arch_update_mapping (page)
|
kPage_arch_update_mapping (page)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid page operation")
|
dpanic (0, "invalid page operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
if page->flags > 0x7f:
|
if page->flags > 0x7f:
|
||||||
dpanic (page->flags, "weird output from page operation")
|
dpanic (page->flags, "weird output from page operation")
|
||||||
@ -755,12 +785,12 @@ static void print_cap (kCapRef cap, kCapRef self):
|
|||||||
else:
|
else:
|
||||||
kdebug (']')
|
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
|
kCaps *caps = (kCapsP)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::Caps::GET & REQUEST_MASK:
|
case Iris::Caps::GET & REQUEST_MASK:
|
||||||
if c->data[1].l >= caps->size:
|
if c->data[1].l >= caps->size:
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
kdebug_num ((unsigned)caps)
|
kdebug_num ((unsigned)caps)
|
||||||
kdebug (" size: ")
|
kdebug (" size: ")
|
||||||
kdebug_num (caps->size)
|
kdebug_num (caps->size)
|
||||||
@ -782,10 +812,10 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
#endif
|
#endif
|
||||||
reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities)
|
reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities)
|
||||||
return
|
return
|
||||||
case Kernel::Caps::GET_SIZE & REQUEST_MASK:
|
case Iris::Caps::GET_SIZE & REQUEST_MASK:
|
||||||
reply_num (caps->size)
|
reply_num (caps->size)
|
||||||
return
|
return
|
||||||
case Kernel::Caps::SET & REQUEST_MASK:
|
case Iris::Caps::SET & REQUEST_MASK:
|
||||||
if c->data[1].l >= caps->size:
|
if c->data[1].l >= caps->size:
|
||||||
dpanic (0, "invalid index for set caps")
|
dpanic (0, "invalid index for set caps")
|
||||||
return
|
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_num (caps->caps[c->data[1].l].protected_data.l)
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
return
|
return
|
||||||
case Kernel::Caps::TRUNCATE & REQUEST_MASK:
|
case Iris::Caps::TRUNCATE & REQUEST_MASK:
|
||||||
dpanic (0, "truncate caps is not implemented yet.")
|
dpanic (0, "truncate caps is not implemented yet.")
|
||||||
return
|
return
|
||||||
case Kernel::Caps::PRINT & REQUEST_MASK:
|
case Iris::Caps::PRINT & REQUEST_MASK:
|
||||||
if c->data[1].l >= caps->size:
|
if c->data[1].l >= caps->size:
|
||||||
dpanic (0, "invalid caps for print")
|
dpanic (0, "invalid caps for print")
|
||||||
return
|
return
|
||||||
@ -839,12 +869,12 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (cmd, "invalid caps operation")
|
dpanic (cmd, "invalid caps operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
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
|
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])
|
list->owner.clone (0, c->arg, c->copy[1])
|
||||||
return
|
return
|
||||||
kListitem *item
|
kListitem *item
|
||||||
@ -853,81 +883,81 @@ static void list_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
|||||||
else:
|
else:
|
||||||
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_LISTITEM:
|
if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_LISTITEM:
|
||||||
dpanic (0, "invalid request for list: arg is no listitem")
|
dpanic (0, "invalid request for list: arg is no listitem")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
item = (kListitem *)c->arg->protected_data.l
|
item = (kListitem *)c->arg->protected_data.l
|
||||||
if item->list != list:
|
if item->list != list:
|
||||||
dpanic (0, "item list is not equal to called object")
|
dpanic (0, "item list is not equal to called object")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::List::GET_NEXT & REQUEST_MASK:
|
case Iris::List::GET_NEXT & REQUEST_MASK:
|
||||||
if !item:
|
if !item:
|
||||||
item = list->first_listitem
|
item = list->first_listitem
|
||||||
else:
|
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")
|
dpanic (0, "trying to get next listitem with insufficient rights")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
item = item->next_item
|
item = item->next_item
|
||||||
if !item:
|
if !item:
|
||||||
reply_num (0)
|
reply_num (0)
|
||||||
return
|
return
|
||||||
reply_cap (CAPTYPE_LISTITEM | Kernel::Listitem::LIST, (unsigned)item, &item->refs)
|
reply_cap (CAPTYPE_LISTITEM | Iris::Listitem::LIST, (unsigned)item, &item->refs)
|
||||||
return
|
return
|
||||||
case Kernel::List::ADD_ITEM & REQUEST_MASK:
|
case Iris::List::ADD_ITEM & REQUEST_MASK:
|
||||||
if !item:
|
if !item:
|
||||||
dpanic (0, "invalid request: no listitem for List::ADD_ITEM")
|
dpanic (0, "invalid request: no listitem for List::ADD_ITEM")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
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")
|
dpanic (0, "trying to add listitem with insufficient rights")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
((kListitem *)c->arg->protected_data.l)->add (list)
|
((kListitem *)c->arg->protected_data.l)->add (list)
|
||||||
break
|
break
|
||||||
case Kernel::List::GET_INFO & REQUEST_MASK:
|
case Iris::List::GET_INFO & REQUEST_MASK:
|
||||||
if !item:
|
if !item:
|
||||||
dpanic (0, "no item for List::GET_INFO")
|
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
|
return
|
||||||
reply_num (item->info)
|
reply_num (item->info)
|
||||||
return
|
return
|
||||||
case Kernel::List::SET_INFO & REQUEST_MASK:
|
case Iris::List::SET_INFO & REQUEST_MASK:
|
||||||
if !item:
|
if !item:
|
||||||
dpanic (0, "no item for List::SET_INFO")
|
dpanic (0, "no item for List::SET_INFO")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
item->info = c->data[1]
|
item->info = c->data[1]
|
||||||
break
|
break
|
||||||
case Kernel::List::GET_CAP & REQUEST_MASK:
|
case Iris::List::GET_CAP & REQUEST_MASK:
|
||||||
if !item:
|
if !item:
|
||||||
dpanic (0, "no item for List::GET_CAP")
|
dpanic (0, "no item for List::GET_CAP")
|
||||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kCapability *cap = item->target.cap (0)
|
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)
|
reply_cap ((unsigned)cap->target, cap->protected_data, ((unsigned)cap->target & ~KERNEL_MASK) == 0 ? &((kObject *)cap->target)->refs : &cap->target->capabilities)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid list operation")
|
dpanic (0, "invalid list operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
reply_num (0)
|
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
|
kListitem *item = (kListitemP)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Kernel::Listitem::CLEAR & REQUEST_MASK:
|
case Iris::Listitem::CLEAR & REQUEST_MASK:
|
||||||
// Disable linked capability.
|
// Disable linked capability.
|
||||||
item->add (NULL)
|
item->add (NULL)
|
||||||
break
|
break
|
||||||
case Kernel::Listitem::SET_CAP & REQUEST_MASK:
|
case Iris::Listitem::SET_CAP & REQUEST_MASK:
|
||||||
// Set linked capability.
|
// Set linked capability.
|
||||||
item->target.clone (0, c->arg, c->copy[1])
|
item->target.clone (0, c->arg, c->copy[1])
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
dpanic (0, "invalid listitem operation")
|
dpanic (0, "invalid listitem operation")
|
||||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
reply_num (0)
|
reply_num (0)
|
||||||
|
|
||||||
@ -936,18 +966,18 @@ static void kill_reply (kReceiver *r):
|
|||||||
while cap.valid ():
|
while cap.valid ():
|
||||||
kCapability *c = cap.deref ()
|
kCapability *c = cap.deref ()
|
||||||
cap = c->sibling_next
|
cap = c->sibling_next
|
||||||
if (unsigned)c->target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY):
|
if (unsigned)c->target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY):
|
||||||
c->invalidate ()
|
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:
|
// Kernel calling convention:
|
||||||
// data[0].l is the request.
|
// data[0].l is the request.
|
||||||
// reply is the reply capability, or (for call capabilities) the target to call.
|
// reply is the reply capability, or (for call capabilities) the target to call.
|
||||||
// other parameters' meanings depend on the operation.
|
// 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.
|
// This is a call capability. reply is the capability to call.
|
||||||
kReceiver *owner = (kReceiver *)protected_data.l
|
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:
|
if must_wait:
|
||||||
old_current->wait ()
|
old_current->wait ()
|
||||||
if !reply_target:
|
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.
|
// This is a user-implemented object. Create a real reply capability.
|
||||||
kReceiver *call_target = reply_target
|
kReceiver *call_target = reply_target
|
||||||
c->reply = kCapRef (&reply_caps, 0)
|
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
|
c->copy[0] = true
|
||||||
call_target->send_message (reply_protected, c)
|
call_target->send_message (reply_protected, c)
|
||||||
c->reply->invalidate ()
|
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.
|
// Reply capability: destroy all before invoke.
|
||||||
kReceiver *r = (kReceiver *)reply_protected.l
|
kReceiver *r = (kReceiver *)reply_protected.l
|
||||||
kill_reply (r)
|
kill_reply (r)
|
||||||
@ -981,7 +1011,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
|
|||||||
return
|
return
|
||||||
if must_wait:
|
if must_wait:
|
||||||
old_current->wait ()
|
old_current->wait ()
|
||||||
if target == (CAPTYPE_RECEIVER | Kernel::Receiver::REPLY):
|
if target == (CAPTYPE_RECEIVER | Iris::Receiver::REPLY):
|
||||||
// This is a reply capability.
|
// This is a reply capability.
|
||||||
kReceiver *r = (kReceiver *)protected_data.l
|
kReceiver *r = (kReceiver *)protected_data.l
|
||||||
kill_reply (r)
|
kill_reply (r)
|
||||||
@ -1026,7 +1056,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
|
|||||||
return
|
return
|
||||||
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:
|
if dbg_code.l && old_current->id != 1:
|
||||||
log_message ("invoke", (unsigned)target, protected_data.l, c)
|
log_message ("invoke", (unsigned)target, protected_data.l, c)
|
||||||
if (unsigned)target & ~KERNEL_MASK:
|
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
|
reply_protected = c->reply->protected_data
|
||||||
else:
|
else:
|
||||||
reply_target = NULL
|
reply_target = NULL
|
||||||
|
reply_protected.l = 0
|
||||||
kernel_invoke ((unsigned)target, protected_data, c)
|
kernel_invoke ((unsigned)target, protected_data, c)
|
||||||
|
28
iris.hhp
28
iris.hhp
@ -53,11 +53,12 @@
|
|||||||
// Master capabilities can create others.
|
// Master capabilities can create others.
|
||||||
#define CAP_MASTER_CREATE (1 << 31)
|
#define CAP_MASTER_CREATE (1 << 31)
|
||||||
|
|
||||||
#define __receiver_num 0
|
#define __caps_num 0
|
||||||
#define __thread_num 1
|
#define __receiver_num 1
|
||||||
#define __memory_num 2
|
#define __thread_num 2
|
||||||
#define __call_num 3
|
#define __memory_num 3
|
||||||
#define __parent_num 4
|
#define __call_num 4
|
||||||
|
#define __parent_num 5
|
||||||
|
|
||||||
// If this flag is set in a capability, it is copied instead of mapped.
|
// 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.
|
// 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.
|
// This constant signifies that no capability is passed.
|
||||||
#define CAP_NONE (~CAP_COPY)
|
#define CAP_NONE (~CAP_COPY)
|
||||||
|
|
||||||
struct Parent
|
namespace Iris:
|
||||||
|
struct Parent
|
||||||
namespace Kernel:
|
|
||||||
enum Exception_code:
|
enum Exception_code:
|
||||||
NO_ERROR
|
NO_ERROR
|
||||||
ERR_WRITE_DENIED
|
ERR_WRITE_DENIED
|
||||||
@ -138,6 +138,7 @@ namespace Kernel:
|
|||||||
Cap alloc_cap ()
|
Cap alloc_cap ()
|
||||||
void free_slot (unsigned slot)
|
void free_slot (unsigned slot)
|
||||||
void free_cap (Cap cap)
|
void free_cap (Cap cap)
|
||||||
|
extern bool enable_debug
|
||||||
|
|
||||||
struct Cap:
|
struct Cap:
|
||||||
unsigned code
|
unsigned code
|
||||||
@ -161,6 +162,7 @@ namespace Kernel:
|
|||||||
Num protected_data
|
Num protected_data
|
||||||
Cap reply, arg
|
Cap reply, arg
|
||||||
|
|
||||||
|
extern Caps my_caps
|
||||||
extern Receiver my_receiver
|
extern Receiver my_receiver
|
||||||
extern Thread my_thread
|
extern Thread my_thread
|
||||||
extern Memory my_memory
|
extern Memory my_memory
|
||||||
@ -280,7 +282,7 @@ namespace Kernel:
|
|||||||
Cap create_capability (Num protected_data):
|
Cap create_capability (Num protected_data):
|
||||||
icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
|
icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
Num get_protected (Kernel::Cap target):
|
Num get_protected (Cap target):
|
||||||
return ocall (target, CAP_MASTER_DIRECT | GET_PROTECTED)
|
return ocall (target, CAP_MASTER_DIRECT | GET_PROTECTED)
|
||||||
Num get_reply_protected_data ():
|
Num get_reply_protected_data ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
|
return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
|
||||||
@ -455,8 +457,8 @@ namespace Kernel:
|
|||||||
PHYSICAL = 0x20
|
PHYSICAL = 0x20
|
||||||
// This is a read-only flag, saying if this is uncachable memory.
|
// This is a read-only flag, saying if this is uncachable memory.
|
||||||
UNCACHED = 0x40
|
UNCACHED = 0x40
|
||||||
void share (Cap target, unsigned flags):
|
void share (Cap target, unsigned flags = 0):
|
||||||
ocall (target, Kernel::Num (CAP_MASTER_DIRECT | SHARE, flags))
|
ocall (target, Num (CAP_MASTER_DIRECT | SHARE, flags))
|
||||||
unsigned get_flags ():
|
unsigned get_flags ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_FLAGS).l
|
return call (CAP_MASTER_DIRECT | GET_FLAGS).l
|
||||||
bool set_flags (unsigned new_flags, unsigned mask):
|
bool set_flags (unsigned new_flags, unsigned mask):
|
||||||
@ -576,7 +578,7 @@ namespace Kernel:
|
|||||||
Cap ().call ()
|
Cap ().call ()
|
||||||
|
|
||||||
// The start function has this prototype (there is no main function).
|
// The start function has this prototype (there is no main function).
|
||||||
Kernel::Num start ()
|
Iris::Num start ()
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
#if 1
|
#if 1
|
||||||
@ -596,7 +598,7 @@ static void kdebug_num (unsigned n, unsigned digits = 8):
|
|||||||
for i = 0; i < digits; ++i:
|
for i = 0; i < digits; ++i:
|
||||||
kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf])
|
kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf])
|
||||||
|
|
||||||
namespace Kernel:
|
namespace Iris:
|
||||||
inline void panic (unsigned code, char const *message = NULL):
|
inline void panic (unsigned code, char const *message = NULL):
|
||||||
if message:
|
if message:
|
||||||
kdebug (message)
|
kdebug (message)
|
||||||
|
32
kernel.hhp
32
kernel.hhp
@ -75,7 +75,7 @@ struct kCapRef:
|
|||||||
kCapRef (kCapsP c, unsigned i) : caps (c), index (i):
|
kCapRef (kCapsP c, unsigned i) : caps (c), index (i):
|
||||||
kCapRef () : caps (NULL), index (~0):
|
kCapRef () : caps (NULL), index (~0):
|
||||||
inline void clone (kCapRef source, bool copy)
|
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:
|
struct kObject:
|
||||||
kCapRef refs
|
kCapRef refs
|
||||||
@ -97,7 +97,7 @@ bool kObject::is_free ():
|
|||||||
|
|
||||||
struct kCapability : public kObject:
|
struct kCapability : public kObject:
|
||||||
struct Context:
|
struct Context:
|
||||||
Kernel::Num data[2]
|
Iris::Num data[2]
|
||||||
kCapRef reply
|
kCapRef reply
|
||||||
kCapRef arg
|
kCapRef arg
|
||||||
bool copy[2]
|
bool copy[2]
|
||||||
@ -105,7 +105,7 @@ struct kCapability : public kObject:
|
|||||||
kCapRef parent
|
kCapRef parent
|
||||||
kCapRef children
|
kCapRef children
|
||||||
kCapRef sibling_prev, sibling_next
|
kCapRef sibling_prev, sibling_next
|
||||||
Kernel::Num protected_data
|
Iris::Num protected_data
|
||||||
inline void invoke (kCapability::Context *c)
|
inline void invoke (kCapability::Context *c)
|
||||||
void invalidate ()
|
void invalidate ()
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ struct kThread : public kObject:
|
|||||||
void wait ()
|
void wait ()
|
||||||
void unwait ()
|
void unwait ()
|
||||||
bool is_waiting ():
|
bool is_waiting ():
|
||||||
return flags & Kernel::Thread::WAITING
|
return flags & Iris::Thread::WAITING
|
||||||
kCapRef find_capability (unsigned code, bool *copy)
|
kCapRef find_capability (unsigned code, bool *copy)
|
||||||
|
|
||||||
struct kReceiver : public kObject:
|
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.
|
// The message queue. kMessages are added at the tail, and removed at the front.
|
||||||
kMessageP messages
|
kMessageP messages
|
||||||
kMessageP last_message
|
kMessageP last_message
|
||||||
Kernel::Num reply_protected_data
|
Iris::Num reply_protected_data
|
||||||
bool protected_only
|
bool protected_only
|
||||||
// This limit is for messages stored in its address space. There is unlimited space if senders provide it.
|
// This limit is for messages stored in its address space. There is unlimited space if senders provide it.
|
||||||
unsigned queue_limit, queue_use
|
unsigned queue_limit, queue_use
|
||||||
void own (kThreadP o)
|
void own (kThreadP o)
|
||||||
void orphan ()
|
void orphan ()
|
||||||
bool try_deliver ()
|
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)
|
void check (unsigned line)
|
||||||
|
|
||||||
struct kPage : public kObject:
|
struct kPage : public kObject:
|
||||||
@ -177,7 +177,7 @@ struct kCaps : public kObject:
|
|||||||
unsigned size
|
unsigned size
|
||||||
kCapability caps[1]
|
kCapability caps[1]
|
||||||
inline kCapability *cap (unsigned idx)
|
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 clone (unsigned index, kCapRef source, bool copy)
|
||||||
void init (unsigned size)
|
void init (unsigned size)
|
||||||
|
|
||||||
@ -185,8 +185,8 @@ struct kCaps : public kObject:
|
|||||||
#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1)
|
#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1)
|
||||||
|
|
||||||
struct kMessage : public kObject:
|
struct kMessage : public kObject:
|
||||||
Kernel::Num protected_data
|
Iris::Num protected_data
|
||||||
Kernel::Num data[2]
|
Iris::Num data[2]
|
||||||
// This is a real Caps of two elements, not a link.
|
// This is a real Caps of two elements, not a link.
|
||||||
kCaps caps
|
kCaps caps
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ struct kList : public kObject:
|
|||||||
struct kListitem : public kObject:
|
struct kListitem : public kObject:
|
||||||
kListP list
|
kListP list
|
||||||
kListitemP prev_item, next_item
|
kListitemP prev_item, next_item
|
||||||
Kernel::Num info
|
Iris::Num info
|
||||||
// This is a real Caps of one element, not a link.
|
// This is a real Caps of one element, not a link.
|
||||||
kCaps target
|
kCaps target
|
||||||
void add (kList *l)
|
void add (kList *l)
|
||||||
@ -257,7 +257,7 @@ extern "C":
|
|||||||
#define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m))
|
#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 = "")
|
void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
EXTERN Kernel::Num dbg_code
|
EXTERN Iris::Num dbg_code
|
||||||
EXTERN unsigned dbg_buffer[32]
|
EXTERN unsigned dbg_buffer[32]
|
||||||
EXTERN unsigned dbg_buffer_head
|
EXTERN unsigned dbg_buffer_head
|
||||||
static void dbg_push (unsigned n):
|
static void dbg_push (unsigned n):
|
||||||
@ -293,7 +293,11 @@ EXTERN kThreadP current, old_current
|
|||||||
EXTERN bool do_schedule, must_wait
|
EXTERN bool do_schedule, must_wait
|
||||||
// reply_caps is the source of a receiver-generated reply capability.
|
// 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.
|
// 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 kCaps reply_caps, replied_caps
|
||||||
|
EXTERN kReceiver *reply_target
|
||||||
|
EXTERN Iris::Num reply_protected
|
||||||
|
|
||||||
// Defined in memory.ccp
|
// Defined in memory.ccp
|
||||||
unsigned init_memory (unsigned mem)
|
unsigned init_memory (unsigned mem)
|
||||||
@ -303,11 +307,11 @@ unsigned phys_alloc (unsigned num)
|
|||||||
void phys_free (unsigned page, unsigned num)
|
void phys_free (unsigned page, unsigned num)
|
||||||
|
|
||||||
// Defind in invoke.ccp
|
// 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.
|
// Defined by architecture-specific files.
|
||||||
void kThread_arch_init (kThread *thread)
|
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)
|
unsigned *kThread_arch_info (kThread *thread, unsigned num)
|
||||||
void kMemory_arch_init (kMemory *mem)
|
void kMemory_arch_init (kMemory *mem)
|
||||||
void kMemory_arch_free (kMemory *mem)
|
void kMemory_arch_free (kMemory *mem)
|
||||||
@ -336,7 +340,7 @@ kCapability *kCapRef::deref ():
|
|||||||
return caps ? caps->cap (index) : NULL
|
return caps ? caps->cap (index) : NULL
|
||||||
void kCapRef::clone (kCapRef source, bool copy):
|
void kCapRef::clone (kCapRef source, bool copy):
|
||||||
caps->clone (index, source, 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 ():
|
if valid ():
|
||||||
deref ()->invalidate ()
|
deref ()->invalidate ()
|
||||||
caps->set (index, target, pdata, parent, parent_ptr)
|
caps->set (index, target, pdata, parent, parent_ptr)
|
||||||
|
@ -172,6 +172,8 @@ void phys_free (unsigned page, unsigned num):
|
|||||||
kFreePages *p
|
kFreePages *p
|
||||||
for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
|
for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
if p == p->next:
|
||||||
|
dpanic (0, "page is its own next")
|
||||||
// The new block should be inserted directly after p.
|
// The new block should be inserted directly after p.
|
||||||
if (unsigned)p->next == page + size:
|
if (unsigned)p->next == page + size:
|
||||||
// It can be merged with the block after it: do that.
|
// It can be merged with the block after it: do that.
|
||||||
|
@ -38,7 +38,7 @@ void kPage_arch_init (kPage *page):
|
|||||||
page->arch.prev_mapped = NULL
|
page->arch.prev_mapped = NULL
|
||||||
page->arch.next_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[0] = data[0].l
|
||||||
thread->arch.a[1] = data[0].h
|
thread->arch.a[1] = data[0].h
|
||||||
thread->arch.a[2] = data[1].l
|
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")
|
//kdebug ("not mapping because there is no frame\n")
|
||||||
return 0
|
return 0
|
||||||
unsigned flags
|
unsigned flags
|
||||||
if page->flags & Kernel::Page::UNCACHED:
|
if page->flags & Iris::Page::UNCACHED:
|
||||||
flags = 0x10 | 0x2
|
flags = 0x10 | 0x2
|
||||||
else:
|
else:
|
||||||
// 18 is write-back cache; 00 is write-through cache.
|
// 18 is write-back cache; 00 is write-through cache.
|
||||||
flags = 0x18 | 0x2
|
flags = 0x18 | 0x2
|
||||||
if ~page->flags & Kernel::Page::MAPPED_READONLY:
|
if ~page->flags & Iris::Page::MAPPED_READONLY:
|
||||||
flags |= 0x4
|
flags |= 0x4
|
||||||
return ((page->frame & ~0x80000000) >> 6) | flags
|
return ((page->frame & ~0x80000000) >> 6) | flags
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ static void init_idle ():
|
|||||||
idle.schedule_next = NULL
|
idle.schedule_next = NULL
|
||||||
idle.address_space = &idle_memory
|
idle.address_space = &idle_memory
|
||||||
idle.refs.reset ()
|
idle.refs.reset ()
|
||||||
idle.flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV
|
idle.flags = Iris::Thread::RUNNING | Iris::Thread::PRIV
|
||||||
// initialize idle_memory.
|
// initialize idle_memory.
|
||||||
idle_memory.prev = NULL
|
idle_memory.prev = NULL
|
||||||
idle_memory.next = NULL
|
idle_memory.next = NULL
|
||||||
@ -52,7 +52,7 @@ static void init_idle ():
|
|||||||
idle_page.prev = NULL
|
idle_page.prev = NULL
|
||||||
idle_page.next = NULL
|
idle_page.next = NULL
|
||||||
idle_page.frame = 0x80000000
|
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.refs.reset ()
|
||||||
idle_page.address_space = NULL
|
idle_page.address_space = NULL
|
||||||
current = &idle
|
current = &idle
|
||||||
@ -147,7 +147,7 @@ static void init_threads ():
|
|||||||
return
|
return
|
||||||
thread->pc = header->e_entry
|
thread->pc = header->e_entry
|
||||||
thread->sp = 0x80000000
|
thread->sp = 0x80000000
|
||||||
unsigned *used = (unsigned *)mem->zalloc ()
|
kPage **used = (kPage **)mem->zalloc ()
|
||||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||||
Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
|
Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
|
||||||
if ~shdr->sh_flags & SHF_ALLOC:
|
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")
|
panic (0, "different pages mapped to one address in intitial file")
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
used[idx] = 1
|
|
||||||
page = mem->alloc_page ()
|
page = mem->alloc_page ()
|
||||||
page->frame = thread_start[i] + (idx << PAGE_BITS)
|
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:
|
if readonly:
|
||||||
page->flags |= Kernel::Page::MAPPED_READONLY
|
page->flags |= Iris::Page::MAPPED_READONLY
|
||||||
if !mem->map (page, p):
|
if !mem->map (page, p):
|
||||||
panic (0x22446688, "unable to map initial page")
|
panic (0x22446688, "unable to map initial page")
|
||||||
return
|
return
|
||||||
@ -200,7 +207,7 @@ static void init_threads ():
|
|||||||
if !page->frame:
|
if !page->frame:
|
||||||
panic (0x02220022, "out of memory");
|
panic (0x02220022, "out of memory");
|
||||||
return
|
return
|
||||||
page->flags = Kernel::Page::PAYING | Kernel::Page::FRAME
|
page->flags = Iris::Page::PAYING | Iris::Page::FRAME
|
||||||
if !mem->map (page, p):
|
if !mem->map (page, p):
|
||||||
panic (0x33557799, "unable to map initial bss page")
|
panic (0x33557799, "unable to map initial bss page")
|
||||||
return
|
return
|
||||||
@ -210,7 +217,7 @@ static void init_threads ():
|
|||||||
kdebug_num (i, 1)
|
kdebug_num (i, 1)
|
||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
else:
|
else:
|
||||||
if page->flags & Kernel::Page::MAPPED_READONLY:
|
if page->flags & Iris::Page::MAPPED_READONLY:
|
||||||
panic (0x20203030, "bss section starts on read-only page")
|
panic (0x20203030, "bss section starts on read-only page")
|
||||||
return
|
return
|
||||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||||
@ -230,7 +237,7 @@ static void init_threads ():
|
|||||||
mem->pfree ((unsigned)used)
|
mem->pfree ((unsigned)used)
|
||||||
kPage *stackpage = mem->alloc_page ()
|
kPage *stackpage = mem->alloc_page ()
|
||||||
stackpage->frame = mem->zalloc ()
|
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):
|
if !stackpage || !mem->map (stackpage, 0x7ffff000):
|
||||||
panic (0x13151719, "unable to map initial stack page")
|
panic (0x13151719, "unable to map initial stack page")
|
||||||
return
|
return
|
||||||
@ -242,11 +249,12 @@ static void init_threads ():
|
|||||||
kReceiver *recv = mem->alloc_receiver ()
|
kReceiver *recv = mem->alloc_receiver ()
|
||||||
recv->owner = thread
|
recv->owner = thread
|
||||||
thread->receivers = recv
|
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 (__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 (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Kernel::Num ((unsigned)thread), kCapRef (), &thread->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 (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Kernel::Num ((unsigned)mem), kCapRef (), &mem->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 (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Kernel::Receiver::CALL), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
|
thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Iris::Num ((unsigned)mem), kCapRef (), &mem->refs)
|
||||||
thread->flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV
|
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:
|
if !i:
|
||||||
first_scheduled = thread
|
first_scheduled = thread
|
||||||
init_receiver = recv
|
init_receiver = recv
|
||||||
|
@ -33,7 +33,7 @@ static kThread *handle_exit ():
|
|||||||
schedule ()
|
schedule ()
|
||||||
if !current:
|
if !current:
|
||||||
current = &idle
|
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")
|
panic (current->flags, "non-scheduled thread running")
|
||||||
if old_current == current:
|
if old_current == current:
|
||||||
return current
|
return current
|
||||||
@ -54,7 +54,7 @@ static kThread *handle_exit ():
|
|||||||
asids[current->address_space->arch.asid] = (unsigned)current->address_space
|
asids[current->address_space->arch.asid] = (unsigned)current->address_space
|
||||||
cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
|
cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)
|
||||||
directory = current->address_space->arch.directory
|
directory = current->address_space->arch.directory
|
||||||
if current->flags & Kernel::Thread::PRIV:
|
if current->flags & Iris::Thread::PRIV:
|
||||||
cp0_set (CP0_STATUS, 0x1000ff13)
|
cp0_set (CP0_STATUS, 0x1000ff13)
|
||||||
else:
|
else:
|
||||||
cp0_set (CP0_STATUS, 0x0000ff13)
|
cp0_set (CP0_STATUS, 0x0000ff13)
|
||||||
@ -69,7 +69,7 @@ kThread *tlb_refill ():
|
|||||||
if !directory:
|
if !directory:
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, 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 ()
|
return handle_exit ()
|
||||||
unsigned EntryHi
|
unsigned EntryHi
|
||||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||||
@ -77,7 +77,7 @@ kThread *tlb_refill ():
|
|||||||
if !t:
|
if !t:
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, 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:
|
else:
|
||||||
// - 2 instead of - 1 means reset bit 0
|
// - 2 instead of - 1 means reset bit 0
|
||||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||||
@ -161,13 +161,22 @@ static void arch_invoke ():
|
|||||||
return
|
return
|
||||||
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
|
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.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[0] = Iris::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[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)
|
target->invoke (&msg)
|
||||||
|
dbg_push (0xfacebeef)
|
||||||
if do_schedule && !must_wait:
|
if do_schedule && !must_wait:
|
||||||
// If the call was to schedule without wait, it isn't done yet.
|
// If the call was to schedule without wait, it isn't done yet.
|
||||||
schedule ()
|
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.
|
// 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
|
current = old_current
|
||||||
|
|
||||||
@ -186,31 +195,31 @@ kThread *exception ():
|
|||||||
// TLB modification.
|
// TLB modification.
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
current->raise (Kernel::ERR_WRITE_DENIED, addr)
|
current->raise (Iris::ERR_WRITE_DENIED, addr)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
// TLB load or instruction fetch.
|
// TLB load or instruction fetch.
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
current->raise (Kernel::ERR_UNMAPPED_READ, addr)
|
current->raise (Iris::ERR_UNMAPPED_READ, addr)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
// TLB store.
|
// TLB store.
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
current->raise (Kernel::ERR_UNMAPPED_WRITE, addr)
|
current->raise (Iris::ERR_UNMAPPED_WRITE, addr)
|
||||||
break
|
break
|
||||||
case 4:
|
case 4:
|
||||||
// Address error load or instruction fetch.
|
// Address error load or instruction fetch.
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, 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
|
break
|
||||||
case 5:
|
case 5:
|
||||||
// Address error store.
|
// Address error store.
|
||||||
unsigned addr
|
unsigned addr
|
||||||
cp0_get (CP0_BAD_V_ADDR, 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
|
break
|
||||||
case 6:
|
case 6:
|
||||||
// Bus error instruction fetch.
|
// Bus error instruction fetch.
|
||||||
@ -229,7 +238,7 @@ kThread *exception ():
|
|||||||
case 9:
|
case 9:
|
||||||
// Breakpoint.
|
// Breakpoint.
|
||||||
#if 0 || defined (NDEBUG)
|
#if 0 || defined (NDEBUG)
|
||||||
//current->raise (Kernel::ERR_BREAKPOINT, 0)
|
//current->raise (Iris::ERR_BREAKPOINT, 0)
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
current->pc += 4
|
current->pc += 4
|
||||||
#endif
|
#endif
|
||||||
@ -251,19 +260,19 @@ kThread *exception ():
|
|||||||
break
|
break
|
||||||
case 10:
|
case 10:
|
||||||
// Reserved instruction.
|
// Reserved instruction.
|
||||||
current->raise (Kernel::ERR_RESERVED_INSTRUCTION, 0)
|
current->raise (Iris::ERR_RESERVED_INSTRUCTION, 0)
|
||||||
break
|
break
|
||||||
case 11:
|
case 11:
|
||||||
// Coprocessor unusable.
|
// Coprocessor unusable.
|
||||||
current->raise (Kernel::ERR_COPROCESSOR_UNUSABLE, 0)
|
current->raise (Iris::ERR_COPROCESSOR_UNUSABLE, 0)
|
||||||
break
|
break
|
||||||
case 12:
|
case 12:
|
||||||
// Arithmetic overflow.
|
// Arithmetic overflow.
|
||||||
current->raise (Kernel::ERR_OVERFLOW, 0)
|
current->raise (Iris::ERR_OVERFLOW, 0)
|
||||||
break
|
break
|
||||||
case 13:
|
case 13:
|
||||||
// Trap.
|
// Trap.
|
||||||
current->raise (Kernel::ERR_TRAP, 0)
|
current->raise (Iris::ERR_TRAP, 0)
|
||||||
break
|
break
|
||||||
case 15:
|
case 15:
|
||||||
// Floating point exception.
|
// Floating point exception.
|
||||||
@ -272,7 +281,7 @@ kThread *exception ():
|
|||||||
case 23:
|
case 23:
|
||||||
// Reference to WatchHi/WatchLo address.
|
// Reference to WatchHi/WatchLo address.
|
||||||
cp0_set0 (CP0_WATCH_LO)
|
cp0_set0 (CP0_WATCH_LO)
|
||||||
current->raise (Kernel::ERR_WATCHPOINT, 0)
|
current->raise (Iris::ERR_WATCHPOINT, 0)
|
||||||
break
|
break
|
||||||
case 24:
|
case 24:
|
||||||
// Machine check.
|
// Machine check.
|
||||||
|
@ -28,12 +28,12 @@ LDFLAGS = --omagic -Ttext $(load)
|
|||||||
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
||||||
boot_sources = mips/init.cc mips/nanonote/board.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
|
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh
|
||||||
boot_threads = init udc
|
boot_threads = bootinit udc
|
||||||
programs = \#nanonote-gpio \#lcd display-emu bsquare display-emu2 ball \#buzzer metronome
|
programs = init gpio lcd display-emu bsquare ball buzzer metronome elfrun
|
||||||
|
|
||||||
all: test
|
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
|
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
|
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/nanonote/threadlist.o: $(addsuffix .elf,$(boot_threads))
|
||||||
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
|
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
|
||||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
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)): TARGET_FLAGS = -I.
|
||||||
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
|
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
|
||||||
$(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL
|
$(addprefix fs/,$(addsuffix .elf,$(programs))): LDFLAGS = -EL
|
||||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
|
$(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
|
source/charset.data: source/charset
|
||||||
$< > $@
|
$< > $@
|
||||||
|
@ -104,14 +104,14 @@
|
|||||||
// Default lcd framebuffer mapping space.
|
// Default lcd framebuffer mapping space.
|
||||||
#define LCD_FRAMEBUFFER_BASE ((unsigned *)0x00015000)
|
#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 <iris.hh>
|
#include <iris.hh>
|
||||||
static void __map_io (unsigned physical, unsigned mapping):
|
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.
|
// false means not cachable; false means don't free when done.
|
||||||
p.alloc_physical (physical, false, false)
|
p.alloc_physical (physical, false, false)
|
||||||
Kernel::my_memory.map (p, mapping)
|
Iris::my_memory.map (p, mapping)
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
|
|
||||||
#define map_cpm() do { __map_io (CPM_PHYSICAL, CPM_BASE); } while (0)
|
#define map_cpm() do { __map_io (CPM_PHYSICAL, CPM_BASE); } while (0)
|
||||||
#define map_intc() do { __map_io (INTC_PHYSICAL, INTC_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
|
// udelay implementation
|
||||||
void cdelay (unsigned cs):
|
void cdelay (unsigned cs):
|
||||||
Kernel::my_receiver.set_alarm (cs + 1)
|
Iris::my_receiver.set_alarm (cs + 1)
|
||||||
Kernel::Cap ().call ()
|
Iris::Cap ().call ()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -105,37 +105,37 @@ void data::poll ():
|
|||||||
case ~1 & 0xffff:
|
case ~1 & 0xffff:
|
||||||
// No event.
|
// No event.
|
||||||
break
|
break
|
||||||
case Directory::GET_SIZE:
|
case Iris::Directory::GET_SIZE:
|
||||||
unsigned long long size = dir.size ()
|
unsigned long long size = dir.size ()
|
||||||
std::cerr << "sending dir size\n"
|
std::cerr << "sending dir size\n"
|
||||||
std::cerr << Directory::GET_SIZE << '\n'
|
std::cerr << Iris::Directory::GET_SIZE << '\n'
|
||||||
char *str = (char *)&size
|
char *str = (char *)&size
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
std::cerr << " " << (unsigned)(str[i] & 0xff)
|
std::cerr << " " << (unsigned)(str[i] & 0xff)
|
||||||
std::cerr << '\n'
|
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
|
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
case Directory::GET_NAME:
|
case Iris::Directory::GET_NAME:
|
||||||
if buffer[1] >= dir.size ():
|
if buffer[1] >= dir.size ():
|
||||||
std::cerr << "invalid file name requested" << std::endl;
|
std::cerr << "invalid file name requested" << std::endl;
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
std::cerr << "sending filename\n"
|
std::cerr << "sending filename " << dir[buffer[1]].full << "\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:
|
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
|
std::cerr << "unable to send name to device: " << usb_strerror () << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
case Directory::LOCK_RO:
|
case Iris::Directory::LOCK_RO:
|
||||||
std::cerr << "lock\n"
|
std::cerr << "lock\n"
|
||||||
lock++
|
lock++
|
||||||
std::cerr << "freezing file list\n"
|
std::cerr << "freezing file list\n"
|
||||||
@ -145,7 +145,7 @@ void data::poll ():
|
|||||||
if !i->name.empty () && i->name[0] != '.':
|
if !i->name.empty () && i->name[0] != '.':
|
||||||
dir.push_back (Name (i->name))
|
dir.push_back (Name (i->name))
|
||||||
continue
|
continue
|
||||||
case Directory::UNLOCK_RO:
|
case Iris::Directory::UNLOCK_RO:
|
||||||
std::cerr << "unlock\n"
|
std::cerr << "unlock\n"
|
||||||
if !lock:
|
if !lock:
|
||||||
std::cerr << "unlocking without lock" << std::endl
|
std::cerr << "unlocking without lock" << std::endl
|
||||||
@ -156,7 +156,7 @@ void data::poll ():
|
|||||||
if !--lock:
|
if !--lock:
|
||||||
dir.clear ()
|
dir.clear ()
|
||||||
continue
|
continue
|
||||||
case String::GET_PAGE:
|
case Iris::String::GET_PAGE:
|
||||||
if buffer[1] >= dir.size ():
|
if buffer[1] >= dir.size ():
|
||||||
std::cerr << "reading invalid file" << std::endl
|
std::cerr << "reading invalid file" << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
@ -178,16 +178,16 @@ void data::poll ():
|
|||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
continue
|
continue
|
||||||
case String::GET_SIZE:
|
case Iris::String::GET_SIZE:
|
||||||
if buffer[1] >= dir.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_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
handle = NULL
|
handle = NULL
|
||||||
return
|
return
|
||||||
unsigned long long size = dir[buffer[1]].content.size ()
|
unsigned long long size = dir[buffer[1]].content.size ()
|
||||||
std::cerr << "sending file size " << size << "\n"
|
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
|
std::cerr << "unable to send size to device: " << usb_strerror () << std::endl
|
||||||
usb_release_interface (handle, 0)
|
usb_release_interface (handle, 0)
|
||||||
usb_close (handle)
|
usb_close (handle)
|
||||||
@ -312,18 +312,18 @@ void data::boot (unsigned entry):
|
|||||||
std::cerr << "(re)booted NanoNote\n"
|
std::cerr << "(re)booted NanoNote\n"
|
||||||
|
|
||||||
static void dump_devices ():
|
static void dump_devices ():
|
||||||
std::cerr << std::hex << "String: " << String::ID
|
std::cerr << std::hex << "String: " << Iris::String::ID
|
||||||
std::cerr << "\nWString: " << WString::ID
|
std::cerr << "\nWString: " << Iris::WString::ID
|
||||||
std::cerr << "\nDevice: " << Device::ID
|
std::cerr << "\nDevice: " << Iris::Device::ID
|
||||||
std::cerr << "\nParent: " << Parent::ID
|
std::cerr << "\nParent: " << Iris::Parent::ID
|
||||||
std::cerr << "\nKeyboard: " << Keyboard::ID
|
std::cerr << "\nKeyboard: " << Iris::Keyboard::ID
|
||||||
std::cerr << "\nBuzzer: " << Buzzer::ID
|
std::cerr << "\nBuzzer: " << Iris::Buzzer::ID
|
||||||
std::cerr << "\nDisplay: " << Display::ID
|
std::cerr << "\nDisplay: " << Iris::Display::ID
|
||||||
std::cerr << "\nSetting: " << Setting::ID
|
std::cerr << "\nSetting: " << Iris::Setting::ID
|
||||||
std::cerr << "\nDirectory: " << Directory::ID
|
std::cerr << "\nDirectory: " << Iris::Directory::ID
|
||||||
std::cerr << "\nWDirectory: " << WDirectory::ID
|
std::cerr << "\nWDirectory: " << Iris::WDirectory::ID
|
||||||
std::cerr << "\nFilesystem: " << Filesystem::ID
|
std::cerr << "\nFilesystem: " << Iris::Filesystem::ID
|
||||||
std::cerr << "\nStream: " << Stream::ID
|
std::cerr << "\nStream: " << Iris::Stream::ID
|
||||||
std::cerr << "\n"
|
std::cerr << "\n"
|
||||||
|
|
||||||
int main (int argc, char **argv):
|
int main (int argc, char **argv):
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread0:
|
thread0:
|
||||||
.incbin "init.elf"
|
.incbin "bootinit.elf"
|
||||||
|
|
||||||
.balign 0x1000
|
.balign 0x1000
|
||||||
thread1:
|
thread1:
|
||||||
|
@ -137,14 +137,14 @@
|
|||||||
// Default lcd framebuffer mapping space.
|
// Default lcd framebuffer mapping space.
|
||||||
#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00021000)
|
#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 <iris.hh>
|
#include <iris.hh>
|
||||||
static void __map_io (unsigned physical, unsigned mapping):
|
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.
|
// false means not cachable; false means don't free when done.
|
||||||
p.alloc_physical (physical, false, false)
|
p.alloc_physical (physical, false, false)
|
||||||
Kernel::my_memory.map (p, mapping)
|
Iris::my_memory.map (p, mapping)
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
|
|
||||||
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
|
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
|
||||||
#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_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__
|
#ifndef __KERNEL__
|
||||||
static __inline__ void cdelay (unsigned ds):
|
static __inline__ void cdelay (unsigned ds):
|
||||||
Kernel::my_receiver.set_alarm (ds * (HZ / 100))
|
Iris::my_receiver.set_alarm (ds * (HZ / 100))
|
||||||
Kernel::Cap ().call (~0)
|
Iris::Cap ().call (~0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
10
panic.ccp
10
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):
|
static void print_addr (char const *t, unsigned addr, bool last = false):
|
||||||
kdebug (t)
|
kdebug (t)
|
||||||
kdebug_num (addr)
|
kdebug_num (addr)
|
||||||
#if 1
|
#if 0
|
||||||
unsigned de = addr >> 21
|
unsigned de = addr >> 21
|
||||||
unsigned te = (addr >> 12) & ((1 << 9) - 1)
|
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]:
|
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_num (((unsigned *)addr)[i])
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
#else
|
#else
|
||||||
kdebug (last ? '\n' : ';')
|
kdebug (last ? "\n" : "; ")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void panic_message (unsigned n, const char *line, char const *name, char const *message):
|
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 (':')
|
||||||
kdebug_num (dbg_code.l)
|
kdebug_num (dbg_code.l)
|
||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
kdebug ("debug buffer:")
|
kdebug ("debug buffer (most recently pushed at end):")
|
||||||
unsigned b = dbg_buffer_head
|
unsigned b = dbg_buffer_head
|
||||||
for unsigned i = 0; i < 16; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
for unsigned j = 0; j < 2; ++j:
|
for unsigned j = 0; j < 4; ++j:
|
||||||
kdebug (' ')
|
kdebug (' ')
|
||||||
kdebug_num (dbg_buffer[b])
|
kdebug_num (dbg_buffer[b])
|
||||||
++b
|
++b
|
||||||
|
81
plan
81
plan
@ -42,3 +42,84 @@ te doen:
|
|||||||
- start programma van filesystem
|
- start programma van filesystem
|
||||||
- nand driver
|
- nand driver
|
||||||
- filesystems met backing store
|
- 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 <name> = <filename> 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 <cap> = <name> (<type> [, <index>]) 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 <name> 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 <cap> use a capability as the system request keyboard.
|
||||||
|
sysreq sysreq
|
||||||
|
|
||||||
|
# give <name> (<type> [, <index>]) = <cap> 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 <name> run a previously loaded program (normally).
|
||||||
|
run emu_lcd
|
||||||
|
run emu_buzzer
|
||||||
|
run emu_keyboard
|
||||||
|
run emu_audio
|
||||||
|
run emu_udc
|
||||||
|
|
||||||
|
# include <name> include a loaded file as another config file.
|
||||||
|
include session
|
||||||
|
|
||||||
|
# loop sit and do nothing (respond to system request).
|
||||||
|
loop
|
||||||
|
16
schedule.ccp
16
schedule.ccp
@ -36,24 +36,24 @@ static void unrun_thread (kThread *thread):
|
|||||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
thread->schedule_next->schedule_prev = thread->schedule_prev
|
||||||
|
|
||||||
void kThread::run ():
|
void kThread::run ():
|
||||||
if flags & Kernel::Thread::RUNNING:
|
if flags & Iris::Thread::RUNNING:
|
||||||
return
|
return
|
||||||
flags |= Kernel::Thread::RUNNING
|
flags |= Iris::Thread::RUNNING
|
||||||
if is_waiting ():
|
if is_waiting ():
|
||||||
return
|
return
|
||||||
run_thread (this)
|
run_thread (this)
|
||||||
|
|
||||||
void kThread::unrun ():
|
void kThread::unrun ():
|
||||||
if !(flags & Kernel::Thread::RUNNING):
|
if !(flags & Iris::Thread::RUNNING):
|
||||||
return
|
return
|
||||||
flags &= ~Kernel::Thread::RUNNING
|
flags &= ~Iris::Thread::RUNNING
|
||||||
if is_waiting ():
|
if is_waiting ():
|
||||||
return
|
return
|
||||||
unrun_thread (this)
|
unrun_thread (this)
|
||||||
|
|
||||||
void kThread::unwait ():
|
void kThread::unwait ():
|
||||||
flags &= ~Kernel::Thread::WAITING
|
flags &= ~Iris::Thread::WAITING
|
||||||
if flags & Kernel::Thread::RUNNING:
|
if flags & Iris::Thread::RUNNING:
|
||||||
run_thread (this)
|
run_thread (this)
|
||||||
|
|
||||||
static void alarm_tick (kReceiver *recv):
|
static void alarm_tick (kReceiver *recv):
|
||||||
@ -73,9 +73,9 @@ static void alarm_tick (kReceiver *recv):
|
|||||||
--recv->alarm_count
|
--recv->alarm_count
|
||||||
|
|
||||||
void kThread::wait ():
|
void kThread::wait ():
|
||||||
if flags & Kernel::Thread::RUNNING:
|
if flags & Iris::Thread::RUNNING:
|
||||||
unrun_thread (this)
|
unrun_thread (this)
|
||||||
flags |= Kernel::Thread::WAITING
|
flags |= Iris::Thread::WAITING
|
||||||
// Try to receive a message from a kReceiver immediately.
|
// Try to receive a message from a kReceiver immediately.
|
||||||
for kReceiver *r = receivers; r; r = r->next_owned:
|
for kReceiver *r = receivers; r; r = r->next_owned:
|
||||||
if r->try_deliver ():
|
if r->try_deliver ():
|
||||||
|
@ -33,16 +33,16 @@ void ball (int x, int y, unsigned colour):
|
|||||||
continue
|
continue
|
||||||
framebuffer[ty * 320 + tx] = (colour)
|
framebuffer[ty * 320 + tx] = (colour)
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
int colour = 0x3f30ff
|
int colour = 0x3f30ff
|
||||||
framebuffer = (unsigned *)0x15000
|
framebuffer = (unsigned *)0x15000
|
||||||
Display display = Kernel::my_parent.get_device <Display> (0x10000)
|
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10000)
|
||||||
int x = r, y = r, dx = 3, dy = 0
|
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:
|
while true:
|
||||||
display.set_eof_cb (eof)
|
display.set_eof_cb (eof)
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
ball (x, y, 0)
|
ball (x, y, 0)
|
||||||
x += dx
|
x += dx
|
||||||
y += dy
|
y += dy
|
||||||
|
@ -32,16 +32,16 @@ void square (int x, int y, bool print):
|
|||||||
continue
|
continue
|
||||||
framebuffer[ty * 320 + tx] = (print ? colour : 0)
|
framebuffer[ty * 320 + tx] = (print ? colour : 0)
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
colour = 0xffff00
|
colour = 0xffff00
|
||||||
framebuffer = (unsigned *)0x15000
|
framebuffer = (unsigned *)0x15000
|
||||||
Display display = Kernel::my_parent.get_device <Display> (0x10001)
|
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10001)
|
||||||
int x = r, y = r, dx = 3, dy = 3
|
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:
|
while true:
|
||||||
display.set_eof_cb (eof)
|
display.set_eof_cb (eof)
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
square (x, y, false)
|
square (x, y, false)
|
||||||
x += dx
|
x += dx
|
||||||
y += dy
|
y += dy
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
class DevBuzzer:
|
class DevBuzzer:
|
||||||
static unsigned const pwm = 4
|
static unsigned const pwm = 4
|
||||||
Kernel::Cap event
|
Iris::Cap event
|
||||||
bool is_beeping
|
bool is_beeping
|
||||||
public:
|
public:
|
||||||
DevBuzzer ():
|
DevBuzzer ():
|
||||||
@ -36,9 +36,9 @@ class DevBuzzer:
|
|||||||
return
|
return
|
||||||
tcu_stop_counter (pwm)
|
tcu_stop_counter (pwm)
|
||||||
event.invoke ()
|
event.invoke ()
|
||||||
Kernel::free_cap (event)
|
Iris::free_cap (event)
|
||||||
is_beeping = false
|
is_beeping = false
|
||||||
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
|
void beep (unsigned freq, unsigned ms, Iris::Cap cb):
|
||||||
stop ()
|
stop ()
|
||||||
event = cb
|
event = cb
|
||||||
unsigned full = JZ_EXTAL / 64 / freq
|
unsigned full = JZ_EXTAL / 64 / freq
|
||||||
@ -46,37 +46,37 @@ class DevBuzzer:
|
|||||||
tcu_set_half_data (pwm, full / 2)
|
tcu_set_half_data (pwm, full / 2)
|
||||||
tcu_set_count (pwm, 0)
|
tcu_set_count (pwm, 0)
|
||||||
tcu_start_counter (pwm)
|
tcu_start_counter (pwm)
|
||||||
Kernel::my_receiver.set_alarm (ms * HZ / 1000)
|
Iris::my_receiver.set_alarm (ms * HZ / 1000)
|
||||||
is_beeping = true
|
is_beeping = true
|
||||||
|
|
||||||
enum codes:
|
enum codes:
|
||||||
BUZZER = 32
|
BUZZER = 32
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
map_tcu ()
|
map_tcu ()
|
||||||
|
|
||||||
DevBuzzer buzzer
|
DevBuzzer buzzer
|
||||||
|
|
||||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
Iris::Device dev = Iris::my_receiver.create_capability (BUZZER)
|
||||||
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
|
Iris::my_parent.provide_device <Iris::Buzzer> (dev.copy ())
|
||||||
Kernel::free_cap (dev)
|
Iris::free_cap (dev)
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
unsigned user (~0)
|
unsigned user (~0)
|
||||||
unsigned next_user (0)
|
unsigned next_user (0)
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Iris::recv.protected_data.h:
|
||||||
case ~0:
|
case ~0:
|
||||||
// Alarm.
|
// Alarm.
|
||||||
buzzer.stop ()
|
buzzer.stop ()
|
||||||
break
|
break
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case BUZZER:
|
case BUZZER:
|
||||||
// Buzzer device control request.
|
// Buzzer device control request.
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Device::host (BUZZER, user, reply, arg)
|
Iris::Device::host (BUZZER, user, reply, arg)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("invalid buzzer request\n")
|
kdebug ("invalid buzzer request\n")
|
||||||
@ -84,22 +84,22 @@ Kernel::Num start ():
|
|||||||
break
|
break
|
||||||
case BUZZER:
|
case BUZZER:
|
||||||
// Buzzer device user request.
|
// Buzzer device user request.
|
||||||
if Kernel::recv.protected_data.l != user:
|
if Iris::recv.protected_data.l != user:
|
||||||
kdebug ("invalid user requesting buzzer\n")
|
kdebug ("invalid user requesting buzzer\n")
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Buzzer::BEEP:
|
case Iris::Buzzer::BEEP:
|
||||||
// Volume is not used by this buzzer.
|
// Volume is not used by this buzzer.
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
|
buzzer.beep (Iris::recv.data[1].l, Iris::recv.data[1].h, arg)
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Buzzer::STOP:
|
case Iris::Buzzer::STOP:
|
||||||
buzzer.stop ()
|
buzzer.stop ()
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("Buzzer: other\n")
|
kdebug ("Buzzer: other\n")
|
||||||
@ -107,5 +107,5 @@ Kernel::Num start ():
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("Buzzer: unknown num: ")
|
kdebug ("Buzzer: unknown num: ")
|
||||||
kdebug_num (Kernel::recv.protected_data.h)
|
kdebug_num (Iris::recv.protected_data.h)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
@ -29,7 +29,9 @@ static unsigned __slots, __caps
|
|||||||
static list *__slot_admin, *__cap_admin
|
static list *__slot_admin, *__cap_admin
|
||||||
static list *__first_free_slot, *__first_free_cap
|
static list *__first_free_slot, *__first_free_cap
|
||||||
|
|
||||||
namespace Kernel:
|
namespace Iris:
|
||||||
|
bool enable_debug
|
||||||
|
Caps my_caps
|
||||||
Receiver my_receiver
|
Receiver my_receiver
|
||||||
Thread my_thread
|
Thread my_thread
|
||||||
Memory my_memory
|
Memory my_memory
|
||||||
@ -44,6 +46,8 @@ namespace Kernel:
|
|||||||
used[i] = true
|
used[i] = true
|
||||||
unsigned num = 0
|
unsigned num = 0
|
||||||
for list *i = __first_free_cap; i; i = i->next:
|
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
|
used[i - __cap_admin] = false
|
||||||
++num
|
++num
|
||||||
kdebug_num (num, 2)
|
kdebug_num (num, 2)
|
||||||
@ -54,6 +58,9 @@ namespace Kernel:
|
|||||||
|
|
||||||
void free_slot (unsigned slot):
|
void free_slot (unsigned slot):
|
||||||
//kdebug ("free slot\n")
|
//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].prev = NULL
|
||||||
__slot_admin[slot].next = __first_free_slot
|
__slot_admin[slot].next = __first_free_slot
|
||||||
if __slot_admin[slot].next:
|
if __slot_admin[slot].next:
|
||||||
@ -61,12 +68,16 @@ namespace Kernel:
|
|||||||
__first_free_slot = &__slot_admin[slot]
|
__first_free_slot = &__slot_admin[slot]
|
||||||
|
|
||||||
void free_cap (Cap cap):
|
void free_cap (Cap cap):
|
||||||
//kdebug ("free cap ")
|
if enable_debug:
|
||||||
//kdebug_num (cap.idx (), 2)
|
kdebug ("free cap ")
|
||||||
//kdebug ("\n")
|
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:
|
if cap.slot () != 0:
|
||||||
kdebug ("trying to free capability from non-0 slot\n")
|
kdebug ("trying to free capability from non-0 slot\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return
|
return
|
||||||
list *l = &__cap_admin[cap.idx ()]
|
list *l = &__cap_admin[cap.idx ()]
|
||||||
l->prev = NULL
|
l->prev = NULL
|
||||||
@ -80,7 +91,7 @@ namespace Kernel:
|
|||||||
if !__first_free_slot:
|
if !__first_free_slot:
|
||||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||||
kdebug ("out of slots!\n")
|
kdebug ("out of slots!\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return ~0
|
return ~0
|
||||||
list *ret = __first_free_slot
|
list *ret = __first_free_slot
|
||||||
__first_free_slot = ret->next
|
__first_free_slot = ret->next
|
||||||
@ -89,42 +100,45 @@ namespace Kernel:
|
|||||||
return ret - __slot_admin
|
return ret - __slot_admin
|
||||||
|
|
||||||
Cap alloc_cap ():
|
Cap alloc_cap ():
|
||||||
//kdebug ("alloc cap ")
|
|
||||||
if !__first_free_cap:
|
if !__first_free_cap:
|
||||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||||
kdebug ("out of capabilities!\n")
|
kdebug ("out of capabilities!\n")
|
||||||
Kernel::panic (0)
|
Iris::panic (0)
|
||||||
return Cap (0, CAP_NONE)
|
return Cap (0, CAP_NONE)
|
||||||
list *ret = __first_free_cap
|
list *ret = __first_free_cap
|
||||||
__first_free_cap = ret->next
|
__first_free_cap = ret->next
|
||||||
if ret->next:
|
if ret->next:
|
||||||
ret->next->prev = NULL
|
ret->next->prev = NULL
|
||||||
//kdebug_num (ret - __cap_admin, 2)
|
if enable_debug:
|
||||||
//kdebug ("\n")
|
kdebug ("alloc cap ")
|
||||||
|
kdebug_num (ret - __cap_admin, 2)
|
||||||
|
kdebug ("\n")
|
||||||
return Cap (0, ret - __cap_admin)
|
return Cap (0, ret - __cap_admin)
|
||||||
|
|
||||||
extern "C":
|
extern "C":
|
||||||
void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
|
void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
|
||||||
|
Iris::enable_debug = false
|
||||||
__slots = slots
|
__slots = slots
|
||||||
__caps = caps
|
__caps = caps
|
||||||
__slot_admin = slot_admin
|
__slot_admin = slot_admin
|
||||||
__cap_admin = cap_admin
|
__cap_admin = cap_admin
|
||||||
__first_free_slot = NULL
|
__first_free_slot = NULL
|
||||||
for unsigned i = 1; i < __slots; ++i:
|
for unsigned i = 1; i < __slots; ++i:
|
||||||
Kernel::free_slot (i)
|
Iris::free_slot (i)
|
||||||
__first_free_cap = NULL
|
__first_free_cap = NULL
|
||||||
for unsigned i = 7; i < __caps; ++i:
|
for unsigned i = 6; i < __caps; ++i:
|
||||||
Kernel::free_cap (Kernel::Cap (0, i))
|
Iris::free_cap (Iris::Cap (0, i))
|
||||||
Kernel::my_receiver = Kernel::Cap (0, __receiver_num)
|
Iris::my_caps = Iris::Cap (0, __caps_num)
|
||||||
Kernel::my_thread = Kernel::Cap (0, __thread_num)
|
Iris::my_receiver = Iris::Cap (0, __receiver_num)
|
||||||
Kernel::my_memory = Kernel::Cap (0, __memory_num)
|
Iris::my_thread = Iris::Cap (0, __thread_num)
|
||||||
Kernel::my_call = Kernel::Cap (0, __call_num)
|
Iris::my_memory = Iris::Cap (0, __memory_num)
|
||||||
Kernel::my_parent = Kernel::Cap (0, __parent_num)
|
Iris::my_call = Iris::Cap (0, __call_num)
|
||||||
Kernel::recv.reply = Kernel::alloc_cap ()
|
Iris::my_parent = Iris::Cap (0, __parent_num)
|
||||||
Kernel::recv.arg = Kernel::alloc_cap ()
|
Iris::recv.reply = Iris::alloc_cap ()
|
||||||
Kernel::Num ret = start ()
|
Iris::recv.arg = Iris::alloc_cap ()
|
||||||
Kernel::my_parent.invoke (~0, ret)
|
Iris::Num ret = start ()
|
||||||
Kernel::my_memory.destroy (Kernel::my_thread)
|
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.
|
// The program no longer exists. If it somehow does, generate an address fault.
|
||||||
while true:
|
while true:
|
||||||
*(volatile unsigned *)~0
|
*(volatile unsigned *)~0
|
||||||
|
@ -19,64 +19,64 @@
|
|||||||
#include <devices.hh>
|
#include <devices.hh>
|
||||||
#include <iris.hh>
|
#include <iris.hh>
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
Device d = Kernel::my_receiver.create_capability (0)
|
Iris::Device d = Iris::my_receiver.create_capability (0)
|
||||||
Kernel::my_parent.provide_device <Display> (d.copy (), 0x10000)
|
Iris::my_parent.provide_device <Iris::Display> (d.copy (), 0x10000)
|
||||||
Kernel::free_cap (d)
|
Iris::free_cap (d)
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
Display real = Kernel::my_parent.get_device <Display> (0)
|
Iris::Display real = Iris::my_parent.get_device <Iris::Display> (0)
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Iris::recv.protected_data.h:
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Device::CREATE_USER:
|
case Iris::Device::CREATE_USER:
|
||||||
Kernel::Memory mem (arg)
|
Iris::Memory mem (arg)
|
||||||
Kernel::Caps ret = mem.create_caps (3)
|
Iris::Caps ret = mem.create_caps (3)
|
||||||
Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1))
|
Iris::Cap target = Iris::my_receiver.create_capability (Iris::Num (0, 1))
|
||||||
ret.set (0, target.copy ())
|
ret.set (0, target.copy ())
|
||||||
ret.set (1, mem)
|
ret.set (1, mem)
|
||||||
Kernel::free_cap (target)
|
Iris::free_cap (target)
|
||||||
for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE:
|
for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE:
|
||||||
Kernel::Page p = Kernel::my_memory.mapping ((void *)(0x15000 + i))
|
Iris::Page p = Iris::my_memory.mapping ((void *)(0x15000 + i))
|
||||||
Kernel::Page t = mem.create_page ()
|
Iris::Page t = mem.create_page ()
|
||||||
t.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING)
|
t.set_flags (Iris::Page::PAYING, Iris::Page::PAYING)
|
||||||
p.share (t, Kernel::Page::FORGET)
|
p.share (t, Iris::Page::FORGET)
|
||||||
mem.map (t, 0x15000 + i)
|
mem.map (t, 0x15000 + i)
|
||||||
Kernel::my_memory.destroy (t)
|
Iris::my_memory.destroy (t)
|
||||||
Kernel::free_cap (t)
|
Iris::free_cap (t)
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
reply.invoke (0, 0, ret.copy ())
|
reply.invoke (0, 0, ret.copy ())
|
||||||
Kernel::free_cap (ret)
|
Iris::free_cap (ret)
|
||||||
break
|
break
|
||||||
case Device::DESTROY_USER:
|
case Iris::Device::DESTROY_USER:
|
||||||
Kernel::panic (0, "destroying emulation user")
|
Iris::panic (0, "destroying emulation user")
|
||||||
case Device::USE:
|
case Iris::Device::USE:
|
||||||
case Device::UNUSE:
|
case Iris::Device::UNUSE:
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug_num (Kernel::recv.data[0].l)
|
kdebug_num (Iris::recv.data[0].l)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
Kernel::panic (0, "invalid emulation command")
|
Iris::panic (0, "invalid emulation command")
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Display::SET_EOF_CB:
|
case Iris::Display::SET_EOF_CB:
|
||||||
real.set_eof_cb (arg.copy ())
|
real.set_eof_cb (arg.copy ())
|
||||||
while Kernel::recv.data[0].l != 0:
|
while Iris::recv.data[0].l != 0:
|
||||||
Kernel::my_parent.wait <Display> (0)
|
Iris::my_parent.wait <Iris::Display> (0)
|
||||||
real.set_eof_cb (arg.copy ())
|
real.set_eof_cb (arg.copy ())
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug_num (Kernel::recv.data[0].l)
|
kdebug_num (Iris::recv.data[0].l)
|
||||||
kdebug_char ('\n')
|
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
|
break
|
||||||
default:
|
default:
|
||||||
Kernel::panic (0, "bug in display emulation")
|
Iris::panic (0, "bug in display emulation")
|
||||||
Kernel::free_cap (arg)
|
Iris::free_cap (arg)
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
|
@ -1 +0,0 @@
|
|||||||
display-emu.ccp
|
|
286
source/elfrun.ccp
Normal file
286
source/elfrun.ccp
Normal file
@ -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 <wijnen@debian.org>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "devices.hh"
|
||||||
|
#include "iris.hh"
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
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 <Iris::Elfrun> (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)
|
1
source/gpio.ccp
Symbolic link
1
source/gpio.ccp
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nanonote-gpio.ccp
|
412
source/init.ccp
Normal file
412
source/init.ccp
Normal file
@ -0,0 +1,412 @@
|
|||||||
|
#pypp 0
|
||||||
|
// Iris: micro-kernel for a capability-based operating system.
|
||||||
|
// bootstrap/init.ccp: Bootstrapping code.
|
||||||
|
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#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 <typename _T> //
|
||||||
|
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 <Device> devices
|
||||||
|
|
||||||
|
static Iris::Memory top_memory
|
||||||
|
static Iris::Directory root
|
||||||
|
static Iris::Elfrun elfrun
|
||||||
|
static List <Program> 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 <name> / <type> [, <index>] = <cap>
|
||||||
|
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 <Program>::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 <Device>::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 <Program>::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 <Iris::Directory> ()
|
||||||
|
elfrun = Iris::my_parent.get_device <Iris::Elfrun> ()
|
||||||
|
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")
|
@ -225,7 +225,7 @@ static void log_str (char const *str):
|
|||||||
while *str:
|
while *str:
|
||||||
log_char (*str++)
|
log_char (*str++)
|
||||||
|
|
||||||
static void log_num (Kernel::Num n):
|
static void log_num (Iris::Num n):
|
||||||
char const *encode = "0123456789abcdef"
|
char const *encode = "0123456789abcdef"
|
||||||
log_char ('[')
|
log_char ('[')
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
@ -237,10 +237,10 @@ static void log_num (Kernel::Num n):
|
|||||||
|
|
||||||
static void log_msg ():
|
static void log_msg ():
|
||||||
log_str ("prot:")
|
log_str ("prot:")
|
||||||
log_num (Kernel::recv.protected_data)
|
log_num (Iris::recv.protected_data)
|
||||||
log_str ("data:")
|
log_str ("data:")
|
||||||
for unsigned i = 0; i < 2; ++i:
|
for unsigned i = 0; i < 2; ++i:
|
||||||
log_num (Kernel::recv.data[i])
|
log_num (Iris::recv.data[i])
|
||||||
log_char ('\n')
|
log_char ('\n')
|
||||||
|
|
||||||
enum captype:
|
enum captype:
|
||||||
@ -261,25 +261,25 @@ static unsigned pages
|
|||||||
static Descriptor descriptor __attribute__ ((aligned (16)))
|
static Descriptor descriptor __attribute__ ((aligned (16)))
|
||||||
static bool is_on
|
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 physical = mem.alloc_range (pages)
|
||||||
unsigned address = 0x15000
|
unsigned address = 0x15000
|
||||||
if physical & ~PAGE_MASK:
|
if physical & ~PAGE_MASK:
|
||||||
Kernel::panic (0, "can't allocate framebuffer")
|
Iris::panic (0, "can't allocate framebuffer")
|
||||||
assert (physical & PAGE_MASK && ~physical)
|
assert (physical & PAGE_MASK && ~physical)
|
||||||
for unsigned i = 0; i < pages; ++i:
|
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)
|
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||||
if address != ~0:
|
if address != ~0:
|
||||||
mem.map (p, address + (i << PAGE_BITS))
|
mem.map (p, address + (i << PAGE_BITS))
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
return physical
|
return physical
|
||||||
|
|
||||||
static void destroy (unsigned physical, Kernel::Caps caps):
|
static void destroy (unsigned physical, Iris::Caps caps):
|
||||||
unsigned address = 0x15000
|
unsigned address = 0x15000
|
||||||
Kernel::Memory mem = caps.get (1)
|
Iris::Memory mem = caps.get (1)
|
||||||
if physical == ~0:
|
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:
|
if descriptor.frame == physical && is_on:
|
||||||
lcd_clr_ena ()
|
lcd_clr_ena ()
|
||||||
#ifdef NANONOTE
|
#ifdef NANONOTE
|
||||||
@ -287,13 +287,13 @@ static void destroy (unsigned physical, Kernel::Caps caps):
|
|||||||
#endif
|
#endif
|
||||||
if address != ~0:
|
if address != ~0:
|
||||||
for unsigned i = 0; i < pages; ++i:
|
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)
|
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:
|
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
|
bool was_unused = descriptor.frame == 0
|
||||||
descriptor.frame = physical
|
descriptor.frame = physical
|
||||||
unsigned dptr = (unsigned)&descriptor
|
unsigned dptr = (unsigned)&descriptor
|
||||||
@ -304,9 +304,9 @@ static void use (unsigned physical, Kernel::Caps caps):
|
|||||||
write_reg (BACKLIGHT1, 0x5f)
|
write_reg (BACKLIGHT1, 0x5f)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void unuse (unsigned physical, Kernel::Caps caps):
|
static void unuse (unsigned physical, Iris::Caps caps):
|
||||||
if physical == ~0:
|
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:
|
if descriptor.frame == physical:
|
||||||
lcd_clr_ena ()
|
lcd_clr_ena ()
|
||||||
#ifdef NANONOTE
|
#ifdef NANONOTE
|
||||||
@ -314,8 +314,8 @@ static void unuse (unsigned physical, Kernel::Caps caps):
|
|||||||
#endif
|
#endif
|
||||||
descriptor.frame = 0
|
descriptor.frame = 0
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
Kernel::schedule ()
|
Iris::schedule ()
|
||||||
map_lcd ()
|
map_lcd ()
|
||||||
map_cpm ()
|
map_cpm ()
|
||||||
#ifdef NANONOTE
|
#ifdef NANONOTE
|
||||||
@ -324,13 +324,13 @@ Kernel::Num start ():
|
|||||||
|
|
||||||
pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||||
#if 0
|
#if 0
|
||||||
unsigned physical = Kernel::my_memory.alloc_range (pages)
|
unsigned physical = Iris::my_memory.alloc_range (pages)
|
||||||
assert (physical & PAGE_MASK && ~physical)
|
assert (physical & PAGE_MASK && ~physical)
|
||||||
for unsigned i = 0; i < pages; ++i:
|
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)
|
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||||
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
|
Iris::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
for unsigned y = 0; y < v; ++y:
|
for unsigned y = 0; y < v; ++y:
|
||||||
for unsigned x = 0; x < h; ++x:
|
for unsigned x = 0; x < h; ++x:
|
||||||
unsigned r = spot (x, y, 100, 160)
|
unsigned r = spot (x, y, 100, 160)
|
||||||
@ -346,10 +346,10 @@ Kernel::Num start ():
|
|||||||
#else
|
#else
|
||||||
unsigned physical = 0
|
unsigned physical = 0
|
||||||
#endif
|
#endif
|
||||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
Iris::Page p = Iris::my_memory.mapping (&descriptor)
|
||||||
unsigned paddr = p.physical_address ()
|
unsigned paddr = p.physical_address ()
|
||||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||||
Kernel::free_cap (p)
|
Iris::free_cap (p)
|
||||||
descriptor.next = physical_descriptor
|
descriptor.next = physical_descriptor
|
||||||
descriptor.frame = physical
|
descriptor.frame = physical
|
||||||
descriptor.id = 0xdeadbeef
|
descriptor.id = 0xdeadbeef
|
||||||
@ -359,67 +359,67 @@ Kernel::Num start ():
|
|||||||
reset ()
|
reset ()
|
||||||
|
|
||||||
#if defined (TRENDTAC)
|
#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")
|
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Register the backlight device.
|
// Register the backlight device.
|
||||||
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
|
Iris::Cap backlight = Iris::my_receiver.create_capability (BACKLIGHT)
|
||||||
Kernel::my_parent.provide_device <Setting> (backlight.copy ())
|
Iris::my_parent.provide_device <Iris::Setting> (backlight.copy ())
|
||||||
Kernel::free_cap (backlight)
|
Iris::free_cap (backlight)
|
||||||
|
|
||||||
// Register the display device.
|
// Register the display device.
|
||||||
Kernel::Cap display = Kernel::my_receiver.create_capability (LCD)
|
Iris::Cap display = Iris::my_receiver.create_capability (LCD)
|
||||||
Kernel::my_parent.provide_device <Display> (display.copy ())
|
Iris::my_parent.provide_device <Iris::Display> (display.copy ())
|
||||||
Kernel::free_cap (display)
|
Iris::free_cap (display)
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
|
|
||||||
Kernel::Cap eof_cb
|
Iris::Cap eof_cb
|
||||||
bool have_eof = false
|
bool have_eof = false
|
||||||
is_on = true
|
is_on = true
|
||||||
unsigned lcd_user = 0
|
unsigned lcd_user = 0
|
||||||
unsigned current_backlight = 0
|
unsigned current_backlight = 0
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
//log_msg ()
|
//log_msg ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Iris::recv.protected_data.h:
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case IRQ_LCD:
|
case IRQ_LCD:
|
||||||
have_eof = false
|
have_eof = false
|
||||||
eof_cb.invoke ()
|
eof_cb.invoke ()
|
||||||
Kernel::free_cap (eof_cb)
|
Iris::free_cap (eof_cb)
|
||||||
break
|
break
|
||||||
#if defined (TRENDTAC)
|
#if defined (TRENDTAC)
|
||||||
case LOG:
|
case LOG:
|
||||||
log_char (Kernel::recv.data[0].l)
|
log_char (Iris::recv.data[0].l)
|
||||||
break
|
break
|
||||||
#endif
|
#endif
|
||||||
case BACKLIGHT:
|
case BACKLIGHT:
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Device::host (BACKLIGHT, current_backlight, reply, arg)
|
Iris::Device::host (BACKLIGHT, current_backlight, reply, arg)
|
||||||
break
|
break
|
||||||
case LCD:
|
case LCD:
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse)
|
Iris::Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse)
|
||||||
break
|
break
|
||||||
default:
|
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
|
||||||
break
|
break
|
||||||
case BACKLIGHT:
|
case BACKLIGHT:
|
||||||
if current_backlight != Kernel::recv.protected_data.l:
|
if current_backlight != Iris::recv.protected_data.l:
|
||||||
log_char ('&')
|
log_char ('&')
|
||||||
log_num (current_backlight)
|
log_num (current_backlight)
|
||||||
log_num (Kernel::recv.protected_data)
|
log_num (Iris::recv.protected_data)
|
||||||
log_char ('\n')
|
log_char ('\n')
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Setting::SET:
|
case Iris::Setting::SET:
|
||||||
// TODO
|
// TODO
|
||||||
unsigned state = Kernel::recv.data[1].l
|
unsigned state = Iris::recv.data[1].l
|
||||||
if !state:
|
if !state:
|
||||||
#if defined (NANONOTE)
|
#if defined (NANONOTE)
|
||||||
if is_on:
|
if is_on:
|
||||||
@ -434,40 +434,40 @@ Kernel::Num start ():
|
|||||||
is_on = true
|
is_on = true
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
case Setting::GET_RANGE:
|
case Iris::Setting::GET_RANGE:
|
||||||
Kernel::recv.reply.invoke (~0)
|
Iris::recv.reply.invoke (~0)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
Kernel::panic (0, "invalid operation for backlight")
|
Iris::panic (0, "invalid operation for backlight")
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
case LCD:
|
case LCD:
|
||||||
if descriptor.frame != Kernel::recv.protected_data.l:
|
if descriptor.frame != Iris::recv.protected_data.l:
|
||||||
//Kernel::panic (0, "invalid user requesting lcd")
|
//Iris::panic (0, "invalid user requesting lcd")
|
||||||
Kernel::recv.reply.invoke (~0)
|
Iris::recv.reply.invoke (~0)
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Display::SET_EOF_CB:
|
case Iris::Display::SET_EOF_CB:
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
if have_eof:
|
if have_eof:
|
||||||
Kernel::free_cap (eof_cb)
|
Iris::free_cap (eof_cb)
|
||||||
Kernel::panic (0, "replacing eof_cb")
|
Iris::panic (0, "replacing eof_cb")
|
||||||
else:
|
else:
|
||||||
lcd_clr_eof ()
|
lcd_clr_eof ()
|
||||||
Kernel::register_interrupt (IRQ_LCD)
|
Iris::register_interrupt (IRQ_LCD)
|
||||||
have_eof = true
|
have_eof = true
|
||||||
eof_cb = arg
|
eof_cb = arg
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Display::GET_INFO:
|
case Iris::Display::GET_INFO:
|
||||||
Kernel::panic (0, "get_info isn't defined yet.")
|
Iris::panic (0, "get_info isn't defined yet.")
|
||||||
default:
|
default:
|
||||||
Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd")
|
Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd")
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
Kernel::panic (0, "invalid master operation type for lcd")
|
Iris::panic (0, "invalid master operation type for lcd")
|
||||||
break
|
break
|
@ -19,11 +19,11 @@
|
|||||||
#include "devices.hh"
|
#include "devices.hh"
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
|
Iris::Buzzer buzzer = Iris::my_parent.get_device <Iris::Buzzer> ()
|
||||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
Iris::Keyboard kbd = Iris::my_parent.get_device <Iris::Keyboard> ()
|
||||||
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
|
Iris::Cap key = Iris::my_receiver.create_capability (0)
|
||||||
kbd.set_cb (key)
|
kbd.set_cb (key)
|
||||||
// Frequency of the pulse train in millihertz.
|
// Frequency of the pulse train in millihertz.
|
||||||
unsigned mHz = 1000
|
unsigned mHz = 1000
|
||||||
@ -31,17 +31,17 @@ Kernel::Num start ():
|
|||||||
unsigned freq = 1000
|
unsigned freq = 1000
|
||||||
bool running (false)
|
bool running (false)
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case ~0:
|
case ~0:
|
||||||
if running:
|
if running:
|
||||||
buzzer.beep (freq, 10, ~0)
|
buzzer.beep (freq, 10, ~0)
|
||||||
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
|
Iris::my_receiver.set_alarm (HZ * 1000 / mHz)
|
||||||
break
|
break
|
||||||
case 0:
|
case 0:
|
||||||
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Key::VOLUME_UP:
|
case Key::VOLUME_UP:
|
||||||
freq = freq * 11 / 10
|
freq = freq * 11 / 10
|
||||||
break
|
break
|
||||||
@ -63,7 +63,7 @@ Kernel::Num start ():
|
|||||||
case Key::P:
|
case Key::P:
|
||||||
running = !running
|
running = !running
|
||||||
if running:
|
if running:
|
||||||
Kernel::my_receiver.set_alarm (0)
|
Iris::my_receiver.set_alarm (0)
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -37,25 +37,25 @@ class DevKbd:
|
|||||||
static unsigned const NUM_KEYS = 58
|
static unsigned const NUM_KEYS = 58
|
||||||
static unsigned const keys[NUM_KEYS]
|
static unsigned const keys[NUM_KEYS]
|
||||||
unsigned state[NUM_COLS]
|
unsigned state[NUM_COLS]
|
||||||
Kernel::Cap event
|
Iris::Cap event
|
||||||
bool is_active
|
bool is_active
|
||||||
bool is_scanning
|
bool is_scanning
|
||||||
public:
|
public:
|
||||||
unsigned size ():
|
unsigned size ():
|
||||||
return NUM_KEYS
|
return NUM_KEYS
|
||||||
void send_keys (unsigned first, Kernel::Cap target):
|
void send_keys (unsigned first, Iris::Cap target):
|
||||||
unsigned d[4]
|
unsigned d[4]
|
||||||
unsigned i
|
unsigned i
|
||||||
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
|
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
|
||||||
d[i] = keys[first + i]
|
d[i] = keys[first + i]
|
||||||
for ; i < 4; ++i:
|
for ; i < 4; ++i:
|
||||||
d[i] = ~0
|
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 ():
|
bool scanning ():
|
||||||
return is_scanning
|
return is_scanning
|
||||||
void inactive ():
|
void inactive ():
|
||||||
if is_active:
|
if is_active:
|
||||||
Kernel::free_cap (event)
|
Iris::free_cap (event)
|
||||||
is_active = false
|
is_active = false
|
||||||
void check (unsigned col, unsigned rowdata):
|
void check (unsigned col, unsigned rowdata):
|
||||||
for unsigned r = 0; r < NUM_ROWS; ++r:
|
for unsigned r = 0; r < NUM_ROWS; ++r:
|
||||||
@ -63,7 +63,7 @@ class DevKbd:
|
|||||||
continue
|
continue
|
||||||
unsigned code = encode[r][col]
|
unsigned code = encode[r][col]
|
||||||
if rowdata & (1 << ROWS[r]):
|
if rowdata & (1 << ROWS[r]):
|
||||||
code |= Keyboard::RELEASE
|
code |= Iris::Keyboard::RELEASE
|
||||||
if is_active:
|
if is_active:
|
||||||
event.invoke (code)
|
event.invoke (code)
|
||||||
state[col] = rowdata
|
state[col] = rowdata
|
||||||
@ -101,7 +101,7 @@ class DevKbd:
|
|||||||
gpio_as_interrupt (ROWS_PORT, high, true, true)
|
gpio_as_interrupt (ROWS_PORT, high, true, true)
|
||||||
gpio_as_interrupt (ROWS_PORT, low, false, true)
|
gpio_as_interrupt (ROWS_PORT, low, false, true)
|
||||||
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
|
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
|
||||||
void active (Kernel::Cap cb):
|
void active (Iris::Cap cb):
|
||||||
inactive ()
|
inactive ()
|
||||||
event = cb
|
event = cb
|
||||||
is_active = true
|
is_active = true
|
||||||
@ -167,7 +167,7 @@ unsigned const DevKbd::keys[NUM_KEYS] = {
|
|||||||
|
|
||||||
class PowerButton:
|
class PowerButton:
|
||||||
bool state, started
|
bool state, started
|
||||||
Kernel::Cap cb
|
Iris::Cap cb
|
||||||
public:
|
public:
|
||||||
void scan ():
|
void scan ():
|
||||||
if !started:
|
if !started:
|
||||||
@ -176,16 +176,16 @@ class PowerButton:
|
|||||||
bool s = gpio_get_port (3) & (1 << 29)
|
bool s = gpio_get_port (3) & (1 << 29)
|
||||||
if s != state:
|
if s != state:
|
||||||
state = s
|
state = s
|
||||||
cb.invoke (state ? Keyboard::RELEASE : 0)
|
cb.invoke (state ? Iris::Keyboard::RELEASE : 0)
|
||||||
gpio_as_interrupt (3, 1 << 29, !state, true)
|
gpio_as_interrupt (3, 1 << 29, !state, true)
|
||||||
gpio_unmask_irq (3, 1 << 29)
|
gpio_unmask_irq (3, 1 << 29)
|
||||||
PowerButton ():
|
PowerButton ():
|
||||||
gpio_as_gpio (3, 29)
|
gpio_as_gpio (3, 29)
|
||||||
state = true
|
state = true
|
||||||
started = false
|
started = false
|
||||||
void set_cb (Kernel::Cap c):
|
void set_cb (Iris::Cap c):
|
||||||
if started:
|
if started:
|
||||||
Kernel::free_cap (cb)
|
Iris::free_cap (cb)
|
||||||
else:
|
else:
|
||||||
started = true
|
started = true
|
||||||
cb = c
|
cb = c
|
||||||
@ -196,100 +196,100 @@ enum codes:
|
|||||||
KBD_DEV = 32
|
KBD_DEV = 32
|
||||||
PWR
|
PWR
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
|
|
||||||
DevKbd kbd
|
DevKbd kbd
|
||||||
PowerButton pwr
|
PowerButton pwr
|
||||||
|
|
||||||
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
|
Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV)
|
||||||
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
|
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
|
||||||
Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
|
Iris::my_parent.provide_device <Iris::Keyboard> (dev.copy (), 0)
|
||||||
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
|
Iris::my_parent.provide_device <Iris::Keyboard> (pw.copy (), 1)
|
||||||
Kernel::free_cap (dev)
|
Iris::free_cap (dev)
|
||||||
Kernel::free_cap (pw)
|
Iris::free_cap (pw)
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
if kbd.scanning ():
|
if kbd.scanning ():
|
||||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||||
unsigned user (0), power_user (0)
|
unsigned user (0), power_user (0)
|
||||||
unsigned next_user (0)
|
unsigned next_user (0)
|
||||||
Kernel::register_interrupt (IRQ_GPIO3)
|
Iris::register_interrupt (IRQ_GPIO3)
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
switch Kernel::recv.protected_data.h:
|
switch Iris::recv.protected_data.h:
|
||||||
case ~0:
|
case ~0:
|
||||||
// Alarm.
|
// Alarm.
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
if kbd.scanning ():
|
if kbd.scanning ():
|
||||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||||
break
|
break
|
||||||
case 0:
|
case 0:
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case IRQ_GPIO3:
|
case IRQ_GPIO3:
|
||||||
// Interrupt.
|
// Interrupt.
|
||||||
pwr.scan ()
|
pwr.scan ()
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
if kbd.scanning ():
|
if kbd.scanning ():
|
||||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||||
Kernel::register_interrupt (IRQ_GPIO3)
|
Iris::register_interrupt (IRQ_GPIO3)
|
||||||
break
|
break
|
||||||
case PWR:
|
case PWR:
|
||||||
// Power button request.
|
// Power button request.
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Device::host (PWR, power_user, reply, arg)
|
Iris::Device::host (PWR, power_user, reply, arg)
|
||||||
break
|
break
|
||||||
case KBD_DEV:
|
case KBD_DEV:
|
||||||
// Keyboard device control request.
|
// Keyboard device control request.
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Kernel::Cap arg = Kernel::get_arg ()
|
Iris::Cap arg = Iris::get_arg ()
|
||||||
Device::host (KBD_DEV, user, reply, arg)
|
Iris::Device::host (KBD_DEV, user, reply, arg)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
case KBD_DEV:
|
case KBD_DEV:
|
||||||
// Keyboard device user request.
|
// Keyboard device user request.
|
||||||
if Kernel::recv.protected_data.l != user:
|
if Iris::recv.protected_data.l != user:
|
||||||
kdebug ("invalid user requesting keyboard\n")
|
kdebug ("invalid user requesting keyboard\n")
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Keyboard::SET_CB:
|
case Iris::Keyboard::SET_CB:
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
kbd.active (Kernel::get_arg ())
|
kbd.active (Iris::get_arg ())
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
case Keyboard::GET_NUM_KEYS:
|
case Iris::Keyboard::GET_NUM_KEYS:
|
||||||
Kernel::recv.reply.invoke (kbd.size ())
|
Iris::recv.reply.invoke (kbd.size ())
|
||||||
break
|
break
|
||||||
case Keyboard::GET_KEYS:
|
case Iris::Keyboard::GET_KEYS:
|
||||||
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
|
kbd.send_keys (Iris::recv.data[0].l, Iris::recv.reply)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("keyboard other\n")
|
kdebug ("keyboard other\n")
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
case PWR:
|
case PWR:
|
||||||
if Kernel::recv.protected_data.l != power_user:
|
if Iris::recv.protected_data.l != power_user:
|
||||||
kdebug ("invalid user requesting power\n")
|
kdebug ("invalid user requesting power\n")
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
switch Kernel::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Keyboard::SET_CB:
|
case Iris::Keyboard::SET_CB:
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
pwr.set_cb (Kernel::get_arg ())
|
pwr.set_cb (Iris::get_arg ())
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("Power button invalid request\n")
|
kdebug ("Power button invalid request\n")
|
||||||
kdebug_num (Kernel::recv.data[0].l)
|
kdebug_num (Iris::recv.data[0].l)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("keyboard unknown num: ")
|
kdebug ("keyboard unknown num: ")
|
||||||
kdebug_num (Kernel::recv.protected_data.h)
|
kdebug_num (Iris::recv.protected_data.h)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
@ -53,14 +53,14 @@ enum event_type:
|
|||||||
TOUCHPAD_EVENT
|
TOUCHPAD_EVENT
|
||||||
NUM_EVENTS
|
NUM_EVENTS
|
||||||
|
|
||||||
static Kernel::Cap events[NUM_EVENTS]
|
static Iris::Cap events[NUM_EVENTS]
|
||||||
|
|
||||||
static void event (event_type type, unsigned data):
|
static void event (event_type type, unsigned data):
|
||||||
events[type].invoke (data)
|
events[type].invoke (data)
|
||||||
|
|
||||||
static void set_cb (event_type type):
|
static void set_cb (event_type type):
|
||||||
Kernel::free_cap (events[type])
|
Iris::free_cap (events[type])
|
||||||
events[type] = Kernel::get_arg ()
|
events[type] = Iris::get_arg ()
|
||||||
|
|
||||||
class DevKeyboard:
|
class DevKeyboard:
|
||||||
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
|
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
|
||||||
@ -252,72 +252,72 @@ enum codes:
|
|||||||
LOCKLEDS
|
LOCKLEDS
|
||||||
PWM
|
PWM
|
||||||
|
|
||||||
Kernel::Num start ():
|
Iris::Num start ():
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
map_pwm0 ()
|
map_pwm0 ()
|
||||||
|
|
||||||
for unsigned i = 0; i < NUM_EVENTS; ++i:
|
for unsigned i = 0; i < NUM_EVENTS; ++i:
|
||||||
events[i] = Kernel::alloc_cap ()
|
events[i] = Iris::alloc_cap ()
|
||||||
|
|
||||||
DevKeyboard kbd
|
DevKeyboard kbd
|
||||||
Touchpad tp
|
Touchpad tp
|
||||||
Lockleds leds
|
Lockleds leds
|
||||||
Pwm pwm
|
Pwm pwm
|
||||||
|
|
||||||
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
|
Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD)
|
||||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
Iris::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
c = Kernel::my_receiver.create_capability (TOUCHPAD)
|
c = Iris::my_receiver.create_capability (TOUCHPAD)
|
||||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
Iris::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
||||||
Kernel::free_cap (c)
|
Iris::free_cap (c)
|
||||||
Kernel::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
|
|
||||||
if kbd.is_scanning ():
|
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.
|
// 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
|
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:
|
while true:
|
||||||
Kernel::schedule ()
|
Iris::schedule ()
|
||||||
Kernel::wait ()
|
Iris::wait ()
|
||||||
switch Kernel::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case ~0:
|
case ~0:
|
||||||
// Alarm.
|
// Alarm.
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
if kbd.is_scanning ():
|
if kbd.is_scanning ():
|
||||||
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
|
Iris::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||||
break
|
break
|
||||||
case IRQ_GPIO0:
|
case IRQ_GPIO0:
|
||||||
// Always scan keyboard and touchpad on any interrupt.
|
// Always scan keyboard and touchpad on any interrupt.
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
tp.check_events ()
|
tp.check_events ()
|
||||||
// Reregister the interrupt.
|
// Reregister the interrupt.
|
||||||
Kernel::register_interrupt (IRQ_GPIO0)
|
Iris::register_interrupt (IRQ_GPIO0)
|
||||||
break
|
break
|
||||||
case KEYBOARD:
|
case KEYBOARD:
|
||||||
set_cb (KEYBOARD_EVENT)
|
set_cb (KEYBOARD_EVENT)
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
kbd.send_initial ()
|
kbd.send_initial ()
|
||||||
event (KEYBOARD_EVENT, ~0)
|
event (KEYBOARD_EVENT, ~0)
|
||||||
break
|
break
|
||||||
case TOUCHPAD:
|
case TOUCHPAD:
|
||||||
set_cb (TOUCHPAD_EVENT)
|
set_cb (TOUCHPAD_EVENT)
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
tp.send_initial ()
|
tp.send_initial ()
|
||||||
event (TOUCHPAD_EVENT, ~0)
|
event (TOUCHPAD_EVENT, ~0)
|
||||||
break
|
break
|
||||||
case LOCKLEDS:
|
case LOCKLEDS:
|
||||||
leds.set (Kernel::recv.data[0].l)
|
leds.set (Iris::recv.data[0].l)
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
case PWM:
|
case PWM:
|
||||||
pwm.set_backlight (Kernel::recv.data[0].l)
|
pwm.set_backlight (Iris::recv.data[0].l)
|
||||||
Kernel::recv.reply.invoke ()
|
Iris::recv.reply.invoke ()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
kdebug ("invalid gpio operation ")
|
kdebug ("invalid gpio operation ")
|
||||||
kdebug_num (Kernel::recv.protected_data.l)
|
kdebug_num (Iris::recv.protected_data.l)
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
break
|
break
|
Loading…
Reference in New Issue
Block a user