diff --git a/Makefile b/Makefile index e94ae01..8ebd14d 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ # along with this program. If not, see . # Define some variables. +SERIAL = /dev/ttyUSB0 CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS) -ggdb3 CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS) CC = $(CROSS)gcc @@ -54,8 +55,8 @@ clean: rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES) debug: - stty -F /dev/ttyS0 raw 9600 - cat /dev/ttyS0 + stty -F $(SERIAL) raw 9600 + cat $(SERIAL) .PHONY: clean .PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index dff8a17..17d9725 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -18,6 +18,7 @@ #include "devices.hh" #include "iris.hh" +#include "keys.hh" #include #define NUM_SLOTS 8 @@ -26,6 +27,7 @@ enum Cap_codes: SYSREQ = 1 << 16 THREAD + KEYBOARD static unsigned _free extern unsigned _end @@ -79,6 +81,7 @@ static Kernel::Caps terminals static unsigned terminal_slot static Kernel::Caps memories static unsigned memory_slot +static unsigned *inuse // Get the initial block device and filesystem. static Directory receive_devices (): @@ -89,30 +92,24 @@ static Directory receive_devices (): for unsigned i = 0; i < 2; ++i: Kernel::wait () if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE: - kdebug ("Invalid bootstrap request.\n") - Kernel::panic (0) + Kernel::panic (Kernel::recv.data[0].l, "Invalid bootstrap request.") switch Kernel::recv.data[1].l: case String::ID: if have_data: - kdebug ("duplicate device.\n") - Kernel::panic (0) + Kernel::panic (0, "duplicate device.") data_dev = Kernel::get_arg () Kernel::recv.reply.invoke () have_data = true break case Filesystem::ID: if have_fs: - kdebug ("duplicate filesystem.\n") - Kernel::panic (0) + Kernel::panic (0, "duplicate filesystem.") fs_dev = Kernel::get_arg () Kernel::recv.reply.invoke () have_fs = true break default: - kdebug ("unexpected device: ") - kdebug_num (Kernel::recv.data[1].l) - kdebug_char ('\n') - Kernel::panic (0) + Kernel::panic (Kernel::recv.data[1].l, "unexpected device") // Initialize the root file system. data = data_dev.create_user (Kernel::my_memory) data_dev.use (data) @@ -204,8 +201,7 @@ static void run (file *f, bool priv, int id): Elf32_Ehdr *header = (Elf32_Ehdr *)mapping for unsigned j = 0; j < SELFMAG; ++j: if header->e_ident[j] != ELFMAG[j]: - kdebug ("invalid ELF magic\n") - Kernel::panic (0) + Kernel::panic (header->e_ident[j], "invalid ELF magic") return if header->e_ident[EI_CLASS] != ELFCLASS32: kdebug ("invalid ELF class:") @@ -216,21 +212,13 @@ static void run (file *f, bool priv, int id): Kernel::panic (0) return if header->e_ident[EI_DATA] != ELFDATA2LSB: - kdebug ("invalid ELF data\n") - Kernel::panic (0) - return + Kernel::panic (header->e_ident[EI_DATA], "invalid ELF data") if header->e_ident[EI_VERSION] != EV_CURRENT: - kdebug ("invalid ELF version\n") - Kernel::panic (0) - return + Kernel::panic (header->e_ident[EI_VERSION], "invalid ELF version") if header->e_type != ET_EXEC: - kdebug ("invalid ELF type\n") - Kernel::panic (0) - return + Kernel::panic (header->e_type, "invalid ELF type") if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS: - kdebug ("invalid ELF machine\n") - Kernel::panic (0) - return + Kernel::panic (header->e_machine, "invalid ELF machine") thread.set_pc (header->e_entry) thread.set_sp (0x80000000) for unsigned section = 0; section < header->e_shnum; ++section: @@ -242,8 +230,7 @@ static void run (file *f, bool priv, int id): if shdr->sh_type != SHT_NOBITS: unsigned file_offset = shdr->sh_offset >> PAGE_BITS if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2): - kdebug ("thread too large\n") - Kernel::panic (0) + Kernel::panic (shdr->sh_size, "thread too large") return for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS @@ -268,14 +255,12 @@ static void run (file *f, bool priv, int id): // kdebug (" (readonly)") //kdebug ("\n") if !mem.map (page, p): - kdebug ("unable to map page\n") - Kernel::panic (0) + Kernel::panic (0, "unable to map page") return Kernel::free_cap (page) else: if readonly: - kdebug ("unwritable bss section\n") - Kernel::panic (0) + Kernel::panic (0, "unwritable bss section") return for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: Kernel::Page page = mem.mapping ((void *)p) @@ -292,26 +277,18 @@ static void run (file *f, bool priv, int id): Kernel::free_cap (page) page = mem.create_page () if Kernel::recv.data[0].l != Kernel::NO_ERROR: - kdebug ("out of memory\n") - Kernel::panic (0) - return + Kernel::panic (Kernel::recv.data[0].l, "out of memory") if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME): - kdebug ("out of memory\n") - Kernel::panic (0) - return + Kernel::panic (0, "out of memory") if !mem.map (page, p): - kdebug ("unable to map bss page\n") - Kernel::panic (0) - return + Kernel::panic (0, "unable to map bss page") Kernel::free_cap (page) for unsigned p = 0; p < num_pages; ++p: Kernel::my_memory.destroy (Kernel::Page (slot, p)) Kernel::Page stackpage = mem.create_page () stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME) if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000): - kdebug ("unable to map initial stack page\n") - Kernel::panic (0) - return + Kernel::panic (Kernel::recv.data[0].l, "unable to map initial stack page") Kernel::free_cap (stackpage) Kernel::Caps caps = mem.create_caps (NUM_CAPS) thread.use (caps, 0) @@ -405,6 +382,8 @@ static void get_device (): unsigned id = Kernel::recv.protected_data.l Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h) if d: + if inuse[id * Dev::num_devs + d->id] > 0: + Kernel::panic (id, "requesting device twice") kdebug ("giving dev ") kdebug_num (Kernel::recv.data[1].l) kdebug (":") @@ -414,7 +393,12 @@ static void get_device (): kdebug (" to ") kdebug_num (id) kdebug ("\n") - Kernel::Cap cap = Kernel::Caps (terminal_slot, id).get (d->id) + Kernel::Cap 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::free_cap (cap) @@ -453,6 +437,10 @@ Kernel::Num start (): run (&files[index[i]], files[index[i]].name[0] == '#', i) kdebug ("running\n") handle_init (i) + inuse = new unsigned[num_files * Dev::num_devs] + for unsigned f = 0; f < num_files; ++f: + for unsigned d = 0; d < Dev::num_devs; ++d: + inuse[f * Dev::num_devs + d] = 0 // Notify all programs that they may start. for unsigned i = 0; i < num_files; ++i: Kernel::Cap (memory_slot, i + num_files).invoke () @@ -462,12 +450,6 @@ Kernel::Num start (): Kernel::Memory mem (memory_slot, i) Kernel::set_recv_arg (term) mem.create_caps (Dev::num_devs) - unsigned termslot = term.use () - for Dev *d = Dev::devs; d; d = d->next: - Kernel::set_recv_arg (Kernel::Cap (termslot, d->id)) - // The 0x15000 is for the Display; the others don't care about it. - d->dev.create_user (mem, 0, 0x15000) - Kernel::free_slot (termslot) // set up system request. Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory) sysreq_dev.use (sysreq) @@ -476,10 +458,22 @@ Kernel::Num start (): sysreq.set_cb (cap.copy ()) Kernel::free_cap (sysreq) Kernel::free_cap (cap) + // set up own capabilities. + 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) + 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) kdebug ("init done\n") root.unlock_ro () Kernel::free_slot (slot) Kernel::my_memory.destroy (caps) + Dev **waiter = new Dev *[num_files] + Kernel::Cap keyboard_cb = Kernel::my_receiver.create_capability (Kernel::Num (0, KEYBOARD)) + bool in_system = false while true: Kernel::wait () switch Kernel::recv.protected_data.h: @@ -487,7 +481,10 @@ Kernel::Num start (): // System request. if Kernel::recv.data[0].l & Keyboard::RELEASE: continue - kdebug ("system request...\n") + keyboard_dev->dev.use (keyboard) + display_dev->dev.use (display) + keyboard.set_cb (keyboard_cb) + in_system = true continue case THREAD: // Request for something from a child thread. @@ -499,10 +496,59 @@ Kernel::Num start (): case Parent::GET_DEVICE: get_device () break + case Parent::WAIT: + unsigned id = Kernel::recv.protected_data.l + Dev *dev = Dev::find (Kernel::recv.data[1].l, 0) + if id >= num_files: + Kernel::panic (0, "invalid id") + if !dev: + Kernel::panic (0, "invalid dev") + switch inuse[id * Dev::num_devs + dev->id]: + case 0: + Kernel::panic (0, "waiting for non-owned device") + case 2: + if !in_system: + Kernel::recv.reply.invoke () + break + // fall through. + case 1: + Kernel::Cap reply = Kernel::get_reply () + memories.set (id + num_files, reply.copy ()) + Kernel::free_cap (reply) + waiter[id] = dev + break + break case Parent::EXIT: Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported") default: Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child") break + case KEYBOARD: + if in_system && Kernel::recv.data[0].l == (Key::ENTER | Keyboard::RELEASE): + for Dev *d = Dev::devs; d; d = d->next: + if d->idx != 0: + continue + for unsigned i = 0; i < num_files; ++i: + if inuse[i * Dev::num_devs + d->id] == 2: + Kernel::Cap c = Kernel::Caps (terminal_slot, i).get (d->id) + d->dev.use (c) + Kernel::free_cap (c) + if waiter[i] == d: + Kernel::Cap (memory_slot, i + num_files).invoke () + waiter[i] = NULL + in_system = false + break + if Kernel::recv.data[0].l & Keyboard::RELEASE: + continue + 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") + break + break default: Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request") diff --git a/devices.hhp b/devices.hhp index cdb7539..acab311 100644 --- a/devices.hhp +++ b/devices.hhp @@ -139,6 +139,7 @@ struct Parent : public Kernel::Cap: enum request: GET_DEVICE = Device::ID PROVIDE_DEVICE + WAIT GET_MEMORY PROVIDE_MEMORY INIT_DONE @@ -151,6 +152,9 @@ struct Parent : public Kernel::Cap: // Provide a device handle. template void provide_device (Device dev, unsigned num = 0): ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID) + // Wait until a device is used by the caller again. + template void wait (unsigned num = 0): + call (Kernel::Num (CAP_MASTER_DIRECT | WAIT, num), _T::ID) // Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user. Kernel::Memory get_memory (Kernel::Cap target): iocall (target, CAP_MASTER_DIRECT | GET_MEMORY) diff --git a/invoke.ccp b/invoke.ccp index 32602ea..55f8d59 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_num ((unsigned)ret) - //kdebug ("\n") + kdebug ("created thread: ") + kdebug_num ((unsigned)ret) + kdebug ("\n") else: dpanic (0x23311992, "out of memory creating thread") reply_num (Kernel::ERR_OUT_OF_MEMORY) @@ -838,7 +838,7 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da kdebug ('\n') return default: - dpanic (0, "invalid caps operation") + dpanic (cmd, "invalid caps operation") reply_num (Kernel::ERR_INVALID_OPERATION) return diff --git a/kernel.hhp b/kernel.hhp index b2d8c67..f23d324 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -344,7 +344,7 @@ void kCapability::invoke (kCapability::Context *c): ::invoke (target, protected_data, c) kCapability *kCaps::cap (unsigned idx): if idx >= size: - dpanic (idx, "invalid capability requested\n") + dpanic (idx, "invalid capability requested") return NULL return &caps[idx] diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index ece3a08..b37015d 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 boot_threads = init udc -programs = \#nanonote-gpio \#buzzer \#lcd metronome ball +programs = \#nanonote-gpio \#buzzer \#lcd metronome ball display-emu all: test @@ -78,12 +78,8 @@ server: servers: while : ; do $(MAKE) server ; done -monitor: - stty -F /dev/ttyS0 raw 9600 - cat /dev/ttyS0 - setup: - x-terminal-emulator -e make monitor + x-terminal-emulator -e make debug x-terminal-emulator -e make servers ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw diff --git a/plan b/plan index 0f67c56..32ae40e 100644 --- a/plan +++ b/plan @@ -26,3 +26,13 @@ top - - - - program - - user session ... + +te doen: +- caps in init met een cap per process +- die cap bevat caps in target memory met een cap per service +- die cap bevat een user van de service +- sysreq is geen aangeboden service, usbfs wel +- sysreq schakelt tussen running processes incl. user switching. + +- display interface: put pixel commando +- typewriter: print toetsen op scherm; shell? diff --git a/source/#lcd.ccp b/source/#lcd.ccp index 9ed44e1..f0eaa54 100644 --- a/source/#lcd.ccp +++ b/source/#lcd.ccp @@ -178,7 +178,7 @@ static void reset (): // Reset the controller. write_reg (BACKLIGHT1, 0x1e) // Enable display. - write_reg (BACKLIGHT1, 0x5f) + write_reg (BACKLIGHT1, 0x5e) // Set data to rgbrgbrgb input, with a delta color filter. write_reg (COLOR, 0x01) #endif @@ -361,16 +361,12 @@ Kernel::Num start (): Kernel::free_cap (reply) Kernel::free_cap (arg) break - Kernel::Caps caps = mem.create_caps (4) - caps.set (1, mem.copy ()) - unsigned slot = caps.use () unsigned physical = mem.alloc_range (pages) if physical & ~PAGE_MASK: kdebug ("can't allocate framebuffer\n") Kernel::panic (0) assert (physical & PAGE_MASK && ~physical) - Kernel::set_recv_arg (Kernel::Cap (slot, 0)) - Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD)) + 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) @@ -378,13 +374,13 @@ Kernel::Num start (): //Kernel::panic (0xdeaddead) mem.map (p, address + (i << PAGE_BITS)) Kernel::free_cap (p) - Kernel::free_slot (slot) - reply.invoke (0, 0, caps.copy ()) - Kernel::free_cap (caps) + reply.invoke (0, 0, ret.copy ()) + Kernel::free_cap (ret) break case Device::DESTROY_USER: - unsigned slot = Kernel::Caps (arg).use () - unsigned physical = Kernel::my_receiver.get_protected (Kernel::Cap (slot, 0)).l + //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) @@ -394,22 +390,18 @@ Kernel::Num start (): #ifdef NANONOTE write_reg (BACKLIGHT1, 0x5e) #endif - Kernel::Memory mem = Kernel::Cap (slot, 1) - for unsigned i = 0; i < pages; ++i: - mem.destroy (Kernel::Cap (slot, 2 + i)) - mem.destroy (arg) - Kernel::free_slot (slot) + //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: - Kernel::Cap first = Kernel::Caps (arg).get (0) - unsigned physical = Kernel::my_receiver.get_protected (first).l + unsigned physical = Kernel::my_receiver.get_protected (arg).l if physical == ~0: - kdebug ("unable to use framebuffer with wrong cap0\n") - Kernel::panic (0) - break - Kernel::free_cap (first) - bool was_unused = descriptor.frame == ~0 + 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") @@ -421,18 +413,15 @@ Kernel::Num start (): reply.invoke () break case Device::UNUSE: - Kernel::Cap first = Kernel::Caps (arg).get (0) - unsigned physical = Kernel::my_receiver.get_protected (first).l + unsigned physical = Kernel::my_receiver.get_protected (arg).l if physical == ~0: - kdebug ("unable to unuse framebuffer with wrong cap0\n") - Kernel::panic (0) - break - Kernel::free_cap (first) + 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: @@ -480,8 +469,8 @@ Kernel::Num start (): break case LCD: if descriptor.frame != Kernel::recv.protected_data.l: - kdebug ("invalid user requesting lcd\n") - Kernel::panic (0) + //Kernel::panic (0, "invalid user requesting lcd") + Kernel::recv.reply.invoke (~0) break switch Kernel::recv.data[0].l: case Display::SET_EOF_CB: @@ -489,8 +478,7 @@ Kernel::Num start (): Kernel::Cap arg = Kernel::get_arg () if have_eof: Kernel::free_cap (eof_cb) - kdebug ("replacing eof_cb\n") - Kernel::panic (0) + Kernel::panic (0, "replacing eof_cb") else: lcd_clr_eof () Kernel::register_interrupt (IRQ_LCD) @@ -500,10 +488,9 @@ Kernel::Num start (): Kernel::free_cap (reply) break case Display::GET_INFO: - kdebug ("get_info isn't defined yet.\n") - Kernel::panic (0) + Kernel::panic (0, "get_info isn't defined yet.") default: - Kernel::panic (0, "invalid operation for lcd") + Kernel::panic (Kernel::recv.data[0].l, "invalid operation for lcd") break default: Kernel::panic (0, "invalid master operation type for lcd") diff --git a/source/ball.ccp b/source/ball.ccp index af64c41..7934214 100644 --- a/source/ball.ccp +++ b/source/ball.ccp @@ -4,10 +4,9 @@ static unsigned *framebuffer static int const r = 10 +static int colour void ball (int x, int y, bool print): - static unsigned bg - static unsigned count for int ty = y - r; ty < y + r; ++ty: if ty < 0 || ty >= 240: continue @@ -16,16 +15,13 @@ void ball (int x, int y, bool print): continue if (x - tx) * (x - tx) + (y - ty) * (y - ty) > r * r: continue - framebuffer[ty * 320 + tx] = (print ? 0xffffff : bg) - if ++count >= 30: - bg += 0x010307 - count = 0 + framebuffer[ty * 320 + tx] = (print ? colour : 0) Kernel::Num start (): Kernel::my_parent.init_done () + colour = 0xffffff framebuffer = (unsigned *)0x15000 - Kernel::Caps caps = Kernel::my_parent.get_device () - Display display = caps.get (0) + Display display = Kernel::my_parent.get_device (0x10000) int x = r, y = r, dx = 3, dy = 0 Kernel::Cap eof = Kernel::my_receiver.create_capability (0) while true: diff --git a/source/charset b/source/charset index 5a073a7..ecaa81e 100755 --- a/source/charset +++ b/source/charset @@ -871,7 +871,6 @@ import sys charsize = 25 * 4 + 1 for c in range (128 - 32): - line = [] for l in range (8): offset = 2 + c * charsize + 25 * (l >> 1) + 12 * (l & 1) ln = "" diff --git a/source/display-emu.ccp b/source/display-emu.ccp new file mode 100644 index 0000000..b4a799b --- /dev/null +++ b/source/display-emu.ccp @@ -0,0 +1,61 @@ +#pypp 0 +#include +#include + +Kernel::Num start (): + Device d = Kernel::my_receiver.create_capability (0) + Kernel::my_parent.provide_device (d.copy (), 0x10000) + Kernel::free_cap (d) + Kernel::my_parent.init_done () + Display real = Kernel::my_parent.get_device (0) + while true: + Kernel::wait () + Kernel::Cap arg = Kernel::get_arg () + Kernel::Cap reply = Kernel::get_reply () + switch Kernel::recv.protected_data.h: + case 0: + switch Kernel::recv.data[0].l: + case Device::CREATE_USER: + Kernel::Memory mem (arg) + Kernel::Cap target = Kernel::my_receiver.create_capability (Kernel::Num (0, 1)) + 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 () + t.set_flags (Kernel::Page::PAYING, Kernel::Page::PAYING) + p.share (t, Kernel::Page::FORGET) + mem.map (t, 0x15000 + i) + Kernel::my_memory.destroy (t) + Kernel::free_cap (t) + Kernel::free_cap (p) + reply.invoke (0, 0, target) + Kernel::free_cap (target) + break + case Device::DESTROY_USER: + Kernel::panic (0, "destroying emulation user") + case Device::USE: + case Device::UNUSE: + reply.invoke () + break + default: + kdebug_num (Kernel::recv.data[0].l) + kdebug ("\n") + Kernel::panic (0, "invalid emulation command") + break + case 1: + switch Kernel::recv.data[0].l: + case Display::SET_EOF_CB: + real.set_eof_cb (arg.copy ()) + while Kernel::recv.data[0].l != 0: + Kernel::my_parent.wait (0) + real.set_eof_cb (arg.copy ()) + reply.invoke () + break + default: + kdebug_num (Kernel::recv.data[0].l) + kdebug_char ('\n') + Kernel::panic (Kernel::recv.data[0].l, "invalid operation on display emulation") + break + default: + Kernel::panic (0, "bug in display emulation") + Kernel::free_cap (arg) + Kernel::free_cap (reply)