mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 02:39:53 +02:00
usb-booting alarm clock, with split gui
This commit is contained in:
parent
a4b5d94200
commit
8c7cac36e6
4
Makefile
4
Makefile
@ -23,7 +23,7 @@ CC = $(CROSS)gcc
|
|||||||
LD = $(CROSS)ld
|
LD = $(CROSS)ld
|
||||||
OBJCOPY = $(CROSS)objcopy
|
OBJCOPY = $(CROSS)objcopy
|
||||||
|
|
||||||
headers = kernel.hh iris.hh $(arch_headers)
|
headers = kernel.hh iris.hh ui.hh $(arch_headers)
|
||||||
iris_sources = panic.cc data.cc alloc.cc memory.cc invoke.cc schedule.cc $(arch_iris_sources)
|
iris_sources = panic.cc data.cc alloc.cc memory.cc invoke.cc schedule.cc $(arch_iris_sources)
|
||||||
BUILT_SOURCES = $(iris_sources) $(boot_sources)
|
BUILT_SOURCES = $(iris_sources) $(boot_sources)
|
||||||
|
|
||||||
@ -62,4 +62,4 @@ debug:
|
|||||||
cat $(SERIAL)
|
cat $(SERIAL)
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
.PRECIOUS: iris.hh kernel.hh ui.hh boot-programs/crt0.o
|
||||||
|
@ -58,6 +58,9 @@ void *operator new[] (unsigned size):
|
|||||||
void *operator new (unsigned size):
|
void *operator new (unsigned size):
|
||||||
return new char[size]
|
return new char[size]
|
||||||
|
|
||||||
|
static unsigned *bss_mapping
|
||||||
|
static Iris::Page bss_page
|
||||||
|
|
||||||
// Get the initial block device and filesystem.
|
// Get the initial block device and filesystem.
|
||||||
static Iris::Directory receive_devices ():
|
static Iris::Directory receive_devices ():
|
||||||
Iris::String data
|
Iris::String data
|
||||||
@ -65,7 +68,7 @@ static Iris::Directory receive_devices ():
|
|||||||
bool have_data = false, have_fs = false
|
bool have_data = false, have_fs = false
|
||||||
for unsigned i = 0; i < 2; ++i:
|
for unsigned i = 0; i < 2; ++i:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE:
|
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_CAPABILITY:
|
||||||
Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.")
|
Iris::panic (Iris::recv.data[0].l, "Invalid bootstrap request.")
|
||||||
switch Iris::recv.data[1].l:
|
switch Iris::recv.data[1].l:
|
||||||
case Iris::String::ID:
|
case Iris::String::ID:
|
||||||
@ -206,13 +209,14 @@ static void run (Iris::String data, Iris::Memory parent_memory, Iris::Cap parent
|
|||||||
Iris::Page page = mem.mapping ((void *)p)
|
Iris::Page page = mem.mapping ((void *)p)
|
||||||
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
||||||
// No error means there is a mapping.
|
// No error means there is a mapping.
|
||||||
|
page.share (bss_page, 0)
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||||
if a >= shdr->sh_addr + shdr->sh_size:
|
if a >= shdr->sh_addr + shdr->sh_size:
|
||||||
break
|
break
|
||||||
if a < shdr->sh_addr:
|
if a < shdr->sh_addr:
|
||||||
continue
|
continue
|
||||||
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
|
bss_mapping[(a & ~PAGE_MASK) >> 2] = 0
|
||||||
else:
|
else:
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
@ -256,6 +260,10 @@ Iris::Num start ():
|
|||||||
Iris::schedule ()
|
Iris::schedule ()
|
||||||
kdebug ("Starting bootinit\n")
|
kdebug ("Starting bootinit\n")
|
||||||
init_alloc ()
|
init_alloc ()
|
||||||
|
bss_mapping = (unsigned *)alloc_space (1)
|
||||||
|
bss_page = Iris::my_memory.create_page ()
|
||||||
|
Iris::my_memory.map (bss_page, (unsigned)bss_mapping)
|
||||||
|
|
||||||
Iris::Memory top_memory = Iris::get_top_memory ()
|
Iris::Memory top_memory = Iris::get_top_memory ()
|
||||||
Iris::Directory root = receive_devices ()
|
Iris::Directory root = receive_devices ()
|
||||||
root.lock_ro ()
|
root.lock_ro ()
|
||||||
@ -263,7 +271,7 @@ Iris::Num start ():
|
|||||||
Iris::Cap parent_cap = Iris::my_receiver.create_capability (0)
|
Iris::Cap parent_cap = Iris::my_receiver.create_capability (0)
|
||||||
run (run_string, top_memory, parent_cap)
|
run (run_string, top_memory, parent_cap)
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE || Iris::recv.data[1].l != Iris::Elfrun::ID:
|
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_CAPABILITY || Iris::recv.data[1].l != Iris::Elfrun::ID:
|
||||||
Iris::panic (0, "elfrun doesn't provide correct capability")
|
Iris::panic (0, "elfrun doesn't provide correct capability")
|
||||||
Iris::Cap reply = Iris::get_reply ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
Iris::Elfrun elfrun = Iris::get_arg ()
|
Iris::Elfrun elfrun = Iris::get_arg ()
|
||||||
@ -287,7 +295,7 @@ Iris::Num start ():
|
|||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
switch Iris::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
case Iris::Parent::GET_DEVICE:
|
case Iris::Parent::GET_CAPABILITY:
|
||||||
switch Iris::recv.data[1].l:
|
switch Iris::recv.data[1].l:
|
||||||
case Iris::Directory::ID:
|
case Iris::Directory::ID:
|
||||||
if have_root:
|
if have_root:
|
||||||
|
@ -573,8 +573,8 @@ Iris::Num start ():
|
|||||||
Iris::register_interrupt (IRQ_UDC)
|
Iris::register_interrupt (IRQ_UDC)
|
||||||
Iris::Filesystem fs = Iris::my_receiver.create_capability (FS)
|
Iris::Filesystem fs = Iris::my_receiver.create_capability (FS)
|
||||||
Iris::String data = Iris::my_receiver.create_capability (DATA)
|
Iris::String data = Iris::my_receiver.create_capability (DATA)
|
||||||
Iris::my_parent.provide_device <Iris::Filesystem> (fs.copy ())
|
Iris::my_parent.provide_capability <Iris::Filesystem> (fs.copy ())
|
||||||
Iris::my_parent.provide_device <Iris::String> (data.copy ())
|
Iris::my_parent.provide_capability <Iris::String> (data.copy ())
|
||||||
Iris::free_cap (fs)
|
Iris::free_cap (fs)
|
||||||
Iris::free_cap (data)
|
Iris::free_cap (data)
|
||||||
unsigned state = 0
|
unsigned state = 0
|
||||||
|
38
devices.hhp
38
devices.hhp
@ -126,21 +126,21 @@ namespace Iris:
|
|||||||
struct Parent : public Iris::Cap:
|
struct Parent : public Iris::Cap:
|
||||||
Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
GET_DEVICE = Elfrun::ID
|
GET_CAPABILITY = Elfrun::ID
|
||||||
PROVIDE_DEVICE
|
PROVIDE_CAPABILITY
|
||||||
WAIT
|
WAIT
|
||||||
GET_MEMORY
|
GET_MEMORY
|
||||||
PROVIDE_MEMORY
|
PROVIDE_MEMORY
|
||||||
INIT_DONE
|
INIT_DONE
|
||||||
EXIT
|
EXIT
|
||||||
ID
|
ID
|
||||||
// Get a device handle.
|
// Get a handle.
|
||||||
template <typename _T> _T get_device (unsigned num = 0):
|
template <typename _T> _T get_capability (unsigned num = 0):
|
||||||
icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
|
icall (Iris::Num (CAP_MASTER_DIRECT | GET_CAPABILITY, num), _T::ID)
|
||||||
return Iris::get_arg ()
|
return Iris::get_arg ()
|
||||||
// Provide a device handle.
|
// Provide a device handle.
|
||||||
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
template <typename _T> void provide_capability (Cap cap, unsigned num = 0):
|
||||||
ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
ocall (cap, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_CAPABILITY, num), _T::ID)
|
||||||
// Wait until a device is used by the caller again.
|
// Wait until a device is used by the caller again.
|
||||||
template <typename _T> void wait (unsigned num = 0):
|
template <typename _T> void wait (unsigned num = 0):
|
||||||
call (Iris::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
|
call (Iris::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
|
||||||
@ -200,6 +200,7 @@ namespace Iris:
|
|||||||
enum request:
|
enum request:
|
||||||
SET_EOF_CB = Buzzer::ID
|
SET_EOF_CB = Buzzer::ID
|
||||||
MAP_FB
|
MAP_FB
|
||||||
|
UNMAP_FB
|
||||||
GET_INFO
|
GET_INFO
|
||||||
ID
|
ID
|
||||||
// Register an end-of-frame callback.
|
// Register an end-of-frame callback.
|
||||||
@ -207,8 +208,11 @@ namespace Iris:
|
|||||||
void set_eof_cb (Iris::Cap cb):
|
void set_eof_cb (Iris::Cap cb):
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
|
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
|
||||||
// Map the framebuffer into memory.
|
// Map the framebuffer into memory.
|
||||||
void map_fb (unsigned address):
|
Iris::Caps map_fb (unsigned address, Iris::Memory mem = Iris::my_memory, bool use = true):
|
||||||
call (CAP_MASTER_DIRECT | MAP_FB, address)
|
iocall (mem, Iris::Num (CAP_MASTER_DIRECT | MAP_FB, use ? 1 : 0), address)
|
||||||
|
return Iris::get_arg ()
|
||||||
|
void unmap_fb (Iris::Caps caps):
|
||||||
|
ocall (caps, CAP_MASTER_DIRECT | UNMAP_FB)
|
||||||
// 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.
|
||||||
@ -319,7 +323,21 @@ namespace Iris:
|
|||||||
Iris::Num write (String s, Iris::Num size):
|
Iris::Num write (String s, Iris::Num size):
|
||||||
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
|
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
|
||||||
|
|
||||||
|
struct UI : public Iris::Cap:
|
||||||
|
UI (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
|
||||||
|
enum request:
|
||||||
|
GET_STATE = Stream::ID
|
||||||
|
EVENT
|
||||||
|
EXIT
|
||||||
|
ID
|
||||||
|
enum constant:
|
||||||
|
INPUT = 1 << 31
|
||||||
|
void get_state (Iris::Cap cap):
|
||||||
|
ocall (cap, CAP_MASTER_DIRECT | GET_STATE)
|
||||||
|
void event (unsigned code, unsigned value = 0):
|
||||||
|
call (Iris::Num (CAP_MASTER_DIRECT | EVENT, code), value)
|
||||||
|
void exit ():
|
||||||
|
call (CAP_MASTER_DIRECT | EXIT)
|
||||||
|
|
||||||
// Block device interface.
|
// Block device interface.
|
||||||
struct Block_device : public WString:
|
struct Block_device : public WString:
|
||||||
|
41
init.config
41
init.config
@ -1,34 +1,29 @@
|
|||||||
# load <name> = '<filename>' load a file into memory. Don't use this after killbootthreads.
|
# driver <name> = '<filename>' load a file into memory to be run priviledged.
|
||||||
load driver_lcd = "lcd.elf"
|
# program <name> = '<filename>' load a file into memory to be run normally.
|
||||||
#load driver_buzzer = "buzzer.elf"
|
driver driver_lcd = "lcd.elf"
|
||||||
#load driver_gpio = "gpio.elf"
|
driver driver_buzzer = "buzzer.elf"
|
||||||
load ball = "ball.elf"
|
driver driver_gpio = "gpio.elf"
|
||||||
|
program alarm = "alarm.elf"
|
||||||
# killbootthreads destroy bootinit, bootfs and bootstore.
|
program gui = "gui.elf"
|
||||||
killbootthreads
|
|
||||||
|
|
||||||
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
|
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
|
||||||
receive driver_lcd / Display = display
|
receive driver_lcd / Display = display
|
||||||
receive driver_lcd / Setting = display_bright
|
receive driver_lcd / Setting = display_bright
|
||||||
#receive driver_buzzer / Buzzer = buzzer
|
receive driver_buzzer / Buzzer = buzzer
|
||||||
#receive driver_gpio / Keyboard , 0 = keyboard
|
receive driver_gpio / Keyboard , 0 = keyboard
|
||||||
#receive driver_gpio / Keyboard , 1 = sysreq
|
receive driver_gpio / Keyboard , 1 = sysreq
|
||||||
|
receive alarm / UI = ui
|
||||||
# driver <name> run a previously loaded program priviledged.
|
|
||||||
driver driver_lcd
|
|
||||||
#driver driver_buzzer
|
|
||||||
#driver driver_gpio
|
|
||||||
|
|
||||||
# wait wait until all expected capabilities are received.
|
|
||||||
wait
|
|
||||||
|
|
||||||
# sysreq <cap> use a capability as the system request keyboard.
|
# sysreq <cap> use a capability as the system request keyboard.
|
||||||
sysreq sysreq
|
sysreq sysreq
|
||||||
|
|
||||||
# give <name> / <type> [, <index>] = <cap> give this capability to this program when it requests it.
|
# give <name> / <type> [, <index>] = <cap> give this capability to this program when it requests it.
|
||||||
give ball / Display = display
|
give gui / UI = ui
|
||||||
|
give gui / Display = display
|
||||||
|
give gui / Setting = display_bright
|
||||||
|
give gui / Buzzer = buzzer
|
||||||
|
give gui / Keyboard = keyboard
|
||||||
|
|
||||||
# run <name> run a previously loaded program (normally).
|
# include <file> include a file as another config file.
|
||||||
run ball
|
|
||||||
|
|
||||||
# include <name> include a loaded file as another config file.
|
# at end of file, the initial threads are killed and the drivers and programs are run as soon as all their dependencies are provided.
|
||||||
|
12
invoke.ccp
12
invoke.ccp
@ -390,7 +390,6 @@ static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
reply_num (0)
|
reply_num (0)
|
||||||
|
|
||||||
static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
|
static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
|
||||||
dbg_push (__LINE__)
|
|
||||||
kThread *thread = (kThread *)protected_data.l
|
kThread *thread = (kThread *)protected_data.l
|
||||||
switch cmd:
|
switch cmd:
|
||||||
case Iris::Thread::GET_INFO & REQUEST_MASK:
|
case Iris::Thread::GET_INFO & REQUEST_MASK:
|
||||||
@ -441,7 +440,6 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
*value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
*value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
|
||||||
break
|
break
|
||||||
case Iris::Thread::USE_SLOT & REQUEST_MASK:
|
case Iris::Thread::USE_SLOT & REQUEST_MASK:
|
||||||
dbg_push (__LINE__)
|
|
||||||
if c->data[1].l >= thread->slots || !c->arg.valid ():
|
if c->data[1].l >= thread->slots || !c->arg.valid ():
|
||||||
if c->data[1].l == 0xdeadbeef:
|
if c->data[1].l == 0xdeadbeef:
|
||||||
bool dummy
|
bool dummy
|
||||||
@ -456,26 +454,18 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
dpanic ((unsigned)c->arg->target, "argument for USE_SLOT is not a caps")
|
dpanic ((unsigned)c->arg->target, "argument for USE_SLOT is not a caps")
|
||||||
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
dbg_push (__LINE__)
|
|
||||||
unsigned slot = c->data[1].l
|
unsigned slot = c->data[1].l
|
||||||
dbg_push (__LINE__)
|
|
||||||
kCaps *new_caps = (kCaps *)c->arg->protected_data.l
|
kCaps *new_caps = (kCaps *)c->arg->protected_data.l
|
||||||
dbg_push (__LINE__)
|
|
||||||
if slot >= thread->slots:
|
if slot >= thread->slots:
|
||||||
dpanic (0, "using invalid slot")
|
dpanic (0, "using invalid slot")
|
||||||
return
|
return
|
||||||
dbg_push (__LINE__)
|
|
||||||
thread->unset_slot (slot)
|
thread->unset_slot (slot)
|
||||||
dbg_push (__LINE__)
|
|
||||||
thread->slot[slot].caps = new_caps
|
thread->slot[slot].caps = new_caps
|
||||||
dbg_push (__LINE__)
|
|
||||||
if new_caps:
|
if new_caps:
|
||||||
dbg_push (__LINE__)
|
|
||||||
thread->slot[slot].next = new_caps->first_slot
|
thread->slot[slot].next = new_caps->first_slot
|
||||||
thread->slot[slot].caps = new_caps
|
thread->slot[slot].caps = new_caps
|
||||||
new_caps->first_slot.thread = thread
|
new_caps->first_slot.thread = thread
|
||||||
new_caps->first_slot.index = slot
|
new_caps->first_slot.index = slot
|
||||||
dbg_push (__LINE__)
|
|
||||||
break
|
break
|
||||||
case Iris::Thread::GET_CAPS & REQUEST_MASK:
|
case Iris::Thread::GET_CAPS & REQUEST_MASK:
|
||||||
unsigned slot = c->data[1].l
|
unsigned slot = c->data[1].l
|
||||||
@ -577,9 +567,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
dpanic (0, "invalid priv thread operation")
|
dpanic (0, "invalid priv thread operation")
|
||||||
reply_num (Iris::ERR_INVALID_OPERATION)
|
reply_num (Iris::ERR_INVALID_OPERATION)
|
||||||
return
|
return
|
||||||
dbg_push (__LINE__)
|
|
||||||
reply_num (0)
|
reply_num (0)
|
||||||
dbg_push (__LINE__)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
static void page_check_payment (kPage *page):
|
static void page_check_payment (kPage *page):
|
||||||
|
5
iris.hhp
5
iris.hhp
@ -546,6 +546,8 @@ namespace Iris:
|
|||||||
// 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 == NO_ERROR
|
return ocall (page, CAP_MASTER_DIRECT | MAP, address).l == NO_ERROR
|
||||||
|
bool unmap (Cap page):
|
||||||
|
return map (page, ~0)
|
||||||
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 ()
|
||||||
@ -601,6 +603,9 @@ static void kdebug_num (unsigned n, unsigned digits = 8):
|
|||||||
namespace Iris:
|
namespace Iris:
|
||||||
inline void panic (unsigned code, char const *message = NULL):
|
inline void panic (unsigned code, char const *message = NULL):
|
||||||
if message:
|
if message:
|
||||||
|
kdebug ("**********************************************************************\n")
|
||||||
|
kdebug_num (code)
|
||||||
|
kdebug_char ('\n')
|
||||||
kdebug (message)
|
kdebug (message)
|
||||||
kdebug_char ('\n')
|
kdebug_char ('\n')
|
||||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
||||||
|
12
memory.ccp
12
memory.ccp
@ -26,7 +26,7 @@ static void clear_page (unsigned page, unsigned num = 1):
|
|||||||
kdebug ("clearing page ")
|
kdebug ("clearing page ")
|
||||||
kdebug_num (page)
|
kdebug_num (page)
|
||||||
kdebug ("+")
|
kdebug ("+")
|
||||||
kdebug_num (num)
|
kdebug_num (num << PAGE_BITS)
|
||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
#endif
|
#endif
|
||||||
page = (page & ~0xc0000000) | 0xa0000000
|
page = (page & ~0xc0000000) | 0xa0000000
|
||||||
@ -34,8 +34,14 @@ static void clear_page (unsigned page, unsigned num = 1):
|
|||||||
arch_uncache_page (page - 0x20000000 + (p << PAGE_BITS))
|
arch_uncache_page (page - 0x20000000 + (p << PAGE_BITS))
|
||||||
for unsigned i = 0; i < (1 << (PAGE_BITS - 2)); ++i:
|
for unsigned i = 0; i < (1 << (PAGE_BITS - 2)); ++i:
|
||||||
// Clear page.
|
// Clear page.
|
||||||
((unsigned *)page)[i] = 0
|
((unsigned *)page)[(p << PAGE_BITS - 2) + i] = 0
|
||||||
if *((unsigned *)page) != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
|
if *(unsigned *)page != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
|
||||||
|
kdebug_num ((num << (PAGE_BITS - 2)) - 1)
|
||||||
|
kdebug ("/")
|
||||||
|
kdebug_num (((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1])
|
||||||
|
kdebug (",")
|
||||||
|
kdebug_num (*(unsigned *)page)
|
||||||
|
kdebug ("\n")
|
||||||
dpanic (0, "clear_page didn't work")
|
dpanic (0, "clear_page didn't work")
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -171,13 +171,13 @@ 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):
|
||||||
if address >= 0x80000000:
|
|
||||||
dpanic (address, "trying to map to kernel address")
|
|
||||||
return false
|
|
||||||
if page->mapping != ~0:
|
if page->mapping != ~0:
|
||||||
mem->unmap (page)
|
mem->unmap (page)
|
||||||
if address == ~0:
|
if address == ~0:
|
||||||
return true
|
return true
|
||||||
|
if address >= 0x80000000:
|
||||||
|
dpanic (address, "trying to map to kernel address")
|
||||||
|
return false
|
||||||
if address & ~PAGE_MASK:
|
if address & ~PAGE_MASK:
|
||||||
dpanic (address, "mapping not page-aligned")
|
dpanic (address, "mapping not page-aligned")
|
||||||
address &= PAGE_MASK
|
address &= PAGE_MASK
|
||||||
|
@ -58,6 +58,8 @@ static kThread *handle_exit ():
|
|||||||
cp0_set (CP0_STATUS, 0x1000ff13)
|
cp0_set (CP0_STATUS, 0x1000ff13)
|
||||||
else:
|
else:
|
||||||
cp0_set (CP0_STATUS, 0x0000ff13)
|
cp0_set (CP0_STATUS, 0x0000ff13)
|
||||||
|
dbg_push ((unsigned)current)
|
||||||
|
dbg_push (current->pc)
|
||||||
return current
|
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
|
||||||
@ -163,16 +165,7 @@ static void arch_invoke ():
|
|||||||
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
|
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
|
||||||
msg.data[0] = Iris::Num (old_current->arch.a[0], old_current->arch.a[1])
|
msg.data[0] = Iris::Num (old_current->arch.a[0], old_current->arch.a[1])
|
||||||
msg.data[1] = Iris::Num (old_current->arch.a[2], old_current->arch.a[3])
|
msg.data[1] = Iris::Num (old_current->arch.a[2], old_current->arch.a[3])
|
||||||
dbg_push (old_current->arch.v[0])
|
|
||||||
dbg_push (old_current->arch.t[0])
|
|
||||||
dbg_push (old_current->arch.t[1])
|
|
||||||
dbg_push (old_current->arch.a[0])
|
|
||||||
dbg_push (old_current->arch.a[1])
|
|
||||||
dbg_push (old_current->arch.a[2])
|
|
||||||
dbg_push (old_current->arch.a[3])
|
|
||||||
dbg_push (0xdeadbeef)
|
|
||||||
target->invoke (&msg)
|
target->invoke (&msg)
|
||||||
dbg_push (0xfacebeef)
|
|
||||||
if do_schedule && !must_wait:
|
if do_schedule && !must_wait:
|
||||||
// If the call was to schedule without wait, it isn't done yet.
|
// If the call was to schedule without wait, it isn't done yet.
|
||||||
schedule ()
|
schedule ()
|
||||||
|
@ -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 devices.hh
|
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh
|
||||||
boot_threads = bootinit udc
|
boot_threads = bootinit udc
|
||||||
programs = init gpio lcd bsquare ball buzzer metronome elfrun
|
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm gui
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
|
50
panic.ccp
50
panic.ccp
@ -105,6 +105,41 @@ static void panic_message (unsigned n, const char *line, char const *name, char
|
|||||||
if old_current:
|
if old_current:
|
||||||
kdebug ('@')
|
kdebug ('@')
|
||||||
kdebug_num (old_current->pc)
|
kdebug_num (old_current->pc)
|
||||||
|
kdebug ("\nregisters: sp=")
|
||||||
|
kdebug_num (old_current->sp)
|
||||||
|
kdebug (" at=")
|
||||||
|
kdebug_num (old_current->arch.at)
|
||||||
|
kdebug ("\nv=")
|
||||||
|
kdebug_num (old_current->arch.v[0])
|
||||||
|
kdebug (" ")
|
||||||
|
kdebug_num (old_current->arch.v[1])
|
||||||
|
kdebug ("\na=")
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
kdebug_num (old_current->arch.a[i])
|
||||||
|
kdebug (" ")
|
||||||
|
kdebug ("\nt=")
|
||||||
|
for unsigned i = 0; i < 10; ++i:
|
||||||
|
kdebug_num (old_current->arch.t[i])
|
||||||
|
kdebug (" ")
|
||||||
|
kdebug ("\ns=")
|
||||||
|
for unsigned i = 0; i < 8; ++i:
|
||||||
|
kdebug_num (old_current->arch.s[i])
|
||||||
|
kdebug (" ")
|
||||||
|
kdebug ("\ngp=")
|
||||||
|
kdebug_num (old_current->arch.gp)
|
||||||
|
kdebug (" fp=")
|
||||||
|
kdebug_num (old_current->arch.fp)
|
||||||
|
kdebug (" ra=")
|
||||||
|
kdebug_num (old_current->arch.ra)
|
||||||
|
kdebug ("\nhi=")
|
||||||
|
kdebug_num (old_current->arch.hi)
|
||||||
|
kdebug (" lo=")
|
||||||
|
kdebug_num (old_current->arch.lo)
|
||||||
|
kdebug ("\nk=")
|
||||||
|
kdebug_num (old_current->arch.k[0])
|
||||||
|
kdebug (" ")
|
||||||
|
kdebug_num (old_current->arch.k[1])
|
||||||
|
kdebug ('\n')
|
||||||
kdebug ("; ")
|
kdebug ("; ")
|
||||||
kdebug (name)
|
kdebug (name)
|
||||||
kdebug (':')
|
kdebug (':')
|
||||||
@ -129,6 +164,21 @@ static void panic_message (unsigned n, const char *line, char const *name, char
|
|||||||
if b == 32:
|
if b == 32:
|
||||||
b = 0
|
b = 0
|
||||||
kdebug ('\n')
|
kdebug ('\n')
|
||||||
|
if old_current:
|
||||||
|
kdebug ("Attempt to print *pc:\n")
|
||||||
|
unsigned page = old_current->pc & PAGE_MASK
|
||||||
|
unsigned start = old_current->pc & ~(4 * 4 - 1)
|
||||||
|
for int i = -4; i < 8; ++i:
|
||||||
|
kdebug_num (start + i * 4 * 4)
|
||||||
|
kdebug (" ==>")
|
||||||
|
for unsigned j = 0; j < 4; ++j:
|
||||||
|
kdebug (' ')
|
||||||
|
unsigned addr = start + (i * 4 + j) * 4
|
||||||
|
if (addr & PAGE_MASK) == page:
|
||||||
|
kdebug_num (*(unsigned *)addr)
|
||||||
|
else:
|
||||||
|
kdebug ("--------")
|
||||||
|
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.
|
||||||
|
71
source/alarm.ccp
Normal file
71
source/alarm.ccp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#pypp 0
|
||||||
|
#include <iris.hh>
|
||||||
|
#include <ui.hh>
|
||||||
|
|
||||||
|
enum Ins:
|
||||||
|
TOTAL_TIME
|
||||||
|
START
|
||||||
|
NUM_INS
|
||||||
|
|
||||||
|
enum Outs:
|
||||||
|
CURRENT_TIME
|
||||||
|
ALARM
|
||||||
|
NUM_OUTS
|
||||||
|
|
||||||
|
static UI <NUM_INS, NUM_OUTS> ui
|
||||||
|
static UI <NUM_INS, NUM_OUTS>::in <unsigned> total_time
|
||||||
|
static UI <NUM_INS, NUM_OUTS>::in_event do_start
|
||||||
|
static UI <NUM_INS, NUM_OUTS>::out <unsigned> current_time
|
||||||
|
static UI <NUM_INS, NUM_OUTS>::out_event do_alarm
|
||||||
|
|
||||||
|
static bool ticking
|
||||||
|
|
||||||
|
static void event (unsigned code):
|
||||||
|
switch code:
|
||||||
|
case TOTAL_TIME:
|
||||||
|
break
|
||||||
|
case START:
|
||||||
|
current_time = total_time
|
||||||
|
if !ticking:
|
||||||
|
if !current_time:
|
||||||
|
do_alarm ()
|
||||||
|
else:
|
||||||
|
ticking = true
|
||||||
|
Iris::my_receiver.set_alarm (HZ)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
Iris::panic (0, "invalid event for alarm clock")
|
||||||
|
|
||||||
|
Iris::Num start ():
|
||||||
|
ticking = false;
|
||||||
|
Iris::Cap ui_cap = Iris::my_receiver.create_capability (0)
|
||||||
|
ui.init (ui_cap.copy ());
|
||||||
|
Iris::free_cap (ui_cap)
|
||||||
|
total_time.init ()
|
||||||
|
do_start.init ()
|
||||||
|
current_time.init ()
|
||||||
|
do_alarm.init ()
|
||||||
|
ui.add_in (&total_time, TOTAL_TIME);
|
||||||
|
ui.add_in (&do_start, START);
|
||||||
|
ui.add_out (¤t_time, CURRENT_TIME);
|
||||||
|
ui.add_out (&do_alarm, ALARM);
|
||||||
|
Iris::my_parent.init_done ()
|
||||||
|
|
||||||
|
while true:
|
||||||
|
Iris::wait ()
|
||||||
|
switch Iris::recv.protected_data.l:
|
||||||
|
case ~0:
|
||||||
|
// alarm.
|
||||||
|
current_time = current_time - 1
|
||||||
|
if !current_time:
|
||||||
|
do_alarm ()
|
||||||
|
ticking = false
|
||||||
|
else:
|
||||||
|
// TODO: use rtc for scheduling an event.
|
||||||
|
Iris::my_receiver.set_alarm (HZ)
|
||||||
|
continue
|
||||||
|
case 0:
|
||||||
|
// ui event.
|
||||||
|
if !ui.event (&event):
|
||||||
|
// Exit request.
|
||||||
|
return 0
|
@ -37,7 +37,8 @@ Iris::Num start ():
|
|||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
int colour = 0x3f30ff
|
int colour = 0x3f30ff
|
||||||
framebuffer = (unsigned *)0x15000
|
framebuffer = (unsigned *)0x15000
|
||||||
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10000)
|
Iris::Display display = Iris::my_parent.get_capability <Iris::Display> ()
|
||||||
|
Iris::Caps fb = display.map_fb ((unsigned)framebuffer)
|
||||||
int x = r, y = r, dx = 3, dy = 0
|
int x = r, y = r, dx = 3, dy = 0
|
||||||
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
||||||
while true:
|
while true:
|
||||||
|
@ -36,7 +36,7 @@ Iris::Num start ():
|
|||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
colour = 0xffff00
|
colour = 0xffff00
|
||||||
framebuffer = (unsigned *)0x15000
|
framebuffer = (unsigned *)0x15000
|
||||||
Iris::Display display = Iris::my_parent.get_device <Iris::Display> (0x10001)
|
Iris::Display display = Iris::my_parent.get_capability <Iris::Display> (0x10001)
|
||||||
int x = r, y = r, dx = 3, dy = 3
|
int x = r, y = r, dx = 3, dy = 3
|
||||||
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
Iris::Cap eof = Iris::my_receiver.create_capability (0)
|
||||||
while true:
|
while true:
|
||||||
|
@ -58,7 +58,7 @@ Iris::Num start ():
|
|||||||
DevBuzzer buzzer
|
DevBuzzer buzzer
|
||||||
|
|
||||||
Iris::Buzzer dev = Iris::my_receiver.create_capability (BUZZER)
|
Iris::Buzzer dev = Iris::my_receiver.create_capability (BUZZER)
|
||||||
Iris::my_parent.provide_device <Iris::Buzzer> (dev.copy ())
|
Iris::my_parent.provide_capability <Iris::Buzzer> (dev.copy ())
|
||||||
Iris::free_cap (dev)
|
Iris::free_cap (dev)
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
while true:
|
while true:
|
||||||
@ -66,7 +66,7 @@ Iris::Num start ():
|
|||||||
if Iris::recv.protected_data.h == ~0:
|
if Iris::recv.protected_data.h == ~0:
|
||||||
// Alarm.
|
// Alarm.
|
||||||
buzzer.stop ()
|
buzzer.stop ()
|
||||||
break
|
continue
|
||||||
switch Iris::recv.protected_data.l:
|
switch Iris::recv.protected_data.l:
|
||||||
case BUZZER:
|
case BUZZER:
|
||||||
// Buzzer device user request.
|
// Buzzer device user request.
|
||||||
|
@ -60,6 +60,8 @@ static char *mapping
|
|||||||
static unsigned pages
|
static unsigned pages
|
||||||
static Iris::Caps pages_caps
|
static Iris::Caps pages_caps
|
||||||
static Iris::Memory mem
|
static Iris::Memory mem
|
||||||
|
static unsigned *bss_mapping
|
||||||
|
static Iris::Page bss_page
|
||||||
|
|
||||||
static Iris::Caps map_string (Iris::String data):
|
static Iris::Caps map_string (Iris::String data):
|
||||||
// Get the size.
|
// Get the size.
|
||||||
@ -142,6 +144,11 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
bool readonly = !(shdr->sh_flags & SHF_WRITE)
|
||||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||||
if shdr->sh_type != SHT_NOBITS:
|
if shdr->sh_type != SHT_NOBITS:
|
||||||
|
//kdebug ("loading ")
|
||||||
|
//kdebug_num (shdr->sh_addr)
|
||||||
|
//kdebug ("+")
|
||||||
|
//kdebug_num (shdr->sh_size)
|
||||||
|
//kdebug ("\n")
|
||||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||||
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
||||||
kdebug ("thread size: ")
|
kdebug ("thread size: ")
|
||||||
@ -181,17 +188,23 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
if readonly:
|
if readonly:
|
||||||
Iris::panic (0, "unwritable bss section")
|
Iris::panic (0, "unwritable bss section")
|
||||||
return Iris::Caps ()
|
return Iris::Caps ()
|
||||||
|
//kdebug ("clearing ")
|
||||||
|
//kdebug_num (shdr->sh_addr)
|
||||||
|
//kdebug ("+")
|
||||||
|
//kdebug_num (shdr->sh_size)
|
||||||
|
//kdebug ("\n")
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||||
Iris::Page page = mem.mapping ((void *)p)
|
Iris::Page page = mem.mapping ((void *)p)
|
||||||
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
if Iris::recv.data[0].l == Iris::NO_ERROR:
|
||||||
// No error means there is a mapping.
|
// No error means there is a mapping.
|
||||||
|
page.share (bss_page, 0)
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||||
if a >= shdr->sh_addr + shdr->sh_size:
|
if a >= shdr->sh_addr + shdr->sh_size:
|
||||||
break
|
break
|
||||||
if a < shdr->sh_addr:
|
if a < shdr->sh_addr:
|
||||||
continue
|
continue
|
||||||
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
|
bss_mapping[(a & ~PAGE_MASK) >> 2] = 0
|
||||||
else:
|
else:
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
page = mem.create_page ()
|
page = mem.create_page ()
|
||||||
@ -202,6 +215,14 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
|
|||||||
if !mem.map (page, p):
|
if !mem.map (page, p):
|
||||||
Iris::panic (0, "unable to map bss page")
|
Iris::panic (0, "unable to map bss page")
|
||||||
Iris::free_cap (page)
|
Iris::free_cap (page)
|
||||||
|
//kdebug ("start of program:\n")
|
||||||
|
//for unsigned i = 0; i < 0x40; i += 4:
|
||||||
|
// kdebug_num ((unsigned)mapping + 4 * i, 3)
|
||||||
|
// kdebug (" ==>")
|
||||||
|
// for unsigned j = 0; j < 4; j += 1:
|
||||||
|
// kdebug (" ")
|
||||||
|
// kdebug_num (((unsigned *)mapping)[i + j])
|
||||||
|
// kdebug ("\n")
|
||||||
for unsigned p = 0; p < pages; ++p:
|
for unsigned p = 0; p < pages; ++p:
|
||||||
Iris::my_memory.destroy (Iris::Page (slot, p))
|
Iris::my_memory.destroy (Iris::Page (slot, p))
|
||||||
Iris::my_memory.destroy (pages_caps)
|
Iris::my_memory.destroy (pages_caps)
|
||||||
@ -235,8 +256,11 @@ Iris::Num start ():
|
|||||||
kdebug ("elfrun started.\n")
|
kdebug ("elfrun started.\n")
|
||||||
init_alloc ()
|
init_alloc ()
|
||||||
Iris::Elfrun dev = Iris::my_receiver.create_capability (0)
|
Iris::Elfrun dev = Iris::my_receiver.create_capability (0)
|
||||||
Iris::my_parent.provide_device <Iris::Elfrun> (dev.copy ())
|
Iris::my_parent.provide_capability <Iris::Elfrun> (dev.copy ())
|
||||||
Iris::free_cap (dev)
|
Iris::free_cap (dev)
|
||||||
|
bss_mapping = (unsigned *)alloc_space (1)
|
||||||
|
bss_page = Iris::my_memory.create_page ()
|
||||||
|
Iris::my_memory.map (bss_page, (unsigned)bss_mapping)
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
|
238
source/gui.ccp
Normal file
238
source/gui.ccp
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#pypp 0
|
||||||
|
#include <iris.hh>
|
||||||
|
#include <devices.hh>
|
||||||
|
#include <keys.hh>
|
||||||
|
|
||||||
|
// Interface: two way, started by ui.
|
||||||
|
|
||||||
|
// From ui to application.
|
||||||
|
// ~0: request reset.
|
||||||
|
// ~1: set reply cap; send current state.
|
||||||
|
// inum: event (with optional value) for input number num.
|
||||||
|
|
||||||
|
// From application to ui.
|
||||||
|
// onum: event (with optional value) for output number num.
|
||||||
|
|
||||||
|
// For now, the code is hardwired to the alarm clock interface.
|
||||||
|
enum outs:
|
||||||
|
CURRENT_TIME
|
||||||
|
ALARM
|
||||||
|
|
||||||
|
enum ins:
|
||||||
|
TOTAL_TIME
|
||||||
|
START
|
||||||
|
|
||||||
|
static Iris::Display display
|
||||||
|
static Iris::Buzzer buzzer
|
||||||
|
static unsigned *framebuffer
|
||||||
|
|
||||||
|
enum PD:
|
||||||
|
UI
|
||||||
|
KBD
|
||||||
|
|
||||||
|
static char const *chardef =
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"..#..."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"....#."
|
||||||
|
"...#.."
|
||||||
|
"..#..."
|
||||||
|
".#...."
|
||||||
|
"#####."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"....#."
|
||||||
|
"..##.."
|
||||||
|
"....#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
"#####."
|
||||||
|
"....#."
|
||||||
|
"....#."
|
||||||
|
"....#."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"#####."
|
||||||
|
"#....."
|
||||||
|
"####.."
|
||||||
|
"....#."
|
||||||
|
"....#."
|
||||||
|
"....#."
|
||||||
|
"####.."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"....#."
|
||||||
|
"...#.."
|
||||||
|
"..#..."
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"#####."
|
||||||
|
"....#."
|
||||||
|
"...#.."
|
||||||
|
"..#..."
|
||||||
|
".#...."
|
||||||
|
"#....."
|
||||||
|
"#....."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
".###.."
|
||||||
|
"#...#."
|
||||||
|
"#...#."
|
||||||
|
".###.."
|
||||||
|
"..#..."
|
||||||
|
".#...."
|
||||||
|
"#....."
|
||||||
|
"......"
|
||||||
|
|
||||||
|
"......"
|
||||||
|
"......"
|
||||||
|
"..#..."
|
||||||
|
"......"
|
||||||
|
"......"
|
||||||
|
"..#..."
|
||||||
|
"......"
|
||||||
|
"......"
|
||||||
|
|
||||||
|
static void draw_pixel (unsigned x, unsigned y, bool set):
|
||||||
|
for unsigned ty = 0; ty < 8; ++ty:
|
||||||
|
for unsigned tx = 0; tx < 8; ++tx:
|
||||||
|
framebuffer[320 * (y + ty) + x + tx] = (set ? 0xffffff : 0x000000)
|
||||||
|
|
||||||
|
static void draw_num (bool upper, unsigned x0, unsigned d):
|
||||||
|
for unsigned y = 0; y < 8; ++y:
|
||||||
|
for unsigned x = 0; x < 6; ++x:
|
||||||
|
draw_pixel (x * 10 + 10 + x0 * 60, y * 10 + (upper ? 30 : 50 + 80), chardef[(d * 8 + y) * 6 + x] == '#')
|
||||||
|
|
||||||
|
static void draw_time (bool upper, unsigned time):
|
||||||
|
unsigned min = time / 60
|
||||||
|
time %= 60
|
||||||
|
if min >= 100:
|
||||||
|
min = 99
|
||||||
|
time = 99
|
||||||
|
draw_num (upper, 0, min / 10)
|
||||||
|
draw_num (upper, 1, min % 10)
|
||||||
|
draw_num (upper, 3, time / 10)
|
||||||
|
draw_num (upper, 4, time % 10)
|
||||||
|
|
||||||
|
static void beep ():
|
||||||
|
buzzer.beep (4 * 440, 1000, ~0)
|
||||||
|
|
||||||
|
Iris::Num start ():
|
||||||
|
Iris::my_parent.init_done ()
|
||||||
|
display = Iris::my_parent.get_capability <Iris::Display> ()
|
||||||
|
Iris::Setting bright = Iris::my_parent.get_capability <Iris::Setting> ()
|
||||||
|
Iris::Keyboard keyboard = Iris::my_parent.get_capability <Iris::Keyboard> ()
|
||||||
|
buzzer = Iris::my_parent.get_capability <Iris::Buzzer> ()
|
||||||
|
Iris::UI app = Iris::my_parent.get_capability <Iris::UI> ()
|
||||||
|
Iris::Cap cb = Iris::my_receiver.create_capability (UI)
|
||||||
|
framebuffer = (unsigned *)0x15000
|
||||||
|
Iris::Caps fb = display.map_fb ((unsigned)framebuffer)
|
||||||
|
bright.set (bright.get_range ())
|
||||||
|
app.get_state (cb.copy ())
|
||||||
|
Iris::free_cap (cb)
|
||||||
|
cb = Iris::my_receiver.create_capability (KBD)
|
||||||
|
keyboard.set_cb (cb.copy ())
|
||||||
|
Iris::free_cap (cb)
|
||||||
|
draw_num (false, 2, 10)
|
||||||
|
draw_num (true, 2, 10)
|
||||||
|
unsigned total_time = 0
|
||||||
|
while true:
|
||||||
|
Iris::wait ()
|
||||||
|
switch Iris::recv.protected_data.l:
|
||||||
|
case UI:
|
||||||
|
switch Iris::recv.data[0].l:
|
||||||
|
case CURRENT_TIME:
|
||||||
|
draw_time (false, Iris::recv.data[1].l)
|
||||||
|
break
|
||||||
|
case ALARM:
|
||||||
|
beep ()
|
||||||
|
break
|
||||||
|
case TOTAL_TIME | Iris::UI::INPUT:
|
||||||
|
total_time = Iris::recv.data[1].l
|
||||||
|
draw_time (true, total_time)
|
||||||
|
break
|
||||||
|
case START | Iris::UI::INPUT:
|
||||||
|
break
|
||||||
|
break
|
||||||
|
case KBD:
|
||||||
|
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||||
|
break
|
||||||
|
switch Iris::recv.data[0].l:
|
||||||
|
case Key::VOLUME_UP:
|
||||||
|
total_time += 60
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::VOLUME_DOWN:
|
||||||
|
if total_time < 60:
|
||||||
|
total_time = 0
|
||||||
|
else:
|
||||||
|
total_time -= 60
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::UP:
|
||||||
|
total_time += 10
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::DOWN:
|
||||||
|
if total_time < 10:
|
||||||
|
total_time = 0
|
||||||
|
else:
|
||||||
|
total_time -= 10
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::LEFT:
|
||||||
|
if total_time < 1:
|
||||||
|
total_time = 0
|
||||||
|
else:
|
||||||
|
total_time -= 1
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::RIGHT:
|
||||||
|
total_time += 1
|
||||||
|
draw_time (true, total_time)
|
||||||
|
app.event (TOTAL_TIME, total_time)
|
||||||
|
break
|
||||||
|
case Key::ENTER:
|
||||||
|
app.event (START)
|
309
source/init.ccp
309
source/init.ccp
@ -23,6 +23,8 @@
|
|||||||
#define NUM_SLOTS 8
|
#define NUM_SLOTS 8
|
||||||
#define NUM_CAPS 32
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
|
#define SYSREQ 0x100
|
||||||
|
|
||||||
static unsigned _free
|
static unsigned _free
|
||||||
extern unsigned _end
|
extern unsigned _end
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ struct List:
|
|||||||
|
|
||||||
struct Program
|
struct Program
|
||||||
|
|
||||||
struct Device:
|
struct Serverdevice:
|
||||||
char *name
|
char *name
|
||||||
unsigned name_len
|
unsigned name_len
|
||||||
unsigned type, index
|
unsigned type, index
|
||||||
@ -107,6 +109,14 @@ struct Device:
|
|||||||
Program *server
|
Program *server
|
||||||
Program *client
|
Program *client
|
||||||
|
|
||||||
|
struct Clientdevice:
|
||||||
|
unsigned type, index
|
||||||
|
Serverdevice *dev
|
||||||
|
|
||||||
|
static Iris::Memory top_memory
|
||||||
|
static Iris::Directory root
|
||||||
|
static Iris::Elfrun elfrun
|
||||||
|
|
||||||
struct Program:
|
struct Program:
|
||||||
char *name
|
char *name
|
||||||
unsigned name_len
|
unsigned name_len
|
||||||
@ -114,15 +124,28 @@ struct Program:
|
|||||||
Iris::Caps pages
|
Iris::Caps pages
|
||||||
Iris::Memory memory
|
Iris::Memory memory
|
||||||
Iris::Thread thread
|
Iris::Thread thread
|
||||||
List <Device> devices
|
List <Serverdevice> server_devices
|
||||||
Iris::Cap waiter
|
List <Clientdevice> client_devices
|
||||||
|
unsigned num_waiting
|
||||||
|
bool priv
|
||||||
|
void run ():
|
||||||
|
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)this)
|
||||||
|
if priv:
|
||||||
|
kdebug ("priv ")
|
||||||
|
kdebug ("running ")
|
||||||
|
for unsigned i = 0; i < name_len; ++i:
|
||||||
|
kdebug_char (name[i])
|
||||||
|
kdebug ("\n")
|
||||||
|
Iris::Caps caps = elfrun.run_caps (top_memory, pages, cap.copy (), (size + PAGE_SIZE - 1) >> PAGE_BITS)
|
||||||
|
Iris::free_cap (cap)
|
||||||
|
thread = caps.get (__thread_num)
|
||||||
|
memory = caps.get (__memory_num)
|
||||||
|
if priv:
|
||||||
|
thread.make_priv ()
|
||||||
|
thread.run ()
|
||||||
|
|
||||||
static Iris::Memory top_memory
|
|
||||||
static Iris::Directory root
|
|
||||||
static Iris::Elfrun elfrun
|
|
||||||
static List <Program> programs
|
static List <Program> programs
|
||||||
static Iris::Cap sysreq
|
static Serverdevice *sysreq
|
||||||
static unsigned to_receive, progs
|
|
||||||
|
|
||||||
static bool name_match (char const *name, unsigned name_len, Iris::String n):
|
static bool name_match (char const *name, unsigned name_len, Iris::String n):
|
||||||
char nm[16]
|
char nm[16]
|
||||||
@ -255,6 +278,7 @@ static Type types[] = {
|
|||||||
{ "WDirectory", 10, Iris::WDirectory::ID },
|
{ "WDirectory", 10, Iris::WDirectory::ID },
|
||||||
{ "Filesystem", 10, Iris::Filesystem::ID },
|
{ "Filesystem", 10, Iris::Filesystem::ID },
|
||||||
{ "Stream", 6, Iris::Stream::ID },
|
{ "Stream", 6, Iris::Stream::ID },
|
||||||
|
{ "UI", 2, Iris::UI::ID },
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,37 +299,25 @@ static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &ind
|
|||||||
return
|
return
|
||||||
Iris::panic (0, "no valid type found")
|
Iris::panic (0, "no valid type found")
|
||||||
|
|
||||||
static void do_run (char *&start, unsigned &maxlen, bool priv):
|
static bool find_cap (char *&line, unsigned &len, Program *&server, Serverdevice *&dev):
|
||||||
char *n
|
char *n
|
||||||
unsigned l
|
unsigned l
|
||||||
if !get_name (start, maxlen, n, l):
|
if !get_name (line, len, n, l):
|
||||||
Iris::panic (0, "syntax error in init.config (driver)")
|
Iris::panic (0, "no capability name found in init.config")
|
||||||
List <Program>::Item *p
|
List <Program>::Item *p
|
||||||
for p = programs.begin (); p; p = p->next:
|
for p = programs.begin (); p; p = p->next:
|
||||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
List <Serverdevice>::Item *d
|
||||||
break
|
for d = (*p)->server_devices.begin (); d; d = d->next:
|
||||||
if !p:
|
if string_match (n, l, (*d)->name, (*d)->name_len):
|
||||||
Iris::panic (0, "program not found for driver")
|
server = &**p
|
||||||
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p)
|
dev = &**d
|
||||||
if priv:
|
return true
|
||||||
kdebug ("priv ")
|
return false
|
||||||
kdebug ("running ")
|
|
||||||
for unsigned i = 0; i < (*p)->name_len; ++i:
|
|
||||||
kdebug_char ((*p)->name[i])
|
|
||||||
kdebug ("\n")
|
|
||||||
Iris::Caps caps = elfrun.run_caps (top_memory, (*p)->pages, cap.copy (), ((*p)->size + PAGE_SIZE - 1) >> PAGE_BITS)
|
|
||||||
Iris::free_cap (cap)
|
|
||||||
(*p)->thread = caps.get (__thread_num)
|
|
||||||
(*p)->memory = caps.get (__memory_num)
|
|
||||||
if priv:
|
|
||||||
(*p)->thread.make_priv ()
|
|
||||||
(*p)->thread.run ()
|
|
||||||
// TODO: pass arguments.
|
|
||||||
start += maxlen
|
|
||||||
maxlen = 0
|
|
||||||
|
|
||||||
static void parse_line (char *&line, unsigned maxlen)
|
static void parse_line (char *&line, unsigned maxlen)
|
||||||
static void include_caps (Iris::Caps caps, unsigned size):
|
static void include (char const *name, unsigned name_len):
|
||||||
|
unsigned size
|
||||||
|
Iris::Caps caps = load (name, name_len, size)
|
||||||
unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS
|
unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||||
char *config = alloc_space (pages)
|
char *config = alloc_space (pages)
|
||||||
unsigned pages_slot = caps.use ()
|
unsigned pages_slot = caps.use ()
|
||||||
@ -321,6 +333,30 @@ static void include_caps (Iris::Caps caps, unsigned size):
|
|||||||
Iris::free_cap (caps)
|
Iris::free_cap (caps)
|
||||||
Iris::free_slot (pages_slot)
|
Iris::free_slot (pages_slot)
|
||||||
|
|
||||||
|
static char *get_filename (char *&line, unsigned &maxlen, unsigned &len):
|
||||||
|
char q = *line++
|
||||||
|
--maxlen
|
||||||
|
len = 0
|
||||||
|
while maxlen && *line != q:
|
||||||
|
++line
|
||||||
|
--maxlen
|
||||||
|
++len
|
||||||
|
if !maxlen:
|
||||||
|
Iris::panic (0, "no closing quote in init.config")
|
||||||
|
return line - len
|
||||||
|
|
||||||
|
static void do_load (char *&line, unsigned &maxlen, bool priv):
|
||||||
|
Program *p = &**programs.insert ()
|
||||||
|
if !get_name (line, maxlen, p->name, p->name_len) || !match (line, maxlen, "=") || !maxlen:
|
||||||
|
Iris::panic (0, "syntax error in init.config (load)")
|
||||||
|
unsigned l
|
||||||
|
char *n = get_filename (line, maxlen, l)
|
||||||
|
p->pages = load (n, l, p->size)
|
||||||
|
p->priv = priv
|
||||||
|
p->num_waiting = 0
|
||||||
|
++line
|
||||||
|
--maxlen
|
||||||
|
|
||||||
static void parse_line (char *&line, unsigned maxlen):
|
static void parse_line (char *&line, unsigned maxlen):
|
||||||
char *start = line
|
char *start = line
|
||||||
while maxlen && *line != '\n':
|
while maxlen && *line != '\n':
|
||||||
@ -333,25 +369,10 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
delspace (start, maxlen)
|
delspace (start, maxlen)
|
||||||
if !maxlen:
|
if !maxlen:
|
||||||
return
|
return
|
||||||
if match (start, maxlen, "load"):
|
if match (start, maxlen, "program"):
|
||||||
Program *p = &**programs.insert ()
|
do_load (start, maxlen, false)
|
||||||
if !get_name (start, maxlen, p->name, p->name_len) || !match (start, maxlen, "=") || !maxlen:
|
else if match (start, maxlen, "driver"):
|
||||||
Iris::panic (0, "syntax error in init.config (load)")
|
do_load (start, maxlen, true)
|
||||||
char q = *start++
|
|
||||||
--maxlen
|
|
||||||
unsigned len = 0
|
|
||||||
while maxlen && *start != q:
|
|
||||||
++start
|
|
||||||
--maxlen
|
|
||||||
++len
|
|
||||||
if !maxlen:
|
|
||||||
Iris::panic (0, "no closing quote in init.config")
|
|
||||||
p->pages = load (start - len, len, p->size)
|
|
||||||
p->waiter = Iris::Cap ()
|
|
||||||
++start
|
|
||||||
--maxlen
|
|
||||||
else if match (start, maxlen, "killbootthreads"):
|
|
||||||
Iris::my_parent.init_done ()
|
|
||||||
else if match (start, maxlen, "receive"):
|
else if match (start, maxlen, "receive"):
|
||||||
// receive <name> / <type> [, <index>] = <cap>
|
// receive <name> / <type> [, <index>] = <cap>
|
||||||
char *n
|
char *n
|
||||||
@ -364,78 +385,53 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
break
|
break
|
||||||
if !p:
|
if !p:
|
||||||
Iris::panic (0, "program not found for receive")
|
Iris::panic (0, "program not found for receive")
|
||||||
if !(*p)->devices.begin ():
|
List <Serverdevice>::Item *dev = (*p)->server_devices.insert ()
|
||||||
++progs
|
|
||||||
List <Device>::Item *dev = (*p)->devices.insert ()
|
|
||||||
find_type (start, maxlen, (*dev)->type, (*dev)->index)
|
find_type (start, maxlen, (*dev)->type, (*dev)->index)
|
||||||
if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len):
|
if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len):
|
||||||
Iris::panic (1, "syntax error in init.config (receive)")
|
Iris::panic (1, "syntax error in init.config (receive)")
|
||||||
(*dev)->server = &**p
|
(*dev)->server = &**p
|
||||||
++to_receive
|
(*dev)->client = NULL
|
||||||
else if match (start, maxlen, "driver"):
|
(*dev)->cap = Iris::Cap ()
|
||||||
do_run (start, maxlen, true)
|
|
||||||
else if match (start, maxlen, "run"):
|
|
||||||
do_run (start, maxlen, false)
|
|
||||||
else if match (start, maxlen, "wait"):
|
|
||||||
kdebug ("waiting for device registration\n")
|
|
||||||
while progs:
|
|
||||||
Iris::wait ()
|
|
||||||
Program *caller = (Program *)Iris::recv.protected_data.l
|
|
||||||
if !caller:
|
|
||||||
Iris::panic (0, "bug in init: no caller")
|
|
||||||
switch Iris::recv.data[0].l:
|
|
||||||
case Iris::Parent::PROVIDE_DEVICE:
|
|
||||||
if Iris::recv.data[1].h != 0:
|
|
||||||
kdebug ("init: too high device provided\n")
|
|
||||||
continue
|
|
||||||
unsigned type = Iris::recv.data[1].l
|
|
||||||
unsigned index = Iris::recv.data[0].h
|
|
||||||
List <Device>::Item *d
|
|
||||||
for d = caller->devices.begin (); d; d = d->next:
|
|
||||||
if (*d)->type == type && (*d)->index == index:
|
|
||||||
break
|
|
||||||
if !d:
|
|
||||||
Iris::panic (0, "unregistered device provided")
|
|
||||||
(*d)->cap = Iris::get_arg ()
|
|
||||||
Iris::recv.reply.invoke ()
|
|
||||||
--to_receive
|
|
||||||
break
|
|
||||||
case Iris::Parent::INIT_DONE:
|
|
||||||
if caller->waiter.code != Iris::Cap ().code:
|
|
||||||
Iris::panic (0, "caller was already waiting")
|
|
||||||
caller->waiter = Iris::get_reply ()
|
|
||||||
--progs
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
Iris::panic (0, "unexpected request to init")
|
|
||||||
if to_receive:
|
|
||||||
Iris::panic (to_receive, "not all expected devices were registered")
|
|
||||||
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
|
||||||
if (*p)->waiter.code != Iris::Cap ().code:
|
|
||||||
(*p)->waiter.invoke ()
|
|
||||||
Iris::free_cap ((*p)->waiter)
|
|
||||||
(*p)->waiter = Iris::Cap ()
|
|
||||||
kdebug ("got all devices\n")
|
|
||||||
else if match (start, maxlen, "sysreq"):
|
else if match (start, maxlen, "sysreq"):
|
||||||
// TODO
|
Program *server
|
||||||
start += maxlen
|
if sysreq:
|
||||||
maxlen = 0
|
Iris::panic (0, "double registration of sysreq")
|
||||||
|
if !find_cap (start, maxlen, server, sysreq):
|
||||||
|
Iris::panic (0, "capability not found for sysreq")
|
||||||
|
if sysreq->type != Iris::Keyboard::ID:
|
||||||
|
kdebug ("capability for sysreq is not a keyboard\n")
|
||||||
else if match (start, maxlen, "give"):
|
else if match (start, maxlen, "give"):
|
||||||
// TODO
|
// give <name> / <type> [, <index>] = <cap>
|
||||||
start += maxlen
|
|
||||||
maxlen = 0
|
|
||||||
else if match (start, maxlen, "include"):
|
|
||||||
char *n
|
char *n
|
||||||
unsigned l
|
unsigned l
|
||||||
if !get_name (start, maxlen, n, l):
|
if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen:
|
||||||
Iris::panic (0, "syntax error in init.config (include)")
|
Iris::panic (0, "syntax error in init.config (give)")
|
||||||
List <Program>::Item *p
|
List <Program>::Item *p
|
||||||
for p = programs.begin (); p; p = p->next:
|
for p = programs.begin (); p; p = p->next:
|
||||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||||
break
|
break
|
||||||
if !p:
|
if !p:
|
||||||
Iris::panic (0, "file not found for include")
|
Iris::panic (0, "program not found for give")
|
||||||
include_caps ((*p)->pages, (*p)->size)
|
List <Clientdevice>::Item *d = (*p)->client_devices.insert ()
|
||||||
|
find_type (start, maxlen, (*d)->type, (*d)->index)
|
||||||
|
if !match (start, maxlen, "="):
|
||||||
|
Iris::panic (1, "syntax error in init.config (give)")
|
||||||
|
Program *server
|
||||||
|
if !find_cap (start, maxlen, server, (*d)->dev):
|
||||||
|
Iris::panic (0, "capability not found for give")
|
||||||
|
if (*d)->dev->type != (*d)->type:
|
||||||
|
kdebug ("capability type mismatch for give\n")
|
||||||
|
if (*d)->dev->client:
|
||||||
|
Iris::panic (0, "capability given out twice")
|
||||||
|
(*d)->dev->client = &**p
|
||||||
|
++(*p)->num_waiting
|
||||||
|
kdebug ("registered give device: ")
|
||||||
|
kdebug_num ((*d)->type)
|
||||||
|
kdebug ("\n")
|
||||||
|
else if match (start, maxlen, "include"):
|
||||||
|
unsigned name_len
|
||||||
|
char *name = get_filename (line, maxlen, name_len)
|
||||||
|
include (name, name_len)
|
||||||
else:
|
else:
|
||||||
Iris::panic (0, "invalid line in init.config")
|
Iris::panic (0, "invalid line in init.config")
|
||||||
delspace (start, maxlen)
|
delspace (start, maxlen)
|
||||||
@ -449,24 +445,90 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
Iris::Num start ():
|
Iris::Num start ():
|
||||||
init_alloc ()
|
init_alloc ()
|
||||||
programs.init ()
|
programs.init ()
|
||||||
root = Iris::my_parent.get_device <Iris::Directory> ()
|
root = Iris::my_parent.get_capability <Iris::Directory> ()
|
||||||
elfrun = Iris::my_parent.get_device <Iris::Elfrun> ()
|
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
|
||||||
|
sysreq = NULL
|
||||||
top_memory = Iris::get_top_memory ()
|
top_memory = Iris::get_top_memory ()
|
||||||
to_receive = 0
|
include ("init.config", 12)
|
||||||
progs = 0
|
kdebug ("killing boot threads\n")
|
||||||
unsigned config_size
|
Iris::my_parent.init_done ()
|
||||||
Iris::Caps config_pages = load ("init.config", 12, config_size)
|
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
||||||
include_caps (config_pages, config_size)
|
if !(*p)->num_waiting:
|
||||||
|
(*p)->run ()
|
||||||
|
if !sysreq:
|
||||||
|
Iris::panic (0, "sysreq not registered")
|
||||||
|
if sysreq->client:
|
||||||
|
Iris::panic (0, "sysreq set to reserved capability")
|
||||||
kdebug ("waiting for events.\n")
|
kdebug ("waiting for events.\n")
|
||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
Program *caller = (Program *)Iris::recv.protected_data.l
|
if Iris::recv.protected_data.l == SYSREQ:
|
||||||
if !caller:
|
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||||
// System request.
|
continue
|
||||||
// TODO.
|
kdebug ("sysreq event\n")
|
||||||
kdebug ("system request\n")
|
|
||||||
continue
|
continue
|
||||||
|
Program *caller = (Program *)Iris::recv.protected_data.l
|
||||||
switch Iris::recv.data[0].l:
|
switch Iris::recv.data[0].l:
|
||||||
|
case Iris::Parent::GET_CAPABILITY:
|
||||||
|
unsigned index = Iris::recv.data[0].h
|
||||||
|
unsigned type = Iris::recv.data[1].l
|
||||||
|
if Iris::recv.data[1].h:
|
||||||
|
Iris::panic (Iris::recv.data[1].h, "high device requested")
|
||||||
|
//kdebug ("requested device ")
|
||||||
|
//kdebug_num (type)
|
||||||
|
//kdebug (":")
|
||||||
|
//kdebug_num (index)
|
||||||
|
//kdebug ("\n")
|
||||||
|
List <Clientdevice>::Item *d
|
||||||
|
for d = caller->client_devices.begin (); d; d = d->next:
|
||||||
|
//kdebug ("checking ")
|
||||||
|
//kdebug_num ((*d)->type)
|
||||||
|
//kdebug (":")
|
||||||
|
//kdebug_num ((*d)->index)
|
||||||
|
//kdebug ("\n")
|
||||||
|
if (*d)->type == type && (*d)->index == index:
|
||||||
|
break
|
||||||
|
if !d:
|
||||||
|
Iris::panic (type, "unregistered device requested")
|
||||||
|
Iris::recv.reply.invoke (0, 0, (*d)->dev->cap)
|
||||||
|
kdebug ("given device ")
|
||||||
|
kdebug_num (type)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num (index)
|
||||||
|
kdebug ("\n")
|
||||||
|
break
|
||||||
|
case Iris::Parent::PROVIDE_CAPABILITY:
|
||||||
|
if Iris::recv.data[1].h != 0:
|
||||||
|
kdebug ("init: too high device provided\n")
|
||||||
|
continue
|
||||||
|
unsigned type = Iris::recv.data[1].l
|
||||||
|
unsigned index = Iris::recv.data[0].h
|
||||||
|
List <Serverdevice>::Item *d
|
||||||
|
for d = caller->server_devices.begin (); d; d = d->next:
|
||||||
|
if (*d)->type == type && (*d)->index == index:
|
||||||
|
break
|
||||||
|
if !d:
|
||||||
|
Iris::panic (0, "unregistered device provided")
|
||||||
|
(*d)->cap = Iris::get_arg ()
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
if (*d)->client:
|
||||||
|
if !--(*d)->client->num_waiting:
|
||||||
|
(*d)->client->run ()
|
||||||
|
kdebug ("provided ")
|
||||||
|
kdebug_num ((*d)->type)
|
||||||
|
kdebug (":")
|
||||||
|
kdebug_num ((*d)->index)
|
||||||
|
kdebug ("\n")
|
||||||
|
break
|
||||||
|
case Iris::Parent::INIT_DONE:
|
||||||
|
kdebug ("init done\n")
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
if caller == sysreq->server:
|
||||||
|
Iris::Cap cap = Iris::my_receiver.create_capability (SYSREQ)
|
||||||
|
Iris::Keyboard (sysreq->cap).set_cb (cap.copy ())
|
||||||
|
Iris::free_cap (cap)
|
||||||
|
kdebug ("registered sysreq\n")
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
// TODO.
|
// TODO.
|
||||||
kdebug ("child request: ")
|
kdebug ("child request: ")
|
||||||
@ -475,4 +537,3 @@ Iris::Num start ():
|
|||||||
for unsigned i = 0; i < caller->name_len; ++i:
|
for unsigned i = 0; i < caller->name_len; ++i:
|
||||||
kdebug_char (caller->name[i])
|
kdebug_char (caller->name[i])
|
||||||
kdebug ("\n")
|
kdebug ("\n")
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ static unsigned pages
|
|||||||
static Descriptor descriptor __attribute__ ((aligned (16)))
|
static Descriptor descriptor __attribute__ ((aligned (16)))
|
||||||
static bool is_on
|
static bool is_on
|
||||||
|
|
||||||
static unsigned create (Iris::Memory mem, Iris::Caps caps):
|
static unsigned create (Iris::Memory mem):
|
||||||
unsigned physical = mem.alloc_range (pages)
|
unsigned physical = mem.alloc_range (pages)
|
||||||
unsigned address = 0x15000
|
unsigned address = 0x15000
|
||||||
if physical & ~PAGE_MASK:
|
if physical & ~PAGE_MASK:
|
||||||
@ -275,9 +275,8 @@ static unsigned create (Iris::Memory mem, Iris::Caps caps):
|
|||||||
Iris::free_cap (p)
|
Iris::free_cap (p)
|
||||||
return physical
|
return physical
|
||||||
|
|
||||||
static void destroy (unsigned physical, Iris::Caps caps):
|
static void destroy (unsigned physical, Iris::Memory mem):
|
||||||
unsigned address = 0x15000
|
unsigned address = 0x15000
|
||||||
Iris::Memory mem = caps.get (1)
|
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
Iris::panic (0, "unable to destroy framebuffer with wrong cap0")
|
Iris::panic (0, "unable to destroy framebuffer with wrong cap0")
|
||||||
if descriptor.frame == physical && is_on:
|
if descriptor.frame == physical && is_on:
|
||||||
@ -291,7 +290,7 @@ static void destroy (unsigned physical, Iris::Caps caps):
|
|||||||
mem.destroy (p)
|
mem.destroy (p)
|
||||||
Iris::free_cap (p)
|
Iris::free_cap (p)
|
||||||
|
|
||||||
static void use (unsigned physical, Iris::Caps caps):
|
static void use (unsigned physical):
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
Iris::panic (0, "unable to use framebuffer with wrong cap0")
|
Iris::panic (0, "unable to use framebuffer with wrong cap0")
|
||||||
bool was_unused = descriptor.frame == 0
|
bool was_unused = descriptor.frame == 0
|
||||||
@ -304,7 +303,7 @@ static void use (unsigned physical, Iris::Caps caps):
|
|||||||
write_reg (BACKLIGHT1, 0x5f)
|
write_reg (BACKLIGHT1, 0x5f)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void unuse (unsigned physical, Iris::Caps caps):
|
static void unuse (unsigned physical):
|
||||||
if physical == ~0:
|
if physical == ~0:
|
||||||
Iris::panic (0, "unable to unuse framebuffer with wrong cap0")
|
Iris::panic (0, "unable to unuse framebuffer with wrong cap0")
|
||||||
if descriptor.frame == physical:
|
if descriptor.frame == physical:
|
||||||
@ -323,29 +322,7 @@ Iris::Num start ():
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||||
#if 0
|
|
||||||
unsigned physical = Iris::my_memory.alloc_range (pages)
|
|
||||||
assert (physical & PAGE_MASK && ~physical)
|
|
||||||
for unsigned i = 0; i < pages; ++i:
|
|
||||||
Iris::Page p = Iris::my_memory.create_page ()
|
|
||||||
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
|
|
||||||
Iris::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
|
|
||||||
Iris::free_cap (p)
|
|
||||||
for unsigned y = 0; y < v; ++y:
|
|
||||||
for unsigned x = 0; x < h; ++x:
|
|
||||||
unsigned r = spot (x, y, 100, 160)
|
|
||||||
unsigned g = spot (x, y, 160, 60)
|
|
||||||
unsigned b = spot (x, y, 220, 160)
|
|
||||||
#if defined (TRENDTAC)
|
|
||||||
LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
|
|
||||||
#elif defined (NANONOTE)
|
|
||||||
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 16) | (g << 8) | b
|
|
||||||
#else
|
|
||||||
#error "Define your framebuffer format."
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
unsigned physical = 0
|
unsigned physical = 0
|
||||||
#endif
|
|
||||||
Iris::Page p = Iris::my_memory.mapping (&descriptor)
|
Iris::Page p = Iris::my_memory.mapping (&descriptor)
|
||||||
unsigned paddr = p.physical_address ()
|
unsigned paddr = p.physical_address ()
|
||||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||||
@ -364,14 +341,15 @@ Iris::Num start ():
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Register the backlight device.
|
// Register the backlight device.
|
||||||
Iris::Cap backlight = Iris::my_receiver.create_capability (BACKLIGHT)
|
Iris::Setting backlight = Iris::my_receiver.create_capability (BACKLIGHT)
|
||||||
Iris::my_parent.provide_device <Iris::Setting> (backlight.copy ())
|
Iris::my_parent.provide_capability <Iris::Setting> (backlight.copy ())
|
||||||
Iris::free_cap (backlight)
|
Iris::free_cap (backlight)
|
||||||
|
|
||||||
// Register the display device.
|
// Register the display device.
|
||||||
Iris::Display display = Iris::my_receiver.create_capability (LCD)
|
Iris::Display display = Iris::my_receiver.create_capability (LCD)
|
||||||
Iris::my_parent.provide_device <Iris::Display> (display.copy ())
|
Iris::my_parent.provide_capability <Iris::Display> (display.copy ())
|
||||||
Iris::free_cap (display)
|
Iris::free_cap (display)
|
||||||
|
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
|
|
||||||
Iris::Cap eof_cb
|
Iris::Cap eof_cb
|
||||||
@ -441,8 +419,49 @@ Iris::Num start ():
|
|||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Iris::free_cap (reply)
|
Iris::free_cap (reply)
|
||||||
break
|
break
|
||||||
|
case Iris::Display::MAP_FB:
|
||||||
|
unsigned addr = Iris::recv.data[1].l
|
||||||
|
unsigned use = Iris::recv.data[0].h
|
||||||
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
|
Iris::Memory mem = Iris::get_arg ()
|
||||||
|
unsigned physical = mem.alloc_range (pages)
|
||||||
|
assert (physical & PAGE_MASK && ~physical)
|
||||||
|
Iris::Caps ret = mem.create_caps (pages / 63 + 1)
|
||||||
|
unsigned slot = ret.use ()
|
||||||
|
for unsigned c = 0; c < pages / 63 + 1; ++c:
|
||||||
|
Iris::Caps caps (Iris::Cap (slot, c))
|
||||||
|
unsigned num = pages - 63 * c >= 63 ? 63 : pages - 63 * c
|
||||||
|
Iris::set_recv_arg (caps)
|
||||||
|
mem.create_caps (num)
|
||||||
|
unsigned slot2 = caps.use ()
|
||||||
|
for unsigned i = 0; i < num; ++i:
|
||||||
|
Iris::Page p = Iris::Cap (slot2, i)
|
||||||
|
Iris::set_recv_arg (p)
|
||||||
|
mem.create_page ()
|
||||||
|
p.alloc_physical (physical + ((63 * c + i) << PAGE_BITS), false, true)
|
||||||
|
mem.map (p, addr + ((63 * c + i) << PAGE_BITS))
|
||||||
|
Iris::free_slot (slot2)
|
||||||
|
Iris::free_slot (slot)
|
||||||
|
reply.invoke (0, 0, ret.copy ())
|
||||||
|
Iris::free_cap (ret)
|
||||||
|
Iris::free_cap (mem)
|
||||||
|
Iris::free_cap (reply)
|
||||||
|
if !use:
|
||||||
|
break
|
||||||
|
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
|
||||||
|
break
|
||||||
|
case Iris::Display::UNMAP_FB:
|
||||||
|
Iris::panic (0, "unmap_fb isn't implemented yet")
|
||||||
case Iris::Display::GET_INFO:
|
case Iris::Display::GET_INFO:
|
||||||
Iris::panic (0, "get_info isn't defined yet.")
|
Iris::panic (0, "get_info isn't implemented yet.")
|
||||||
default:
|
default:
|
||||||
Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd")
|
Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd")
|
||||||
break
|
break
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
Iris::Num start ():
|
Iris::Num start ():
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
Iris::Buzzer buzzer = Iris::my_parent.get_device <Iris::Buzzer> ()
|
Iris::Buzzer buzzer = Iris::my_parent.get_capability <Iris::Buzzer> ()
|
||||||
Iris::Keyboard kbd = Iris::my_parent.get_device <Iris::Keyboard> ()
|
Iris::Keyboard kbd = Iris::my_parent.get_capability <Iris::Keyboard> ()
|
||||||
Iris::Cap key = Iris::my_receiver.create_capability (0)
|
Iris::Cap key = Iris::my_receiver.create_capability (0)
|
||||||
kbd.set_cb (key)
|
kbd.set_cb (key)
|
||||||
// Frequency of the pulse train in millihertz.
|
// Frequency of the pulse train in millihertz.
|
||||||
|
@ -204,8 +204,8 @@ Iris::Num start ():
|
|||||||
|
|
||||||
Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV)
|
Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV)
|
||||||
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
|
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
|
||||||
Iris::my_parent.provide_device <Iris::Keyboard> (dev.copy (), 0)
|
Iris::my_parent.provide_capability <Iris::Keyboard> (dev.copy (), 0)
|
||||||
Iris::my_parent.provide_device <Iris::Keyboard> (pw.copy (), 1)
|
Iris::my_parent.provide_capability <Iris::Keyboard> (pw.copy (), 1)
|
||||||
Iris::free_cap (dev)
|
Iris::free_cap (dev)
|
||||||
Iris::free_cap (pw)
|
Iris::free_cap (pw)
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
|
@ -265,10 +265,10 @@ Iris::Num start ():
|
|||||||
Pwm pwm
|
Pwm pwm
|
||||||
|
|
||||||
Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD)
|
Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD)
|
||||||
Iris::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
Iris::my_parent.provide_capability <Keyboard> (c.copy (), 0)
|
||||||
Iris::free_cap (c)
|
Iris::free_cap (c)
|
||||||
c = Iris::my_receiver.create_capability (TOUCHPAD)
|
c = Iris::my_receiver.create_capability (TOUCHPAD)
|
||||||
Iris::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
Iris::my_parent.provide_capability <Keyboard> (c.copy (), 1)
|
||||||
Iris::free_cap (c)
|
Iris::free_cap (c)
|
||||||
Iris::my_parent.init_done ()
|
Iris::my_parent.init_done ()
|
||||||
|
|
||||||
|
116
ui.hhp
Normal file
116
ui.hhp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#pypp 0
|
||||||
|
#include <iris.hh>
|
||||||
|
#include <devices.hh>
|
||||||
|
|
||||||
|
template <unsigned I, unsigned O> //
|
||||||
|
class UI:
|
||||||
|
struct in_base:
|
||||||
|
UI <I, O> *ui
|
||||||
|
unsigned my_index
|
||||||
|
void (*handle) (in_base *self, void (*cb)(unsigned))
|
||||||
|
void (*send) (in_base *self, Iris::Cap c)
|
||||||
|
in_base () : ui (NULL), my_index (0), handle (NULL), send (NULL):
|
||||||
|
struct out_base:
|
||||||
|
UI <I, O> *ui
|
||||||
|
unsigned my_index
|
||||||
|
void (*send) (out_base *self, Iris::Cap c)
|
||||||
|
out_base () : ui (NULL), my_index (0), send (NULL):
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void init (Iris::Cap my_cap):
|
||||||
|
Iris::my_parent.provide_capability <Iris::UI> (my_cap)
|
||||||
|
template <typename _T> //
|
||||||
|
class in : public in_base:
|
||||||
|
friend class UI <I, O>
|
||||||
|
_T my_data
|
||||||
|
static void send_impl (in_base *self, Iris::Cap c):
|
||||||
|
c.invoke (self->my_index | Iris::UI::INPUT, reinterpret_cast <in <_T> *> (self)->my_data)
|
||||||
|
static void handle_impl (in_base *self, void (*cb)(unsigned)):
|
||||||
|
in *me = reinterpret_cast <in *> (self)
|
||||||
|
if me->my_data == Iris::recv.data[1].l:
|
||||||
|
return
|
||||||
|
me->my_data = Iris::recv.data[1].l
|
||||||
|
cb (me->my_index)
|
||||||
|
public:
|
||||||
|
void init ():
|
||||||
|
this->send = &send_impl
|
||||||
|
this->handle = &handle_impl
|
||||||
|
operator _T () const:
|
||||||
|
return my_data
|
||||||
|
class in_event : public in_base:
|
||||||
|
friend class UI <I, O>
|
||||||
|
static void send_impl (in_base *self, Iris::Cap c):
|
||||||
|
c.invoke (self->my_index | Iris::UI::INPUT)
|
||||||
|
static void handle_impl (in_base *self, void (*cb)(unsigned)):
|
||||||
|
cb (self->my_index)
|
||||||
|
public:
|
||||||
|
void init ():
|
||||||
|
this->send = &send_impl
|
||||||
|
this->handle = &handle_impl
|
||||||
|
template <typename _T> //
|
||||||
|
class out : public out_base:
|
||||||
|
friend class UI <I, O>
|
||||||
|
_T my_data
|
||||||
|
static void send_impl (out_base *self, Iris::Cap c):
|
||||||
|
c.invoke (self->my_index, reinterpret_cast <out <_T> *> (self)->my_data)
|
||||||
|
public:
|
||||||
|
void init ():
|
||||||
|
this->send = &send_impl
|
||||||
|
out <_T> &operator= (_T const &t):
|
||||||
|
if !this->ui || my_data == t:
|
||||||
|
return *this
|
||||||
|
my_data = t
|
||||||
|
send_impl (this, this->ui->cap)
|
||||||
|
return *this
|
||||||
|
operator _T () const:
|
||||||
|
return my_data
|
||||||
|
class out_event : public out_base:
|
||||||
|
friend class UI <I, O>
|
||||||
|
public:
|
||||||
|
static void send_impl (out_base *self, Iris::Cap c):
|
||||||
|
// Don't send an event. This is only for listing the state.
|
||||||
|
void operator() ():
|
||||||
|
if !this->ui:
|
||||||
|
return
|
||||||
|
this->ui->cap.invoke (this->my_index)
|
||||||
|
void init ():
|
||||||
|
this->send = &send_impl
|
||||||
|
void add_in (in_base *obj, unsigned code):
|
||||||
|
ins[code] = obj
|
||||||
|
obj->ui = this
|
||||||
|
obj->my_index = code
|
||||||
|
void add_out (out_base *obj, unsigned code):
|
||||||
|
outs[code] = obj
|
||||||
|
obj->ui = this
|
||||||
|
obj->my_index = code
|
||||||
|
bool event (void (*cb)(unsigned)):
|
||||||
|
switch Iris::recv.data[0].l:
|
||||||
|
case Iris::UI::EXIT:
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
return false
|
||||||
|
case Iris::UI::GET_STATE:
|
||||||
|
if cap.code != CAP_NONE:
|
||||||
|
Iris::free_cap (cap)
|
||||||
|
cap = Iris::get_arg ()
|
||||||
|
Iris::recv.reply.invoke ()
|
||||||
|
for unsigned i = 0; i < I; ++i:
|
||||||
|
ins[i]->send (ins[i], cap)
|
||||||
|
for unsigned i = 0; i < O; ++i:
|
||||||
|
outs[i]->send (outs[i], cap)
|
||||||
|
break
|
||||||
|
case Iris::UI::EVENT:
|
||||||
|
Iris::Cap r = Iris::get_reply ()
|
||||||
|
if Iris::recv.data[0].h >= I:
|
||||||
|
Iris::panic (Iris::recv.data[0].h, "invalid input requested by ui")
|
||||||
|
ins[Iris::recv.data[0].h]->handle (ins[Iris::recv.data[0].h], cb)
|
||||||
|
r.invoke ()
|
||||||
|
Iris::free_cap (r)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
Iris::panic (Iris::recv.data[0].l, "invalid request for ui")
|
||||||
|
return true
|
||||||
|
private:
|
||||||
|
in_base *ins[I]
|
||||||
|
out_base *outs[O]
|
||||||
|
Iris::Cap cap
|
Loading…
Reference in New Issue
Block a user