diff --git a/alloc.ccp b/alloc.ccp index 13f2050..d2792b7 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -308,6 +308,8 @@ void kMemory::free_thread (kThread *thread): free_obj (thread, (void **)&threads) void kMemory::free_message (kReceiver *owner, kMessage *message): + for unsigned i = 0; i < 2; ++i: + message->caps.cap (i)->invalidate () if !message->next: owner->last_message = (kMessageP)message->prev free_obj (message, (void **)&owner->messages) @@ -405,3 +407,98 @@ void kPage::forget (): frame = 0 flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED) kPage_arch_update_mapping (this) + +static void check_receiver (kReceiver *r, kCapRef cap, unsigned line): + if (unsigned)cap->target & ~KERNEL_MASK: + if cap->target != r: + dpanic (line, "consistency bug in capabilities") + else: + if cap->protected_data.l != (unsigned)r: + dbg_log ("Buggy: ") + dbg_log_num ((unsigned)r) + dbg_log (" ") + dbg_log_num ((unsigned)cap.caps) + dbg_log (" ") + dbg_log_num ((unsigned)cap.caps->address_space) + dbg_log (" ") + dbg_log_num ((unsigned)cap.deref ()) + dbg_log (" ") + dbg_log_num ((unsigned)cap->target) + dbg_log ("/") + dbg_log_num (cap->protected_data.l) + dbg_log ("\n") + dpanic (line, "consistency bug in kernel capabilities") + for kCapRef c = cap->children; c.valid (); c = c->sibling_next: + check_receiver (r, c, line) + +void kReceiver::check (unsigned line): + for kCapRef cap = capabilities; cap.valid (); cap = cap->sibling_next: + check_receiver (this, cap, line) + +void kMemory::check (unsigned line): + for kReceiver *r = receivers; r; r = (kReceiver *)r->next: + r->check (line) + for kMemory *m = memories; m; m = (kMemory *)m->next: + m->check (line) + +static void print_obj (kObject *o): + for kObject *obj = o; o; o = (kObject *)o->next: + dbg_log_num ((unsigned)o) + dbg_log ("->") + dbg_log ("NULL\n") + +void kMemory::print (unsigned line, unsigned indent): + if indent == 0: + print_free () + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + ++indent + dbg_log ("Memory ") + dbg_log_num ((unsigned)this) + dbg_log ("\n") + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + dbg_log ("frees: ") + for kFree *f = frees; f; f = (kFree *)f->next: + dbg_log_num ((unsigned)f) + dbg_log (":") + unsigned n = (unsigned)NEXT (f) + if n: + n -= (unsigned)f + if n >= PAGE_SIZE: + dpanic (0, "invalid kFree") + dbg_log_num (n, 3) + dbg_log ("->") + dbg_log ("NULL\n") + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + dbg_log ("pages: ") + print_obj (pages) + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + dbg_log ("threads: ") + print_obj (threads) + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + dbg_log ("receivers: ") + for kReceiver *r = receivers; r; r = (kReceiver *)r->next: + dbg_log_num ((unsigned)r) + dbg_log ("(") + for kMessage *m = r->messages; m; m = (kMessage *)m->next: + dbg_log_num ((unsigned)m) + dbg_log ("->") + dbg_log ("NULL)->") + dbg_log ("NULL\n") + for unsigned i = 0; i < indent; ++i: + dbg_log_char ('\t') + dbg_log ("capses: ") + print_obj (capses) + for kMemory *m = memories; m; m = (kMemory *)m->next: + m->print (line, indent) + +void check_impl (kObject *o, unsigned num, char const *msg): + for ; o; o = (kObject *)o->next: + unsigned n = (unsigned)NEXT (o) + unsigned size = n ? n - (unsigned)o : PAGE_SIZE - ((unsigned)o & PAGE_MASK) + if !check_free (o, size): + panic (num, msg) diff --git a/boot-programs/buzzer.ccp b/boot-programs/buzzer.ccp index 0fbea4f..f6fb5ce 100644 --- a/boot-programs/buzzer.ccp +++ b/boot-programs/buzzer.ccp @@ -23,10 +23,9 @@ class DevBuzzer: static unsigned const pwm = 4 Kernel::Cap event - bool is_active, is_beeping + bool is_beeping public: DevBuzzer (): - is_active = false is_beeping = false gpio_as_pwm4 () tcu_stop_counter (pwm) @@ -38,8 +37,8 @@ class DevBuzzer: return tcu_stop_counter (pwm) event.invoke () - is_active = false Kernel::free_cap (event) + is_beeping = false void beep (unsigned freq, unsigned ms, Kernel::Cap cb): stop () event = cb @@ -115,12 +114,11 @@ Kernel::Num start (): break switch Kernel::recv.data[0].l: case Buzzer::BEEP: - // Volume is not used for this buzzer. + // Volume is not used by this buzzer. Kernel::Cap arg = Kernel::get_arg () Kernel::Cap reply = Kernel::get_reply () buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg) reply.invoke () - Kernel::free_cap (arg) Kernel::free_cap (reply) break case Buzzer::STOP: diff --git a/boot-programs/crt0.ccp b/boot-programs/crt0.ccp index efd1702..cd5a0d9 100644 --- a/boot-programs/crt0.ccp +++ b/boot-programs/crt0.ccp @@ -17,6 +17,7 @@ // along with this program. If not, see . #include "iris.hh" +#include "devices.hh" // For some unknown reason, gcc needs this to be defined. unsigned __gxx_personality_v0 @@ -33,7 +34,7 @@ namespace Kernel: Thread my_thread Memory my_memory Cap my_call - Cap my_parent + Parent my_parent __recv_data_t recv void print_caps (): diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index e996ad2..431d305 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -19,28 +19,50 @@ #include "devices.hh" #include "iris.hh" -static Keyboard kbd, sysreq -static Buzzer buzzer +static Keyboard sysreq static Device kbd_dev, buz_dev -static List kbd_names static unsigned slot // Event types. enum type: - MEMORY - KBDDEV - KBD - KEYNAMES SYSREQ + KBDDEV BUZDEV - BUZZER + +static void user_reply (Kernel::Cap target, unsigned dev): + switch dev: + case Keyboard::ID: + // keyboard user + kdebug ("keyboard requested\n") + Kernel::Cap kbd = kbd_dev.create_user (Kernel::Cap ()) + kbd_dev.use (kbd) + target.invoke (0, 0, kbd.copy ()) + Kernel::free_cap (kbd) + break + case Buzzer::ID: + // buzzer user + kdebug ("buzzer requested\n") + Kernel::Cap buzzer = buz_dev.create_user (Kernel::Cap ()) + buz_dev.use (buzzer) + kdebug ("invoking reply: ") + kdebug_num (target.code) + kdebug ("\n") + target.invoke (0, 0, buzzer.copy ()) + Kernel::free_cap (buzzer) + break + default: + kdebug ("invalid id requested:") + kdebug_num (dev) + kdebug_char ('\n') + break static void setup (): unsigned state = 0 Kernel::Caps caps = Kernel::my_memory.create_caps (32) slot = caps.use () - Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY)) - Kernel::Cap driver_memory = Kernel::my_memory.create_memory () + Kernel::Caps slot0 = Kernel::my_thread.get_caps (0) + Kernel::Cap user + unsigned device while true: Kernel::wait () Kernel::Cap reply = Kernel::get_reply () @@ -59,44 +81,38 @@ static void setup (): default: kdebug ("unexpected keyboard\n") break + reply.invoke () + Kernel::free_cap (reply) break case Buzzer::ID: caps.set (BUZDEV, arg.copy ()) buz_dev = Kernel::Cap (slot, BUZDEV) + reply.invoke () + Kernel::free_cap (reply) + break + case Parent::GET_DEVICE: + user = reply + device = Kernel::recv.data[1].l + slot0.print (reply.idx ()) break default: + kdebug ("unknown setup request for init\n") + reply.invoke () Kernel::free_cap (reply) Kernel::free_cap (arg) - kdebug ("unknown setup request for init\n") continue - reply.invoke () - Kernel::free_cap (reply) Kernel::free_cap (arg) - if ++state == 3: + if ++state == 4: break // sysreq + kdebug ("using sysreq\n") Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ) sysreq.set_cb (cb.copy ()) - // keyboard user - Kernel::set_recv_arg (Kernel::Cap (slot, KBD)) - kbd = kbd_dev.create_user (driver_memory) - kbd_dev.use (kbd) - // keyboard callback - Kernel::set_recv_arg (cb) - Kernel::my_receiver.create_capability (KBD) - kbd.set_cb (cb.copy ()) - // keyboard name list - Kernel::set_recv_arg (Kernel::Cap (slot, KEYNAMES)) - kbd_names = kbd.get_keys () - // buzzer user - Kernel::set_recv_arg (Kernel::Cap (slot, BUZZER)) - buzzer = buz_dev.create_user (driver_memory) - buz_dev.use (buzzer) - // clean up. Kernel::free_cap (cb) - -//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":" -char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA" + // First user reply. + kdebug ("sending first user reply\n") + user_reply (user, device) + Kernel::free_cap (user) Kernel::Num start (): setup () @@ -112,20 +128,11 @@ Kernel::Num start (): else: kdebug ("pressed.\n\n") break - case KBD: - unsigned code = Kernel::recv.data[0].l - if code & Keyboard::RELEASE: - kdebug_char ('-') - else: - kdebug_char ('+') - buzzer.beep (2000, 100, 0) - String name = kbd_names.get (code & ~Keyboard::RELEASE) - unsigned size = name.get_size ().l - char buffer[16] - for unsigned i = 0; i < size; i += 16: - name.get_chars (i, buffer) - for unsigned k = 0; k < size - i && k < 16; ++k: - kdebug_char (buffer[k]) - kdebug_char ('\n') - Kernel::free_cap (name) + default: + if Kernel::recv.data[0].l != Parent::GET_DEVICE: + kdebug ("invalid call from user\n") + break + Kernel::Cap reply = Kernel::get_reply () + user_reply (reply, Kernel::recv.data[1].l) + Kernel::free_cap (reply) break diff --git a/boot-programs/lcd.ccp b/boot-programs/lcd.ccp index 7a354b9..2b9b85f 100644 --- a/boot-programs/lcd.ccp +++ b/boot-programs/lcd.ccp @@ -27,9 +27,15 @@ extern unsigned char const charset[127-32][6] #define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0) +#if defined (TRENDTAC) // For now, support only 16 bpp. // Screen is 800x480 tft. static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 +#else if defined (NANONOTE) +static unsigned h = 320, v = 240, fps = 70, Bpp = 3 +#else +#error unknown board +#endif #define frame_size (v * h * Bpp) static unsigned physical_descriptor @@ -40,21 +46,49 @@ struct Descriptor: unsigned id unsigned cmd -#if defined (TRENDTAC) static void reset (): - LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 - LCD_VSYNC = vs - LCD_HSYNC = hs - LCD_DAV = (vs << 16) | (vs + v) - LCD_DAH = (hs << 16) | (hs + h) - LCD_VAT = ((hs + h) << 16) | (vs + v) +#if defined (TRENDTAC) + unsigned fps = 60 + // Vertical timings. + unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde + // Horizontal timings. + unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde + unsigned extra = 0 + // Bits per pixel. + unsigned bpp = LCD_CTRL_BPP_16 + // Configuration. #define MODE_TFT_GEN 0 #define VSYNC_N (1 << 8) - LCD_CFG = MODE_TFT_GEN | VSYNC_N + unsigned cfg = MODE_TFT_GEN | VSYNC_N +#elif defined (NANONOTE) + unsigned fps = 70 + // Vertical timings. + unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1 + // Horizontal timings. + unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273 + // 3 bytes per pixel, so for the display area 2 extra clocks are sent. + unsigned extra = 2 + // Bits per pixel. + unsigned bpp = LCD_CTRL_BPP_18_24 + // Configuration. + unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP +#else +#error unknown board +#endif + + LCD_CTRL = bpp | LCD_CTRL_BST_16 + LCD_VSYNC = (vps << 16) | vpe + LCD_HSYNC = (hps << 16) | hpe + LCD_DAV = (vds << 16) | vde + LCD_DAH = (hds << 16) | hde + LCD_VAT = (ht << 16) | vt + LCD_CFG = cfg cpm_stop_lcd () - unsigned pixclock = fps * (hs + h) * (vs + v) + unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt + + #if defined (TRENDTAC) unsigned pllout = cpm_get_pllout () CPM_CFCR2 = pllout / pixclock - 1 @@ -63,18 +97,29 @@ static void reset (): assert (val <= 0xf) cpm_set_lcdclk_div (val) CPM_CFCR |= CPM_CFCR_UPE + #elif defined (NANONOTE) + unsigned val = cpm_get_pllout2 () / pclk - 1 + if val > 0x3ff: + kdebug ("pixel clock too large\n") + Kernel::panic () + return + cpm_set_pixdiv (val); + + val = cpm_get_pllout () / (pixclock * 3) + if val > 0x1f: + kdebug ("pixel divider too large\n") + Kernel::panic () + return + cpm_set_ldiv (val) + // Update dividers. + CPM_CPCCR |= CPM_CPCCR_CE + #endif cpm_start_lcd () LCD_DA0 = physical_descriptor lcd_set_ena () lcd_enable_eof_intr () -#elif defined (NANONOTE) -static void reset (): - // TODO -#else -#error unknown board -#endif static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000): if ch < 32 || ch > 126: @@ -83,19 +128,19 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned lookup[2] = { bg, fg } for unsigned k = 0; k < 6; ++k: for unsigned r = 0; r < 8; ++r: - LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0] + LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0] static unsigned log_x = 1, log_y = 1 static void inc_logx (): - if ++log_x >= 800 / 6: + if ++log_x >= h / 6: log_x = 1 - if ++log_y >= 480 / 8: + if ++log_y >= v / 8: log_y = 1 static void log_char (unsigned ch): switch ch: case '\n': - while log_x < 800 / 6: + while log_x < h / 6: putchar (log_x++, log_y, ' ') inc_logx () break @@ -138,22 +183,22 @@ Kernel::Num start (): p.alloc_physical (physical + i * PAGE_SIZE, false, true) Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE) Kernel::free_cap (p) - for unsigned y = 0; y < 480; ++y: - unsigned g = (y << 6) / 480 - unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480) - for unsigned x = 0; x < 800; ++x: - unsigned r = (x << 5) / 800 - unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480) + for unsigned y = 0; y < v; ++y: + unsigned g = (y << 6) / v + unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v) + for unsigned x = 0; x < h; ++x: + unsigned r = (x << 5) / h + unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v) if r != olr: olr = r r = 0x1f unsigned oyb = b if y > 0: - oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480) + oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v) if b != ob || b != oyb: ob = b b = 0x1f - LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b) + LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b) Kernel::Page p = Kernel::my_memory.mapping (&descriptor) physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK) Kernel::free_cap (p) @@ -166,11 +211,12 @@ Kernel::Num start (): reset () Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG) + #if defined (TRENDTAC) __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") + #endif - ((Init)Kernel::my_parent).register_lcd () - - Kernel::Cap eof_cb = Kernel::alloc_cap () + Kernel::Cap eof_cb + bool have_eof = false while true: Kernel::wait () //log_msg () @@ -180,11 +226,15 @@ Kernel::Num start (): eof_cb.invoke () break case Init::LCD_SET_EOF_CB: - Kernel::free_cap (eof_cb) - eof_cb = Kernel::recv.arg - Kernel::recv.arg = Kernel::alloc_cap () - Kernel::recv.reply.invoke () + if have_eof: + Kernel::free_cap (eof_cb) + else: + have_eof = true + eof_cb = Kernel::get_arg () + Kernel::Cap reply = Kernel::get_reply () Kernel::register_interrupt (IRQ_LCD) + reply.invoke () + Kernel::free_cap (reply) break case Init::LCD_LOG: log_char (Kernel::recv.data[0].l) diff --git a/boot-programs/metronome.ccp b/boot-programs/metronome.ccp new file mode 100644 index 0000000..a0f0a30 --- /dev/null +++ b/boot-programs/metronome.ccp @@ -0,0 +1,70 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// boot-programs/metronome.ccp: Userspace program. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "devices.hh" +#include "keys.hh" + +Kernel::Num start (): + kdebug ("metronome started\n") + Buzzer buzzer = Kernel::my_parent.get_device () + Keyboard kbd = Kernel::my_parent.get_device () + Kernel::Cap key = Kernel::my_receiver.create_capability (0) + kbd.set_cb (key) + unsigned mHz = 1000 + unsigned freq = 1000 + Kernel::my_receiver.set_alarm (1) + bool running (true) + while true: + Kernel::wait () + switch Kernel::recv.protected_data.l: + case ~0: + if running: + buzzer.beep (freq, 10, ~0) + Kernel::my_receiver.set_alarm (HZ * 1000 / mHz) + break + case 0: + if Kernel::recv.data[0].l & Keyboard::RELEASE: + break + switch Kernel::recv.data[0].l: + case Key::VOLUME_UP: + freq = freq * 11 / 10 + break + case Key::VOLUME_DOWN: + freq = freq * 9 / 10 + break + case Key::LEFT: + mHz = mHz * 101 / 100 + break + case Key::RIGHT: + mHz = mHz * 99 / 100 + break + case Key::UP: + mHz = mHz * 11 / 10 + break + case Key::DOWN: + mHz = mHz * 9 / 10 + break + case Key::P: + running = !running + if running: + Kernel::my_receiver.set_alarm (1) + break + break + default: + kdebug ("huh?\n") + break diff --git a/boot-programs/nanonote-gpio.ccp b/boot-programs/nanonote-gpio.ccp index 64a3cee..7b7b7a3 100644 --- a/boot-programs/nanonote-gpio.ccp +++ b/boot-programs/nanonote-gpio.ccp @@ -19,6 +19,7 @@ #include "devices.hh" #define ARCH #include "arch.hh" +#include "keys.hh" //#define QI #define SCAN_INTERVAL HZ / 50 @@ -33,27 +34,8 @@ class DevKbd: static unsigned const COLS[NUM_COLS] static unsigned const ROWS[NUM_ROWS] static unsigned const encode[NUM_ROWS][NUM_COLS] - enum Keys: - #ifdef QI - A, B, C, D, E, F, G, H, I, J, K, L, M - N, O, P, Q, R, S, T, U, V, W, X, Y, Z - F1, F2, F3, F4, F5, F6, F7, F8 - TAB, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, EQUAL, SPACE - ESCAPE, ENTER, BACKSPACE - UP, DOWN, LEFT, RIGHT - CAPS, ARROW, QI, CTRL, VOLUP, VOLDOWN, SHIFT, ALT, FN - #else - N0, N1, N2, N3, N4, N5, N6, N7, N8, N9 - A, B, C, D, E, F, G, H, I, J, K, L, M - N, O, P, Q, R, S, T, U, V, W, X, Y, Z - F1, F2, F3, F4 - CAPS, TAB, ENTER, ESCAPE, MP3, SPACE, BACKSPACE, EQUALS - UP, DOWN, LEFT, RIGHT - VOLUP, VOLDOWN - FN, SHIFT, CTRL, ALT - #endif - NUM_KEYS - static char const *const names[NUM_KEYS] + static unsigned const NUM_KEYS = 58 + static unsigned const keys[NUM_KEYS] unsigned state[NUM_COLS] Kernel::Cap event bool is_active @@ -61,27 +43,14 @@ class DevKbd: public: unsigned size (): return NUM_KEYS - unsigned get_name_size (unsigned n): - if n >= NUM_KEYS: - return 0 - unsigned ret = 0 - for char const *p = names[n]; *p; ++p: - ++ret - return ret - void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset): - if n >= NUM_KEYS: - c.invoke (0, 0) - return - unsigned data[4] - char *d = (char *)data - if offset.value () < get_name_size (n): - unsigned o = offset.l & ~3; - unsigned p - for p = 0; p < 16 && names[n][p + o]; ++p: - *d++ = names[n][p + o] - for ; p < 16; ++p: - *d++ = 0 - c.invoke (Kernel::Num (data[0], data[1]), Kernel::Num (data[2], data[3])) + void send_keys (unsigned first, Kernel::Cap target): + unsigned d[4] + unsigned i + for i = 0; first + i < NUM_KEYS && i < 4; ++i: + d[i] = keys[first + i] + for ; i < 4; ++i: + d[i] = ~0 + target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3])) bool scanning (): return is_scanning void inactive (): @@ -155,43 +124,44 @@ unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 } unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 } unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = { #ifdef QI - { F1, F2, F3, F4, F5, F6, F7, ~0 }, - { Q, W, E, R, T, Y, U, I }, - { A, S, D, F, G, H, J, K }, - { ESCAPE, Z, X, C, V, B, N, M }, - { TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP }, - { O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT }, - { F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT }, - { SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 } + { Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 }, + { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I }, + { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K }, + { Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M }, + { Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP }, + { Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT }, + { Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT }, + { Key::SHIFT, Key::ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 } #else - { ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 }, - { N1, N2, N3, N4, N5, N6, N7, N8 }, - { Q, W, E, R, T, Y, U, I }, - { A, S, D, F, G, H, J, K }, - { Z, X, C, V, B, N, M, UP }, - { N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT }, - { BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT }, - { FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 } + { Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 }, + { Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 }, + { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I }, + { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K }, + { Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP }, + { Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT }, + { Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT }, + { Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 } #endif } -char const *const DevKbd::names[NUM_KEYS] = { +unsigned const DevKbd::keys[NUM_KEYS] = { #ifdef QI - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", - "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", - "tab", "\\", "'", ",", ".", "/", "=", "space", - "escape", "enter", "backspace", - "up", "down", "left", "right", - "caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn" + Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, + Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I, + Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K, + Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, + Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP, + Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT, + Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT, + Key::SHIFT, Key::ALT, Key::FN #else - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", - "f1", "f2", "f3", "f4", - "caps lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=", - "up", "down", "left", "right", - "volume up", "volume down", - "fn", "left shift", "left control", "left alt" + Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, + Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8, + Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I, + Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K, + Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP, + Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT, + Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT, + Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL #endif } @@ -222,12 +192,10 @@ class PowerButton: enum codes: KBD_DEV = 32 - KBD_LIST PWR Kernel::Num start (): map_gpio () - map_tcu () DevKbd kbd PowerButton pwr @@ -242,7 +210,6 @@ Kernel::Num start (): Kernel::my_receiver.set_alarm (SCAN_INTERVAL) unsigned user (~0) unsigned next_user (0) - List list = List (Kernel::my_receiver.create_capability (KBD_LIST)) Kernel::register_interrupt (IRQ_GPIO3) while true: Kernel::wait () @@ -307,24 +274,6 @@ Kernel::Num start (): kdebug ("\n") break break - case KBD_LIST: - // Keyboard name lookup. - switch Kernel::recv.data[0].l: - case Kernel::Caps::GET: - Kernel::Cap reply = Kernel::get_reply () - unsigned num = Kernel::recv.data[1].l - Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (num, KBD_LIST)) - reply.invoke (kbd.get_name_size (num), 0, name.copy ()) - Kernel::free_cap (name) - Kernel::free_cap (reply) - break - case Kernel::Caps::GET_SIZE: - Kernel::recv.reply.invoke (kbd.size ()) - break - default: - kdebug ("invalid list operation\n") - break - break default: break break @@ -337,29 +286,23 @@ Kernel::Num start (): switch Kernel::recv.data[0].l: case Keyboard::SET_CB: kdebug ("set cb\n") + Kernel::Cap reply = Kernel::get_reply () kbd.active (Kernel::get_arg ()) - Kernel::recv.reply.invoke () + reply.invoke () + Kernel::free_cap (reply) + break + case Keyboard::GET_NUM_KEYS: + kdebug ("get #keys\n") + Kernel::recv.reply.invoke (kbd.size ()) break case Keyboard::GET_KEYS: kdebug ("get keys\n") - Kernel::recv.reply.invoke (0, 0, list) + kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply) break default: kdebug ("other\n") break break - case KBD_LIST: - switch Kernel::recv.data[0].l: - case String::GET_SIZE: - Kernel::recv.reply.invoke (kbd.get_name_size (Kernel::recv.protected_data.l)) - break - case String::GET_CHARS: - kbd.send_name (Kernel::recv.protected_data.l, Kernel::recv.reply, Kernel::recv.data[1]) - break - default: - kdebug ("invalid string operation\n") - break - break default: kdebug ("unknown num: ") kdebug_num (Kernel::recv.protected_data.h) diff --git a/boot-programs/devices.hhp b/devices.hhp similarity index 93% rename from boot-programs/devices.hhp rename to devices.hhp index 38fb9e8..ec60ff5 100644 --- a/boot-programs/devices.hhp +++ b/devices.hhp @@ -75,11 +75,26 @@ struct WString : public String: void set_page (Kernel::Num idx, Kernel::Page page): ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx) +// Interface for talking to the parent process. +struct Parent : public Kernel::Cap: + Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): + enum request: + GET_DEVICE = WString::ID + EXIT + ID + // Get a device handle. + template _T get_device (unsigned num = 0): + icall (CAP_MASTER_DIRECT | GET_DEVICE, Kernel::Num (_T::ID, num)) + return Kernel::get_arg () + // Exit the program. The parent does not reply, but kills the process. + void exit (Kernel::Num code): + call (CAP_MASTER_DIRECT | EXIT, code) + // Every process which wants to be switchable through a terminal must implement this interface. struct Device : public Kernel::Cap: Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: - CREATE_USER = WString::ID + CREATE_USER = Parent::ID DESTROY_USER UNUSE USE @@ -104,6 +119,7 @@ struct Keyboard : public Kernel::Cap: Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: SET_CB = Device::ID + GET_NUM_KEYS GET_KEYS ID // At event: the callback is called with a keycode. One bit defines if it's a press or release event. @@ -112,10 +128,10 @@ struct Keyboard : public Kernel::Cap: // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately. void set_cb (Kernel::Cap cb): ocall (cb, CAP_MASTER_DIRECT | SET_CB) - // Get a list of keys on this keyboard. The key codes start at zero with no gaps. - List get_keys (): - icall (CAP_MASTER_DIRECT | GET_KEYS) - return List (Kernel::get_arg ()) + unsigned get_num_keys (): + return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l + void get_keys (unsigned first): + call (CAP_MASTER_DIRECT | GET_KEYS, first) // Buzzer interface. struct Buzzer : public Kernel::Cap: diff --git a/invoke.ccp b/invoke.ccp index b22beaa..83ef494 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -19,33 +19,32 @@ #include "kernel.hh" static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c): - if !dbg_code.l: - dbg_log (prefix) - dbg_log (": caller=") - dbg_log_num ((unsigned)old_current) - dbg_log ("; target=") - dbg_log_num (target) + dbg_log (prefix) + dbg_log (": caller=") + dbg_log_num ((unsigned)old_current) + dbg_log ("; target=") + dbg_log_num (target) + dbg_log ("; pdata=") + dbg_log_num (pdata) + dbg_log ("; data=") + dbg_log_num (c->data[0].h) + dbg_log (":") + dbg_log_num (c->data[0].l) + dbg_log (",") + dbg_log_num (c->data[1].h) + dbg_log (":") + dbg_log_num (c->data[1].l) + if c->reply.valid (): + dbg_log ("; reply target=") + dbg_log_num ((unsigned)c->reply->target) dbg_log ("; pdata=") - dbg_log_num (pdata) - dbg_log ("; data=") - dbg_log_num (c->data[0].h) - dbg_log (":") - dbg_log_num (c->data[0].l) - dbg_log (",") - dbg_log_num (c->data[1].h) - dbg_log (":") - dbg_log_num (c->data[1].l) - if c->reply.valid (): - dbg_log ("; reply target=") - dbg_log_num ((unsigned)c->reply->target) - dbg_log ("; pdata=") - dbg_log_num (c->reply->protected_data.l) - if c->arg.valid (): - dbg_log ("; arg target=") - dbg_log_num ((unsigned)c->arg->target) - dbg_log ("; pdata=") - dbg_log_num (c->arg->protected_data.l) - dbg_log ("\n") + dbg_log_num (c->reply->protected_data.l) + if c->arg.valid (): + dbg_log ("; arg target=") + dbg_log_num ((unsigned)c->arg->target) + dbg_log ("; pdata=") + dbg_log_num (c->arg->protected_data.l) + dbg_log ("\n") void kThread::raise (unsigned code, unsigned data): dpanic (code, "raise") @@ -104,8 +103,8 @@ bool kReceiver::try_deliver (): if m->protected_data.value () == reply_protected_data.value (): protected_only = false break - if !m: - return false + if !m: + return false bool dummy kCapRef c = owner->find_capability (owner->recv_reply, &dummy) if c.valid (): @@ -121,7 +120,7 @@ bool kReceiver::try_deliver (): // Send a message to a receiver; try to deliver it immediately. bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c): //log_message ("send_message", (unsigned)this, protected_data.l, c) - if owner && owner->is_waiting () && (protected_data.value () == reply_protected_data.value () || !protected_only): + if owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()): if protected_only: protected_only = false bool dummy @@ -145,16 +144,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context * if !msg: return false msg->protected_data = protected_data - if protected_only && protected_data.value () == reply_protected_data.value (): - // Put this message in the end (where it will be first seen). Clear the protected_only flag. - protected_only = false - if msg->next: - ((kMessage *)msg->next)->prev = NULL - messages = (kMessage *)msg->next - msg->next = NULL - msg->prev = last_message - ((kMessage *)msg->prev)->next = msg - last_message = msg for unsigned i = 0; i < 2; ++i: msg->data[i] = c->data[i] msg->caps.clone (0, c->reply, c->copy[0]) @@ -194,9 +183,9 @@ static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref c.data[0] = Kernel::Num (num, 0) if reply_target: reply_target->send_message (reply_protected, &c) + c.arg->invalidate () else: dpanic (0, "nothing to reply to") - c.arg->invalidate () static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): kReceiver *receiver = (kReceiver *)protected_data.l @@ -713,6 +702,8 @@ static void print_cap (kCapRef cap, kCapRef self): dbg_log_char ('!') else: dbg_log_char ('=') + dbg_log_num ((unsigned)cap->target) + dbg_log_char (':') dbg_log_num (cap->protected_data.l) for kCapRef c = cap->children; c.valid (); c = c->sibling_next: print_cap (c, self) @@ -746,12 +737,9 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da return case Kernel::Caps::PRINT & REQUEST_MASK: if c->data[1].l >= caps->size: - if c->data[1].l == ~0: - // debug: power down. - *((volatile unsigned *)0xa0003020) = 1 - return dpanic (0, "invalid caps for print") return + dbg_code.h = (unsigned)caps->cap (c->data[1].l) kCapRef cap (caps, c->data[1].l) kCapRef orig (caps, c->data[1].l) while cap->parent.valid (): @@ -796,11 +784,12 @@ static void kill_reply (kReceiver *r): static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c): // Kernel calling convention: // data[0].l is the request. - // caps[0] is the reply capability + // reply is the reply capability, or (for call capabilities) the target to call. // other parameters' meanings depend on the operation. if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC): - // This is a call capability. reply is the capability to call. It should be replaced by the reply capability. - ((kReceiver *)protected_data.l)->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) + // This is a call capability. reply is the capability to call. + kReceiver *owner = (kReceiver *)protected_data.l + owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) if must_wait: old_current->wait () if !reply_target: @@ -825,6 +814,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil c->reply.reset () reply_target = (kReceiver *)protected_data.l reply_protected = reply_target->reply_protected_data + kReceiver *r = reply_target kernel_invoke ((unsigned)call_target->target, call_target->protected_data, c) return if must_wait: diff --git a/iris.hhp b/iris.hhp index 05e02d1..12d8761 100644 --- a/iris.hhp +++ b/iris.hhp @@ -65,6 +65,8 @@ // This constant signifies that no capability is passed. #define CAP_NONE (~CAP_COPY) +struct Parent + namespace Kernel: enum Exception_code: NO_ERROR @@ -161,7 +163,7 @@ namespace Kernel: extern Thread my_thread extern Memory my_memory extern Cap my_call - extern Cap my_parent + extern Parent my_parent extern __recv_data_t recv inline Cap get_reply (): diff --git a/kernel.hhp b/kernel.hhp index cbe9b92..0991fc4 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -137,11 +137,12 @@ struct kReceiver : public kObject: Kernel::Num reply_protected_data bool protected_only // This limit is for messages stored in its address space. There is unlimited space if senders provide it. - unsigned queue_limit + unsigned queue_limit, queue_use void own (kThreadP o) void orphan () bool try_deliver () bool send_message (Kernel::Num protected_data, kCapability::Context *c) + void check (unsigned line) struct kPage : public kObject: unsigned frame @@ -205,6 +206,8 @@ struct kMemory : public kObject: void free_memory (kMemory *mem) void free_obj (kObject *obj, void **first) + void check (unsigned line) + void print (unsigned line, unsigned indent) // Functions which can be called from assembly must not be mangled. extern "C": @@ -219,7 +222,12 @@ extern "C": void dbg_log_num (unsigned num, unsigned digits = 8) void dbg_send (unsigned num, unsigned bits) void check (unsigned num, char const *msg) + #define dbg_check() ::check (__LINE__, __FILE__) + void print_free () + void check_impl (kObject *o, unsigned num, char const *msg) + bool check_free (kObject *o, unsigned size) #define dpanic(n, msg) panic (n, msg) + #define dbg_print() top_memory.print (__LINE__, 0) #else #define dbg_log_char(x) do {} while (0) #define dbg_log(x) do {} while (0) diff --git a/keys.hhp b/keys.hhp new file mode 100644 index 0000000..3b2b573 --- /dev/null +++ b/keys.hhp @@ -0,0 +1,147 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// boot-programs/keys.hhp: Keycode definitions. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef __KEYS_HH +#define __KEYS_HH + +namespace Key: + enum codes: + N0 = '0' + N1 = '1' + N2 = '2' + N3 = '3' + N4 = '4' + N5 = '5' + N6 = '6' + N7 = '7' + N8 = '8' + N9 = '9' + A = 'a' + B = 'b' + C = 'c' + D = 'd' + E = 'e' + F = 'f' + G = 'g' + H = 'h' + I = 'i' + J = 'j' + K = 'k' + L = 'l' + M = 'm' + N = 'n' + O = 'o' + P = 'p' + Q = 'q' + R = 'r' + S = 's' + T = 't' + U = 'u' + V = 'v' + W = 'w' + X = 'x' + Y = 'y' + Z = 'z' + ESCAPE = 27 + ENTER = '\n' + TAB = '\t' + COMMA = ',' + PERIOD = '.' + SLASH = '/' + BACKSLASH = '\\' + SEMICOLON = ';' + QUOTE = '\'' + BACKQUOTE = '`' + OPEN_BRACKET = '[' + CLOSE_BRACKET = ']' + MINUS = '-' + EQUALS = '=' + BACKSPACE = 8 + HOME = 11 + DELETE = 127 + SPACE = ' ' + KP_0 = 0x100 + KP_1 + KP_2 + KP_3 + KP_4 + KP_5 + KP_6 + KP_7 + KP_8 + KP_9 + KP_PERIOD = '.' + 0x100 + KP_ENTER = '\n' + 0x100 + KP_PLUS = '+' + 0x100 + KP_MINUS = '-' + 0x100 + KP_MULTIPLY = '*' + 0x100 + KP_DIVIDE = '/' + 0x100 + FN = 0x200 + F1 + F2 + F3 + F4 + F5 + F6 + F7 + F8 + F9 + F10 + F11 + F12 + F13 + F14 + F15 + F16 + F17 + F18 + F19 + F20 + F21 + F22 + F23 + F24 + POWER_OFF + SLEEP + WAKE_UP + VOLUME_UP + VOLUME_DOWN + UP + DOWN + LEFT + RIGHT + INSERT + END + PAGE_UP + PAGE_DOWN + PRINT_SCREEN + PAUSE + CAPS_LOCK + NUM_LOCK + SCROLL_LOCK + LEFT_SHIFT + RIGHT_SHIFT + LEFT_CONTROL + RIGHT_CONTROL + LEFT_ALT + RIGHT_ALT + LEFT_LOGO + RIGHT_LOGO + MENU + SPECIAL +#endif diff --git a/memory.ccp b/memory.ccp index 5c244f3..757f3a6 100644 --- a/memory.ccp +++ b/memory.ccp @@ -34,6 +34,7 @@ void check_impl (kObject *o, unsigned num, char const *msg): for ; o; o = o->next: if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end: panic (num, msg) +void print_free (): #endif #else @@ -129,11 +130,20 @@ void phys_free (unsigned page, unsigned num): n->num = num #ifndef NDEBUG -void check_impl (kObject *o, unsigned num, char const *msg): - for ; o; o = (kObject *)o->next: - for kFreePages *p = first_free; p; p = p->next: - if (unsigned)o >= (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE: - panic (num, msg) +bool check_free (kObject *o, unsigned size): + for kFreePages *p = first_free; p; p = p->next: + if (unsigned)o + size > (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE: + return false + return true + +void print_free (): + dbg_log ("Free pages: ") + for kFreePages *p = first_free; p; p = p->next: + dbg_log_num ((unsigned)p) + dbg_log (":") + dbg_log_num (p->num, 4) + dbg_log ("->") + dbg_log ("NULL\n") #endif #endif @@ -142,6 +152,8 @@ void check_memory (kMemory *mem, unsigned num, char const *msg): check_impl (mem->pages, num, msg) check_impl (mem->threads, num, msg) check_impl (mem->receivers, num, msg) + for kReceiver *r = mem->receivers; r; r = (kReceiver *)r->next: + check_impl (r->messages, num, msg) check_impl (mem->capses, num, msg) check_impl (mem->memories, num, msg) for kMemory *m = mem->memories; m; m = (kMemory *)m->next: @@ -149,6 +161,7 @@ void check_memory (kMemory *mem, unsigned num, char const *msg): void check (unsigned num, char const *msg): check_memory (&top_memory, num, msg) + top_memory.check (num) #endif unsigned raw_zalloc (): diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index 43ff434..eaac778 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -131,20 +131,18 @@ void flush_tlb (unsigned asid): __asm__ volatile ("tlbwi") static void arch_invoke (): - kCapRef target - target = old_current->find_capability (old_current->arch.v[0], &must_wait) + kCapRef target = old_current->find_capability (old_current->arch.v[0], &must_wait) do_schedule = false kCapability::Context msg - msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0]) - msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1]) if must_wait: - bool dummy old_current->recv_reply = old_current->arch.t[2] old_current->recv_arg = old_current->arch.t[3] if !target.valid (): if must_wait: old_current->wait () return + msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0]) + msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1]) msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1]) msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3]) target->invoke (&msg) diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index 5a5d7c2..04809b2 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -17,7 +17,7 @@ load = 0x80000000 -ARCH_CXXFLAGS = -DNUM_THREADS=4 +ARCH_CXXFLAGS = -DNUM_THREADS=5 ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL CROSS = mipsel-linux-gnu- OBJDUMP = $(CROSS)objdump @@ -28,7 +28,7 @@ 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 -boot_threads = init udc nanonote-gpio buzzer +boot_threads = init udc nanonote-gpio buzzer metronome test: iris.raw nanonote-boot ./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') @@ -50,7 +50,7 @@ mips/entry.o: $(boot_threads) mips/init.o: TARGET_FLAGS = -I/usr/include $(boot_threads): TARGET_FLAGS = -I. $(boot_threads): LDFLAGS = -EL -$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh +$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh lcd: boot-programs/charset.data boot-programs/charset.data: boot-programs/charset @@ -63,4 +63,4 @@ boot-programs/charset.data: boot-programs/charset iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources)) $(LD) $(LDFLAGS) $^ -o $@ -ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) boot_programs/devices.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw +ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw diff --git a/mips/nanonote/board.ccp b/mips/nanonote/board.ccp index ce27307..92e8782 100644 --- a/mips/nanonote/board.ccp +++ b/mips/nanonote/board.ccp @@ -54,4 +54,5 @@ void board_init (): UART0_DLLR = uart_div UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS + dbg_code.l = 1 dbg_log ("Serial port initialized\n") diff --git a/mips/nanonote/threadlist.S b/mips/nanonote/threadlist.S index 4187f9a..c46ae99 100644 --- a/mips/nanonote/threadlist.S +++ b/mips/nanonote/threadlist.S @@ -35,7 +35,11 @@ thread2: thread3: .incbin "buzzer" + .balign 0x1000 thread4: + .incbin "metronome" + +thread5: // Everything from here may be freed after kernel initialization. init_start: @@ -46,3 +50,4 @@ thread_start: .word thread2 .word thread3 .word thread4 + .word thread5 diff --git a/panic.ccp b/panic.ccp index 67864fc..52eb924 100644 --- a/panic.ccp +++ b/panic.ccp @@ -21,6 +21,8 @@ #ifdef USE_SERIAL void dbg_log_char (unsigned ch): + if dbg_code.l == 0: + return while !(UART0_LSR & UARTLSR_TDRQ): UART0_TDR = ch #else diff --git a/schedule.ccp b/schedule.ccp index a1abd5d..2357472 100644 --- a/schedule.ccp +++ b/schedule.ccp @@ -90,6 +90,6 @@ void schedule (): void timer_interrupt (): kReceiver *recv, *next for recv = first_alarm; recv; recv = next: - next = (kReceiver *)recv->next + next = (kReceiver *)recv->next_alarm alarm_tick (recv) //schedule ()