mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-30 06:21:06 +02:00
make things work with terminals
This commit is contained in:
parent
5ef2934bf8
commit
06390fd2d1
4
Makefile
4
Makefile
@ -44,11 +44,11 @@ PYPP = /usr/bin/pypp
|
||||
|
||||
%.elf: boot-programs/crt0.o boot-programs/%.o
|
||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||
#$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||
|
||||
fs/%.elf: source/crt0.o source/%.o
|
||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||
#$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||
|
||||
clean:
|
||||
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
||||
|
163
alloc.ccp
163
alloc.ccp
@ -27,6 +27,7 @@
|
||||
|
||||
#define PREV(x) (((kObject **)(x))[-2])
|
||||
#define NEXT(x) (((kObject **)(x))[-1])
|
||||
// ATTENTION! When changing SIZE, be sure to also change the hard-coded 8 in kernel.hhp which defines MAX_NUM_CAPS.
|
||||
#define SIZE (2 * sizeof (kObject *))
|
||||
|
||||
bool kMemory::use (unsigned num):
|
||||
@ -45,12 +46,14 @@ void kMemory::unuse (unsigned num):
|
||||
m->used -= num
|
||||
|
||||
// This allocates a new block of memory for use by the kernel.
|
||||
// size is the requires size of the block (excluding SIZE)
|
||||
// size is the required size of the block (excluding SIZE)
|
||||
// first is a pointer to the first object pointer of this type.
|
||||
// The result is a block of size at least size, which is linked as an object in the list of first.
|
||||
void *kMemory::search_free (unsigned size, void **first):
|
||||
kFree *f
|
||||
unsigned s = 0
|
||||
if size >= PAGE_SIZE - SIZE:
|
||||
panic (size, "requested size is too large")
|
||||
int s = 0
|
||||
// Let's see if there already is a kFree chunk which is large enough.
|
||||
for f = frees; f; f = (kFree *)f->next:
|
||||
if NEXT (f):
|
||||
@ -65,7 +68,7 @@ void *kMemory::search_free (unsigned size, void **first):
|
||||
// No chunk was found; allocate a new page and add a chunk in it. It is always large enough.
|
||||
unsigned p = palloc ()
|
||||
if !p:
|
||||
dbg_log ("no free space: kernel allocation failed")
|
||||
kdebug ("no free space: kernel allocation failed")
|
||||
return NULL
|
||||
f = (kFree *)(p + SIZE)
|
||||
// Mark it as a kFree object.
|
||||
@ -199,9 +202,9 @@ kThread *kMemory::alloc_thread (unsigned size):
|
||||
ret->slot[i].prev.thread = NULL
|
||||
ret->slot[i].next.thread = NULL
|
||||
ret->slot[i].caps = NULL
|
||||
//dbg_log ("new thread: ")
|
||||
//dbg_log_num ((unsigned)ret)
|
||||
//dbg_log ("\n")
|
||||
//kdebug ("new thread: ")
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ("\n")
|
||||
return ret
|
||||
|
||||
void kCaps::init (unsigned s):
|
||||
@ -211,10 +214,22 @@ void kCaps::init (unsigned s):
|
||||
set (i, NULL, 0, kCapRef (), NULL)
|
||||
|
||||
kCaps *kMemory::alloc_caps (unsigned size):
|
||||
kCaps *ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses)
|
||||
if size == 0:
|
||||
dpanic (0, "zero-size caps")
|
||||
return NULL
|
||||
kCaps *ret
|
||||
if size > MAX_NUM_CAPS:
|
||||
dpanic (size, "requested caps is too large")
|
||||
return NULL
|
||||
ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses)
|
||||
if !ret:
|
||||
return NULL
|
||||
ret->init (size)
|
||||
//kdebug ("allocate caps ")
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ('+')
|
||||
//kdebug_num (size)
|
||||
//kdebug ('\n')
|
||||
return ret
|
||||
|
||||
kMessage *kMemory::alloc_message (kReceiver *target):
|
||||
@ -278,22 +293,36 @@ kMemory *kMemory::alloc_memory ():
|
||||
return ret
|
||||
|
||||
void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr):
|
||||
caps[index].target = target
|
||||
caps[index].protected_data = pdata
|
||||
caps[index].parent = parent
|
||||
caps[index].children.reset ()
|
||||
caps[index].sibling_prev.reset ()
|
||||
if index >= size:
|
||||
kdebug ("size: ")
|
||||
kdebug_num (size)
|
||||
kdebug ("\n")
|
||||
dpanic (index, "index too large for kCaps")
|
||||
return
|
||||
kCapability *c = &caps[index]
|
||||
if (unsigned)target == 0x81fdc350:
|
||||
kdebug ("setting cap ")
|
||||
kdebug_num (index)
|
||||
kdebug (" old target: ")
|
||||
kdebug_num ((unsigned)c->target)
|
||||
c->target = target
|
||||
c->protected_data = pdata
|
||||
c->parent = parent
|
||||
c->children.reset ()
|
||||
c->sibling_prev.reset ()
|
||||
if parent.valid ():
|
||||
caps[index].sibling_next = parent->children
|
||||
c->sibling_next = parent->children
|
||||
parent->children = kCapRef (this, index)
|
||||
else:
|
||||
if parent_ptr:
|
||||
caps[index].sibling_next = *parent_ptr
|
||||
c->sibling_next = *parent_ptr
|
||||
*parent_ptr = kCapRef (this, index)
|
||||
else:
|
||||
caps[index].sibling_next.reset ()
|
||||
if caps[index].sibling_next.valid ():
|
||||
caps[index].sibling_next->sibling_prev = kCapRef (this, index)
|
||||
c->sibling_next.reset ()
|
||||
if c->sibling_next.valid ():
|
||||
c->sibling_next->sibling_prev = kCapRef (this, index)
|
||||
if (unsigned)target == 0x81fdc350:
|
||||
kdebug (" done\n")
|
||||
|
||||
void kCaps::clone (unsigned index, kCapRef source, bool copy):
|
||||
cap (index)->invalidate ()
|
||||
@ -375,6 +404,10 @@ void kReceiver::own (kThread *o):
|
||||
void kCapability::invalidate ():
|
||||
if !target:
|
||||
return
|
||||
//kdebug_num ((unsigned)target)
|
||||
//kdebug (":")
|
||||
//kdebug_num ((unsigned)protected_data.l)
|
||||
//kdebug ("\n")
|
||||
if sibling_prev.valid ():
|
||||
sibling_prev->sibling_next = sibling_next
|
||||
else if parent.valid ():
|
||||
@ -404,8 +437,11 @@ void kCapability::invalidate ():
|
||||
c = next
|
||||
|
||||
void kMemory::free_caps (kCaps *c):
|
||||
//kdebug ("free caps ")
|
||||
//kdebug_num ((unsigned)c)
|
||||
//kdebug ('\n')
|
||||
for unsigned i = 0; i < c->size; ++i:
|
||||
c->caps[i].invalidate ()
|
||||
c->cap (i)->invalidate ()
|
||||
while c->first_slot.thread:
|
||||
c->first_slot.thread->unset_slot (c->first_slot.index)
|
||||
free_obj (c, (void **)&capses)
|
||||
@ -474,10 +510,6 @@ void kMemory::free_memory (kMemory *mem):
|
||||
free_obj (mem, (void **)&memories)
|
||||
|
||||
void kPage::forget ():
|
||||
//dbg_log ("forget ")
|
||||
//dbg_log_num ((unsigned)this)
|
||||
//dbg_log ("\n")
|
||||
dbg_code.l = (unsigned)old_current
|
||||
if share_prev || share_next:
|
||||
if share_prev:
|
||||
share_prev->share_next = share_next
|
||||
@ -499,19 +531,19 @@ static void check_receiver (kReceiver *r, kCapRef cap, unsigned line):
|
||||
dpanic (line, "consistency bug in capabilities")
|
||||
else:
|
||||
if cap->protected_data.l != (unsigned)r:
|
||||
dbg_log ("Buggy: receiver=")
|
||||
dbg_log_num ((unsigned)r)
|
||||
dbg_log ("; caps=")
|
||||
dbg_log_num ((unsigned)cap.caps)
|
||||
dbg_log ("; caps mem=")
|
||||
dbg_log_num ((unsigned)cap.caps->address_space)
|
||||
dbg_log ("; cap=")
|
||||
dbg_log_num ((unsigned)cap.deref ())
|
||||
dbg_log ("; cap target=")
|
||||
dbg_log_num ((unsigned)cap->target)
|
||||
dbg_log ("; protected=")
|
||||
dbg_log_num (cap->protected_data.l)
|
||||
dbg_log ("!= receiver\n")
|
||||
kdebug ("Buggy: receiver=")
|
||||
kdebug_num ((unsigned)r)
|
||||
kdebug ("; caps=")
|
||||
kdebug_num ((unsigned)cap.caps)
|
||||
kdebug ("; caps mem=")
|
||||
kdebug_num ((unsigned)cap.caps->address_space)
|
||||
kdebug ("; cap=")
|
||||
kdebug_num ((unsigned)cap.deref ())
|
||||
kdebug ("; cap target=")
|
||||
kdebug_num ((unsigned)cap->target)
|
||||
kdebug ("; protected=")
|
||||
kdebug_num (cap->protected_data.l)
|
||||
kdebug ("!= receiver\n")
|
||||
dpanic (line, "consistency bug in kernel capabilities")
|
||||
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
|
||||
check_receiver (r, c, line)
|
||||
@ -523,60 +555,65 @@ void kReceiver::check (unsigned line):
|
||||
void kMemory::check (unsigned line):
|
||||
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
|
||||
r->check (line)
|
||||
for kThread *t = threads; t; t = (kThread *)t->next:
|
||||
if t->flags & Kernel::Thread::RUNNING && t->pc == 0:
|
||||
kdebug_num ((unsigned)t)
|
||||
kdebug ("\n")
|
||||
panic (line, "pc is 0")
|
||||
for kMemory *m = memories; m; m = (kMemory *)m->next:
|
||||
m->check (line)
|
||||
|
||||
static void print_obj (kObject *o):
|
||||
for kObject *obj = o; o; o = (kObject *)o->next:
|
||||
dbg_log_num ((unsigned)o)
|
||||
dbg_log ("->")
|
||||
dbg_log ("NULL\n")
|
||||
kdebug_num ((unsigned)o)
|
||||
kdebug ("->")
|
||||
kdebug ("NULL\n")
|
||||
|
||||
void kMemory::print (unsigned line, unsigned indent):
|
||||
if indent == 0:
|
||||
print_free ()
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
kdebug ('\t')
|
||||
++indent
|
||||
dbg_log ("Memory ")
|
||||
dbg_log_num ((unsigned)this)
|
||||
dbg_log ("\n")
|
||||
kdebug ("Memory ")
|
||||
kdebug_num ((unsigned)this)
|
||||
kdebug ("\n")
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
dbg_log ("frees: ")
|
||||
kdebug ('\t')
|
||||
kdebug ("frees: ")
|
||||
for kFree *f = frees; f; f = (kFree *)f->next:
|
||||
dbg_log_num ((unsigned)f)
|
||||
dbg_log (":")
|
||||
kdebug_num ((unsigned)f)
|
||||
kdebug (":")
|
||||
unsigned n = (unsigned)NEXT (f)
|
||||
if n:
|
||||
n -= (unsigned)f
|
||||
if n >= PAGE_SIZE:
|
||||
dpanic (0, "invalid kFree")
|
||||
dbg_log_num (n, 3)
|
||||
dbg_log ("->")
|
||||
dbg_log ("NULL\n")
|
||||
kdebug_num (n, 3)
|
||||
kdebug ("->")
|
||||
kdebug ("NULL\n")
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
dbg_log ("pages: ")
|
||||
kdebug ('\t')
|
||||
kdebug ("pages: ")
|
||||
print_obj (pages)
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
dbg_log ("threads: ")
|
||||
kdebug ('\t')
|
||||
kdebug ("threads: ")
|
||||
print_obj (threads)
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
dbg_log ("receivers: ")
|
||||
kdebug ('\t')
|
||||
kdebug ("receivers: ")
|
||||
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
|
||||
dbg_log_num ((unsigned)r)
|
||||
dbg_log ("(")
|
||||
kdebug_num ((unsigned)r)
|
||||
kdebug ("(")
|
||||
for kMessage *m = r->messages; m; m = (kMessage *)m->next:
|
||||
dbg_log_num ((unsigned)m)
|
||||
dbg_log ("->")
|
||||
dbg_log ("NULL)->")
|
||||
dbg_log ("NULL\n")
|
||||
kdebug_num ((unsigned)m)
|
||||
kdebug ("->")
|
||||
kdebug ("NULL)->")
|
||||
kdebug ("NULL\n")
|
||||
for unsigned i = 0; i < indent; ++i:
|
||||
dbg_log_char ('\t')
|
||||
dbg_log ("capses: ")
|
||||
kdebug ('\t')
|
||||
kdebug ("capses: ")
|
||||
print_obj (capses)
|
||||
for kMemory *m = memories; m; m = (kMemory *)m->next:
|
||||
m->print (line, indent)
|
||||
|
@ -105,7 +105,7 @@ extern "C":
|
||||
__slot_admin = slot_admin
|
||||
__cap_admin = cap_admin
|
||||
__first_free_slot = NULL
|
||||
for unsigned i = 2; i < __slots; ++i:
|
||||
for unsigned i = 1; i < __slots; ++i:
|
||||
Kernel::free_slot (i)
|
||||
__first_free_cap = NULL
|
||||
for unsigned i = 7; i < __caps; ++i:
|
||||
|
@ -20,9 +20,13 @@
|
||||
#include "iris.hh"
|
||||
#include <elf.h>
|
||||
|
||||
#define NUM_SLOTS 4
|
||||
#define NUM_SLOTS 8
|
||||
#define NUM_CAPS 32
|
||||
|
||||
enum Cap_codes:
|
||||
SYSREQ = 1 << 16
|
||||
THREAD
|
||||
|
||||
static unsigned _free
|
||||
extern unsigned _end
|
||||
|
||||
@ -71,6 +75,10 @@ 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
|
||||
|
||||
// Get the initial block device and filesystem.
|
||||
static Directory receive_devices ():
|
||||
@ -175,8 +183,10 @@ static void sort ():
|
||||
index[i + 1] = index[i]
|
||||
index[i + 1] = f
|
||||
|
||||
static void run (file *f, bool priv):
|
||||
Kernel::Memory mem = top_memory.create_memory ()
|
||||
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)
|
||||
@ -310,7 +320,7 @@ static void run (file *f, bool priv):
|
||||
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 (++current_thread)
|
||||
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 ())
|
||||
@ -319,7 +329,6 @@ static void run (file *f, bool priv):
|
||||
thread.run ()
|
||||
Kernel::free_cap (receiver)
|
||||
Kernel::free_cap (thread)
|
||||
Kernel::free_cap (mem)
|
||||
Kernel::free_cap (call)
|
||||
Kernel::free_cap (parent)
|
||||
Kernel::free_cap (caps)
|
||||
@ -331,10 +340,13 @@ static void kdebug_name (char const *t, file *f):
|
||||
kdebug_char (f->name[j])
|
||||
kdebug ("...")
|
||||
|
||||
static Device sysreq_dev
|
||||
|
||||
struct Dev:
|
||||
static Dev *devs
|
||||
static unsigned num_devs
|
||||
Dev *next
|
||||
unsigned code, idx
|
||||
unsigned code, idx, id
|
||||
Device dev
|
||||
static Dev *find (unsigned c, unsigned i):
|
||||
for Dev *d = devs; d; d = d->next:
|
||||
@ -342,6 +354,9 @@ struct Dev:
|
||||
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 ()
|
||||
@ -350,6 +365,7 @@ struct Dev:
|
||||
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 (">")
|
||||
@ -358,8 +374,9 @@ struct Dev:
|
||||
kdebug_num (d->idx)
|
||||
|
||||
Dev *Dev::devs
|
||||
unsigned Dev::num_devs
|
||||
|
||||
void handle_init ():
|
||||
static void handle_init (unsigned id):
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.data[0].l:
|
||||
@ -368,46 +385,55 @@ void handle_init ():
|
||||
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::GET_DEVICE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h)
|
||||
if d:
|
||||
kdebug ("giving dev ")
|
||||
kdebug_num (Kernel::recv.data[1].l)
|
||||
kdebug (":")
|
||||
kdebug_num (Kernel::recv.data[0].h)
|
||||
kdebug ("\n")
|
||||
Kernel::Cap cap = d->dev.create_user (Kernel::my_memory)
|
||||
d->dev.use (cap)
|
||||
reply.invoke (0, 0, cap.copy ())
|
||||
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)
|
||||
break
|
||||
case Parent::INIT_DONE:
|
||||
memories.set (id + num_files, Kernel::get_reply ())
|
||||
return
|
||||
default:
|
||||
kdebug ("unknown init request\n")
|
||||
Kernel::panic (0)
|
||||
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:
|
||||
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::Cap cap = Kernel::Caps (terminal_slot, id).get (d->id)
|
||||
d->dev.use (cap)
|
||||
reply.invoke (0, 0, cap.copy ())
|
||||
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)
|
||||
|
||||
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 ()
|
||||
@ -417,16 +443,66 @@ Kernel::Num start ():
|
||||
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] == '#')
|
||||
run (&files[index[i]], files[index[i]].name[0] == '#', i)
|
||||
kdebug ("running\n")
|
||||
handle_init ()
|
||||
handle_init (i)
|
||||
// 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)
|
||||
unsigned termslot = term.use ()
|
||||
for Dev *d = Dev::devs; d; d = d->next:
|
||||
Kernel::set_recv_arg (Kernel::Cap (termslot, d->id))
|
||||
// The 0x15000 is for the Display; the others don't care about it.
|
||||
d->dev.create_user (mem, 0, 0x15000)
|
||||
Kernel::free_slot (termslot)
|
||||
// set up system request.
|
||||
Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory)
|
||||
sysreq_dev.use (sysreq)
|
||||
Kernel::free_cap (sysreq_dev)
|
||||
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)
|
||||
kdebug ("init done\n")
|
||||
root.unlock_ro ()
|
||||
Kernel::free_slot (slot)
|
||||
Kernel::my_memory.destroy (caps)
|
||||
while true:
|
||||
handle_init ()
|
||||
//Kernel::wait ()
|
||||
//kdebug ("request!\n")
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case SYSREQ:
|
||||
// System request.
|
||||
if Kernel::recv.data[0].l & Keyboard::RELEASE:
|
||||
continue
|
||||
kdebug ("system request...\n")
|
||||
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::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
|
||||
default:
|
||||
Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request")
|
||||
|
33
devices.hhp
33
devices.hhp
@ -86,8 +86,8 @@ struct Device : public Kernel::Cap:
|
||||
ID
|
||||
// Create a new user for this device. It will not be the active user.
|
||||
// The provided storage must allow object creation; no other actions may be used by the terminal.
|
||||
Kernel::Cap create_user (Kernel::Memory storage):
|
||||
iocall (storage, CAP_MASTER_DIRECT | CREATE_USER)
|
||||
Kernel::Cap create_user (Kernel::Memory storage, unsigned arg1 = 0, Kernel::Num arg2 = 0):
|
||||
iocall (storage, Kernel::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2)
|
||||
return Kernel::get_arg ()
|
||||
// Destroy a user. It is made inactive if it was active.
|
||||
void destroy_user (Kernel::Cap user):
|
||||
@ -161,7 +161,7 @@ struct Parent : public Kernel::Cap:
|
||||
return Kernel::get_arg ()
|
||||
// Signal the parent that the initialisation phase is over.
|
||||
void init_done ():
|
||||
invoke (CAP_MASTER_DIRECT | 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)
|
||||
@ -205,33 +205,24 @@ struct Buzzer : public Kernel::Cap:
|
||||
struct Display : public Kernel::Cap:
|
||||
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
EOF_CB = Buzzer::ID
|
||||
CREATE_FB
|
||||
USE_FB
|
||||
SET_EOF_CB = Buzzer::ID
|
||||
MAP_FB
|
||||
GET_INFO
|
||||
SET_STATE
|
||||
ID
|
||||
// Register an end-of-frame callback.
|
||||
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
|
||||
void set_eof_cb (Kernel::Cap cb):
|
||||
ocall (cb, CAP_MASTER_DIRECT | EOF_CB)
|
||||
// Create a framebuffer for the display. When not in use, it can be freed by the user.
|
||||
// The pages must be cappages holding Page capabilities. They are filled by the display.
|
||||
// The passed numbers must be 0 or match a mode that the device can use.
|
||||
// The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
|
||||
unsigned create_framebuffer (unsigned w = 0, unsigned h = 0, unsigned mode = 0):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Kernel::Num ((w << 16) | h, mode)).l
|
||||
// Use a framebuffer. The address must have been returned from display_create_framebuffer.
|
||||
// w, h and mode must match the values given at creation time.
|
||||
// unuse_cb is called the next time this operation is requested for this display.
|
||||
void use_framebuffer (unsigned addr, Kernel::Cap unuse_cb = Kernel::Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0):
|
||||
ocall (unuse_cb, Kernel::Num (CAP_MASTER_DIRECT | USE_FB, addr), Kernel::Num ((w << 16) | h, mode))
|
||||
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
|
||||
// Map the framebuffer into memory.
|
||||
void map_fb (unsigned address):
|
||||
call (CAP_MASTER_DIRECT | MAP_FB, address)
|
||||
// Get information about the display.
|
||||
void get_info ():
|
||||
// TODO: Interface is to be designed.
|
||||
kdebug ("using undefined interface Display::get_info ()\n")
|
||||
Kernel::panic (0)
|
||||
|
||||
|
||||
// Numeric setting, such as a display backlight.
|
||||
// Numerical setting, such as a display backlight.
|
||||
struct Setting : public Kernel::Cap:
|
||||
Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
|
218
invoke.ccp
218
invoke.ccp
@ -19,50 +19,55 @@
|
||||
#include "kernel.hh"
|
||||
|
||||
static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c):
|
||||
dbg_log (prefix)
|
||||
dbg_log (": caller=")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log ("; target=")
|
||||
dbg_log_num (target)
|
||||
dbg_log ("; pdata=")
|
||||
dbg_log_num (pdata)
|
||||
dbg_log ("; data=")
|
||||
dbg_log_num (c->data[0].h)
|
||||
dbg_log (":")
|
||||
dbg_log_num (c->data[0].l)
|
||||
dbg_log (",")
|
||||
dbg_log_num (c->data[1].h)
|
||||
dbg_log (":")
|
||||
dbg_log_num (c->data[1].l)
|
||||
kdebug (prefix)
|
||||
kdebug (": caller=")
|
||||
if old_current:
|
||||
kdebug_num (old_current->id, 2)
|
||||
else
|
||||
kdebug ("xx")
|
||||
kdebug (":")
|
||||
kdebug_num ((unsigned)old_current)
|
||||
kdebug ("; target=")
|
||||
kdebug_num (target)
|
||||
kdebug ("; pdata=")
|
||||
kdebug_num (pdata)
|
||||
kdebug ("; data=")
|
||||
kdebug_num (c->data[0].h)
|
||||
kdebug (":")
|
||||
kdebug_num (c->data[0].l)
|
||||
kdebug (",")
|
||||
kdebug_num (c->data[1].h)
|
||||
kdebug (":")
|
||||
kdebug_num (c->data[1].l)
|
||||
if c->reply.valid ():
|
||||
dbg_log ("; reply target=")
|
||||
dbg_log_num ((unsigned)c->reply->target)
|
||||
dbg_log ("; pdata=")
|
||||
dbg_log_num (c->reply->protected_data.l)
|
||||
kdebug ("; reply target=")
|
||||
kdebug_num ((unsigned)c->reply->target)
|
||||
kdebug ("; pdata=")
|
||||
kdebug_num (c->reply->protected_data.l)
|
||||
if c->arg.valid ():
|
||||
dbg_log ("; arg target=")
|
||||
dbg_log_num ((unsigned)c->arg->target)
|
||||
dbg_log ("; pdata=")
|
||||
dbg_log_num (c->arg->protected_data.l)
|
||||
dbg_log ("\n")
|
||||
kdebug ("; arg target=")
|
||||
kdebug_num ((unsigned)c->arg->target)
|
||||
kdebug ("; pdata=")
|
||||
kdebug_num (c->arg->protected_data.l)
|
||||
kdebug ("\n")
|
||||
|
||||
void kThread::raise (unsigned code, unsigned data):
|
||||
dbg_log ("raise ")
|
||||
kdebug ("raise ")
|
||||
if old_current:
|
||||
dbg_log_num (old_current->id, 2)
|
||||
kdebug_num (old_current->id, 2)
|
||||
else:
|
||||
dbg_log ("xx")
|
||||
dbg_log_char (':')
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log_char ('/')
|
||||
kdebug ("xx")
|
||||
kdebug (':')
|
||||
kdebug_num ((unsigned)old_current)
|
||||
kdebug ('/')
|
||||
if code < Kernel::NUM_EXCEPTION_CODES:
|
||||
dbg_log (Kernel::exception_name[code])
|
||||
kdebug (Kernel::exception_name[code])
|
||||
else:
|
||||
dbg_log ("invalid code:")
|
||||
dbg_log_num (code)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (data)
|
||||
dbg_log_char ('\n')
|
||||
kdebug ("invalid code:")
|
||||
kdebug_num (code)
|
||||
kdebug ('/')
|
||||
kdebug_num (data)
|
||||
kdebug ('\n')
|
||||
dpanic (code, "raise")
|
||||
unrun ()
|
||||
if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target:
|
||||
@ -79,20 +84,20 @@ kCapRef kThread::find_capability (unsigned code, bool *copy):
|
||||
unsigned num = c & 0xffff
|
||||
if s >= slots || !slot[s].caps || num >= slot[s].caps->size:
|
||||
if c != CAP_NONE:
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log (": invalid capability ")
|
||||
dbg_log_num (code)
|
||||
dbg_log_char ('\n')
|
||||
dbg_log_num (num)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (s)
|
||||
dbg_log (" > ")
|
||||
kdebug_num ((unsigned)old_current)
|
||||
kdebug (": invalid capability ")
|
||||
kdebug_num (code)
|
||||
kdebug ('\n')
|
||||
kdebug_num (num)
|
||||
kdebug (':')
|
||||
kdebug_num (s)
|
||||
kdebug (" > ")
|
||||
if slot[s].caps:
|
||||
dbg_log_num (slot[s].caps->size)
|
||||
kdebug_num (slot[s].caps->size)
|
||||
else:
|
||||
dbg_log ("no caps")
|
||||
dbg_log_char ('\n')
|
||||
dpanic (code, "debug")
|
||||
kdebug ("no caps")
|
||||
kdebug ('\n')
|
||||
dpanic (code, "invalid capability")
|
||||
return kCapRef ()
|
||||
return kCapRef (slot[s].caps, num)
|
||||
|
||||
@ -156,9 +161,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *
|
||||
return true
|
||||
|
||||
static kCapability::Context *context
|
||||
// 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.
|
||||
static kCaps reply_caps, replied_caps
|
||||
static kReceiver *reply_target
|
||||
static Kernel::Num reply_protected
|
||||
|
||||
@ -181,16 +183,16 @@ static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
||||
dpanic (0, "nothing to reply to")
|
||||
|
||||
static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref, unsigned num = 0):
|
||||
if !reply_target:
|
||||
dpanic (0, "nothing to reply to")
|
||||
return
|
||||
replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
|
||||
kCapability::Context c
|
||||
c.arg = kCapRef (&replied_caps, 0)
|
||||
c.copy[1] = true
|
||||
c.data[0] = Kernel::Num (num, 0)
|
||||
if reply_target:
|
||||
reply_target->send_message (reply_protected, &c)
|
||||
c.arg->invalidate ()
|
||||
else:
|
||||
dpanic (0, "nothing to reply to")
|
||||
reply_target->send_message (reply_protected, &c)
|
||||
c.arg->invalidate ()
|
||||
|
||||
static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
|
||||
kReceiver *receiver = (kReceiver *)protected_data.l
|
||||
@ -214,15 +216,15 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
||||
case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
|
||||
if !c->arg.valid () || c->arg->target != receiver:
|
||||
if !c->arg.valid ():
|
||||
dbg_log ("invalid arg\n")
|
||||
kdebug ("invalid arg\n")
|
||||
else:
|
||||
dbg_log ("target: ")
|
||||
dbg_log_num ((unsigned)c->arg->target)
|
||||
dbg_log ("/")
|
||||
dbg_log_num ((unsigned)c->arg->protected_data.h)
|
||||
dbg_log (":")
|
||||
dbg_log_num ((unsigned)c->arg->protected_data.l)
|
||||
dbg_log ("\n")
|
||||
kdebug ("target: ")
|
||||
kdebug_num ((unsigned)c->arg->target)
|
||||
kdebug ("/")
|
||||
kdebug_num ((unsigned)c->arg->protected_data.h)
|
||||
kdebug (":")
|
||||
kdebug_num ((unsigned)c->arg->protected_data.l)
|
||||
kdebug ("\n")
|
||||
dpanic (0, "wrong argument for get_protected")
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
@ -264,7 +266,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
||||
reply_num (receiver->alarm_count)
|
||||
return
|
||||
default:
|
||||
dpanic (0, "invalid receiver operation")
|
||||
dpanic (cmd, "invalid receiver operation")
|
||||
reply_num (Kernel::ERR_INVALID_OPERATION)
|
||||
return
|
||||
reply_num (0)
|
||||
@ -294,6 +296,9 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
kThread *ret = mem->alloc_thread (c->data[1].l)
|
||||
if ret:
|
||||
reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs)
|
||||
//kdebug ("created thread: ")
|
||||
//kdebug_num ((unsigned)ret)
|
||||
//kdebug ("\n")
|
||||
else:
|
||||
dpanic (0x23311992, "out of memory creating thread")
|
||||
reply_num (Kernel::ERR_OUT_OF_MEMORY)
|
||||
@ -358,7 +363,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
if c->data[1].l & (unsigned)c->arg->target & Kernel::Page::READONLY:
|
||||
dbg_log ("Mapping readonly because capability is readonly\n")
|
||||
kdebug ("Mapping readonly because capability is readonly\n")
|
||||
page->flags |= Kernel::Page::MAPPED_READONLY
|
||||
mem->map (page, c->data[1].l & PAGE_MASK)
|
||||
break
|
||||
@ -526,7 +531,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
page->address_space->unuse ()
|
||||
else:
|
||||
page->flags |= Kernel::Page::PAYING
|
||||
page->frame = c->data[1].l & PAGE_MASK
|
||||
page->frame = (c->data[1].l & PAGE_MASK) | 0x80000000
|
||||
page->flags |= Kernel::Page::FRAME
|
||||
if !(c->data[1].l & 1):
|
||||
page->flags |= Kernel::Page::UNCACHED
|
||||
@ -545,6 +550,9 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK:
|
||||
arch_reboot ()
|
||||
case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
|
||||
if c->data[1].l == 0xdeaddead:
|
||||
dbg_code.l = 1
|
||||
break
|
||||
panic (c->data[1].l, "panic requested by thread")
|
||||
reply_num (~0)
|
||||
return
|
||||
@ -602,9 +610,9 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY:
|
||||
t->flags |= Kernel::Page::READONLY
|
||||
if !(page->flags & Kernel::Page::FRAME):
|
||||
dbg_log ("share problem: ")
|
||||
dbg_log_num (page->flags)
|
||||
dbg_log ("\n")
|
||||
kdebug ("share problem: ")
|
||||
kdebug_num (page->flags)
|
||||
kdebug ("\n")
|
||||
dpanic (0, "sharing nothing results in lost page")
|
||||
kPage_arch_update_mapping (t)
|
||||
break
|
||||
@ -727,35 +735,52 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
|
||||
static void print_cap (kCapRef cap, kCapRef self):
|
||||
if cap.deref () == self.deref ():
|
||||
dbg_log_char ('{')
|
||||
kdebug ('{')
|
||||
else:
|
||||
dbg_log_char ('[')
|
||||
dbg_log_num ((unsigned)cap.caps)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (cap.index, 1)
|
||||
kdebug ('[')
|
||||
kdebug_num ((unsigned)cap.caps)
|
||||
kdebug (':')
|
||||
kdebug_num (cap.index, 1)
|
||||
if !cap.valid ():
|
||||
dbg_log_char ('!')
|
||||
kdebug ('!')
|
||||
else:
|
||||
dbg_log_char ('=')
|
||||
dbg_log_num ((unsigned)cap->target)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (cap->protected_data.l)
|
||||
kdebug ('=')
|
||||
kdebug_num ((unsigned)cap->target)
|
||||
kdebug (':')
|
||||
kdebug_num (cap->protected_data.l)
|
||||
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
|
||||
print_cap (c, self)
|
||||
if cap.deref () == self.deref ():
|
||||
dbg_log_char ('}')
|
||||
kdebug ('}')
|
||||
else:
|
||||
dbg_log_char (']')
|
||||
kdebug (']')
|
||||
|
||||
static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
|
||||
kCaps *caps = (kCapsP)protected_data.l
|
||||
switch cmd:
|
||||
case Kernel::Caps::GET & REQUEST_MASK:
|
||||
if c->data[1].l >= caps->size:
|
||||
dpanic (0, "invalid index for get caps")
|
||||
reply_num (Kernel::ERR_INVALID_ARGUMENT)
|
||||
kdebug_num ((unsigned)caps)
|
||||
kdebug (" size: ")
|
||||
kdebug_num (caps->size)
|
||||
kdebug ('\n')
|
||||
dpanic (c->data[1].l, "invalid index for get caps")
|
||||
return
|
||||
kCapability *ret = caps->cap (c->data[1].l)
|
||||
reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->target)->refs : &ret->target->capabilities)
|
||||
#if 0
|
||||
kdebug_num ((unsigned)caps)
|
||||
kdebug (" get cap ")
|
||||
kdebug_num (c->data[1].l)
|
||||
kdebug (" = ")
|
||||
kdebug_num ((unsigned)ret->target)
|
||||
kdebug ("/")
|
||||
kdebug_num (ret->protected_data.h)
|
||||
kdebug (":")
|
||||
kdebug_num (ret->protected_data.l)
|
||||
kdebug ("\n")
|
||||
#endif
|
||||
reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities)
|
||||
return
|
||||
case Kernel::Caps::GET_SIZE & REQUEST_MASK:
|
||||
reply_num (caps->size)
|
||||
@ -766,6 +791,16 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
return
|
||||
caps->clone (c->data[1].l, c->arg, c->copy[1])
|
||||
reply_num (0)
|
||||
//kdebug_num ((unsigned)caps)
|
||||
//kdebug (" set cap ")
|
||||
//kdebug_num (c->data[1].l)
|
||||
//kdebug (" to ")
|
||||
//kdebug_num ((unsigned)caps->caps[c->data[1].l].target)
|
||||
//kdebug ("/")
|
||||
//kdebug_num (caps->caps[c->data[1].l].protected_data.h)
|
||||
//kdebug (":")
|
||||
//kdebug_num (caps->caps[c->data[1].l].protected_data.l)
|
||||
//kdebug ("\n")
|
||||
return
|
||||
case Kernel::Caps::TRUNCATE & REQUEST_MASK:
|
||||
dpanic (0, "truncate caps is not implemented yet.")
|
||||
@ -800,7 +835,7 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
|
||||
while cap.valid ():
|
||||
print_cap (cap, orig)
|
||||
cap = cap->sibling_next
|
||||
dbg_log_char ('\n')
|
||||
kdebug ('\n')
|
||||
return
|
||||
default:
|
||||
dpanic (0, "invalid caps operation")
|
||||
@ -916,7 +951,11 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
|
||||
if must_wait:
|
||||
old_current->wait ()
|
||||
if !reply_target:
|
||||
dpanic (0x54635675, "no target to call")
|
||||
if (c->reply.index & ~CAP_COPY) != CAP_NONE:
|
||||
kdebug ("target index: ")
|
||||
kdebug_num (c->reply.index)
|
||||
kdebug ("\n")
|
||||
dpanic (0x54635675, "no target to call")
|
||||
return
|
||||
if ((unsigned)reply_target & ~KERNEL_MASK) != 0:
|
||||
// This is a user-implemented object. Create a real reply capability.
|
||||
@ -988,14 +1027,19 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
|
||||
return
|
||||
|
||||
void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c):
|
||||
//log_message ("invoke", (unsigned)target, protected_data.l, c)
|
||||
if dbg_code.l && old_current->id != 1:
|
||||
log_message ("invoke", (unsigned)target, protected_data.l, c)
|
||||
if (unsigned)target & ~KERNEL_MASK:
|
||||
// This is not a kernel capability: send a message to the receiver.
|
||||
if must_wait:
|
||||
old_current->wait ()
|
||||
//else
|
||||
// log_message ("user invoke", (unsigned)target, protected_data.l, c)
|
||||
target->send_message (protected_data, c)
|
||||
return
|
||||
// This is a kernel capability. Use a function to allow optimized call capabilities.
|
||||
//if !must_wait && old_current->id == ~0
|
||||
// log_message ("kernel invoke", (unsigned)target, protected_data.l, c)
|
||||
context = c
|
||||
if c->reply.valid ():
|
||||
reply_target = c->reply->target
|
||||
|
21
iris.hhp
21
iris.hhp
@ -229,12 +229,14 @@ namespace Kernel:
|
||||
IMessage i
|
||||
i.data[0] = d0
|
||||
i.data[1] = d1
|
||||
i.arg = Cap (CAP_NONE)
|
||||
_call (&i)
|
||||
return recv.data[0]
|
||||
Num Cap::icall (Num d0, Num d1):
|
||||
IMessage i
|
||||
i.data[0] = d0
|
||||
i.data[1] = d1
|
||||
i.arg = Cap (CAP_NONE)
|
||||
_call (&i)
|
||||
return recv.data[0]
|
||||
Num Cap::ocall (Cap c, Num d0, Num d1):
|
||||
@ -541,7 +543,7 @@ namespace Kernel:
|
||||
ocall (target, CAP_MASTER_DIRECT | DESTROY)
|
||||
// TODO: LIST
|
||||
bool map (Cap page, unsigned address):
|
||||
return ocall (page, CAP_MASTER_DIRECT | MAP, address).l != ~0
|
||||
return ocall (page, CAP_MASTER_DIRECT | MAP, address).l == NO_ERROR
|
||||
Page mapping (void *address):
|
||||
icall (CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address))
|
||||
return get_arg ()
|
||||
@ -568,8 +570,6 @@ namespace Kernel:
|
||||
my_thread.call (CAP_MASTER_DIRECT | Thread::DBG_SEND, Num (code, bits))
|
||||
inline void reboot ():
|
||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REBOOT)
|
||||
inline void panic (unsigned code):
|
||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
||||
|
||||
void Receiver::sleep (unsigned value):
|
||||
my_receiver.set_alarm (value)
|
||||
@ -578,7 +578,8 @@ namespace Kernel:
|
||||
// The start function has this prototype (there is no main function).
|
||||
Kernel::Num start ()
|
||||
|
||||
#if 1 && !defined (__KERNEL__)
|
||||
#ifndef __KERNEL__
|
||||
#if 1
|
||||
// Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing.
|
||||
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
|
||||
#else
|
||||
@ -595,4 +596,16 @@ static void kdebug_num (unsigned n, unsigned digits = 8):
|
||||
for i = 0; i < digits; ++i:
|
||||
kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf])
|
||||
|
||||
namespace Kernel:
|
||||
inline void panic (unsigned code, char const *message = NULL):
|
||||
if message:
|
||||
kdebug (message)
|
||||
kdebug_char ('\n')
|
||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
||||
if code == 0xdeaddead:
|
||||
return
|
||||
while true:
|
||||
wait ()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
50
kernel.hhp
50
kernel.hhp
@ -40,16 +40,14 @@ struct kList
|
||||
struct kListitem
|
||||
|
||||
// Some functions which must be defined early.
|
||||
extern "C":
|
||||
#ifndef NDEBUG
|
||||
void dbg_log_char (unsigned ch)
|
||||
void dbg_log (char const *str)
|
||||
void dbg_log_num (unsigned num, unsigned digits = 8)
|
||||
#else
|
||||
#define dbg_log_char(x) do {} while (0)
|
||||
#define dbg_log(x) do {} while (0)
|
||||
#define dbg_log_num(n) do {} while (0)
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
void kdebug (unsigned ch)
|
||||
void kdebug (char const *str)
|
||||
void kdebug_num (unsigned num, unsigned digits = 8)
|
||||
#else
|
||||
#define kdebug(x) do {} while (0)
|
||||
#define kdebug_num(n) do {} while (0)
|
||||
#endif
|
||||
|
||||
#include "iris.hh"
|
||||
|
||||
@ -178,12 +176,14 @@ struct kCaps : public kObject:
|
||||
_slot_data first_slot
|
||||
unsigned size
|
||||
kCapability caps[1]
|
||||
kCapability *cap (unsigned idx):
|
||||
return &caps[idx]
|
||||
inline kCapability *cap (unsigned idx)
|
||||
void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
|
||||
void clone (unsigned index, kCapRef source, bool copy)
|
||||
void init (unsigned size)
|
||||
|
||||
// The 8 comes from the size of the admin data in a free page. When changing that, this must be changed as well.
|
||||
#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1)
|
||||
|
||||
struct kMessage : public kObject:
|
||||
Kernel::Num protected_data
|
||||
Kernel::Num data[2]
|
||||
@ -258,6 +258,12 @@ extern "C":
|
||||
void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
|
||||
#ifndef NDEBUG
|
||||
EXTERN Kernel::Num dbg_code
|
||||
EXTERN unsigned dbg_buffer[32]
|
||||
EXTERN unsigned dbg_buffer_head
|
||||
static void dbg_push (unsigned n):
|
||||
dbg_buffer[dbg_buffer_head++] = n
|
||||
if dbg_buffer_head == 32:
|
||||
dbg_buffer_head = 0
|
||||
EXTERN kCapRef dbg_cap
|
||||
void dbg_send (unsigned num, unsigned bits)
|
||||
void check (unsigned num, char const *msg)
|
||||
@ -285,6 +291,9 @@ EXTERN kPage idle_page
|
||||
EXTERN kThreadP first_scheduled
|
||||
EXTERN kThreadP current, old_current
|
||||
EXTERN bool do_schedule, must_wait
|
||||
// reply_caps is the source of a receiver-generated reply capability.
|
||||
// replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply.
|
||||
EXTERN kCaps reply_caps, replied_caps
|
||||
|
||||
// Defined in memory.ccp
|
||||
unsigned init_memory (unsigned mem)
|
||||
@ -311,6 +320,11 @@ void arch_register_interrupt (unsigned num, kReceiverP r)
|
||||
void arch_reboot ()
|
||||
void arch_uncache_page (unsigned page)
|
||||
|
||||
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||
#define __stringify2(x) #x
|
||||
#define __stringify(x) __stringify2 (x)
|
||||
#define kdebug_line() do { kdebug (__FILE__ ":"); kdebug (__PRETTY_FUNCTION__); kdebug (":"); kdebug (__stringify (__LINE__)); kdebug ('\n'); } while (0)
|
||||
|
||||
bool kMemory::map (kPage *page, unsigned address):
|
||||
return kMemory_arch_map (this, page, address)
|
||||
void kMemory::unmap (kPage *page):
|
||||
@ -323,13 +337,15 @@ kCapability *kCapRef::deref ():
|
||||
void kCapRef::clone (kCapRef source, bool copy):
|
||||
caps->clone (index, source, copy)
|
||||
void kCapRef::set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr):
|
||||
if valid ():
|
||||
deref ()->invalidate ()
|
||||
caps->set (index, target, pdata, parent, parent_ptr)
|
||||
void kCapability::invoke (kCapability::Context *c):
|
||||
::invoke (target, protected_data, c)
|
||||
|
||||
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||
#define __stringify2(x) #x
|
||||
#define __stringify(x) __stringify2 (x)
|
||||
#define dbg_log_line() do { dbg_log (__FILE__ ":"); dbg_log (__PRETTY_FUNCTION__); dbg_log (":"); dbg_log (__stringify (__LINE__)); dbg_log_char ('\n'); } while (0)
|
||||
kCapability *kCaps::cap (unsigned idx):
|
||||
if idx >= size:
|
||||
dpanic (idx, "invalid capability requested\n")
|
||||
return NULL
|
||||
return &caps[idx]
|
||||
|
||||
#endif
|
||||
|
78
memory.ccp
78
memory.ccp
@ -1,9 +1,17 @@
|
||||
#pypp 0
|
||||
#include "kernel.hh"
|
||||
//#define DEBUG_ALLOC
|
||||
|
||||
extern unsigned _end
|
||||
|
||||
static void clear_page (unsigned page, unsigned num = 1):
|
||||
#ifdef DEBUG_ALLOC
|
||||
kdebug ("clearing page ")
|
||||
kdebug_num (page)
|
||||
kdebug ("+")
|
||||
kdebug_num (num)
|
||||
kdebug ('\n')
|
||||
#endif
|
||||
page = (page & ~0xc0000000) | 0xa0000000
|
||||
for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
|
||||
arch_uncache_page (page - 0x20000000)
|
||||
@ -24,7 +32,7 @@ unsigned init_memory (unsigned mem):
|
||||
|
||||
unsigned phys_alloc (unsigned num):
|
||||
if free_begin + num * PAGE_SIZE > free_end:
|
||||
dbg_log ("memory allocation failed\n")
|
||||
kdebug ("memory allocation failed\n")
|
||||
return 0
|
||||
unsigned ret = free_begin
|
||||
free_begin += num * PAGE_SIZE
|
||||
@ -57,14 +65,22 @@ unsigned init_memory (unsigned mem):
|
||||
first_free->next = NULL
|
||||
first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free & ~0xc0000000)) >> PAGE_BITS
|
||||
#ifdef DEBUG_ALLOC
|
||||
dbg_log ("initial memory: ")
|
||||
dbg_log_num ((unsigned)first_free & ~0xc0000000)
|
||||
dbg_log ("+")
|
||||
dbg_log_num (first_free->num)
|
||||
dbg_log ("\n")
|
||||
kdebug ("initial memory: ")
|
||||
kdebug_num ((unsigned)first_free & ~0xc0000000)
|
||||
kdebug ("+")
|
||||
kdebug_num (first_free->num)
|
||||
kdebug ("\n")
|
||||
#endif
|
||||
return first_free->num
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
static bool is_free (unsigned page):
|
||||
for kFreePages *p = first_free; p; p = p->next:
|
||||
if page >= (unsigned)p && page < (unsigned)p + (p->num << PAGE_BITS):
|
||||
return true
|
||||
return false
|
||||
#endif
|
||||
|
||||
unsigned phys_alloc (unsigned num):
|
||||
kFreePages *choice = NULL
|
||||
for kFreePages *p = first_free; p; p = p->next:
|
||||
@ -81,11 +97,13 @@ unsigned phys_alloc (unsigned num):
|
||||
p->next->prev = p->prev
|
||||
clear_page ((unsigned)p, num)
|
||||
#ifdef DEBUG_ALLOC
|
||||
dbg_log ("allocating ")
|
||||
dbg_log_num ((unsigned)p & ~0xc0000000)
|
||||
dbg_log ("+")
|
||||
dbg_log_num (num << PAGE_BITS)
|
||||
dbg_log ("\n")
|
||||
kdebug ("allocating ")
|
||||
kdebug_num ((unsigned)p & ~0xc0000000)
|
||||
kdebug ("+")
|
||||
kdebug_num (num << PAGE_BITS)
|
||||
kdebug ("\n")
|
||||
if is_free ((unsigned)p):
|
||||
panic ((unsigned)p, "page still free after allocation")
|
||||
#endif
|
||||
return (unsigned)p
|
||||
choice = p
|
||||
@ -97,21 +115,25 @@ unsigned phys_alloc (unsigned num):
|
||||
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
|
||||
clear_page (ret, num)
|
||||
#ifdef DEBUG_ALLOC
|
||||
dbg_log ("allocating ")
|
||||
dbg_log_num (ret & ~0xc0000000)
|
||||
dbg_log ("+")
|
||||
dbg_log_num (num << PAGE_BITS)
|
||||
dbg_log ("\n")
|
||||
kdebug ("allocating ")
|
||||
kdebug_num (ret & ~0xc0000000)
|
||||
kdebug ("+")
|
||||
kdebug_num (num << PAGE_BITS)
|
||||
kdebug ("\n")
|
||||
if is_free (ret):
|
||||
panic (ret, "page still free after allocation")
|
||||
#endif
|
||||
return ret
|
||||
|
||||
void phys_free (unsigned page, unsigned num):
|
||||
#ifdef DEBUG_ALLOC
|
||||
dbg_log ("free ")
|
||||
dbg_log_num (page & ~0xc0000000)
|
||||
dbg_log ("+")
|
||||
dbg_log_num (num)
|
||||
dbg_log ("\n")
|
||||
kdebug ("free ")
|
||||
kdebug_num (page & ~0xc0000000)
|
||||
kdebug ("+")
|
||||
kdebug_num (num << PAGE_BITS)
|
||||
kdebug ("\n")
|
||||
if is_free (page):
|
||||
panic (page, "page already free")
|
||||
#endif
|
||||
unsigned size = num << PAGE_BITS
|
||||
if !first_free || (unsigned)first_free > page:
|
||||
@ -172,13 +194,13 @@ bool check_free (kObject *o, unsigned size):
|
||||
return true
|
||||
|
||||
void print_free ():
|
||||
dbg_log ("Free pages: ")
|
||||
kdebug ("Free pages: ")
|
||||
for kFreePages *p = first_free; p; p = p->next:
|
||||
dbg_log_num ((unsigned)p)
|
||||
dbg_log (":")
|
||||
dbg_log_num (p->num, 4)
|
||||
dbg_log ("->")
|
||||
dbg_log ("NULL\n")
|
||||
kdebug_num ((unsigned)p)
|
||||
kdebug (":")
|
||||
kdebug_num (p->num, 4)
|
||||
kdebug ("->")
|
||||
kdebug ("NULL\n")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -208,7 +230,7 @@ void raw_pfree (unsigned page):
|
||||
unsigned kMemory::zalloc ():
|
||||
if !use ():
|
||||
dpanic (0x34638920, "limit reached: allocation not allowed")
|
||||
dbg_log ("limit reached: allocation not allowed\n")
|
||||
kdebug ("limit reached: allocation not allowed\n")
|
||||
return NULL
|
||||
return raw_zalloc ()
|
||||
|
||||
|
@ -119,19 +119,19 @@ void kMemory_arch_init (kMemory *mem):
|
||||
mem->arch.shadow = NULL
|
||||
|
||||
static void tlb_reset (kMemory *mem, unsigned address, unsigned value):
|
||||
//dbg_log_line ()
|
||||
//kdebug_line ()
|
||||
unsigned asid = mem->arch.asid
|
||||
if asids[asid] != (unsigned)mem:
|
||||
//dbg_log ("not resetting tlb, because the asid is not in use.\n")
|
||||
//kdebug ("not resetting tlb, because the asid is not in use.\n")
|
||||
return
|
||||
//dbg_log ("resetting tlb for ")
|
||||
//dbg_log_num (address)
|
||||
//dbg_log ("\n")
|
||||
//kdebug ("resetting tlb for ")
|
||||
//kdebug_num (address)
|
||||
//kdebug ("\n")
|
||||
cp0_set (CP0_ENTRY_HI, address | asid)
|
||||
__asm__ volatile ("tlbp")
|
||||
unsigned idx
|
||||
cp0_get (CP0_INDEX, idx)
|
||||
if ~idx & 0x80000000:
|
||||
if !(idx & (1 << 31)):
|
||||
__asm__ volatile ("tlbr")
|
||||
if address & (1 << PAGE_BITS):
|
||||
cp0_set (CP0_ENTRY_LO1, value)
|
||||
@ -139,23 +139,26 @@ static void tlb_reset (kMemory *mem, unsigned address, unsigned value):
|
||||
cp0_set (CP0_ENTRY_LO0, value)
|
||||
__asm__ volatile ("tlbwi")
|
||||
#if 0
|
||||
dbg_log ("tlb reset ")
|
||||
kdebug ("tlb reset ")
|
||||
unsigned hi, lo0, lo1
|
||||
cp0_get (CP0_ENTRY_LO0, lo0)
|
||||
cp0_get (CP0_ENTRY_LO1, lo1)
|
||||
cp0_get (CP0_ENTRY_HI, hi)
|
||||
dbg_log_num (lo0)
|
||||
dbg_log (":")
|
||||
dbg_log_num (lo1)
|
||||
dbg_log (" for ")
|
||||
dbg_log_num (hi)
|
||||
dbg_log ("\n")
|
||||
kdebug_num (idx, 2)
|
||||
kdebug ('|')
|
||||
kdebug_num (lo0)
|
||||
kdebug (":")
|
||||
kdebug_num (lo1)
|
||||
kdebug (" for ")
|
||||
kdebug_num (hi)
|
||||
kdebug ("\n")
|
||||
#endif
|
||||
cp0_set (CP0_ENTRY_HI, old_current->address_space->arch.asid)
|
||||
|
||||
static unsigned make_entry_lo (kPage *page):
|
||||
//dbg_log_line ()
|
||||
//kdebug_line ()
|
||||
if !page->frame:
|
||||
//dbg_log ("not mapping because there is no frame\n")
|
||||
//kdebug ("not mapping because there is no frame\n")
|
||||
return 0
|
||||
unsigned flags
|
||||
if page->flags & Kernel::Page::UNCACHED:
|
||||
@ -168,7 +171,6 @@ static unsigned make_entry_lo (kPage *page):
|
||||
return ((page->frame & ~0x80000000) >> 6) | flags
|
||||
|
||||
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
|
||||
//dbg_log_line ()
|
||||
if address >= 0x80000000:
|
||||
dpanic (address, "trying to map to kernel address")
|
||||
return false
|
||||
@ -180,7 +182,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
|
||||
dpanic (address, "mapping not page-aligned")
|
||||
address &= PAGE_MASK
|
||||
if !mem->arch.directory:
|
||||
//dbg_log ("creating directory\n")
|
||||
//kdebug ("creating directory\n")
|
||||
mem->arch.directory = (Table **)mem->zalloc ()
|
||||
if !mem->arch.directory:
|
||||
dpanic (0, "unable to allocate directory")
|
||||
@ -193,7 +195,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
|
||||
return false
|
||||
Table *table = mem->arch.directory[address >> 21]
|
||||
if !table:
|
||||
//dbg_log ("creating table\n")
|
||||
//kdebug ("creating table\n")
|
||||
table = (Table *)mem->zalloc ()
|
||||
if !table:
|
||||
dpanic (0, "unable to allocate table")
|
||||
@ -206,21 +208,23 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
|
||||
mem->arch.directory[address >> 21] = table
|
||||
unsigned idx = (address >> 12) & ((1 << 9) - 1)
|
||||
if table->entrylo[idx]:
|
||||
dbg_log ("page already mapped: ")
|
||||
dbg_log_num (idx, 3)
|
||||
dbg_log (";")
|
||||
dbg_log_num (table->entrylo[idx])
|
||||
dbg_log ("/")
|
||||
dbg_log_num ((unsigned)table->page[idx])
|
||||
dbg_log (" table: ")
|
||||
dbg_log_num ((unsigned)table)
|
||||
dbg_log ("\n")
|
||||
kdebug ("page already mapped: ")
|
||||
kdebug_num (idx, 3)
|
||||
kdebug (";")
|
||||
kdebug_num (table->entrylo[idx])
|
||||
kdebug ("/")
|
||||
kdebug_num ((unsigned)table->page[idx])
|
||||
kdebug (" table: ")
|
||||
kdebug_num ((unsigned)table)
|
||||
kdebug ("\n")
|
||||
mem->unmap (table->page[idx])
|
||||
table->entrylo[idx] = make_entry_lo (page)
|
||||
table->page[idx] = page
|
||||
//dbg_log ("mapped at address ")
|
||||
//dbg_log_num (address)
|
||||
//dbg_log_char ('\n')
|
||||
//kdebug ("mapped ")
|
||||
//kdebug_num (page->frame)
|
||||
//kdebug (" at address ")
|
||||
//kdebug_num (address)
|
||||
//kdebug ('\n')
|
||||
page->mapping = address
|
||||
page->arch.next_mapped = mem->arch.shadow[address >> 21]
|
||||
if page->arch.next_mapped:
|
||||
@ -230,7 +234,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
|
||||
return true
|
||||
|
||||
void kMemory_arch_unmap (kMemory *mem, kPage *page):
|
||||
//dbg_log_line ()
|
||||
//kdebug_line ()
|
||||
unsigned didx = page->mapping >> 21
|
||||
unsigned tidx = (page->mapping >> 12) & ((1 << 9) - 1)
|
||||
Table *table = mem->arch.directory[didx]
|
||||
@ -248,7 +252,7 @@ void kMemory_arch_unmap (kMemory *mem, kPage *page):
|
||||
page->mapping = ~0
|
||||
|
||||
kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address):
|
||||
//dbg_log_line ()
|
||||
//kdebug_line ()
|
||||
if address >= 0x80000000 || !mem->arch.directory:
|
||||
return NULL
|
||||
Table *table = mem->arch.directory[address >> 21]
|
||||
@ -257,7 +261,7 @@ kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address):
|
||||
return table->page[(address >> 12) & ((1 << 9) - 1)]
|
||||
|
||||
void kPage_arch_update_mapping (kPage *page):
|
||||
//dbg_log_line ()
|
||||
//kdebug_line ()
|
||||
if page->mapping == ~0:
|
||||
return
|
||||
unsigned target = make_entry_lo (page)
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "../kernel.hh"
|
||||
#include <elf.h>
|
||||
|
||||
#define NUM_SLOTS 4
|
||||
#define NUM_SLOTS 8
|
||||
#define NUM_CAPS 32
|
||||
|
||||
static void init_idle ():
|
||||
@ -116,9 +116,9 @@ static void init_threads ():
|
||||
first_alarm = NULL
|
||||
kReceiver *init_receiver = NULL
|
||||
for unsigned i = 0; i < NUM_THREADS; ++i:
|
||||
dbg_log ("Starting thread ")
|
||||
dbg_log_num (i, 2)
|
||||
dbg_log ("\n")
|
||||
kdebug ("Starting thread ")
|
||||
kdebug_num (i, 2)
|
||||
kdebug ("\n")
|
||||
kMemory *mem = top_memory.alloc_memory ()
|
||||
assert (mem)
|
||||
kThread *thread = mem->alloc_thread (NUM_SLOTS)
|
||||
@ -177,14 +177,14 @@ static void init_threads ():
|
||||
if !mem->map (page, p):
|
||||
panic (0x22446688, "unable to map initial page")
|
||||
return
|
||||
//dbg_log ("mapped page ")
|
||||
//kdebug ("mapped page ")
|
||||
//if readonly:
|
||||
// dbg_log ("as readonly ")
|
||||
//dbg_log ("at address ")
|
||||
//dbg_log_num (p)
|
||||
//dbg_log (" for ")
|
||||
//dbg_log_num (i, 1)
|
||||
//dbg_log_char ('\n')
|
||||
// kdebug ("as readonly ")
|
||||
//kdebug ("at address ")
|
||||
//kdebug_num (p)
|
||||
//kdebug (" for ")
|
||||
//kdebug_num (i, 1)
|
||||
//kdebug ('\n')
|
||||
else:
|
||||
if readonly:
|
||||
panic (0x33399993, "unwritable bss section")
|
||||
@ -204,11 +204,11 @@ static void init_threads ():
|
||||
if !mem->map (page, p):
|
||||
panic (0x33557799, "unable to map initial bss page")
|
||||
return
|
||||
dbg_log ("mapped bss page at address ")
|
||||
dbg_log_num (p)
|
||||
dbg_log (" for ")
|
||||
dbg_log_num (i, 1)
|
||||
dbg_log_char ('\n')
|
||||
kdebug ("mapped bss page at address ")
|
||||
kdebug_num (p)
|
||||
kdebug (" for ")
|
||||
kdebug_num (i, 1)
|
||||
kdebug ('\n')
|
||||
else:
|
||||
if page->flags & Kernel::Page::MAPPED_READONLY:
|
||||
panic (0x20203030, "bss section starts on read-only page")
|
||||
@ -224,7 +224,9 @@ static void init_threads ():
|
||||
if used[p]:
|
||||
mem->use ()
|
||||
continue
|
||||
//kdebug ("freeing unused page from initial file\n")
|
||||
top_memory.pfree (thread_start[i] + (p << PAGE_BITS))
|
||||
//kdebug ("freeing unused page list\n")
|
||||
mem->pfree ((unsigned)used)
|
||||
kPage *stackpage = mem->alloc_page ()
|
||||
stackpage->frame = mem->zalloc ()
|
||||
@ -262,6 +264,9 @@ void init (unsigned mem):
|
||||
must_wait = false
|
||||
// Initialize kernel variables to empty.
|
||||
unsigned count = init_memory (mem)
|
||||
// Set up invoke system.
|
||||
reply_caps.init (1)
|
||||
replied_caps.init (1)
|
||||
// initialize system control coprocessor.
|
||||
init_cp0 ()
|
||||
// initialize everything about the idle task.
|
||||
|
@ -24,7 +24,8 @@ void arch_flush_cache ():
|
||||
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
|
||||
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
||||
|
||||
static void handle_exit ():
|
||||
static kThread *handle_exit ():
|
||||
dbg_check ()
|
||||
--dbg_code.h
|
||||
// Set must_wait to false, so random threads are not set to waiting when the kernel invokes something (such as a dbg_cap).
|
||||
must_wait = false
|
||||
@ -32,11 +33,10 @@ static void handle_exit ():
|
||||
schedule ()
|
||||
if !current:
|
||||
current = &idle
|
||||
//if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING:
|
||||
//panic (current->flags, "non-scheduled thread running")
|
||||
if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING:
|
||||
panic (current->flags, "non-scheduled thread running")
|
||||
if old_current == current:
|
||||
return
|
||||
//dbg_send ((unsigned)current >> 12, 3)
|
||||
return current
|
||||
arch_flush_cache ()
|
||||
if current != &idle:
|
||||
if (kMemory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||
@ -58,6 +58,7 @@ static void handle_exit ():
|
||||
cp0_set (CP0_STATUS, 0x1000ff13)
|
||||
else:
|
||||
cp0_set (CP0_STATUS, 0x0000ff13)
|
||||
return current
|
||||
|
||||
/// A TLB miss has occurred. This is the slow version. It is only used
|
||||
/// when k0 or k1 is not 0, or when an error occurs.
|
||||
@ -69,8 +70,7 @@ kThread *tlb_refill ():
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (Kernel::ERR_NO_PAGE_DIRECTORY, addr)
|
||||
handle_exit ()
|
||||
return current
|
||||
return handle_exit ()
|
||||
unsigned EntryHi
|
||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||
Table *t = directory[EntryHi >> 21]
|
||||
@ -84,17 +84,20 @@ kThread *tlb_refill ():
|
||||
cp0_set (CP0_ENTRY_LO0, t->entrylo[idx])
|
||||
cp0_set (CP0_ENTRY_LO1, t->entrylo[idx + 1])
|
||||
__asm__ volatile ("tlbwr")
|
||||
#if 0
|
||||
dbg_log ("tlb refill ")
|
||||
dbg_log_num (t->entrylo[idx])
|
||||
dbg_log (":")
|
||||
dbg_log_num (t->entrylo[idx + 1])
|
||||
dbg_log (" for ")
|
||||
dbg_log_num (EntryHi)
|
||||
dbg_log ("\n")
|
||||
#endif
|
||||
handle_exit ()
|
||||
return current
|
||||
if dbg_code.l:
|
||||
kdebug ("tlb refill ")
|
||||
__asm__ volatile ("tlbp")
|
||||
unsigned index
|
||||
cp0_get (CP0_INDEX, index)
|
||||
kdebug_num (index, 2)
|
||||
kdebug ("|")
|
||||
kdebug_num (t->entrylo[idx])
|
||||
kdebug (":")
|
||||
kdebug_num (t->entrylo[idx + 1])
|
||||
kdebug (" for ")
|
||||
kdebug_num (EntryHi)
|
||||
kdebug ("\n")
|
||||
return handle_exit ()
|
||||
|
||||
/// An interrupt which is not an exception has occurred.
|
||||
kThread *interrupt ():
|
||||
@ -126,8 +129,7 @@ kThread *interrupt ():
|
||||
#endif
|
||||
intc_ack_irq (TIMER_INTERRUPT)
|
||||
timer_interrupt ()
|
||||
handle_exit ()
|
||||
return current
|
||||
return handle_exit ()
|
||||
|
||||
void flush_tlb (unsigned asid):
|
||||
for unsigned tlb = 1; tlb < 32; ++tlb:
|
||||
@ -147,9 +149,15 @@ static void arch_invoke ():
|
||||
if must_wait:
|
||||
old_current->recv_reply = old_current->arch.t[2]
|
||||
old_current->recv_arg = old_current->arch.t[3]
|
||||
//kdebug_num (old_current->recv_reply)
|
||||
//kdebug ("/")
|
||||
//kdebug_num (old_current->recv_arg)
|
||||
//kdebug ("\n")
|
||||
if !target.valid ():
|
||||
if must_wait:
|
||||
old_current->wait ()
|
||||
else:
|
||||
dpanic (target.index, "invalid target called")
|
||||
return
|
||||
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
|
||||
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
|
||||
@ -236,9 +244,9 @@ kThread *exception ():
|
||||
if !dbg_cap.valid ():
|
||||
dpanic (0, "no log capability provided")
|
||||
break
|
||||
dbg_log ("log capability registered.\n")
|
||||
kdebug ("log capability registered.\n")
|
||||
break
|
||||
dbg_log_char (current->arch.a[1])
|
||||
kdebug (current->arch.a[1])
|
||||
#endif
|
||||
break
|
||||
case 10:
|
||||
@ -294,13 +302,11 @@ kThread *exception ():
|
||||
default:
|
||||
panic (0xf6223344, "Impossible exception code")
|
||||
break
|
||||
handle_exit ()
|
||||
return current
|
||||
return handle_exit ()
|
||||
|
||||
/// There's a cache error. Big trouble. Probably not worth trying to recover.
|
||||
kThread *cache_error ():
|
||||
++dbg_code.h
|
||||
panic (0x33333333, "cache error")
|
||||
old_current = current
|
||||
handle_exit ()
|
||||
return current
|
||||
return handle_exit ()
|
||||
|
@ -29,7 +29,7 @@ arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
||||
boot_sources = mips/init.cc mips/nanonote/board.cc
|
||||
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||
boot_threads = init udc
|
||||
programs = \#nanonote-gpio \#buzzer \#lcd metronome
|
||||
programs = \#nanonote-gpio \#buzzer \#lcd metronome ball
|
||||
|
||||
all: test
|
||||
|
||||
|
@ -72,7 +72,7 @@ void board_init ():
|
||||
UART0_DLLR = uart_div
|
||||
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
|
||||
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
|
||||
dbg_log ("\n\nSerial port initialized\n")
|
||||
kdebug ("\n\nSerial port initialized\n")
|
||||
#endif
|
||||
|
||||
void arch_reboot ():
|
||||
|
@ -137,13 +137,13 @@ void data::poll ():
|
||||
continue
|
||||
case Directory::LOCK_RO:
|
||||
std::cerr << "lock\n"
|
||||
if !lock++:
|
||||
std::cerr << "freezing file list\n"
|
||||
shevek::dir d (files)
|
||||
dir.clear ()
|
||||
for shevek::dir::const_iterator i = d.begin (); i != d.end (); ++i:
|
||||
if !i->name.empty () && i->name[0] != '.':
|
||||
dir.push_back (Name (i->name))
|
||||
lock++
|
||||
std::cerr << "freezing file list\n"
|
||||
shevek::dir d (files)
|
||||
dir.clear ()
|
||||
for shevek::dir::const_iterator i = d.begin (); i != d.end (); ++i:
|
||||
if !i->name.empty () && i->name[0] != '.':
|
||||
dir.push_back (Name (i->name))
|
||||
continue
|
||||
case Directory::UNLOCK_RO:
|
||||
std::cerr << "unlock\n"
|
||||
|
122
panic.ccp
122
panic.ccp
@ -20,11 +20,11 @@
|
||||
#include "kernel.hh"
|
||||
|
||||
#ifdef USE_SERIAL
|
||||
void dbg_log_char (unsigned ch):
|
||||
void kdebug (unsigned ch):
|
||||
while !(UART0_LSR & UARTLSR_TDRQ):
|
||||
UART0_TDR = ch
|
||||
#else
|
||||
void dbg_log_char (unsigned ch):
|
||||
void kdebug (unsigned ch):
|
||||
if !dbg_cap.valid () || dbg_code.l:
|
||||
return
|
||||
kCapability::Context c
|
||||
@ -34,51 +34,57 @@ void dbg_log_char (unsigned ch):
|
||||
--dbg_code.l
|
||||
#endif
|
||||
|
||||
void dbg_log (char const *str):
|
||||
void kdebug (char const *str):
|
||||
while *str:
|
||||
dbg_log_char (*str++)
|
||||
kdebug (*str++)
|
||||
|
||||
void dbg_log_num (unsigned num, unsigned digits):
|
||||
void kdebug_num (unsigned num, unsigned digits):
|
||||
char const *encode = "0123456789abcdef"
|
||||
for unsigned i = 0; i < digits; ++i:
|
||||
dbg_log_char (encode[(num >> (4 * ((digits - 1) - i))) & 0xf])
|
||||
kdebug (encode[(num >> (4 * ((digits - 1) - i))) & 0xf])
|
||||
return
|
||||
|
||||
#if 1 || defined (NDEBUG)
|
||||
static void print_addr (char const *t, unsigned addr):
|
||||
dbg_log (t)
|
||||
dbg_log_num (addr)
|
||||
static void print_addr (char const *t, unsigned addr, bool last = false):
|
||||
kdebug (t)
|
||||
kdebug_num (addr)
|
||||
#if 1
|
||||
unsigned de = addr >> 21
|
||||
unsigned te = (addr >> 12) & ((1 << 9) - 1)
|
||||
if de < 0x400 && old_current && old_current->address_space->arch.directory && old_current->address_space->arch.directory[de]:
|
||||
dbg_log ("; EntryLo = ")
|
||||
dbg_log_num (old_current->address_space->arch.directory[de]->entrylo[te])
|
||||
kdebug ("; EntryLo = ")
|
||||
kdebug_num (old_current->address_space->arch.directory[de]->entrylo[te])
|
||||
else:
|
||||
dbg_log ("; no directory or page table")
|
||||
if old_current:
|
||||
kdebug ("; no directory or page table")
|
||||
if old_current && de < 0x400:
|
||||
cp0_set (CP0_ENTRY_HI, (addr & (PAGE_MASK << 1)) | old_current->address_space->arch.asid)
|
||||
__asm__ volatile ("tlbp")
|
||||
unsigned idx, hi
|
||||
cp0_get (CP0_INDEX, idx)
|
||||
dbg_log ("; tlb index: ")
|
||||
kdebug ("; tlb index: ")
|
||||
if idx & (1 << 31):
|
||||
dbg_log ("none\n")
|
||||
kdebug ("none\n")
|
||||
else:
|
||||
__asm__ volatile ("tlbr")
|
||||
dbg_log_num (idx, 2)
|
||||
dbg_log ("; EntryLo = ")
|
||||
kdebug_num (idx, 2)
|
||||
kdebug ("; EntryLo = ")
|
||||
unsigned lo
|
||||
cp0_get (CP0_ENTRY_LO0, lo)
|
||||
dbg_log_num (lo)
|
||||
dbg_log (":")
|
||||
kdebug_num (lo)
|
||||
kdebug (":")
|
||||
cp0_get (CP0_ENTRY_LO1, lo)
|
||||
dbg_log_num (lo)
|
||||
dbg_log ("\n")
|
||||
if addr >= 0x80000000:
|
||||
kdebug_num (lo)
|
||||
kdebug ("\n")
|
||||
else:
|
||||
kdebug ('\n')
|
||||
if addr >= 0x80000000 && addr < 0xc0000000:
|
||||
for int i = -4; i < 4; ++i:
|
||||
dbg_log (" ")
|
||||
dbg_log_num (((unsigned *)addr)[i])
|
||||
dbg_log ("\n")
|
||||
kdebug (" ")
|
||||
kdebug_num (((unsigned *)addr)[i])
|
||||
kdebug ("\n")
|
||||
#else
|
||||
kdebug (last ? '\n' : ';')
|
||||
#endif
|
||||
|
||||
static void panic_message (unsigned n, const char *line, char const *name, char const *message):
|
||||
unsigned vaddr, epc
|
||||
@ -89,29 +95,40 @@ static void panic_message (unsigned n, const char *line, char const *name, char
|
||||
print_addr ("BadVAddr: ", vaddr)
|
||||
if old_current:
|
||||
print_addr ("PC: ", old_current->pc)
|
||||
print_addr ("epc: ", epc)
|
||||
print_addr ("epc: ", epc, true)
|
||||
#endif
|
||||
dbg_log ("Panic: caller = ")
|
||||
kdebug ("Panic: caller = ")
|
||||
if old_current:
|
||||
dbg_log_num (old_current->id, 2)
|
||||
dbg_log (":")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
kdebug_num (old_current->id, 2)
|
||||
kdebug (":")
|
||||
kdebug_num ((unsigned)old_current)
|
||||
if old_current:
|
||||
dbg_log_char ('@')
|
||||
dbg_log_num (old_current->pc)
|
||||
dbg_log ("; ")
|
||||
dbg_log (name)
|
||||
dbg_log_char (':')
|
||||
dbg_log (line)
|
||||
dbg_log (": ")
|
||||
dbg_log (message)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (n)
|
||||
dbg_log ("; debug: ")
|
||||
dbg_log_num (dbg_code.h)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (dbg_code.l)
|
||||
dbg_log_char ('\n')
|
||||
kdebug ('@')
|
||||
kdebug_num (old_current->pc)
|
||||
kdebug ("; ")
|
||||
kdebug (name)
|
||||
kdebug (':')
|
||||
kdebug (line)
|
||||
kdebug (": ")
|
||||
kdebug (message)
|
||||
kdebug ('/')
|
||||
kdebug_num (n)
|
||||
kdebug ("; debug: ")
|
||||
kdebug_num (dbg_code.h)
|
||||
kdebug (':')
|
||||
kdebug_num (dbg_code.l)
|
||||
kdebug ('\n')
|
||||
kdebug ("debug buffer:")
|
||||
unsigned b = dbg_buffer_head
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
kdebug ('\n')
|
||||
for unsigned j = 0; j < 2; ++j:
|
||||
kdebug (' ')
|
||||
kdebug_num (dbg_buffer[b])
|
||||
++b
|
||||
if b == 32:
|
||||
b = 0
|
||||
kdebug ('\n')
|
||||
|
||||
void panic_impl (unsigned n, const char *line, char const *name, char const *message):
|
||||
// Stop all threads.
|
||||
@ -126,23 +143,22 @@ void panic_impl (unsigned n, const char *line, char const *name, char const *mes
|
||||
#ifndef NDEBUG
|
||||
// If a log capability is registered, run its owner.
|
||||
panic_message (n, line, name, message)
|
||||
#ifndef USE_SERIAL
|
||||
if dbg_cap.valid () && dbg_cap->target->owner:
|
||||
#ifndef USE_SERIAL
|
||||
dbg_cap->target->owner->run ()
|
||||
#endif
|
||||
// Use the (now running) log thread to display the message.
|
||||
// If no log capability is registered, the machine just hangs.
|
||||
#ifdef USE_SERIAL
|
||||
#else
|
||||
arch_reboot ()
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
void dbg_send (unsigned num, unsigned bits):
|
||||
dbg_log ("Warning: ")
|
||||
dbg_log_num (num)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (bits)
|
||||
dbg_log_char ('\n')
|
||||
kdebug ("Warning: ")
|
||||
kdebug_num (num)
|
||||
kdebug ('/')
|
||||
kdebug_num (bits)
|
||||
kdebug ('\n')
|
||||
#endif
|
||||
#else
|
||||
void delay (unsigned ms):
|
||||
|
@ -60,9 +60,9 @@ Kernel::Num start ():
|
||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
||||
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::my_parent.init_done ()
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
Kernel::my_parent.init_done ()
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
|
@ -270,6 +270,7 @@ Kernel::Num start ():
|
||||
c = Kernel::my_receiver.create_capability (TOUCHPAD)
|
||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
||||
Kernel::free_cap (c)
|
||||
Kernel::my_parent.init_done ()
|
||||
|
||||
if kbd.is_scanning ():
|
||||
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
@ -278,7 +279,6 @@ Kernel::Num start ():
|
||||
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
|
||||
Kernel::register_interrupt (IRQ_GPIO0)
|
||||
|
||||
Kernel::my_parent.init_done ()
|
||||
while true:
|
||||
Kernel::schedule ()
|
||||
Kernel::wait ()
|
||||
|
181
source/#lcd.ccp
181
source/#lcd.ccp
@ -183,7 +183,7 @@ static void reset ():
|
||||
write_reg (COLOR, 0x01)
|
||||
#endif
|
||||
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM
|
||||
LCD_CFG = cfg
|
||||
LCD_HSYNC = hpe
|
||||
LCD_VSYNC = vpe
|
||||
@ -191,8 +191,8 @@ static void reset ():
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_DA0 = physical_descriptor
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_ENA
|
||||
//lcd_enable_eof_intr ()
|
||||
LCD_STATE = 0
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM | LCD_CTRL_ENA
|
||||
|
||||
static void putchar (unsigned x, unsigned y, unsigned ch):
|
||||
if ch < 32 || ch > 126:
|
||||
@ -245,8 +245,8 @@ static void log_msg ():
|
||||
|
||||
enum captype:
|
||||
LOG = 32
|
||||
SET_EOF_CB
|
||||
BACKLIGHT
|
||||
LCD
|
||||
|
||||
static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
|
||||
unsigned dx2 = (x - cx) * (x - cx)
|
||||
@ -267,6 +267,7 @@ Kernel::Num start ():
|
||||
|
||||
Descriptor descriptor __attribute__ ((aligned (16)))
|
||||
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||
#if 0
|
||||
unsigned physical = Kernel::my_memory.alloc_range (pages)
|
||||
assert (physical & PAGE_MASK && ~physical)
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
@ -286,6 +287,9 @@ Kernel::Num start ():
|
||||
#else
|
||||
#error "Define your framebuffer format."
|
||||
#endif
|
||||
#else
|
||||
unsigned physical = 0
|
||||
#endif
|
||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
||||
unsigned paddr = p.physical_address ()
|
||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
@ -305,14 +309,20 @@ Kernel::Num start ():
|
||||
|
||||
// Register the backlight device.
|
||||
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
|
||||
Kernel::my_parent.provide_device <Setting> (backlight)
|
||||
Kernel::my_parent.provide_device <Setting> (backlight.copy ())
|
||||
Kernel::free_cap (backlight)
|
||||
|
||||
// Register the display device.
|
||||
Kernel::Cap display = Kernel::my_receiver.create_capability (LCD)
|
||||
Kernel::my_parent.provide_device <Display> (display.copy ())
|
||||
Kernel::free_cap (display)
|
||||
Kernel::my_parent.init_done ()
|
||||
|
||||
Kernel::Cap eof_cb
|
||||
bool have_eof = false
|
||||
bool is_on = true
|
||||
unsigned backlight_user = 0
|
||||
Kernel::Num current_backlight = 0
|
||||
Kernel::my_parent.init_done ()
|
||||
unsigned current_backlight = 0
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
//log_msg ()
|
||||
@ -320,9 +330,8 @@ Kernel::Num start ():
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_LCD:
|
||||
lcd_clr_eof ()
|
||||
eof_cb.invoke ()
|
||||
have_eof = false
|
||||
eof_cb.invoke ()
|
||||
Kernel::free_cap (eof_cb)
|
||||
break
|
||||
#if defined (TRENDTAC)
|
||||
@ -331,46 +340,112 @@ Kernel::Num start ():
|
||||
break
|
||||
#endif
|
||||
case BACKLIGHT:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (BACKLIGHT, current_backlight, reply, arg)
|
||||
break
|
||||
case LCD:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (backlight_user++, BACKLIGHT))
|
||||
reply.invoke (0, 0, c.copy ())
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::Memory mem (arg)
|
||||
unsigned width = Kernel::recv.data[0].h >> 16
|
||||
unsigned height = Kernel::recv.data[0].h & 0xffff
|
||||
unsigned mode = Kernel::recv.data[1].l & ~PAGE_MASK
|
||||
unsigned address = Kernel::recv.data[1].l & PAGE_MASK
|
||||
if (width != 0 && width != h) || (height != 0 && height != v) || mode != 0:
|
||||
reply.invoke (Kernel::ERR_INVALID_ARGUMENT)
|
||||
kdebug ("invalid framebuffer requested\n")
|
||||
Kernel::panic (0)
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
Kernel::Caps caps = mem.create_caps (4)
|
||||
caps.set (1, mem.copy ())
|
||||
unsigned slot = caps.use ()
|
||||
unsigned physical = mem.alloc_range (pages)
|
||||
if physical & ~PAGE_MASK:
|
||||
kdebug ("can't allocate framebuffer\n")
|
||||
Kernel::panic (0)
|
||||
assert (physical & PAGE_MASK && ~physical)
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 0))
|
||||
Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD))
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
Kernel::Page p = mem.create_page ()
|
||||
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
||||
if address != ~0:
|
||||
//Kernel::panic (0xdeaddead)
|
||||
mem.map (p, address + (i << PAGE_BITS))
|
||||
Kernel::free_cap (p)
|
||||
Kernel::free_slot (slot)
|
||||
reply.invoke (0, 0, caps.copy ())
|
||||
Kernel::free_cap (caps)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::recv.reply.invoke ()
|
||||
unsigned slot = Kernel::Caps (arg).use ()
|
||||
unsigned physical = Kernel::my_receiver.get_protected (Kernel::Cap (slot, 0)).l
|
||||
if physical == ~0:
|
||||
kdebug ("unable to destroy framebuffer with wrong cap0\n")
|
||||
Kernel::panic (0)
|
||||
break
|
||||
if descriptor.frame == physical && is_on:
|
||||
lcd_clr_ena ()
|
||||
#ifdef NANONOTE
|
||||
write_reg (BACKLIGHT1, 0x5e)
|
||||
#endif
|
||||
Kernel::Memory mem = Kernel::Cap (slot, 1)
|
||||
for unsigned i = 0; i < pages; ++i:
|
||||
mem.destroy (Kernel::Cap (slot, 2 + i))
|
||||
mem.destroy (arg)
|
||||
Kernel::free_slot (slot)
|
||||
reply.invoke ()
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
current_backlight = Kernel::my_receiver.get_protected (arg)
|
||||
Kernel::Cap first = Kernel::Caps (arg).get (0)
|
||||
unsigned physical = Kernel::my_receiver.get_protected (first).l
|
||||
if physical == ~0:
|
||||
kdebug ("unable to use framebuffer with wrong cap0\n")
|
||||
Kernel::panic (0)
|
||||
break
|
||||
Kernel::free_cap (first)
|
||||
bool was_unused = descriptor.frame == ~0
|
||||
descriptor.frame = physical
|
||||
unsigned dptr = (unsigned)&descriptor
|
||||
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
|
||||
if was_unused && is_on:
|
||||
lcd_set_ena ()
|
||||
#ifdef NANONOTE:
|
||||
write_reg (BACKLIGHT1, 0x5f)
|
||||
#endif
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::UNUSE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
if current_backlight.value () == Kernel::my_receiver.get_protected (arg).value ():
|
||||
current_backlight = 0
|
||||
Kernel::Cap first = Kernel::Caps (arg).get (0)
|
||||
unsigned physical = Kernel::my_receiver.get_protected (first).l
|
||||
if physical == ~0:
|
||||
kdebug ("unable to unuse framebuffer with wrong cap0\n")
|
||||
Kernel::panic (0)
|
||||
break
|
||||
Kernel::free_cap (first)
|
||||
if descriptor.frame == physical:
|
||||
lcd_clr_ena ()
|
||||
#ifdef NANONOTE
|
||||
write_reg (BACKLIGHT1, 0x5e)
|
||||
#endif
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
log_char ('@')
|
||||
break
|
||||
Kernel::panic (0, "invalid operation for lcd device")
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
log_char ('#')
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_char ('\n')
|
||||
Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd")
|
||||
break
|
||||
break
|
||||
case BACKLIGHT:
|
||||
if current_backlight.value () != Kernel::recv.protected_data.value ():
|
||||
if current_backlight != Kernel::recv.protected_data.l:
|
||||
log_char ('&')
|
||||
log_num (current_backlight)
|
||||
log_num (Kernel::recv.protected_data)
|
||||
@ -400,22 +475,36 @@ Kernel::Num start ():
|
||||
Kernel::recv.reply.invoke (~0)
|
||||
break
|
||||
default:
|
||||
log_char ('$')
|
||||
Kernel::panic (0, "invalid operation for backlight")
|
||||
break
|
||||
break
|
||||
case SET_EOF_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
else:
|
||||
Kernel::register_interrupt (IRQ_LCD)
|
||||
have_eof = true
|
||||
eof_cb = Kernel::get_arg ()
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
case LCD:
|
||||
if descriptor.frame != Kernel::recv.protected_data.l:
|
||||
kdebug ("invalid user requesting lcd\n")
|
||||
Kernel::panic (0)
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Display::SET_EOF_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
kdebug ("replacing eof_cb\n")
|
||||
Kernel::panic (0)
|
||||
else:
|
||||
lcd_clr_eof ()
|
||||
Kernel::register_interrupt (IRQ_LCD)
|
||||
have_eof = true
|
||||
eof_cb = arg
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Display::GET_INFO:
|
||||
kdebug ("get_info isn't defined yet.\n")
|
||||
Kernel::panic (0)
|
||||
default:
|
||||
Kernel::panic (0, "invalid operation for lcd")
|
||||
break
|
||||
default:
|
||||
log_char ('~')
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_char ('\n')
|
||||
Kernel::panic (0, "invalid master operation type for lcd")
|
||||
break
|
||||
|
@ -170,6 +170,8 @@ class PowerButton:
|
||||
Kernel::Cap cb
|
||||
public:
|
||||
void scan ():
|
||||
if !started:
|
||||
return
|
||||
gpio_mask_irq (3, 1 << 29)
|
||||
bool s = gpio_get_port (3) & (1 << 29)
|
||||
if s != state:
|
||||
@ -206,12 +208,12 @@ Kernel::Num start ():
|
||||
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::free_cap (pw)
|
||||
Kernel::my_parent.init_done ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
unsigned user (~0)
|
||||
unsigned user (0), power_user (0)
|
||||
unsigned next_user (0)
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
Kernel::my_parent.init_done ()
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
@ -233,43 +235,15 @@ Kernel::Num start ():
|
||||
break
|
||||
case PWR:
|
||||
// Power button request.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
pwr.set_cb (Kernel::get_arg ())
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("power button invalid request\n")
|
||||
break
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (PWR, power_user, reply, arg)
|
||||
break
|
||||
case KBD_DEV:
|
||||
// Keyboard device control request.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, KBD_DEV))
|
||||
reply.invoke (0, 0, cap.copy ())
|
||||
Kernel::free_cap (cap)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::UNUSE:
|
||||
kbd.inactive ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("gpio other dev:")
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Device::host (KBD_DEV, user, reply, arg)
|
||||
break
|
||||
default:
|
||||
break
|
||||
@ -277,7 +251,7 @@ Kernel::Num start ():
|
||||
case KBD_DEV:
|
||||
// Keyboard device user request.
|
||||
if Kernel::recv.protected_data.l != user:
|
||||
kdebug ("invalid user requesting\n")
|
||||
kdebug ("invalid user requesting keyboard\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
@ -297,6 +271,24 @@ Kernel::Num start ():
|
||||
kdebug ("keyboard other\n")
|
||||
break
|
||||
break
|
||||
case PWR:
|
||||
if Kernel::recv.protected_data.l != power_user:
|
||||
kdebug ("invalid user requesting power\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
pwr.set_cb (Kernel::get_arg ())
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("Power button invalid request\n")
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("keyboard unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
|
49
source/ball.ccp
Normal file
49
source/ball.ccp
Normal file
@ -0,0 +1,49 @@
|
||||
#pypp 0
|
||||
#include <iris.hh>
|
||||
#include <devices.hh>
|
||||
|
||||
static unsigned *framebuffer
|
||||
static int const r = 10
|
||||
|
||||
void ball (int x, int y, bool print):
|
||||
static unsigned bg
|
||||
static unsigned count
|
||||
for int ty = y - r; ty < y + r; ++ty:
|
||||
if ty < 0 || ty >= 240:
|
||||
continue
|
||||
for int tx = x - r; tx < x + r; ++tx:
|
||||
if tx < 0 || tx >= 320:
|
||||
continue
|
||||
if (x - tx) * (x - tx) + (y - ty) * (y - ty) > r * r:
|
||||
continue
|
||||
framebuffer[ty * 320 + tx] = (print ? 0xffffff : bg)
|
||||
if ++count >= 30:
|
||||
bg += 0x010307
|
||||
count = 0
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::my_parent.init_done ()
|
||||
framebuffer = (unsigned *)0x15000
|
||||
Kernel::Caps caps = Kernel::my_parent.get_device <Display> ()
|
||||
Display display = caps.get (0)
|
||||
int x = r, y = r, dx = 3, dy = 0
|
||||
Kernel::Cap eof = Kernel::my_receiver.create_capability (0)
|
||||
while true:
|
||||
display.set_eof_cb (eof)
|
||||
Kernel::wait ()
|
||||
ball (x, y, false)
|
||||
x += dx
|
||||
y += dy
|
||||
if y + r >= 240:
|
||||
dy = -dy
|
||||
y = 240 - r
|
||||
if x - r < 0:
|
||||
x = r
|
||||
dx = -dx
|
||||
if x + r >= 320:
|
||||
x = 320 - r
|
||||
dx = -dx
|
||||
if y == 240 - r && dy == 0:
|
||||
dy = -21
|
||||
++dy
|
||||
ball (x, y, true)
|
@ -46,7 +46,7 @@ namespace Kernel:
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
used[i - __cap_admin] = false
|
||||
++num
|
||||
kdebug_num (num, 1)
|
||||
kdebug_num (num, 2)
|
||||
kdebug (":")
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
kdebug_char (used[i] ? '#' : '.')
|
||||
@ -61,9 +61,12 @@ namespace Kernel:
|
||||
__first_free_slot = &__slot_admin[slot]
|
||||
|
||||
void free_cap (Cap cap):
|
||||
//kdebug ("free cap\n")
|
||||
//kdebug ("free cap ")
|
||||
//kdebug_num (cap.idx (), 2)
|
||||
//kdebug ("\n")
|
||||
if cap.slot () != 0:
|
||||
kdebug ("trying to free capability from non-0 slot\n")
|
||||
Kernel::panic (0)
|
||||
return
|
||||
list *l = &__cap_admin[cap.idx ()]
|
||||
l->prev = NULL
|
||||
@ -77,6 +80,7 @@ namespace Kernel:
|
||||
if !__first_free_slot:
|
||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||
kdebug ("out of slots!\n")
|
||||
Kernel::panic (0)
|
||||
return ~0
|
||||
list *ret = __first_free_slot
|
||||
__first_free_slot = ret->next
|
||||
@ -85,15 +89,18 @@ namespace Kernel:
|
||||
return ret - __slot_admin
|
||||
|
||||
Cap alloc_cap ():
|
||||
//kdebug ("alloc cap\n")
|
||||
//kdebug ("alloc cap ")
|
||||
if !__first_free_cap:
|
||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||
kdebug ("out of capabilities!\n")
|
||||
Kernel::panic (0)
|
||||
return Cap (0, CAP_NONE)
|
||||
list *ret = __first_free_cap
|
||||
__first_free_cap = ret->next
|
||||
if ret->next:
|
||||
ret->next->prev = NULL
|
||||
//kdebug_num (ret - __cap_admin, 2)
|
||||
//kdebug ("\n")
|
||||
return Cap (0, ret - __cap_admin)
|
||||
|
||||
extern "C":
|
||||
@ -103,7 +110,7 @@ extern "C":
|
||||
__slot_admin = slot_admin
|
||||
__cap_admin = cap_admin
|
||||
__first_free_slot = NULL
|
||||
for unsigned i = 2; i < __slots; ++i:
|
||||
for unsigned i = 1; i < __slots; ++i:
|
||||
Kernel::free_slot (i)
|
||||
__first_free_cap = NULL
|
||||
for unsigned i = 7; i < __caps; ++i:
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "keys.hh"
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::my_parent.init_done ()
|
||||
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
|
||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
||||
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
|
||||
@ -29,7 +30,6 @@ Kernel::Num start ():
|
||||
// Frequency of single pulses in hertz.
|
||||
unsigned freq = 1000
|
||||
bool running (false)
|
||||
Kernel::my_parent.init_done ()
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
|
Loading…
x
Reference in New Issue
Block a user