1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-26 02:37:17 +03:00

usb-booting alarm clock, with split gui

This commit is contained in:
Bas Wijnen 2010-05-10 01:07:17 +02:00
parent a4b5d94200
commit 8c7cac36e6
24 changed files with 829 additions and 236 deletions

View File

@ -23,7 +23,7 @@ CC = $(CROSS)gcc
LD = $(CROSS)ld
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)
BUILT_SOURCES = $(iris_sources) $(boot_sources)
@ -62,4 +62,4 @@ debug:
cat $(SERIAL)
.PHONY: clean
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
.PRECIOUS: iris.hh kernel.hh ui.hh boot-programs/crt0.o

View File

@ -58,6 +58,9 @@ void *operator new[] (unsigned size):
void *operator new (unsigned size):
return new char[size]
static unsigned *bss_mapping
static Iris::Page bss_page
// Get the initial block device and filesystem.
static Iris::Directory receive_devices ():
Iris::String data
@ -65,7 +68,7 @@ static Iris::Directory receive_devices ():
bool have_data = false, have_fs = false
for unsigned i = 0; i < 2; ++i:
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.")
switch Iris::recv.data[1].l:
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)
if Iris::recv.data[0].l == Iris::NO_ERROR:
// No error means there is a mapping.
page.share (bss_page, 0)
Iris::free_cap (page)
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
if a >= shdr->sh_addr + shdr->sh_size:
break
if a < shdr->sh_addr:
continue
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
bss_mapping[(a & ~PAGE_MASK) >> 2] = 0
else:
Iris::free_cap (page)
page = mem.create_page ()
@ -256,6 +260,10 @@ Iris::Num start ():
Iris::schedule ()
kdebug ("Starting bootinit\n")
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::Directory root = receive_devices ()
root.lock_ro ()
@ -263,7 +271,7 @@ Iris::Num start ():
Iris::Cap parent_cap = Iris::my_receiver.create_capability (0)
run (run_string, top_memory, parent_cap)
Iris::wait ()
if Iris::recv.data[0].l != Iris::Parent::PROVIDE_DEVICE || Iris::recv.data[1].l != Iris::Elfrun::ID:
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::Cap reply = Iris::get_reply ()
Iris::Elfrun elfrun = Iris::get_arg ()
@ -287,7 +295,7 @@ Iris::Num start ():
while true:
Iris::wait ()
switch Iris::recv.data[0].l:
case Iris::Parent::GET_DEVICE:
case Iris::Parent::GET_CAPABILITY:
switch Iris::recv.data[1].l:
case Iris::Directory::ID:
if have_root:

View File

@ -573,8 +573,8 @@ Iris::Num start ():
Iris::register_interrupt (IRQ_UDC)
Iris::Filesystem fs = Iris::my_receiver.create_capability (FS)
Iris::String data = Iris::my_receiver.create_capability (DATA)
Iris::my_parent.provide_device <Iris::Filesystem> (fs.copy ())
Iris::my_parent.provide_device <Iris::String> (data.copy ())
Iris::my_parent.provide_capability <Iris::Filesystem> (fs.copy ())
Iris::my_parent.provide_capability <Iris::String> (data.copy ())
Iris::free_cap (fs)
Iris::free_cap (data)
unsigned state = 0

View File

@ -126,21 +126,21 @@ namespace Iris:
struct Parent : public Iris::Cap:
Parent (Iris::Cap c = Iris::Cap ()) : Iris::Cap (c):
enum request:
GET_DEVICE = Elfrun::ID
PROVIDE_DEVICE
GET_CAPABILITY = Elfrun::ID
PROVIDE_CAPABILITY
WAIT
GET_MEMORY
PROVIDE_MEMORY
INIT_DONE
EXIT
ID
// Get a device handle.
template <typename _T> _T get_device (unsigned num = 0):
icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
// Get a handle.
template <typename _T> _T get_capability (unsigned num = 0):
icall (Iris::Num (CAP_MASTER_DIRECT | GET_CAPABILITY, num), _T::ID)
return Iris::get_arg ()
// Provide a device handle.
template <typename _T> void provide_device (Device dev, unsigned num = 0):
ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
template <typename _T> void provide_capability (Cap cap, unsigned num = 0):
ocall (cap, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_CAPABILITY, num), _T::ID)
// Wait until a device is used by the caller again.
template <typename _T> void wait (unsigned num = 0):
call (Iris::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID)
@ -200,6 +200,7 @@ namespace Iris:
enum request:
SET_EOF_CB = Buzzer::ID
MAP_FB
UNMAP_FB
GET_INFO
ID
// Register an end-of-frame callback.
@ -207,8 +208,11 @@ namespace Iris:
void set_eof_cb (Iris::Cap cb):
ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB)
// Map the framebuffer into memory.
void map_fb (unsigned address):
call (CAP_MASTER_DIRECT | MAP_FB, address)
Iris::Caps map_fb (unsigned address, Iris::Memory mem = Iris::my_memory, bool use = true):
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.
void get_info ():
// TODO: Interface is to be designed.
@ -319,7 +323,21 @@ namespace Iris:
Iris::Num write (String s, Iris::Num 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.
struct Block_device : public WString:

View File

@ -1,34 +1,29 @@
# load <name> = '<filename>' load a file into memory. Don't use this after killbootthreads.
load driver_lcd = "lcd.elf"
#load driver_buzzer = "buzzer.elf"
#load driver_gpio = "gpio.elf"
load ball = "ball.elf"
# killbootthreads destroy bootinit, bootfs and bootstore.
killbootthreads
# driver <name> = '<filename>' load a file into memory to be run priviledged.
# program <name> = '<filename>' load a file into memory to be run normally.
driver driver_lcd = "lcd.elf"
driver driver_buzzer = "buzzer.elf"
driver driver_gpio = "gpio.elf"
program alarm = "alarm.elf"
program gui = "gui.elf"
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
receive driver_lcd / Display = display
receive driver_lcd / Setting = display_bright
#receive driver_buzzer / Buzzer = buzzer
#receive driver_gpio / Keyboard , 0 = keyboard
#receive driver_gpio / Keyboard , 1 = sysreq
# 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
receive driver_buzzer / Buzzer = buzzer
receive driver_gpio / Keyboard , 0 = keyboard
receive driver_gpio / Keyboard , 1 = sysreq
receive alarm / UI = ui
# sysreq <cap> use a capability as the system request keyboard.
sysreq sysreq
# give <name> / <type> [, <index>] = <cap> give this capability to this program when it requests it.
give 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).
run ball
# include <file> include a file as another config file.
# 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.

View File

@ -390,7 +390,6 @@ static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
reply_num (0)
static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_data, kCapability::Context *c):
dbg_push (__LINE__)
kThread *thread = (kThread *)protected_data.l
switch cmd:
case 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)
break
case Iris::Thread::USE_SLOT & REQUEST_MASK:
dbg_push (__LINE__)
if c->data[1].l >= thread->slots || !c->arg.valid ():
if c->data[1].l == 0xdeadbeef:
bool dummy
@ -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")
reply_num (Iris::ERR_INVALID_ARGUMENT)
return
dbg_push (__LINE__)
unsigned slot = c->data[1].l
dbg_push (__LINE__)
kCaps *new_caps = (kCaps *)c->arg->protected_data.l
dbg_push (__LINE__)
if slot >= thread->slots:
dpanic (0, "using invalid slot")
return
dbg_push (__LINE__)
thread->unset_slot (slot)
dbg_push (__LINE__)
thread->slot[slot].caps = new_caps
dbg_push (__LINE__)
if new_caps:
dbg_push (__LINE__)
thread->slot[slot].next = new_caps->first_slot
thread->slot[slot].caps = new_caps
new_caps->first_slot.thread = thread
new_caps->first_slot.index = slot
dbg_push (__LINE__)
break
case Iris::Thread::GET_CAPS & REQUEST_MASK:
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")
reply_num (Iris::ERR_INVALID_OPERATION)
return
dbg_push (__LINE__)
reply_num (0)
dbg_push (__LINE__)
return
static void page_check_payment (kPage *page):

View File

@ -546,6 +546,8 @@ namespace Iris:
// TODO: LIST
bool map (Cap page, unsigned address):
return ocall (page, CAP_MASTER_DIRECT | MAP, address).l == NO_ERROR
bool unmap (Cap page):
return map (page, ~0)
Page mapping (void *address):
icall (CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address))
return get_arg ()
@ -601,6 +603,9 @@ static void kdebug_num (unsigned n, unsigned digits = 8):
namespace Iris:
inline void panic (unsigned code, char const *message = NULL):
if message:
kdebug ("**********************************************************************\n")
kdebug_num (code)
kdebug_char ('\n')
kdebug (message)
kdebug_char ('\n')
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)

View File

@ -26,7 +26,7 @@ static void clear_page (unsigned page, unsigned num = 1):
kdebug ("clearing page ")
kdebug_num (page)
kdebug ("+")
kdebug_num (num)
kdebug_num (num << PAGE_BITS)
kdebug ('\n')
#endif
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))
for unsigned i = 0; i < (1 << (PAGE_BITS - 2)); ++i:
// Clear page.
((unsigned *)page)[i] = 0
if *((unsigned *)page) != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
((unsigned *)page)[(p << PAGE_BITS - 2) + i] = 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")
#if 0

View File

@ -171,13 +171,13 @@ static unsigned make_entry_lo (kPage *page):
return ((page->frame & ~0x80000000) >> 6) | flags
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:
mem->unmap (page)
if address == ~0:
return true
if address >= 0x80000000:
dpanic (address, "trying to map to kernel address")
return false
if address & ~PAGE_MASK:
dpanic (address, "mapping not page-aligned")
address &= PAGE_MASK

View File

@ -58,6 +58,8 @@ static kThread *handle_exit ():
cp0_set (CP0_STATUS, 0x1000ff13)
else:
cp0_set (CP0_STATUS, 0x0000ff13)
dbg_push ((unsigned)current)
dbg_push (current->pc)
return current
/// 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.data[0] = Iris::Num (old_current->arch.a[0], old_current->arch.a[1])
msg.data[1] = Iris::Num (old_current->arch.a[2], old_current->arch.a[3])
dbg_push (old_current->arch.v[0])
dbg_push (old_current->arch.t[0])
dbg_push (old_current->arch.t[1])
dbg_push (old_current->arch.a[0])
dbg_push (old_current->arch.a[1])
dbg_push (old_current->arch.a[2])
dbg_push (old_current->arch.a[3])
dbg_push (0xdeadbeef)
target->invoke (&msg)
dbg_push (0xfacebeef)
if do_schedule && !must_wait:
// If the call was to schedule without wait, it isn't done yet.
schedule ()

View File

@ -29,7 +29,7 @@ arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc mips/nanonote/board.cc
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh
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

View File

@ -105,6 +105,41 @@ static void panic_message (unsigned n, const char *line, char const *name, char
if old_current:
kdebug ('@')
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 (name)
kdebug (':')
@ -129,6 +164,21 @@ static void panic_message (unsigned n, const char *line, char const *name, char
if b == 32:
b = 0
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):
// Stop all threads.

71
source/alarm.ccp Normal file
View 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 (&current_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

View File

@ -37,7 +37,8 @@ Iris::Num start ():
Iris::my_parent.init_done ()
int colour = 0x3f30ff
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
Iris::Cap eof = Iris::my_receiver.create_capability (0)
while true:

View File

@ -36,7 +36,7 @@ Iris::Num start ():
Iris::my_parent.init_done ()
colour = 0xffff00
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
Iris::Cap eof = Iris::my_receiver.create_capability (0)
while true:

View File

@ -58,7 +58,7 @@ Iris::Num start ():
DevBuzzer 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::my_parent.init_done ()
while true:
@ -66,7 +66,7 @@ Iris::Num start ():
if Iris::recv.protected_data.h == ~0:
// Alarm.
buzzer.stop ()
break
continue
switch Iris::recv.protected_data.l:
case BUZZER:
// Buzzer device user request.

View File

@ -60,6 +60,8 @@ static char *mapping
static unsigned pages
static Iris::Caps pages_caps
static Iris::Memory mem
static unsigned *bss_mapping
static Iris::Page bss_page
static Iris::Caps map_string (Iris::String data):
// 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 executable = shdr->sh_flags & SHF_EXEC_INSTR
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
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
kdebug ("thread size: ")
@ -181,17 +188,23 @@ static Iris::Caps run (Iris::Caps data, Iris::Memory parent_memory, Iris::Cap pa
if readonly:
Iris::panic (0, "unwritable bss section")
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:
Iris::Page page = mem.mapping ((void *)p)
if Iris::recv.data[0].l == Iris::NO_ERROR:
// No error means there is a mapping.
page.share (bss_page, 0)
Iris::free_cap (page)
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
if a >= shdr->sh_addr + shdr->sh_size:
break
if a < shdr->sh_addr:
continue
((unsigned *)&mapping[p - shdr->sh_addr])[(a & ~PAGE_MASK) >> 2] = 0
bss_mapping[(a & ~PAGE_MASK) >> 2] = 0
else:
Iris::free_cap (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):
Iris::panic (0, "unable to map bss 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:
Iris::my_memory.destroy (Iris::Page (slot, p))
Iris::my_memory.destroy (pages_caps)
@ -235,8 +256,11 @@ Iris::Num start ():
kdebug ("elfrun started.\n")
init_alloc ()
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)
bss_mapping = (unsigned *)alloc_space (1)
bss_page = Iris::my_memory.create_page ()
Iris::my_memory.map (bss_page, (unsigned)bss_mapping)
while true:
Iris::wait ()

238
source/gui.ccp Normal file
View 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)

View File

@ -23,6 +23,8 @@
#define NUM_SLOTS 8
#define NUM_CAPS 32
#define SYSREQ 0x100
static unsigned _free
extern unsigned _end
@ -99,7 +101,7 @@ struct List:
struct Program
struct Device:
struct Serverdevice:
char *name
unsigned name_len
unsigned type, index
@ -107,6 +109,14 @@ struct Device:
Program *server
Program *client
struct Clientdevice:
unsigned type, index
Serverdevice *dev
static Iris::Memory top_memory
static Iris::Directory root
static Iris::Elfrun elfrun
struct Program:
char *name
unsigned name_len
@ -114,15 +124,28 @@ struct Program:
Iris::Caps pages
Iris::Memory memory
Iris::Thread thread
List <Device> devices
Iris::Cap waiter
List <Serverdevice> server_devices
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 Iris::Cap sysreq
static unsigned to_receive, progs
static Serverdevice *sysreq
static bool name_match (char const *name, unsigned name_len, Iris::String n):
char nm[16]
@ -255,6 +278,7 @@ static Type types[] = {
{ "WDirectory", 10, Iris::WDirectory::ID },
{ "Filesystem", 10, Iris::Filesystem::ID },
{ "Stream", 6, Iris::Stream::ID },
{ "UI", 2, Iris::UI::ID },
{ NULL, 0, 0 }
}
@ -275,37 +299,25 @@ static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &ind
return
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
unsigned l
if !get_name (start, maxlen, n, l):
Iris::panic (0, "syntax error in init.config (driver)")
if !get_name (line, len, n, l):
Iris::panic (0, "no capability name found in init.config")
List <Program>::Item *p
for p = programs.begin (); p; p = p->next:
if string_match ((*p)->name, (*p)->name_len, n, l):
break
if !p:
Iris::panic (0, "program not found for driver")
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p)
if priv:
kdebug ("priv ")
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
List <Serverdevice>::Item *d
for d = (*p)->server_devices.begin (); d; d = d->next:
if string_match (n, l, (*d)->name, (*d)->name_len):
server = &**p
dev = &**d
return true
return false
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
char *config = alloc_space (pages)
unsigned pages_slot = caps.use ()
@ -321,6 +333,30 @@ static void include_caps (Iris::Caps caps, unsigned size):
Iris::free_cap (caps)
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):
char *start = line
while maxlen && *line != '\n':
@ -333,25 +369,10 @@ static void parse_line (char *&line, unsigned maxlen):
delspace (start, maxlen)
if !maxlen:
return
if match (start, maxlen, "load"):
Program *p = &**programs.insert ()
if !get_name (start, maxlen, p->name, p->name_len) || !match (start, maxlen, "=") || !maxlen:
Iris::panic (0, "syntax error in init.config (load)")
char q = *start++
--maxlen
unsigned len = 0
while maxlen && *start != q:
++start
--maxlen
++len
if !maxlen:
Iris::panic (0, "no closing quote in init.config")
p->pages = load (start - len, len, p->size)
p->waiter = Iris::Cap ()
++start
--maxlen
else if match (start, maxlen, "killbootthreads"):
Iris::my_parent.init_done ()
if match (start, maxlen, "program"):
do_load (start, maxlen, false)
else if match (start, maxlen, "driver"):
do_load (start, maxlen, true)
else if match (start, maxlen, "receive"):
// receive <name> / <type> [, <index>] = <cap>
char *n
@ -364,78 +385,53 @@ static void parse_line (char *&line, unsigned maxlen):
break
if !p:
Iris::panic (0, "program not found for receive")
if !(*p)->devices.begin ():
++progs
List <Device>::Item *dev = (*p)->devices.insert ()
List <Serverdevice>::Item *dev = (*p)->server_devices.insert ()
find_type (start, maxlen, (*dev)->type, (*dev)->index)
if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len):
Iris::panic (1, "syntax error in init.config (receive)")
(*dev)->server = &**p
++to_receive
else if match (start, maxlen, "driver"):
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")
(*dev)->client = NULL
(*dev)->cap = Iris::Cap ()
else if match (start, maxlen, "sysreq"):
// TODO
start += maxlen
maxlen = 0
Program *server
if sysreq:
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"):
// TODO
start += maxlen
maxlen = 0
else if match (start, maxlen, "include"):
// give <name> / <type> [, <index>] = <cap>
char *n
unsigned l
if !get_name (start, maxlen, n, l):
Iris::panic (0, "syntax error in init.config (include)")
if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen:
Iris::panic (0, "syntax error in init.config (give)")
List <Program>::Item *p
for p = programs.begin (); p; p = p->next:
if string_match ((*p)->name, (*p)->name_len, n, l):
break
if !p:
Iris::panic (0, "file not found for include")
include_caps ((*p)->pages, (*p)->size)
Iris::panic (0, "program not found for give")
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:
Iris::panic (0, "invalid line in init.config")
delspace (start, maxlen)
@ -449,24 +445,90 @@ static void parse_line (char *&line, unsigned maxlen):
Iris::Num start ():
init_alloc ()
programs.init ()
root = Iris::my_parent.get_device <Iris::Directory> ()
elfrun = Iris::my_parent.get_device <Iris::Elfrun> ()
root = Iris::my_parent.get_capability <Iris::Directory> ()
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
sysreq = NULL
top_memory = Iris::get_top_memory ()
to_receive = 0
progs = 0
unsigned config_size
Iris::Caps config_pages = load ("init.config", 12, config_size)
include_caps (config_pages, config_size)
include ("init.config", 12)
kdebug ("killing boot threads\n")
Iris::my_parent.init_done ()
for List <Program>::Item *p = programs.begin (); p; p = p->next:
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")
while true:
Iris::wait ()
Program *caller = (Program *)Iris::recv.protected_data.l
if !caller:
// System request.
// TODO.
kdebug ("system request\n")
if Iris::recv.protected_data.l == SYSREQ:
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
continue
kdebug ("sysreq event\n")
continue
Program *caller = (Program *)Iris::recv.protected_data.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:
// TODO.
kdebug ("child request: ")
@ -475,4 +537,3 @@ Iris::Num start ():
for unsigned i = 0; i < caller->name_len; ++i:
kdebug_char (caller->name[i])
kdebug ("\n")

View File

@ -261,7 +261,7 @@ static unsigned pages
static Descriptor descriptor __attribute__ ((aligned (16)))
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 address = 0x15000
if physical & ~PAGE_MASK:
@ -275,9 +275,8 @@ static unsigned create (Iris::Memory mem, Iris::Caps caps):
Iris::free_cap (p)
return physical
static void destroy (unsigned physical, Iris::Caps caps):
static void destroy (unsigned physical, Iris::Memory mem):
unsigned address = 0x15000
Iris::Memory mem = caps.get (1)
if physical == ~0:
Iris::panic (0, "unable to destroy framebuffer with wrong cap0")
if descriptor.frame == physical && is_on:
@ -291,7 +290,7 @@ static void destroy (unsigned physical, Iris::Caps caps):
mem.destroy (p)
Iris::free_cap (p)
static void use (unsigned physical, Iris::Caps caps):
static void use (unsigned physical):
if physical == ~0:
Iris::panic (0, "unable to use framebuffer with wrong cap0")
bool was_unused = descriptor.frame == 0
@ -304,7 +303,7 @@ static void use (unsigned physical, Iris::Caps caps):
write_reg (BACKLIGHT1, 0x5f)
#endif
static void unuse (unsigned physical, Iris::Caps caps):
static void unuse (unsigned physical):
if physical == ~0:
Iris::panic (0, "unable to unuse framebuffer with wrong cap0")
if descriptor.frame == physical:
@ -323,29 +322,7 @@ Iris::Num start ():
#endif
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
#endif
Iris::Page p = Iris::my_memory.mapping (&descriptor)
unsigned paddr = p.physical_address ()
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
@ -364,14 +341,15 @@ Iris::Num start ():
#endif
// Register the backlight device.
Iris::Cap backlight = Iris::my_receiver.create_capability (BACKLIGHT)
Iris::my_parent.provide_device <Iris::Setting> (backlight.copy ())
Iris::Setting backlight = Iris::my_receiver.create_capability (BACKLIGHT)
Iris::my_parent.provide_capability <Iris::Setting> (backlight.copy ())
Iris::free_cap (backlight)
// Register the display device.
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::my_parent.init_done ()
Iris::Cap eof_cb
@ -441,8 +419,49 @@ Iris::Num start ():
reply.invoke ()
Iris::free_cap (reply)
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:
Iris::panic (0, "get_info isn't defined yet.")
Iris::panic (0, "get_info isn't implemented yet.")
default:
Iris::panic (Iris::recv.data[0].l, "invalid operation for lcd")
break

View File

@ -21,8 +21,8 @@
Iris::Num start ():
Iris::my_parent.init_done ()
Iris::Buzzer buzzer = Iris::my_parent.get_device <Iris::Buzzer> ()
Iris::Keyboard kbd = Iris::my_parent.get_device <Iris::Keyboard> ()
Iris::Buzzer buzzer = Iris::my_parent.get_capability <Iris::Buzzer> ()
Iris::Keyboard kbd = Iris::my_parent.get_capability <Iris::Keyboard> ()
Iris::Cap key = Iris::my_receiver.create_capability (0)
kbd.set_cb (key)
// Frequency of the pulse train in millihertz.

View File

@ -204,8 +204,8 @@ Iris::Num start ():
Iris::Device dev = Iris::my_receiver.create_capability (KBD_DEV)
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
Iris::my_parent.provide_device <Iris::Keyboard> (dev.copy (), 0)
Iris::my_parent.provide_device <Iris::Keyboard> (pw.copy (), 1)
Iris::my_parent.provide_capability <Iris::Keyboard> (dev.copy (), 0)
Iris::my_parent.provide_capability <Iris::Keyboard> (pw.copy (), 1)
Iris::free_cap (dev)
Iris::free_cap (pw)
Iris::my_parent.init_done ()

View File

@ -265,10 +265,10 @@ Iris::Num start ():
Pwm pwm
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)
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::my_parent.init_done ()

116
ui.hhp Normal file
View 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