diff --git a/Makefile b/Makefile index 0595de3..a42b81f 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/boot-programs/bootinit.ccp b/boot-programs/bootinit.ccp index 9bb703b..e369a3f 100644 --- a/boot-programs/bootinit.ccp +++ b/boot-programs/bootinit.ccp @@ -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: diff --git a/boot-programs/udc.ccp b/boot-programs/udc.ccp index fc0e526..1d69c7f 100644 --- a/boot-programs/udc.ccp +++ b/boot-programs/udc.ccp @@ -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 (fs.copy ()) - Iris::my_parent.provide_device (data.copy ()) + Iris::my_parent.provide_capability (fs.copy ()) + Iris::my_parent.provide_capability (data.copy ()) Iris::free_cap (fs) Iris::free_cap (data) unsigned state = 0 diff --git a/devices.hhp b/devices.hhp index 5542b98..140903e 100644 --- a/devices.hhp +++ b/devices.hhp @@ -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 _T get_device (unsigned num = 0): - icall (Iris::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID) + // Get a handle. + template _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 void provide_device (Device dev, unsigned num = 0): - ocall (dev, Iris::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID) + template 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 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: diff --git a/init.config b/init.config index 0641ea4..2f5dbe1 100644 --- a/init.config +++ b/init.config @@ -1,34 +1,29 @@ - # load = '' 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 = '' load a file into memory to be run priviledged. + # program = '' 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 / [, ] = 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 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 use a capability as the system request keyboard. sysreq sysreq # give / [, ] = 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 run a previously loaded program (normally). - run ball + # include include a file as another config file. - # include 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. diff --git a/invoke.ccp b/invoke.ccp index 11d5644..ea5556b 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -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): diff --git a/iris.hhp b/iris.hhp index ab5ca88..8f07de8 100644 --- a/iris.hhp +++ b/iris.hhp @@ -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) diff --git a/memory.ccp b/memory.ccp index 6b5c00a..01b1c8d 100644 --- a/memory.ccp +++ b/memory.ccp @@ -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 diff --git a/mips/arch.ccp b/mips/arch.ccp index cdd9ff8..31518d4 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -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 diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index cade086..1e40202 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -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 () diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index e8d4ceb..9fca787 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -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 diff --git a/panic.ccp b/panic.ccp index a1c05bd..84a010a 100644 --- a/panic.ccp +++ b/panic.ccp @@ -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. diff --git a/source/alarm.ccp b/source/alarm.ccp new file mode 100644 index 0000000..028ba4b --- /dev/null +++ b/source/alarm.ccp @@ -0,0 +1,71 @@ +#pypp 0 +#include +#include + +enum Ins: + TOTAL_TIME + START + NUM_INS + +enum Outs: + CURRENT_TIME + ALARM + NUM_OUTS + +static UI ui +static UI ::in total_time +static UI ::in_event do_start +static UI ::out current_time +static UI ::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 diff --git a/source/ball.ccp b/source/ball.ccp index 76d22bd..33f09ae 100644 --- a/source/ball.ccp +++ b/source/ball.ccp @@ -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 (0x10000) + Iris::Display display = Iris::my_parent.get_capability () + 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: diff --git a/source/bsquare.ccp b/source/bsquare.ccp index 53c9c2f..4360e2e 100644 --- a/source/bsquare.ccp +++ b/source/bsquare.ccp @@ -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 (0x10001) + Iris::Display display = Iris::my_parent.get_capability (0x10001) int x = r, y = r, dx = 3, dy = 3 Iris::Cap eof = Iris::my_receiver.create_capability (0) while true: diff --git a/source/buzzer.ccp b/source/buzzer.ccp index 633e57a..7112353 100644 --- a/source/buzzer.ccp +++ b/source/buzzer.ccp @@ -58,7 +58,7 @@ Iris::Num start (): DevBuzzer buzzer Iris::Buzzer dev = Iris::my_receiver.create_capability (BUZZER) - Iris::my_parent.provide_device (dev.copy ()) + Iris::my_parent.provide_capability (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. diff --git a/source/elfrun.ccp b/source/elfrun.ccp index 0c52754..fbb9eb4 100644 --- a/source/elfrun.ccp +++ b/source/elfrun.ccp @@ -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 (dev.copy ()) + Iris::my_parent.provide_capability (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 () diff --git a/source/gui.ccp b/source/gui.ccp new file mode 100644 index 0000000..199ca17 --- /dev/null +++ b/source/gui.ccp @@ -0,0 +1,238 @@ +#pypp 0 +#include +#include +#include + +// 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::Setting bright = Iris::my_parent.get_capability () + Iris::Keyboard keyboard = Iris::my_parent.get_capability () + buzzer = Iris::my_parent.get_capability () + Iris::UI app = Iris::my_parent.get_capability () + 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) diff --git a/source/init.ccp b/source/init.ccp index d78d6aa..1ce4064 100644 --- a/source/init.ccp +++ b/source/init.ccp @@ -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 devices - Iris::Cap waiter + List server_devices + List 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 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 ::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 ::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 / [, ] = 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 ::Item *dev = (*p)->devices.insert () + List ::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 ::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 ::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 / [, ] = 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 ::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 ::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 () - elfrun = Iris::my_parent.get_device () + root = Iris::my_parent.get_capability () + elfrun = Iris::my_parent.get_capability () + 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 ::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 ::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 ::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") - diff --git a/source/lcd.ccp b/source/lcd.ccp index c929c1e..00f0e63 100644 --- a/source/lcd.ccp +++ b/source/lcd.ccp @@ -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 (backlight.copy ()) + Iris::Setting backlight = Iris::my_receiver.create_capability (BACKLIGHT) + Iris::my_parent.provide_capability (backlight.copy ()) Iris::free_cap (backlight) // Register the display device. Iris::Display display = Iris::my_receiver.create_capability (LCD) - Iris::my_parent.provide_device (display.copy ()) + Iris::my_parent.provide_capability (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 diff --git a/source/metronome.ccp b/source/metronome.ccp index b665c61..f6b07c4 100644 --- a/source/metronome.ccp +++ b/source/metronome.ccp @@ -21,8 +21,8 @@ Iris::Num start (): Iris::my_parent.init_done () - Iris::Buzzer buzzer = Iris::my_parent.get_device () - Iris::Keyboard kbd = Iris::my_parent.get_device () + Iris::Buzzer buzzer = Iris::my_parent.get_capability () + Iris::Keyboard kbd = Iris::my_parent.get_capability () Iris::Cap key = Iris::my_receiver.create_capability (0) kbd.set_cb (key) // Frequency of the pulse train in millihertz. diff --git a/source/nanonote-gpio.ccp b/source/nanonote-gpio.ccp index fe5df1c..2a7256c 100644 --- a/source/nanonote-gpio.ccp +++ b/source/nanonote-gpio.ccp @@ -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 (dev.copy (), 0) - Iris::my_parent.provide_device (pw.copy (), 1) + Iris::my_parent.provide_capability (dev.copy (), 0) + Iris::my_parent.provide_capability (pw.copy (), 1) Iris::free_cap (dev) Iris::free_cap (pw) Iris::my_parent.init_done () diff --git a/source/trendtac-gpio.ccp b/source/trendtac-gpio.ccp index 7ff2d01..b3e12bb 100644 --- a/source/trendtac-gpio.ccp +++ b/source/trendtac-gpio.ccp @@ -265,10 +265,10 @@ Iris::Num start (): Pwm pwm Iris::Cap c = Iris::my_receiver.create_capability (KEYBOARD) - Iris::my_parent.provide_device (c.copy (), 0) + Iris::my_parent.provide_capability (c.copy (), 0) Iris::free_cap (c) c = Iris::my_receiver.create_capability (TOUCHPAD) - Iris::my_parent.provide_device (c.copy (), 1) + Iris::my_parent.provide_capability (c.copy (), 1) Iris::free_cap (c) Iris::my_parent.init_done () diff --git a/ui.hhp b/ui.hhp new file mode 100644 index 0000000..c7e36a9 --- /dev/null +++ b/ui.hhp @@ -0,0 +1,116 @@ +#pypp 0 +#include +#include + +template // +class UI: + struct in_base: + UI *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 *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 (my_cap) + template // + class in : public in_base: + friend class UI + _T my_data + static void send_impl (in_base *self, Iris::Cap c): + c.invoke (self->my_index | Iris::UI::INPUT, reinterpret_cast *> (self)->my_data) + static void handle_impl (in_base *self, void (*cb)(unsigned)): + in *me = reinterpret_cast (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 + 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 // + class out : public out_base: + friend class UI + _T my_data + static void send_impl (out_base *self, Iris::Cap c): + c.invoke (self->my_index, reinterpret_cast *> (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 + 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