1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 00:44:31 +03:00

better interfaces

This commit is contained in:
Bas Wijnen 2009-09-06 23:34:50 +02:00
parent a838dd63c6
commit a2e13cbcda
8 changed files with 95 additions and 106 deletions

View File

@ -21,12 +21,6 @@
#include "iris.hh"
// This shouldn't really be here. But where should it be?
// Requests made by initial threads to tell init about themselves.
enum init_requests:
INIT_SET_GPIO = 1
INIT_SET_LCD
// List interface.
template <typename _T> //
struct List : public Kernel::Cap:

View File

@ -17,6 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "devices.hh"
#include "init.hh"
#define ARCH
#include "arch.hh"
@ -53,12 +54,6 @@ enum event_type:
TOUCHPAD_EVENT
NUM_EVENTS
enum cap_type:
CAP_KEYBOARD = 32
CAP_TOUCHPAD
CAP_LOCKLEDS
CAP_PWM
static Kernel::Cap events[NUM_EVENTS]
static void event (event_type type, unsigned data):
@ -265,20 +260,7 @@ Kernel::Num start ():
Lockleds leds
Pwm pwm
Kernel::Caps c = Kernel::my_memory.create_caps (4)
unsigned init_slot = c.use ()
Kernel::set_recv_arg (Kernel::Cap (init_slot, 0))
Kernel::my_receiver.create_capability (CAP_KEYBOARD)
Kernel::set_recv_arg (Kernel::Cap (init_slot, 1))
Kernel::my_receiver.create_capability (CAP_TOUCHPAD)
Kernel::set_recv_arg (Kernel::Cap (init_slot, 2))
Kernel::my_receiver.create_capability (CAP_LOCKLEDS)
Kernel::set_recv_arg (Kernel::Cap (init_slot, 3))
Kernel::my_receiver.create_capability (CAP_PWM)
Kernel::my_parent.ocall (c, INIT_SET_GPIO)
free_cap (c)
Kernel::free_slot (init_slot)
((Init)Kernel::my_parent).register_gpio ()
if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
@ -304,25 +286,23 @@ Kernel::Num start ():
// Reregister the interrupt.
Kernel::register_interrupt (IRQ_GPIO0)
break
case CAP_KEYBOARD:
kdebug ("gpio: keyboard callback registered.\n")
case Init::GPIO_KEYBOARD:
set_cb (KEYBOARD_EVENT)
Kernel::recv.reply.invoke ()
kbd.send_initial ()
event (KEYBOARD_EVENT, ~0)
break
case CAP_TOUCHPAD:
kdebug ("gpio: touchpad callback registered.\n")
case Init::GPIO_TOUCHPAD:
set_cb (TOUCHPAD_EVENT)
Kernel::recv.reply.invoke ()
tp.send_initial ()
event (TOUCHPAD_EVENT, ~0)
break
case CAP_LOCKLEDS:
case Init::GPIO_LOCKLEDS:
leds.set (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
case CAP_PWM:
case Init::GPIO_PWM:
pwm.set_backlight (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break

View File

@ -18,6 +18,7 @@
#include "devices.hh"
#include "iris.hh"
#include "init.hh"
static Keyboard kbd, tp
static Display lcd
@ -30,33 +31,39 @@ enum type:
static void setup ():
unsigned state = 0
Kernel::recv.arg = Kernel::alloc_cap ()
Kernel::Caps my_caps = Kernel::my_memory.create_caps (4 + 1)
unsigned my_slot = my_caps.use ()
unsigned slot = Kernel::alloc_slot ()
while true:
Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Caps caps = Kernel::get_arg ()
switch Kernel::recv.data[0].value ():
case INIT_SET_GPIO:
kdebug ("gpio\n")
Kernel::Caps caps = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply ()
unsigned gpio_slot = caps.use ()
kbd = Kernel::Cap (gpio_slot, 0)
tp = Kernel::Cap (gpio_slot, 1)
lockleds = Kernel::Cap (gpio_slot, 2)
pwm = Kernel::Cap (gpio_slot, 3)
reply.invoke ()
Kernel::free_cap (reply)
++state
case Init::REGISTER_GPIO:
caps.use (slot)
for unsigned i = 0; i < 4; ++i:
my_caps.set (i, Kernel::Cap (slot, i).copy ())
kbd = Kernel::Cap (my_slot, 0)
tp = Kernel::Cap (my_slot, 1)
lockleds = Kernel::Cap (my_slot, 2)
pwm = Kernel::Cap (my_slot, 3)
break
case INIT_SET_LCD:
kdebug ("lcd\n")
lcd = Kernel::get_arg ()
Kernel::recv.reply.invoke ()
++state
case Init::REGISTER_LCD:
caps.use (slot)
my_caps.set (4, Kernel::Cap (slot, 0).copy ())
lcd = Kernel::Cap (my_slot, 4)
break
if state == 2:
default:
kdebug ("unknown setup request for init\n")
continue
reply.invoke ()
Kernel::free_cap (caps)
Kernel::free_cap (reply)
if ++state == 2:
break
Kernel::free_cap (my_caps)
Kernel::free_slot (slot)
Kernel::schedule ()
kdebug ("init registering keyboard\n")
Kernel::Cap kc = Kernel::my_receiver.create_capability (KBD)
kbd.set_cb (kc)
Kernel::Cap tc = Kernel::my_receiver.create_capability (TP)
@ -68,9 +75,7 @@ char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.
Kernel::Num start ():
// Set up lcd first
Kernel::schedule ()
kdebug ("start init\n")
setup ()
kdebug ("run init\n")
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.value ():

View File

@ -17,6 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "devices.hh"
#include "init.hh"
#define ARCH
#include "arch.hh"
@ -26,10 +27,6 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
enum types:
LCD_EOF_CB = 32
LCD_LOG
// For now, support only 16 bpp.
// Screen is 800x480 tft.
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
@ -161,11 +158,10 @@ Kernel::Num start ():
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset ()
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LCD_LOG)
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
Kernel::Cap set_eof_cb = Kernel::my_receiver.create_capability (LCD_EOF_CB)
Kernel::my_parent.ocall (set_eof_cb, INIT_SET_LCD)
((Init)Kernel::my_parent).register_lcd ()
unsigned slot = Kernel::alloc_slot ()
Kernel::Cap eof_cb = Kernel::alloc_cap ()
@ -177,14 +173,14 @@ Kernel::Num start ():
lcd_clr_eof ()
eof_cb.invoke ()
break
case LCD_EOF_CB:
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 ()
Kernel::register_interrupt (IRQ_LCD)
break
case LCD_LOG:
case Init::LCD_LOG:
log_char (Kernel::recv.data[0].l)
break
default:

View File

@ -179,11 +179,12 @@ static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
else:
dpanic (0, "nothing to reply to")
static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref):
static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref, unsigned num = 0):
replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
kCapability::Context c
c.arg = kCapRef (&replied_caps, 0)
c.copy[1] = true
c.data[0] = Kernel::Num (num, 0)
if reply_target:
reply_target->send_message (reply_protected, &c)
else:
@ -193,7 +194,7 @@ static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref
static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kReceiver *receiver = (kReceiver *)protected_data.l
switch cmd:
case Kernel::Receiver::SET_OWNER:
case Kernel::Receiver::SET_OWNER & REQUEST_MASK:
if !c->arg.valid ():
reply_num (~0)
return
@ -203,25 +204,25 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
return
receiver->own ((kThread *)c->arg->protected_data.l)
break
case Kernel::Receiver::CREATE_CAPABILITY:
case Kernel::Receiver::CREATE_CAPABILITY & REQUEST_MASK:
reply_cap ((unsigned)receiver, c->data[1], &receiver->capabilities)
return
case Kernel::Receiver::CREATE_CALL_CAPABILITY:
case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Kernel::Receiver::CALL_ASYNC : Kernel::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
return
case Kernel::Receiver::GET_REPLY_PROTECTED_DATA:
case Kernel::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK:
reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0)
return
case Kernel::Receiver::SET_REPLY_PROTECTED_DATA:
case Kernel::Receiver::SET_REPLY_PROTECTED_DATA & REQUEST_MASK:
receiver->reply_protected_data = c->data[1]
break
case Kernel::Receiver::GET_ALARM:
case Kernel::Receiver::GET_ALARM & REQUEST_MASK:
reply_num (receiver->alarm_count)
return
case Kernel::Receiver::SET_ALARM:
case Kernel::Receiver::ADD_ALARM:
case Kernel::Receiver::SET_ALARM & REQUEST_MASK:
case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
unsigned old = receiver->alarm_count
if cmd == Kernel::Receiver::SET_ALARM:
if cmd == Kernel::Receiver::SET_ALARM & REQUEST_MASK:
receiver->alarm_count = c->data[1].l
else:
receiver->alarm_count += c->data[1].l
@ -253,7 +254,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kMemory *mem = (kMemory *)protected_data.l
switch cmd:
case Kernel::Memory::CREATE:
case Kernel::Memory::CREATE & REQUEST_MASK:
switch c->data[0].h:
case CAPTYPE_RECEIVER:
kReceiver *ret = mem->alloc_receiver ()
@ -300,7 +301,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
reply_num (~0)
return
break
case Kernel::Memory::DESTROY:
case Kernel::Memory::DESTROY & REQUEST_MASK:
if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || !c->arg->target || ((kObject *)c->arg->protected_data.l)->address_space != mem:
reply_num (~0)
return
@ -324,10 +325,10 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
panic (0x55228930, "invalid case")
return
break
case Kernel::Memory::LIST:
case Kernel::Memory::LIST & REQUEST_MASK:
// TODO
break
case Kernel::Memory::MAP:
case Kernel::Memory::MAP & REQUEST_MASK:
// FIXME: this should work for fake pages as well.
if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || ((unsigned)c->arg->target & CAPTYPE_MASK) != CAPTYPE_PAGE:
dpanic (0x22993341, "Trying to map non-page")
@ -341,7 +342,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
bool readonly = c->data[1].l & (unsigned)c->arg->target & Kernel::Page::READONLY
mem->map (page, c->data[1].l & PAGE_MASK, readonly)
break
case Kernel::Memory::MAPPING:
case Kernel::Memory::MAPPING & REQUEST_MASK:
bool readonly
kPage *page = mem->get_mapping (c->data[1].l, &readonly)
unsigned t = CAPTYPE_PAGE | CAP_MASTER
@ -349,10 +350,10 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
t |= Kernel::Page::READONLY
reply_cap (t, (unsigned)page, &page->refs)
return
case Kernel::Memory::GET_LIMIT:
case Kernel::Memory::GET_LIMIT & REQUEST_MASK:
reply_num (mem->limit)
return
case Kernel::Memory::SET_LIMIT:
case Kernel::Memory::SET_LIMIT & REQUEST_MASK:
mem->limit = c->data[1].l
break
default:
@ -364,7 +365,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kThread *thread = (kThread *)protected_data.l
switch cmd:
case Kernel::Thread::GET_INFO:
case Kernel::Thread::GET_INFO & REQUEST_MASK:
switch c->data[0].h:
case Kernel::Thread::PC:
reply_num (thread->pc)
@ -378,7 +379,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
default:
reply_num (*kThread_arch_info (thread, c->data[0].h))
return
case Kernel::Thread::SET_INFO:
case Kernel::Thread::SET_INFO & REQUEST_MASK:
unsigned *value
switch c->data[1].l:
case Kernel::Thread::PC:
@ -411,7 +412,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
if value:
*value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h)
break
case Kernel::Thread::USE_SLOT:
case Kernel::Thread::USE_SLOT & REQUEST_MASK:
if c->data[1].l >= thread->slots || !c->arg.valid ():
dbg_send (5, 3)
dpanic (c->data[1].l, "no argument given for USE_SLOT")
@ -433,7 +434,14 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
if new_caps:
// TODO: link it into a list.
break
case Kernel::Thread::SCHEDULE:
case Kernel::Thread::GET_CAPS & REQUEST_MASK:
unsigned slot = c->data[1].l
if slot < thread->slots:
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->caps[slot], &thread->caps[slot]->refs, thread->slots)
else:
reply_num (thread->slots)
return
case Kernel::Thread::SCHEDULE & REQUEST_MASK:
do_schedule = true
return
default:
@ -442,19 +450,19 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
reply_num (Kernel::ERR_INVALID_OPERATION)
return
switch cmd:
case Kernel::Thread::PRIV_REGISTER_INTERRUPT:
case Kernel::Thread::PRIV_REGISTER_INTERRUPT & REQUEST_MASK:
arch_register_interrupt (c->data[1].l, c->arg.valid () && (((unsigned)c->arg->target) & ~REQUEST_MASK) == CAPTYPE_RECEIVER ? (kReceiver *)c->arg->protected_data.l : NULL)
break
case Kernel::Thread::PRIV_GET_TOP_MEMORY:
case Kernel::Thread::PRIV_GET_TOP_MEMORY & REQUEST_MASK:
reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)&top_memory, &top_memory.refs)
return
case Kernel::Thread::PRIV_MAKE_PRIV:
case Kernel::Thread::PRIV_MAKE_PRIV & REQUEST_MASK:
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_THREAD:
reply_num (~0)
return
((kThread *)c->arg->protected_data.l)->flags |= Kernel::Thread::PRIV
break
case Kernel::Thread::PRIV_ALLOC_RANGE:
case Kernel::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
panic (0x54365435, "non-memory argument to alloc_range")
reply_num (~0)
@ -472,7 +480,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
return
reply_num (data & ~0xc0000000)
return
case Kernel::Thread::PRIV_ALLOC_PHYSICAL:
case Kernel::Thread::PRIV_ALLOC_PHYSICAL & REQUEST_MASK:
if !c->arg.valid ():
panic (0x71342134, "no argument provided for alloc physical")
reply_num (~0)
@ -501,7 +509,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
page->flags |= Kernel::Page::PHYSICAL
kPage_arch_update_mapping (page)
break
case Kernel::Thread::PRIV_PHYSICAL_ADDRESS:
case Kernel::Thread::PRIV_PHYSICAL_ADDRESS & REQUEST_MASK:
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_PAGE:
dpanic (0x99049380, "invalid page for physical address")
reply_num (~0)
@ -509,11 +517,11 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
kPage *page = (kPage *)c->arg->protected_data.l
reply_num (page->frame & ~0xc0000000)
return
case Kernel::Thread::PRIV_PANIC:
case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
panic (c->data[1].l, "panic requested by thread")
reply_num (~0)
return
case Kernel::Thread::DBG_SEND:
case Kernel::Thread::DBG_SEND & REQUEST_MASK:
dbg_send (c->data[1].l, c->data[1].h)
break
default:
@ -551,7 +559,7 @@ static bool page_check_payment (kPage *page):
static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kPage *page = (kPage *)protected_data.l
switch cmd & ~Kernel::Page::READONLY:
case Kernel::Page::SHARE:
case Kernel::Page::SHARE & REQUEST_MASK:
if !c->arg.valid ():
// Cannot share without a target page.
reply_num (~0)
@ -626,7 +634,7 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
t->share_prev->share_next = t
kPage_arch_update_mapping (t)
break
case Kernel::Page::SET_FLAGS:
case Kernel::Page::SET_FLAGS & REQUEST_MASK:
if cmd & Kernel::Page::READONLY:
reply_num (~0)
return
@ -698,14 +706,14 @@ static void print_cap (kCapRef cap, kCapRef self):
static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kCaps *caps = (kCapsP)protected_data.l
switch cmd:
case Kernel::Caps::SET:
case Kernel::Caps::SET & REQUEST_MASK:
if c->data[1].l >= caps->size:
dpanic (0, "invalid index for set caps")
return
caps->clone (c->data[1].l, c->arg, c->copy[1])
reply_num (0)
return
case Kernel::Caps::PRINT:
case Kernel::Caps::PRINT & REQUEST_MASK:
if c->data[1].l >= caps->size:
dpanic (0, "invalid caps for print")
return
@ -802,7 +810,8 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
cmd = c->data[0].l
c->data[0].l = 0
else:
cmd = target & REQUEST_MASK
cmd = target
cmd &= REQUEST_MASK
switch target & CAPTYPE_MASK:
case CAPTYPE_RECEIVER:
receiver_invoke (cmd, target, protected_data, c)

View File

@ -252,7 +252,7 @@ namespace Kernel:
Receiver (Cap c = Cap ()) : Cap (c):
enum request:
// Operations
SET_OWNER = 1
SET_OWNER = CAPTYPE_RECEIVER + 1
CREATE_CAPABILITY
CREATE_CALL_CAPABILITY
CREATE_ASYNC_CALL_CAPABILITY
@ -295,9 +295,10 @@ namespace Kernel:
Thread (Cap c = Cap ()) : Cap (c):
enum request:
// Info details are arch-specific.
GET_INFO = 1
GET_INFO = CAPTYPE_THREAD + 1
SET_INFO
USE_SLOT
GET_CAPS
SCHEDULE
PRIV_ALLOC_RANGE
PRIV_PHYSICAL_ADDRESS
@ -342,13 +343,16 @@ namespace Kernel:
void wait (bool wait):
set_flags (wait ? WAITING : 0, WAITING)
inline unsigned use (Caps caps, unsigned slot = alloc_slot ())
inline Caps get_caps (unsigned slot)
unsigned get_num_caps ():
return call (CAP_MASTER_DIRECT | GET_CAPS, ~0).l
struct Caps : public Cap:
Caps (unsigned slot, unsigned idx) : Cap (slot, idx):
Caps (Cap c = Cap ()) : Cap (c):
enum request:
// Not an operation; this capability can be used in Thread::USE_SLOT.
USE = 1
USE = CAPTYPE_CAPS + 1
SET
PRINT
unsigned use (unsigned slot = alloc_slot ()):
@ -358,6 +362,10 @@ namespace Kernel:
void print (unsigned idx):
invoke (CAP_MASTER_DIRECT | PRINT, idx)
Caps Thread::get_caps (unsigned slot):
call (CAP_MASTER_DIRECT | GET_CAPS, slot)
return get_arg ()
unsigned Thread::use (Caps caps, unsigned slot):
ocall (caps, CAP_MASTER_DIRECT | USE_SLOT, slot)
return slot
@ -366,7 +374,7 @@ namespace Kernel:
Page (unsigned slot, unsigned idx) : Cap (slot, idx):
Page (Cap c = Cap ()) : Cap (c):
enum request:
SHARE = 1
SHARE = CAPTYPE_PAGE + 1
GET_FLAGS
SET_FLAGS
// Not an operation; a capability with this bit cannot write to the page.
@ -407,7 +415,7 @@ namespace Kernel:
Memory (unsigned slot, unsigned idx) : Cap (slot, idx):
Memory (Cap c = Cap ()) : Cap (c):
enum request:
CREATE = 1
CREATE = CAPTYPE_MEMORY + 1
DESTROY
LIST
MAP

View File

@ -34,7 +34,7 @@ uimage:
mips/entry.o: $(boot_threads)
mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I.
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh boot-programs/init.hh
lcd: boot-programs/charset.data
boot-programs/charset.data: boot-programs/charset

View File

@ -221,9 +221,6 @@ kThread *exception ():
if !dbg_cap.valid ():
dpanic (0, "no log capability provided")
break
dbg_log ("debug capability registered. thread = ")
dbg_log_num ((unsigned)current)
dbg_log_char ('\n')
break
if dbg_cap.valid ():
dbg_log_char (current->arch.a[1])