From 7a8d7c28c45678e89b93685fcb05bd24ce01d626 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Sun, 31 Jan 2010 09:26:23 +0100 Subject: [PATCH] working device swapping --- boot-programs/init.ccp | 64 +++++++++++----- boot-programs/udc.ccp | 4 +- devices.hhp | 61 ++++++++++++--- invoke.ccp | 4 +- mips/nanonote/Makefile.arch | 4 +- panic.ccp | 2 +- source/#buzzer.ccp | 29 +------ source/#lcd.ccp | 146 +++++++++++++++--------------------- source/bsquare.ccp | 43 +++++++++++ source/display-emu.ccp | 8 +- source/display-emu2.ccp | 1 + 11 files changed, 218 insertions(+), 148 deletions(-) create mode 100644 source/bsquare.ccp create mode 120000 source/display-emu2.ccp diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index 17d9725..dd4bafe 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -85,8 +85,7 @@ static unsigned *inuse // Get the initial block device and filesystem. static Directory receive_devices (): - String data - Filesystem fs + Kernel::Caps data, fs bool have_data = false, have_fs = false Device fs_dev, data_dev for unsigned i = 0; i < 2; ++i: @@ -115,9 +114,11 @@ static Directory receive_devices (): data_dev.use (data) fs = fs_dev.create_user (Kernel::my_memory) fs_dev.use (fs) - Directory root = fs.use_device_ro (data.copy ()) + Filesystem fs_cap = fs.get (0) + Directory root = fs_cap.use_device_ro (data.copy ()) Kernel::free_cap (data) Kernel::free_cap (fs) + Kernel::free_cap (fs_cap) Kernel::free_cap (data_dev) Kernel::free_cap (fs_dev) return root @@ -371,7 +372,9 @@ static void handle_init (unsigned id): Kernel::free_cap (reply) break case Parent::INIT_DONE: - memories.set (id + num_files, Kernel::get_reply ()) + Kernel::Cap reply = Kernel::get_reply () + memories.set (id + num_files, reply.copy ()) + Kernel::free_cap (reply) return default: kdebug ("unknown init request\n") @@ -393,14 +396,16 @@ static void get_device (): kdebug (" to ") kdebug_num (id) kdebug ("\n") - Kernel::Cap cap = d->dev.create_user (Kernel::Memory (memory_slot, id), 0, 0x15000) + Kernel::Caps cap = d->dev.create_user (Kernel::Memory (memory_slot, id), 0, 0x15000) Kernel::Caps (terminal_slot, id).set (d->id, cap.copy ()) for unsigned i = 0; i < num_files; ++i: if inuse[i * Dev::num_devs + d->id] == 2: inuse[i * Dev::num_devs + d->id] = 1 inuse[id * Dev::num_devs + d->id] = 2 d->dev.use (cap) - reply.invoke (0, 0, cap.copy ()) + Kernel::Cap ret = cap.get (0) + reply.invoke (0, 0, ret.copy ()) + Kernel::free_cap (ret) Kernel::free_cap (cap) else: kdebug ("device not found: ") @@ -451,9 +456,11 @@ Kernel::Num start (): Kernel::set_recv_arg (term) mem.create_caps (Dev::num_devs) // set up system request. - Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory) - sysreq_dev.use (sysreq) + Kernel::Caps sysreq_caps = sysreq_dev.create_user (Kernel::my_memory) + sysreq_dev.use (sysreq_caps) + Keyboard sysreq = sysreq_caps.get (0) Kernel::free_cap (sysreq_dev) + Kernel::free_cap (sysreq_caps) Kernel::Cap cap = Kernel::my_receiver.create_capability (Kernel::Num (0, SYSREQ)) sysreq.set_cb (cap.copy ()) Kernel::free_cap (sysreq) @@ -462,11 +469,13 @@ Kernel::Num start (): Dev *display_dev = Dev::find (Display::ID, 0) if !display_dev: Kernel::panic (0, "no display") - Display display = display_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) + Kernel::Caps display_caps = display_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) + Display display = display_caps.get (0) Dev *keyboard_dev = Dev::find (Keyboard::ID, 0) if !keyboard_dev: Kernel::panic (0, "no keyboard") - Keyboard keyboard = keyboard_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) + Kernel::Caps keyboard_caps = keyboard_dev->dev.create_user (Kernel::my_memory, 0, 0x15000) + Keyboard keyboard = keyboard_caps.get (0) kdebug ("init done\n") root.unlock_ro () Kernel::free_slot (slot) @@ -481,8 +490,8 @@ Kernel::Num start (): // System request. if Kernel::recv.data[0].l & Keyboard::RELEASE: continue - keyboard_dev->dev.use (keyboard) - display_dev->dev.use (display) + keyboard_dev->dev.use (keyboard_caps) + display_dev->dev.use (display_caps) keyboard.set_cb (keyboard_cb) in_system = true continue @@ -540,15 +549,34 @@ Kernel::Num start (): break if Kernel::recv.data[0].l & Keyboard::RELEASE: continue + unsigned const r = 50 + unsigned which = 0 switch Kernel::recv.data[0].l: - case Key::UP: - case Key::DOWN: - case Key::LEFT: - case Key::RIGHT: - case Key::VOLUME_UP: case Key::VOLUME_DOWN: - kdebug ("key pressed.\n") + // Set ball. + for int y = -r; y < r; ++y: + for int x = -r; x < r; ++x: + if x * x + y * y > r * r: + ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0x000000 + else: + ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0xffffff + which = 2 break + case Key::VOLUME_UP: + // Set square. + for int y = -r; y < r; ++y: + for int x = -r; x < r; ++x: + ((unsigned *)0x15000)[(120 + y) * 320 + 160 + x] = 0xffffff + which = 1 + break + if which != 0: + for Dev *d = Dev::devs; d; d = d->next: + if d->code != Display::ID || d->idx != 0: + continue + for unsigned f = 0; f < num_files; ++f: + if inuse[f * Dev::num_devs + d->id] == 0: + continue + inuse[f * Dev::num_devs + d->id] = (--which ? 2 : 1) break default: Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request") diff --git a/boot-programs/udc.ccp b/boot-programs/udc.ccp index bf13925..26c67ec 100644 --- a/boot-programs/udc.ccp +++ b/boot-programs/udc.ccp @@ -567,8 +567,8 @@ Kernel::Num start (): map_cpm () Udc udc - //Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG) - //__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") + Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG) + __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") udc.init () Kernel::register_interrupt (IRQ_UDC) Device fs_dev = Kernel::my_receiver.create_capability (FS) diff --git a/devices.hhp b/devices.hhp index acab311..b500aee 100644 --- a/devices.hhp +++ b/devices.hhp @@ -99,34 +99,75 @@ struct Device : public Kernel::Cap: void use (Kernel::Cap user): ocall (user, CAP_MASTER_DIRECT | USE) // Convenience function for threads implementing a device. - static void host (unsigned id, unsigned ¤t_user, Kernel::Cap &reply, Kernel::Cap &arg): + static void host (unsigned id, unsigned ¤t_user, Kernel::Cap &reply, Kernel::Cap &arg, unsigned capssize = 3, unsigned (*create)(Kernel::Memory mem, Kernel::Caps caps) = NULL, void (*destroy)(unsigned id, Kernel::Caps caps) = NULL, void (*use)(unsigned id, Kernel::Caps caps) = NULL, void (*unuse)(unsigned id, Kernel::Caps caps) = NULL): static unsigned last_user switch Kernel::recv.data[0].l: case Device::CREATE_USER: - // Increment last_user; skip 0. - // FIXME: if this really wraps, it is possible that two users share their id. - if !++last_user: - ++last_user - Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (last_user, id)) - reply.invoke (0, 0, c.copy ()) + Kernel::Memory mem (arg) + Kernel::Caps caps = mem.create_caps (capssize) + unsigned user + if create: + user = create (mem, caps) + else: + // Increment last_user; skip 0. + // FIXME: if this really wraps, it is possible that two users share their id. + if !++last_user: + ++last_user + user = last_user + Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (user, id)) + caps.set (0, c.copy ()) + caps.set (1, mem.copy ()) + reply.invoke (0, 0, caps.copy ()) Kernel::free_cap (c) + Kernel::free_cap (caps) Kernel::free_cap (reply) Kernel::free_cap (arg) break case Device::DESTROY_USER: + Kernel::Caps caps (arg) + Kernel::Cap c = caps.get (0) + Kernel::Num user = Kernel::my_receiver.get_protected (c) + Kernel::free_cap (c) + if user.h != id: + Kernel::panic (user.h, "invalid id for destroy") + // TODO: unuse. + if destroy: + destroy (user.l, caps) reply.invoke () Kernel::free_cap (reply) Kernel::free_cap (arg) break case Device::USE: - current_user = Kernel::my_receiver.get_protected (arg).l + Kernel::Caps caps (arg) + Kernel::Cap c = caps.get (0) + Kernel::Num user = Kernel::my_receiver.get_protected (c) + Kernel::free_cap (c) + if user.h != id: + Kernel::panic (user.h, "invalid id for use") + // TODO: send unuse signal. + current_user = user.l + if use: + use (user.l, caps) + c = caps.get (2) + c.invoke (1) + Kernel::free_cap (c) reply.invoke () Kernel::free_cap (reply) Kernel::free_cap (arg) break case Device::UNUSE: - Kernel::Num p = Kernel::my_receiver.get_protected (arg) - if p.h == id && current_user == p.l: + Kernel::Caps caps (arg) + Kernel::Cap c = caps.get (0) + Kernel::Num user = Kernel::my_receiver.get_protected (c) + Kernel::free_cap (c) + if user.h != id: + Kernel::panic (user.h, "invalid id for unuse") + if unuse: + unuse (user.l, caps) + if user.l == current_user: + c = caps.get (2) + c.invoke (0) + Kernel::free_cap (c) current_user = 0 reply.invoke () Kernel::free_cap (reply) diff --git a/invoke.ccp b/invoke.ccp index 55f8d59..cd65e4a 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -296,9 +296,9 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ kThread *ret = mem->alloc_thread (c->data[1].l) if ret: reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs) - kdebug ("created thread: ") + kdebug ("(created thread ") kdebug_num ((unsigned)ret) - kdebug ("\n") + kdebug (")") else: dpanic (0x23311992, "out of memory creating thread") reply_num (Kernel::ERR_OUT_OF_MEMORY) diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index b37015d..f1a9408 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -27,9 +27,9 @@ LDFLAGS = --omagic -Ttext $(load) 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 +arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh devices.hh boot_threads = init udc -programs = \#nanonote-gpio \#buzzer \#lcd metronome ball display-emu +programs = \#nanonote-gpio \#lcd display-emu bsquare display-emu2 ball all: test diff --git a/panic.ccp b/panic.ccp index 210dbf2..f058cf9 100644 --- a/panic.ccp +++ b/panic.ccp @@ -141,8 +141,8 @@ void panic_impl (unsigned n, const char *line, char const *name, char const *mes if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner: arch_interrupt_receiver[i]->owner->unrun () #ifndef NDEBUG - // If a log capability is registered, run its owner. panic_message (n, line, name, message) + // If a log capability is registered, run its owner. #ifndef USE_SERIAL if dbg_cap.valid () && dbg_cap->target->owner: dbg_cap->target->owner->run () diff --git a/source/#buzzer.ccp b/source/#buzzer.ccp index 3826be4..f18c5fa 100644 --- a/source/#buzzer.ccp +++ b/source/#buzzer.ccp @@ -74,32 +74,9 @@ Kernel::Num start (): switch Kernel::recv.protected_data.l: case BUZZER: // Buzzer device control request. - switch Kernel::recv.data[0].l: - case Device::CREATE_USER: - Kernel::Cap reply = Kernel::get_reply () - Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, BUZZER)) - reply.invoke (0, 0, cap.copy ()) - Kernel::free_cap (cap) - Kernel::free_cap (reply) - break - case Device::DESTROY_USER: - Kernel::recv.reply.invoke () - break - case Device::UNUSE: - buzzer.stop () - Kernel::recv.reply.invoke () - break - case Device::USE: - Kernel::Cap reply = Kernel::get_reply () - user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l - reply.invoke () - Kernel::free_cap (reply) - break - default: - kdebug ("invalid buzzer control command: ") - kdebug_num (Kernel::recv.data[0].l) - kdebug ("\n") - break + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () + Device::host (BUZZER, user, reply, arg) break default: kdebug ("invalid buzzer request\n") diff --git a/source/#lcd.ccp b/source/#lcd.ccp index f0eaa54..9925cab 100644 --- a/source/#lcd.ccp +++ b/source/#lcd.ccp @@ -257,6 +257,63 @@ static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy): return 0 return ((l * l - d2 - 1) << 8) / (l * l) +static unsigned pages +static Descriptor descriptor __attribute__ ((aligned (16))) +static bool is_on + +static unsigned create (Kernel::Memory mem, Kernel::Caps caps): + unsigned physical = mem.alloc_range (pages) + unsigned address = 0x15000 + if physical & ~PAGE_MASK: + Kernel::panic (0, "can't allocate framebuffer") + assert (physical & PAGE_MASK && ~physical) + for unsigned i = 0; i < pages; ++i: + Kernel::Page p = mem.create_page () + p.alloc_physical (physical + (i << PAGE_BITS), false, true) + if address != ~0: + mem.map (p, address + (i << PAGE_BITS)) + Kernel::free_cap (p) + return physical + +static void destroy (unsigned physical, Kernel::Caps caps): + unsigned address = 0x15000 + Kernel::Memory mem = caps.get (1) + if physical == ~0: + Kernel::panic (0, "unable to destroy framebuffer with wrong cap0") + if descriptor.frame == physical && is_on: + lcd_clr_ena () + #ifdef NANONOTE + write_reg (BACKLIGHT1, 0x5e) + #endif + if address != ~0: + for unsigned i = 0; i < pages; ++i: + Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS))) + mem.destroy (p) + Kernel::free_cap (p) + +static void use (unsigned physical, Kernel::Caps caps): + if physical == ~0: + Kernel::panic (0, "unable to use framebuffer with wrong cap0") + 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 + +static void unuse (unsigned physical, Kernel::Caps caps): + if physical == ~0: + Kernel::panic (0, "unable to unuse framebuffer with wrong cap0") + if descriptor.frame == physical: + lcd_clr_ena () + #ifdef NANONOTE + write_reg (BACKLIGHT1, 0x5e) + #endif + descriptor.frame = 0 + Kernel::Num start (): Kernel::schedule () map_lcd () @@ -265,8 +322,7 @@ Kernel::Num start (): map_gpio () #endif - Descriptor descriptor __attribute__ ((aligned (16))) - unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS + pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS #if 0 unsigned physical = Kernel::my_memory.alloc_range (pages) assert (physical & PAGE_MASK && ~physical) @@ -320,8 +376,8 @@ Kernel::Num start (): Kernel::Cap eof_cb bool have_eof = false - bool is_on = true - unsigned backlight_user = 0 + is_on = true + unsigned lcd_user = 0 unsigned current_backlight = 0 while true: Kernel::wait () @@ -347,87 +403,7 @@ Kernel::Num start (): case LCD: Kernel::Cap reply = Kernel::get_reply () Kernel::Cap arg = Kernel::get_arg () - switch Kernel::recv.data[0].l: - case Device::CREATE_USER: - Kernel::Memory mem (arg) - unsigned width = Kernel::recv.data[0].h >> 16 - unsigned height = Kernel::recv.data[0].h & 0xffff - unsigned mode = Kernel::recv.data[1].l & ~PAGE_MASK - unsigned address = Kernel::recv.data[1].l & PAGE_MASK - if (width != 0 && width != h) || (height != 0 && height != v) || mode != 0: - reply.invoke (Kernel::ERR_INVALID_ARGUMENT) - kdebug ("invalid framebuffer requested\n") - Kernel::panic (0) - Kernel::free_cap (reply) - Kernel::free_cap (arg) - break - unsigned physical = mem.alloc_range (pages) - if physical & ~PAGE_MASK: - kdebug ("can't allocate framebuffer\n") - Kernel::panic (0) - assert (physical & PAGE_MASK && ~physical) - Kernel::Cap ret = Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD)) - for unsigned i = 0; i < pages; ++i: - Kernel::Page p = mem.create_page () - p.alloc_physical (physical + (i << PAGE_BITS), false, true) - if address != ~0: - //Kernel::panic (0xdeaddead) - mem.map (p, address + (i << PAGE_BITS)) - Kernel::free_cap (p) - reply.invoke (0, 0, ret.copy ()) - Kernel::free_cap (ret) - break - case Device::DESTROY_USER: - //Kernel::Memory mem (arg) - unsigned address = Kernel::recv.data[1].l & PAGE_MASK - unsigned physical = Kernel::my_receiver.get_protected (arg).l - if physical == ~0: - kdebug ("unable to destroy framebuffer with wrong cap0\n") - Kernel::panic (0) - break - if descriptor.frame == physical && is_on: - lcd_clr_ena () - #ifdef NANONOTE - write_reg (BACKLIGHT1, 0x5e) - #endif - //for unsigned i = 0; i < pages; ++i: - //if address != ~0: - //Kernel::Page p = mem.mapping ((void *)(address + (i << PAGE_BITS))) - //mem.destroy (p) - //Kernel::free_cap (p) - reply.invoke () - break - case Device::USE: - unsigned physical = Kernel::my_receiver.get_protected (arg).l - if physical == ~0: - Kernel::panic (0, "unable to use framebuffer with wrong cap0") - bool was_unused = descriptor.frame == 0 - descriptor.frame = physical - unsigned dptr = (unsigned)&descriptor - __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0") - if was_unused && is_on: - lcd_set_ena () - #ifdef NANONOTE: - write_reg (BACKLIGHT1, 0x5f) - #endif - reply.invoke () - break - case Device::UNUSE: - unsigned physical = Kernel::my_receiver.get_protected (arg).l - if physical == ~0: - Kernel::panic (0, "unable to unuse framebuffer with wrong cap0") - if descriptor.frame == physical: - lcd_clr_ena () - #ifdef NANONOTE - write_reg (BACKLIGHT1, 0x5e) - #endif - descriptor.frame = 0 - reply.invoke () - break - default: - Kernel::panic (0, "invalid operation for lcd device") - Kernel::free_cap (arg) - Kernel::free_cap (reply) + Device::host (LCD, lcd_user, reply, arg, 3, create, destroy, use, unuse) break default: Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd") diff --git a/source/bsquare.ccp b/source/bsquare.ccp new file mode 100644 index 0000000..dfd0ec7 --- /dev/null +++ b/source/bsquare.ccp @@ -0,0 +1,43 @@ +#pypp 0 +#include +#include + +static unsigned *framebuffer +static int const r = 10 +static int colour + +void square (int x, int y, bool print): + for int ty = y - r; ty < y + r; ++ty: + if ty < 0 || ty >= 240: + continue + for int tx = x - r; tx < x + r; ++tx: + if tx < 0 || tx >= 320: + continue + framebuffer[ty * 320 + tx] = (print ? colour : 0) + +Kernel::Num start (): + Kernel::my_parent.init_done () + colour = 0xffffff + framebuffer = (unsigned *)0x15000 + Display display = Kernel::my_parent.get_device (0x10001) + int x = r, y = r, dx = 3, dy = 3 + Kernel::Cap eof = Kernel::my_receiver.create_capability (0) + while true: + display.set_eof_cb (eof) + Kernel::wait () + square (x, y, false) + x += dx + y += dy + if y + r >= 240: + dy = -dy + y = 240 - r + if x - r < 0: + x = r + dx = -dx + if x + r >= 320: + x = 320 - r + dx = -dx + if y - r < 0: + y = r + dy = -dy + square (x, y, true) diff --git a/source/display-emu.ccp b/source/display-emu.ccp index b4a799b..97ed261 100644 --- a/source/display-emu.ccp +++ b/source/display-emu.ccp @@ -17,7 +17,11 @@ Kernel::Num start (): switch Kernel::recv.data[0].l: case Device::CREATE_USER: Kernel::Memory mem (arg) + Kernel::Caps ret = mem.create_caps (3) Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1)) + ret.set (0, target.copy ()) + ret.set (1, mem) + Kernel::free_cap (target) for unsigned i = 0; i < 320 * 240 * 4; i += PAGE_SIZE: Kernel::Page p = Kernel::my_memory.mapping ((void *)(0x15000 + i)) Kernel::Page t = mem.create_page () @@ -27,8 +31,8 @@ Kernel::Num start (): Kernel::my_memory.destroy (t) Kernel::free_cap (t) Kernel::free_cap (p) - reply.invoke (0, 0, target) - Kernel::free_cap (target) + reply.invoke (0, 0, ret.copy ()) + Kernel::free_cap (ret) break case Device::DESTROY_USER: Kernel::panic (0, "destroying emulation user") diff --git a/source/display-emu2.ccp b/source/display-emu2.ccp new file mode 120000 index 0000000..c7f93ff --- /dev/null +++ b/source/display-emu2.ccp @@ -0,0 +1 @@ +display-emu.ccp \ No newline at end of file