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