mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 19:44:16 +02:00
things are working
This commit is contained in:
parent
b7d9b1554c
commit
df38266bb8
137
alloc.ccp
137
alloc.ccp
@ -18,6 +18,13 @@
|
||||
|
||||
#include "kernel.hh"
|
||||
|
||||
// Memory model used for kernel structure storage
|
||||
// Each Memory object has several pointers, one for each type of objects it contains. These pointers are the start of double-linked lists.
|
||||
// Each object also has a NEXT and PREV pointer, which point to the next and previous object in the same page. These pointers are 0 for the first (or last) object in a page. There is no pointer to the first object, it always starts at page_base + SIZE.
|
||||
// The PREV/NEXT-list contains all objects in the page, including Free objects, in the order they appear in the page.
|
||||
// The prev/next-lists contain only objects of one type, unsorted.
|
||||
// All pointers are to the start of the object. There is a header of size SIZE before it, containing NEXT and PREV.
|
||||
|
||||
#define PREV(x) (((Object_base **)(x))[-2])
|
||||
#define NEXT(x) (((Object_base **)(x))[-1])
|
||||
#define SIZE (2 * sizeof (Object_base *))
|
||||
@ -37,75 +44,116 @@ void Memory::unuse (unsigned num):
|
||||
for Memory *m = this; m; m = m->address_space:
|
||||
m->used -= num
|
||||
|
||||
// This allocates a new block of memory for use by the kernel.
|
||||
// size is the requires size of the block (excluding SIZE)
|
||||
// first is a pointer to the first object pointer of this type.
|
||||
// The result is a block of size at least size, which is linked as an object in the list of first.
|
||||
void *Memory::search_free (unsigned size, void **first):
|
||||
Free *f
|
||||
unsigned s = 0
|
||||
// Let's see if there already is a Free chunk which is large enough.
|
||||
for f = frees; f; f = f->next:
|
||||
if NEXT (f):
|
||||
s = (unsigned)NEXT (f) - (unsigned)f
|
||||
else:
|
||||
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK) + SIZE
|
||||
// s is now the size of the current free block, including SIZE.
|
||||
// The requirement is to fit a block of size, plus its SIZE header.
|
||||
if s >= size + SIZE:
|
||||
break
|
||||
if !f:
|
||||
// No chunk was found; allocate a new page and add a chunk in it. It is always large enough.
|
||||
unsigned p = palloc ()
|
||||
if !p:
|
||||
assert (false)
|
||||
dbg_log ("no free space: kernel allocation failed")
|
||||
return NULL
|
||||
f = (Free *)(p + SIZE)
|
||||
// Mark it as a Free object.
|
||||
f->marker = ~0
|
||||
// Link it in the Free list.
|
||||
f->next = frees
|
||||
f->prev = NULL
|
||||
frees = f
|
||||
if f->next:
|
||||
f->next->prev = f
|
||||
// There are no other objects in this page.
|
||||
NEXT (f) = NULL
|
||||
PREV (f) = NULL
|
||||
// The size of this block is the entire page.
|
||||
s = PAGE_SIZE
|
||||
// We have a free block, possibly too large.
|
||||
// We have a free block, possibly too large. The block is linked in frees, and in the page.
|
||||
if s >= size + sizeof (Free) + 2 * SIZE:
|
||||
// Create the new object at the end and keep the Free.
|
||||
Free *obj = (Free *)((unsigned)f + s - size - SIZE)
|
||||
// f is the start of the free block
|
||||
// f + (s - SIZE) is the end of the free block, compensated for the header of the next block.
|
||||
// f + (s - SIZE) - size is the address where the new block should start.
|
||||
Free *obj = (Free *)((unsigned)f + (s - SIZE) - size)
|
||||
// Link the new object in the page.
|
||||
NEXT (obj) = NEXT (f)
|
||||
if NEXT (obj):
|
||||
PREV (NEXT (obj)) = obj
|
||||
PREV (obj) = f
|
||||
NEXT (f) = obj
|
||||
// Set f to the new object, because it is used by that name later.
|
||||
f = obj
|
||||
else:
|
||||
// The block was only just large enough: turn it into a new type. It is already linked into the page.
|
||||
// Unlink it from the free list.
|
||||
if f->prev:
|
||||
f->prev->next = f->next
|
||||
else:
|
||||
frees = f->next
|
||||
if f->next:
|
||||
f->next->prev = f->prev
|
||||
f->address_space = this
|
||||
f->refs = NULL
|
||||
// f is now a block which is linked in the page, but not in any list. Link it into first.
|
||||
f->next = (Free *)*first
|
||||
f->prev = NULL
|
||||
if f->next:
|
||||
f->next->prev = f
|
||||
*first = f
|
||||
// Set common initial values.
|
||||
f->address_space = this
|
||||
f->refs = NULL
|
||||
return f
|
||||
|
||||
void Memory::free_obj (Object_base *obj):
|
||||
Free *self
|
||||
// Merge with previous, if it exists and is a Free.
|
||||
if PREV (obj) && PREV (obj)->is_free ():
|
||||
self = (Free *)PREV (obj)
|
||||
NEXT (self) = NEXT (obj)
|
||||
if NEXT (obj):
|
||||
PREV (NEXT (obj)) = self
|
||||
// Free an object; it is still in its list, and it is still in the page list.
|
||||
void Memory::free_obj (Object_base *obj, void **first):
|
||||
Free *self = (Free *)obj
|
||||
// Free it from its list.
|
||||
if self->prev:
|
||||
self->prev->next = self->next
|
||||
else:
|
||||
self = (Free *)obj
|
||||
*(Object_base **)first = self->next
|
||||
if self->next:
|
||||
self->next->prev = self->prev
|
||||
// Merge with previous, if it exists and is a Free.
|
||||
if PREV (self) && PREV (self)->is_free ():
|
||||
self = (Free *)PREV (self)
|
||||
// Remove the object from the page list.
|
||||
NEXT (self) = NEXT (obj)
|
||||
if NEXT (self):
|
||||
PREV (NEXT (self)) = self
|
||||
else:
|
||||
// The previous object is not a Free, so create a new one.
|
||||
// It is already linked in the page, but needs to be linked into the free list.
|
||||
self->next = frees
|
||||
self->prev = NULL
|
||||
if self->next:
|
||||
self->next->prev = self
|
||||
frees = self
|
||||
// Mark it as a Free.
|
||||
self->marker = ~0
|
||||
// Merge with next, if it exists and is a Free.
|
||||
if NEXT (self) && NEXT (self)->is_free ():
|
||||
// Unlink the next from the frees list.
|
||||
Free *n = (Free *)NEXT (self)
|
||||
if n->prev:
|
||||
n->prev->next = n->next
|
||||
else:
|
||||
frees = n->next
|
||||
if n->next:
|
||||
n->next->prev = n->prev
|
||||
// Unlink the next from the page list.
|
||||
NEXT (self) = NEXT (NEXT (self))
|
||||
if NEXT (self):
|
||||
PREV (NEXT (self)) = self
|
||||
@ -139,6 +187,7 @@ Thread *Memory::alloc_thread ():
|
||||
ret->schedule_prev = NULL
|
||||
ret->schedule_next = NULL
|
||||
ret->receivers = NULL
|
||||
top_memory.alloc_capability (NULL, NULL, NULL, 0, &ret->exception)
|
||||
return ret
|
||||
|
||||
Message *Memory::alloc_message (Receiver *target):
|
||||
@ -222,48 +271,26 @@ Memory *Memory::alloc_memory ():
|
||||
return ret
|
||||
|
||||
void Memory::free_page (Page *page):
|
||||
if page->prev:
|
||||
page->prev->next = page->next
|
||||
else:
|
||||
pages = page->next
|
||||
if page->next:
|
||||
page->next->prev = page->prev
|
||||
unuse ()
|
||||
if page->data.flags & PAGE_FLAG_PAYING:
|
||||
unuse ()
|
||||
if page->data.frame:
|
||||
pfree (page->data.frame)
|
||||
free_obj (page)
|
||||
free_obj (page, (void **)&pages)
|
||||
|
||||
void Memory::free_thread (Thread *thread):
|
||||
if thread->prev:
|
||||
thread->prev->next = thread->next
|
||||
else:
|
||||
threads = thread->next
|
||||
if thread->next:
|
||||
thread->next->prev = thread->prev
|
||||
// Unschedule.
|
||||
if thread->schedule_prev:
|
||||
thread->schedule_prev->schedule_next = thread->schedule_next
|
||||
else if first_scheduled == thread:
|
||||
first_scheduled = thread->schedule_next
|
||||
if thread->schedule_next:
|
||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
||||
thread->unrun ()
|
||||
while thread->receivers:
|
||||
thread->receivers->orphan ()
|
||||
free_obj (thread)
|
||||
thread->exception.invalidate ()
|
||||
free_obj (thread, (void **)&threads)
|
||||
|
||||
void Memory::free_message (Receiver *owner, Message *message):
|
||||
if message->prev:
|
||||
message->prev->next = message->next
|
||||
else:
|
||||
owner->messages = message->next
|
||||
if message->next:
|
||||
message->next->prev = message->prev
|
||||
else:
|
||||
if !message->next:
|
||||
owner->last_message = message->prev
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
if message->capabilities[i]:
|
||||
free_capability (message->capabilities[i])
|
||||
free_obj (message)
|
||||
free_obj (message, (void **)&owner->messages)
|
||||
|
||||
void Memory::free_receiver (Receiver *receiver):
|
||||
receiver->orphan ()
|
||||
@ -271,7 +298,7 @@ void Memory::free_receiver (Receiver *receiver):
|
||||
receiver->capabilities->invalidate ()
|
||||
while receiver->messages:
|
||||
free_message (receiver, receiver->messages)
|
||||
free_obj (receiver)
|
||||
free_obj (receiver, (void **)&receivers)
|
||||
|
||||
void Receiver::orphan ():
|
||||
if prev_owned:
|
||||
@ -293,7 +320,7 @@ void Receiver::own (Thread *o):
|
||||
|
||||
void Memory::free_capability (Capability *capability):
|
||||
capability->invalidate ()
|
||||
free_obj (capability)
|
||||
free_obj (capability, (void **)&capabilities)
|
||||
|
||||
void Capability::invalidate ():
|
||||
if !target:
|
||||
@ -328,23 +355,25 @@ void Memory::free_cappage (Cappage *p):
|
||||
for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
|
||||
((Capability *)p->data.frame)[i].invalidate ()
|
||||
zfree (p->data.frame)
|
||||
free_obj (p)
|
||||
free_obj (p, (void **)&cappages)
|
||||
|
||||
void Memory::free_memory (Memory *mem):
|
||||
if mem->prev:
|
||||
mem->prev->next = mem->next
|
||||
else:
|
||||
memories = mem->next
|
||||
if mem->next:
|
||||
mem->next->prev = mem->prev
|
||||
while mem->pages:
|
||||
free_page (mem->pages)
|
||||
while mem->cappages:
|
||||
free_cappage (mem->cappages)
|
||||
while mem->threads:
|
||||
free_thread (mem->threads)
|
||||
while mem->memories:
|
||||
free_memory (mem->memories)
|
||||
while mem->receivers:
|
||||
free_receiver (mem->receivers)
|
||||
while mem->capabilities:
|
||||
free_capability (mem->capabilities)
|
||||
Memory_arch_free (mem)
|
||||
free_obj (mem)
|
||||
if mem->frees:
|
||||
panic (0, "kernel memory leak: memory still in use")
|
||||
free_obj (mem, (void **)&memories)
|
||||
|
||||
void Page::forget ():
|
||||
if data.share_prev || data.share_next:
|
||||
|
@ -20,6 +20,9 @@
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
// Interval between polls for keyboard (when keys are pressed) and battery/power (always) events
|
||||
#define ALARM_INTERVAL (HZ / 10)
|
||||
|
||||
// GPIO pins for the devices (port.pin)
|
||||
|
||||
// keyboard
|
||||
@ -111,14 +114,15 @@ class Keyboard:
|
||||
|
||||
for unsigned i = 0; i < NUM_COLS; ++i:
|
||||
keys[i] = 0xff
|
||||
scan ()
|
||||
void scan ():
|
||||
// Set all columns to 0 when the become output.
|
||||
// Set all columns to 0 when they become output.
|
||||
GPIO_GPDR (3) &= ~COL_MASK
|
||||
bool key_pressed = false
|
||||
scanning = false
|
||||
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
|
||||
for unsigned col = 0; col < NUM_COLS; ++col:
|
||||
GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col])
|
||||
udelay (100)
|
||||
//udelay (100)
|
||||
unsigned data = GPIO_GPDR (0) & ROW_MASK
|
||||
// Generate events.
|
||||
for unsigned row = 0; row < 8; ++row:
|
||||
@ -129,45 +133,46 @@ class Keyboard:
|
||||
event (KEYBOARD_EVENT, code)
|
||||
keys[col] = data
|
||||
if data != ROW_MASK:
|
||||
key_pressed = true
|
||||
if key_pressed:
|
||||
scanning = true
|
||||
scanning = true
|
||||
scanning = true
|
||||
if scanning:
|
||||
GPIO_GPDIR (3) &= ~COL_MASK
|
||||
else:
|
||||
GPIO_GPDIR (3) |= COL_MASK
|
||||
|
||||
class Touchpad:
|
||||
unsigned old_state
|
||||
public:
|
||||
enum buttons:
|
||||
LEFT = 1 << 16
|
||||
RIGHT = 1 << 13
|
||||
void check_events ():
|
||||
unsigned state = GPIO_GPDR (0)
|
||||
if (state ^ old_state) & LEFT:
|
||||
if state & LEFT:
|
||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0))
|
||||
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
|
||||
if state & (1 << GPIO_TP_LEFT):
|
||||
gpio_irq_fall (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
event (TOUCHPAD_EVENT, 0)
|
||||
else:
|
||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_RAISEDG << (2 * 0))
|
||||
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
event (TOUCHPAD_EVENT, 0x10000)
|
||||
if (state ^ old_state) & RIGHT:
|
||||
if state & RIGHT:
|
||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
|
||||
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
|
||||
if state & (1 << GPIO_TP_RIGHT):
|
||||
gpio_irq_fall (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
event (TOUCHPAD_EVENT, 1)
|
||||
else:
|
||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_RAISEDG << (2 * 13))
|
||||
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
event (TOUCHPAD_EVENT, 0x10001)
|
||||
old_state = state
|
||||
Touchpad ():
|
||||
// Set pins to input with pull-ups.
|
||||
GPIO_GPDIR (0) &= ~(LEFT | RIGHT)
|
||||
GPIO_GPPUR (0) |= LEFT | RIGHT
|
||||
// Enable interrupts.
|
||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0))
|
||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
|
||||
gpio_as_input (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
gpio_as_input (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
GPIO_GPPUR (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
|
||||
// Set up interrupts.
|
||||
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
old_state = 0
|
||||
// See if they are already pressed. If so, the interrupt detection is changed.
|
||||
check_events ()
|
||||
// Now enable the interrupts.
|
||||
GPIO_GPIER (0) |= LEFT | RIGHT
|
||||
GPIO_GPIER (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
|
||||
|
||||
class Lockleds:
|
||||
// Note that num lock is in port 2. The others are in port 0.
|
||||
@ -176,23 +181,25 @@ class Lockleds:
|
||||
enum { SCROLL = 1 << 9 }
|
||||
public:
|
||||
Lockleds ():
|
||||
GPIO_GPDR (2) &= ~NUM
|
||||
GPIO_GPDR (0) &= ~(SCROLL | CAPS)
|
||||
GPIO_GPDIR (2) |= NUM
|
||||
GPIO_GPDIR (0) |= CAPS | SCROLL
|
||||
gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
|
||||
gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS)
|
||||
gpio_as_output (GPIO_SCROLL_PORT, GPIO_SCROLL)
|
||||
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
|
||||
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
|
||||
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
|
||||
void set (unsigned state):
|
||||
if state & 4:
|
||||
GPIO_GPDR (2) &= ~NUM
|
||||
GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
|
||||
else:
|
||||
GPIO_GPDR (2) |= NUM
|
||||
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
|
||||
if state & 2:
|
||||
GPIO_GPDR (0) &= ~CAPS
|
||||
GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
|
||||
else:
|
||||
GPIO_GPDR (0) |= CAPS
|
||||
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
|
||||
if state & 1:
|
||||
GPIO_GPDR (0) &= ~SCROLL
|
||||
GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
|
||||
else:
|
||||
GPIO_GPDR (0) |= SCROLL
|
||||
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
|
||||
|
||||
class Power:
|
||||
// Power out is in port 2, the rest in port 3.
|
||||
@ -207,14 +214,14 @@ class Power:
|
||||
GPIO_GPIER (0) &= ~0xff
|
||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||
GPIO_GPPUR (3) &= ~(PWR_IN | BATTERY)
|
||||
udelay (100)
|
||||
//udelay (100)
|
||||
unsigned state = GPIO_GPDR (3)
|
||||
if (state ^ old_state) & PWR_IN:
|
||||
event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000)
|
||||
if (state ^ old_state) & BATTERY:
|
||||
if !(state & BATTERY):
|
||||
GPIO_GPPUR (3) |= BATTERY
|
||||
udelay (100)
|
||||
//udelay (100)
|
||||
if GPIO_GPDR (3) & BATTERY:
|
||||
if !was_present:
|
||||
event (BATTERY_EVENT, BATTERY_CHARGED)
|
||||
@ -228,7 +235,7 @@ class Power:
|
||||
old_state = state
|
||||
GPIO_GPPUR (3) &= ~BATTERY
|
||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||
udelay (100)
|
||||
//udelay (100)
|
||||
GPIO_GPIER (3) |= 0xff
|
||||
Power ():
|
||||
GPIO_GPDR (2) |= PWR_OUT
|
||||
@ -237,10 +244,16 @@ class Power:
|
||||
old_state = BATTERY
|
||||
poll ()
|
||||
void poweroff ():
|
||||
GPIO_GPDR (2) &= ~PWR_OUT
|
||||
GPIO_GPDIR (2) |= PWR_OUT
|
||||
gpio_as_gpio (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||
gpio_as_output (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||
GPIO_GPDR (GPIO_PW_O) &= ~(1 << GPIO_PW_O)
|
||||
while true:
|
||||
// Do nothing; wait until the device stops running.
|
||||
void reboot ():
|
||||
wdt_set_count (0xffffffff - 32)
|
||||
wdt_start ()
|
||||
while true:
|
||||
// Do nothing; wait until the device reboots.
|
||||
|
||||
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
|
||||
class Pwm:
|
||||
@ -263,14 +276,14 @@ class Pwm:
|
||||
|
||||
int main ():
|
||||
schedule ()
|
||||
*(unsigned *)~3 = 0
|
||||
|
||||
map_gpio ()
|
||||
map_pwm0 ()
|
||||
map_wdt ()
|
||||
|
||||
Keyboard kbd
|
||||
Touchpad tp
|
||||
//Lockleds leds
|
||||
Lockleds leds
|
||||
Power power
|
||||
Pwm pwm
|
||||
|
||||
@ -287,7 +300,7 @@ int main ():
|
||||
invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0)
|
||||
invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1)
|
||||
|
||||
receiver_set_alarm (__my_receiver, HZ / 5)
|
||||
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||
while true:
|
||||
Message msg
|
||||
wait (&msg)
|
||||
@ -296,17 +309,20 @@ int main ():
|
||||
// Alarm.
|
||||
if kbd.is_scanning ():
|
||||
kbd.scan ()
|
||||
power.poll ()
|
||||
receiver_set_alarm (__my_receiver, HZ / 5)
|
||||
//power.poll ()
|
||||
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||
break
|
||||
case IRQ_GPIO0:
|
||||
kdebug ("gpio interrupt")
|
||||
unsigned irq = GPIO_GPFR (0)
|
||||
// Ack all. This works because they are all edge triggered.
|
||||
GPIO_GPFR (0) = irq
|
||||
if irq & 0xff:
|
||||
kbd.scan ()
|
||||
if irq & (Touchpad::LEFT | Touchpad::RIGHT):
|
||||
if irq & ((1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)):
|
||||
tp.check_events ()
|
||||
register_interrupt (IRQ_GPIO0)
|
||||
break
|
||||
case CAP_KEYBOARD:
|
||||
set_cb (KEYBOARD_EVENT, msg.cap[0])
|
||||
break
|
||||
@ -314,7 +330,10 @@ int main ():
|
||||
set_cb (TOUCHPAD_EVENT, msg.cap[0])
|
||||
break
|
||||
case CAP_POWEROFF:
|
||||
power.poweroff ()
|
||||
if msg.data[0]:
|
||||
power.poweroff ()
|
||||
else:
|
||||
power.reboot ()
|
||||
break
|
||||
case CAP_POWERBUTTON:
|
||||
set_cb (POWERBUTTON_EVENT, msg.cap[0])
|
||||
@ -323,7 +342,7 @@ int main ():
|
||||
set_cb (BATTERY_EVENT, msg.cap[0])
|
||||
break
|
||||
case CAP_LOCKLEDS:
|
||||
//leds.set (msg.data[0])
|
||||
leds.set (msg.data[0])
|
||||
break
|
||||
case CAP_PWM:
|
||||
pwm.set_backlight (msg.data[0])
|
||||
|
@ -76,14 +76,18 @@ int main ():
|
||||
wait (&msg)
|
||||
switch msg.protected_data:
|
||||
case KBD:
|
||||
kdebug ("keyboard event")
|
||||
kdebug ("keyboard event: ")
|
||||
kdebug_num (msg.data[0])
|
||||
kdebug_char ('\n')
|
||||
break
|
||||
case TP:
|
||||
kdebug ("touchpad event")
|
||||
if msg.data[0] == 0:
|
||||
// Press left button.
|
||||
invoke_00 (poweroff)
|
||||
break
|
||||
case POWERBUTTON:
|
||||
kdebug ("powerbutton event")
|
||||
kdebug ("powerbutton event\n")
|
||||
break
|
||||
case BATTERY:
|
||||
kdebug ("battery event")
|
||||
kdebug ("battery event\n")
|
||||
break
|
||||
|
68
invoke.ccp
68
invoke.ccp
@ -18,6 +18,31 @@
|
||||
|
||||
#include "kernel.hh"
|
||||
|
||||
void Thread::raise (unsigned code, unsigned data):
|
||||
dbg_log ("raise ")
|
||||
dbg_log_num ((unsigned)current)
|
||||
dbg_log_char ('/')
|
||||
if code < NUM_EXCEPTION_CODES:
|
||||
dbg_log (exception_name[code])
|
||||
else:
|
||||
dbg_log ("invalid code:")
|
||||
dbg_log_num (code)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (data)
|
||||
dbg_log_char ('\n')
|
||||
unrun ()
|
||||
if !exception.target:
|
||||
return
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
c.data[0] = code
|
||||
c.data[1] = data
|
||||
c.data[2] = 0
|
||||
c.data[3] = 0
|
||||
exception.invoke (&c)
|
||||
|
||||
// From user-provided, thus untrusted, data, find a capability.
|
||||
Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
*copy = code & 2 ? true : false
|
||||
@ -27,7 +52,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
// Cappage capability
|
||||
unsigned num = (code & ~PAGE_MASK) >> 2
|
||||
if num >= CAPPAGE_SIZE:
|
||||
panic (0x15544551, "invalid cappage index")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log (": invalid cappage index ")
|
||||
dbg_log_num (num)
|
||||
dbg_log_char ('\n')
|
||||
return NULL
|
||||
unsigned page = code & PAGE_MASK
|
||||
for Cappage *p = cappages; p; p = p->next:
|
||||
@ -39,8 +67,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
for Capability *c = capabilities; c; c = c->next:
|
||||
if c == target:
|
||||
return c
|
||||
dbg_send (code)
|
||||
panic (0xfffeee00, "invalid capability")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log (": invalid capability ")
|
||||
dbg_log_num (code)
|
||||
dbg_log_char ('\n')
|
||||
return NULL
|
||||
|
||||
// Try to deliver a message.
|
||||
@ -56,7 +86,6 @@ bool Receiver::try_deliver ():
|
||||
protected_only = false
|
||||
break
|
||||
if !m:
|
||||
//panic (0x32547688, "protected only")
|
||||
return false
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
@ -64,7 +93,7 @@ bool Receiver::try_deliver ():
|
||||
if m->capabilities[i]:
|
||||
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||
if !c.cap[i]:
|
||||
panic (0xffaaaaaa, "out of memory")
|
||||
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c.cap[i])
|
||||
return false
|
||||
@ -85,24 +114,22 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||
orig[i] = c->cap[i]
|
||||
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
||||
if !c->cap[i]:
|
||||
panic (0xdddddddd, "out of memory")
|
||||
return false
|
||||
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c->cap[j])
|
||||
c->cap[j] = orig[j]
|
||||
c->cap[i] = orig[i]
|
||||
tried_direct = true
|
||||
break
|
||||
if !tried_direct:
|
||||
if protected_data == reply_protected_data:
|
||||
protected_only = false
|
||||
Thread_arch_receive (owner, protected_data, c)
|
||||
owner->unwait ()
|
||||
return true
|
||||
return false
|
||||
if protected_data == reply_protected_data:
|
||||
protected_only = false
|
||||
Thread_arch_receive (owner, protected_data, c)
|
||||
owner->unwait ()
|
||||
return true
|
||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||
Message *msg = address_space->alloc_message (this)
|
||||
if !msg:
|
||||
panic (0xbbbbbbbb, "out of memory")
|
||||
if owner:
|
||||
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||
return false
|
||||
msg->protected_data = protected_data
|
||||
if protected_data == reply_protected_data:
|
||||
@ -122,7 +149,8 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||
else:
|
||||
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
||||
if !msg->capabilities[i]:
|
||||
panic (0xcccccccc, "out of memory")
|
||||
if owner:
|
||||
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
address_space->free_capability (msg->capabilities[j])
|
||||
address_space->free_message (this, msg)
|
||||
@ -768,8 +796,10 @@ static void kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
return
|
||||
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
||||
// You are not allowed to perform this operation.
|
||||
dbg_send (1, 2)
|
||||
dbg_send (c->data[0])
|
||||
dbg_log ("operation not allowed: ")
|
||||
dbg_log_num (c->data[0])
|
||||
dbg_log ("; target = ")
|
||||
dbg_log_num (target)
|
||||
return
|
||||
reply = c->cap[0]
|
||||
if c->data[0] == CAP_DEGRADE:
|
||||
|
45
iris.h
45
iris.h
@ -36,6 +36,41 @@ extern "C" {
|
||||
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
|
||||
enum Exception_code {
|
||||
ERR_WRITE_DENIED,
|
||||
ERR_UNMAPPED_READ,
|
||||
ERR_UNMAPPED_WRITE,
|
||||
ERR_INVALID_ADDRESS_READ,
|
||||
ERR_INVALID_ADDRESS_WRITE,
|
||||
ERR_RESERVED_INSTRUCTION,
|
||||
ERR_COPROCESSOR_UNUSABLE,
|
||||
ERR_OVERFLOW,
|
||||
ERR_TRAP,
|
||||
ERR_WATCHPOINT,
|
||||
ERR_NO_PAGE_DIRECTORY,
|
||||
ERR_NO_PAGE_TABLE,
|
||||
ERR_OUT_OF_MEMORY,
|
||||
NUM_EXCEPTION_CODES
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
static const char *exception_name[NUM_EXCEPTION_CODES] = {
|
||||
"write denied",
|
||||
"unmapped read",
|
||||
"unmapped write",
|
||||
"invalid address read",
|
||||
"invalid address write",
|
||||
"reserved instruction",
|
||||
"coprocessor unusable",
|
||||
"overflow",
|
||||
"trap",
|
||||
"watchpoint",
|
||||
"no page directory",
|
||||
"no page table",
|
||||
"out of memory"
|
||||
};
|
||||
#endif
|
||||
|
||||
#define KERNEL_MASK 0xfff
|
||||
#define CAPTYPE_MASK 0xe00
|
||||
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
||||
@ -801,7 +836,15 @@ static void cappage_set (Capability page, Capability cap, unsigned index)
|
||||
|
||||
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
|
||||
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
|
||||
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); kdebug_char ('\n'); } while (0)
|
||||
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); } while (0)
|
||||
|
||||
static void kdebug_num (unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
const char *encode = "0123456789abcdef";
|
||||
for (i = 0; i < 8; ++i)
|
||||
kdebug_char (encode[(n >> (4 * (7 - i))) & 0xf]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
40
kernel.hhp
40
kernel.hhp
@ -60,21 +60,6 @@ bool Object_base::is_free ():
|
||||
// Include architecture-specific parts.
|
||||
#include "arch.hh"
|
||||
|
||||
struct Thread : public Object <Thread>:
|
||||
Receiver *receivers
|
||||
unsigned pc, sp
|
||||
Thread_arch arch
|
||||
unsigned flags
|
||||
Thread *schedule_prev, *schedule_next
|
||||
Thread *exception
|
||||
void raise (unsigned code)
|
||||
void run ()
|
||||
void unrun ()
|
||||
void wait ()
|
||||
void unwait ()
|
||||
bool is_waiting ():
|
||||
return flags & THREAD_FLAG_WAITING
|
||||
|
||||
struct Message : public Object <Message>:
|
||||
Capability *capabilities[4]
|
||||
unsigned data[4]
|
||||
@ -93,6 +78,22 @@ struct Capability : public Object <Capability>:
|
||||
void invoke (Context *c)
|
||||
void invalidate ()
|
||||
|
||||
struct Thread : public Object <Thread>:
|
||||
Receiver *receivers
|
||||
unsigned pc, sp
|
||||
Thread_arch arch
|
||||
unsigned flags
|
||||
Thread *schedule_prev, *schedule_next
|
||||
// This is not a pointer, but a real Capability. That means that at capability destroy, no check is needed if it is used for an exception handler.
|
||||
Capability exception
|
||||
void raise (unsigned code, unsigned data)
|
||||
void run ()
|
||||
void unrun ()
|
||||
void wait ()
|
||||
void unwait ()
|
||||
bool is_waiting ():
|
||||
return flags & THREAD_FLAG_WAITING
|
||||
|
||||
struct Receiver : public Object <Receiver>:
|
||||
Thread *owner
|
||||
Receiver *prev_owned, *next_owned
|
||||
@ -167,20 +168,21 @@ struct Memory : public Object <Memory>:
|
||||
void free_cappage (Cappage *page)
|
||||
void free_memory (Memory *mem)
|
||||
|
||||
void free_obj (Object_base *obj)
|
||||
void free_obj (Object_base *obj, void **first)
|
||||
|
||||
Capability *find_capability (unsigned code, bool *copy)
|
||||
|
||||
// Functions which can be called from assembly must not be mangled.
|
||||
extern "C":
|
||||
// Panic. n is sent over caps led. message is currently ignored.
|
||||
void panic (unsigned n, char const *message = "")
|
||||
// Debug: send a message to the user.
|
||||
void dbg_send (unsigned code, unsigned bits = 32)
|
||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
|
||||
EXTERN unsigned dbg_code
|
||||
EXTERN Capability *dbg_cap
|
||||
void dbg_log_char (unsigned ch)
|
||||
void dbg_log (char const *str)
|
||||
void dbg_log_num (unsigned num)
|
||||
|
||||
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m))
|
||||
|
||||
/// Defined in schedule.ccp
|
||||
void schedule ()
|
||||
|
@ -19,7 +19,7 @@ unsigned init_memory (unsigned mem):
|
||||
|
||||
unsigned phys_alloc (unsigned num):
|
||||
if free_begin + num * PAGE_SIZE > free_end:
|
||||
panic (0xaaaaaaaa, "out of memory")
|
||||
dbg_log ("memory allocation failed\n")
|
||||
return 0
|
||||
unsigned ret = free_begin
|
||||
free_begin += num * PAGE_SIZE
|
||||
@ -54,7 +54,7 @@ unsigned phys_alloc (unsigned num):
|
||||
choice = p
|
||||
if !choice:
|
||||
// TODO: reorganizing may work to allow allocation.
|
||||
panic (0x01100223, "out of large enough memory")
|
||||
dbg_log ("range memory allocation failed")
|
||||
return 0
|
||||
if choice->num == num:
|
||||
if choice->prev:
|
||||
@ -132,7 +132,7 @@ void raw_pfree (unsigned page):
|
||||
|
||||
unsigned Memory::zalloc ():
|
||||
if !use ():
|
||||
panic (0x4536928, "no memory due to limit")
|
||||
dbg_log ("limit reached: allocation not allowed")
|
||||
return NULL
|
||||
return raw_zalloc ()
|
||||
|
||||
|
@ -157,16 +157,10 @@ static arch_page *alloc_page (Memory *mem, arch_page_table *t):
|
||||
|
||||
static void free_page_table (arch_page_table *t, unsigned idx):
|
||||
Memory *mem = t->address_space
|
||||
if t->next:
|
||||
t->next->prev = t->prev
|
||||
if t->prev:
|
||||
t->prev->next = t->next
|
||||
else:
|
||||
mem->arch.first_page_table = t->next
|
||||
mem->zfree ((unsigned)mem->arch.directory[idx])
|
||||
mem->arch.directory[idx] = NULL
|
||||
mem->arch.shadow[idx] = NULL
|
||||
mem->free_obj (t)
|
||||
mem->free_obj (t, (void **)&mem->arch.first_page_table)
|
||||
if !mem->arch.first_page_table:
|
||||
mem->zfree ((unsigned)mem->arch.directory)
|
||||
mem->zfree ((unsigned)mem->arch.shadow)
|
||||
@ -186,12 +180,6 @@ static void tlb_reset (unsigned address, unsigned asid, unsigned value):
|
||||
__asm__ volatile ("tlbwi")
|
||||
|
||||
static void free_page (arch_page_table *t, arch_page *p):
|
||||
if p->next:
|
||||
p->next->prev = p->prev
|
||||
if p->prev:
|
||||
p->prev->next = p->next
|
||||
else:
|
||||
t->first_page = p->next
|
||||
if p->prev_mapped:
|
||||
p->prev_mapped->next_mapped = p->next_mapped
|
||||
else:
|
||||
@ -200,7 +188,7 @@ static void free_page (arch_page_table *t, arch_page *p):
|
||||
p->next_mapped->prev_mapped = p->prev_mapped
|
||||
tlb_reset (p->mapping, p->address_space->arch.asid, 0)
|
||||
unsigned idx = p->mapping >> 21
|
||||
p->address_space->free_obj (p)
|
||||
p->address_space->free_obj (p, (void **)&t->first_page)
|
||||
if !t->first_page:
|
||||
free_page_table (t, idx)
|
||||
|
||||
|
@ -274,6 +274,12 @@ void init (unsigned mem):
|
||||
gpio_as_ssi()
|
||||
gpio_as_msc ()
|
||||
|
||||
gpio_as_gpio (GPIO_CAPS_PORT, GPIO_CAPS)
|
||||
gpio_as_gpio (GPIO_SCROLL_PORT, GPIO_SCROLL)
|
||||
gpio_as_gpio (GPIO_NUM_PORT, GPIO_NUM)
|
||||
gpio_as_gpio (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
gpio_as_gpio (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
|
||||
// Start the operating system timer, and set it to give an interrupt immediately.
|
||||
// This is better, because the kernel starts with jumping into the idle task and
|
||||
// waiting for the first interrupt.
|
||||
|
@ -30,7 +30,7 @@ static void handle_exit ():
|
||||
if !current:
|
||||
current = &idle
|
||||
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
|
||||
panic (0x99338844, "non-scheduled thread running")
|
||||
panic (current->flags, "non-scheduled thread running")
|
||||
if !current:
|
||||
current = &idle
|
||||
if old_current == current:
|
||||
@ -61,22 +61,20 @@ static void handle_exit ():
|
||||
/// when k0 or k1 is not 0, or when an error occurs.
|
||||
/// Otherwise, the ultra-fast code in entry.S is used.
|
||||
Thread *tlb_refill ():
|
||||
//panic (0x88776655, "TLB refill")
|
||||
old_current = current
|
||||
if !directory:
|
||||
panic (0x44449999, "No directory")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_NO_PAGE_DIRECTORY, addr)
|
||||
handle_exit ()
|
||||
return current
|
||||
unsigned EntryHi
|
||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||
unsigned *t = directory[EntryHi >> 21]
|
||||
if !t:
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
//dbg_send (a)
|
||||
panic (0x99992222, "No page table")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_NO_PAGE_TABLE, addr)
|
||||
else:
|
||||
// - 2 instead of - 1 means reset bit 0
|
||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||
@ -88,7 +86,6 @@ Thread *tlb_refill ():
|
||||
|
||||
/// An interrupt which is not an exception has occurred.
|
||||
Thread *interrupt ():
|
||||
//panic (0x88877722, "Interrupt")
|
||||
old_current = current
|
||||
unsigned ipr = INTC_IPR
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
@ -134,7 +131,6 @@ static void arch_invoke ():
|
||||
if wait:
|
||||
old_current->wait ()
|
||||
if !target:
|
||||
//dbg_send (0, 0)
|
||||
// There must be no action here.
|
||||
else:
|
||||
Capability::Context c
|
||||
@ -164,55 +160,45 @@ Thread *exception ():
|
||||
switch (cause >> 2) & 0x1f:
|
||||
case 0:
|
||||
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
||||
panic (0x01223344, "Interrupt on exception vector.")
|
||||
panic (0, "Interrupt on exception vector.")
|
||||
break
|
||||
case 1:
|
||||
// TLB modification.
|
||||
panic (0x11223344, "TLB modification.")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_WRITE_DENIED, addr)
|
||||
break
|
||||
case 2:
|
||||
// TLB load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
//dbg_send (a)
|
||||
panic (0x21223344, "TLB load or instruction fetch.")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_UNMAPPED_READ, addr)
|
||||
break
|
||||
case 3:
|
||||
// TLB store.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
//dbg_send (a)
|
||||
panic (0x31223344, "TLB store.")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_UNMAPPED_WRITE, addr)
|
||||
break
|
||||
case 4:
|
||||
// Address error load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
//dbg_send (a)
|
||||
panic (0x41223344, "Address error load or instruction fetch.")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_INVALID_ADDRESS_READ, addr)
|
||||
break
|
||||
case 5:
|
||||
// Address error store.
|
||||
//dbg_send (current->arch.v1, 4)
|
||||
//unsigned a
|
||||
//cp0_get (CP0_EPC, a)
|
||||
//dbg_send (*(unsigned *)(a & ~3), 32)
|
||||
//dbg_send (a, 32)
|
||||
//cp0_get (CP0_BAD_V_ADDR, a)
|
||||
//dbg_send (a, 32)
|
||||
panic (0x51223344, "Address error store.")
|
||||
unsigned addr
|
||||
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||
current->raise (ERR_INVALID_ADDRESS_WRITE, addr)
|
||||
break
|
||||
case 6:
|
||||
// Bus error instruction fetch.
|
||||
panic (0x61223344, "Bus error instruction fetch.")
|
||||
panic (0, "Bus error instruction fetch.")
|
||||
break
|
||||
case 7:
|
||||
// Bus error load or store.
|
||||
panic (0x71223344, "Bus error load or store.")
|
||||
panic (0, "Bus error load or store.")
|
||||
break
|
||||
case 8:
|
||||
// Syscall.
|
||||
@ -221,37 +207,40 @@ Thread *exception ():
|
||||
break
|
||||
case 9:
|
||||
// Breakpoint.
|
||||
//panic (0x91223344, "Breakpoint.")
|
||||
#if 0
|
||||
current->raise (ERR_BREAKPOINT, 0)
|
||||
#else
|
||||
current->pc += 4
|
||||
if current->arch.a0:
|
||||
if dbg_cap:
|
||||
panic (0x34259380, "Break instruction while log capability was already set")
|
||||
panic (0, "Break instruction while log capability was already set")
|
||||
break
|
||||
bool dummy
|
||||
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
||||
if !dbg_cap:
|
||||
panic (0x06111129, "no log capability provided")
|
||||
panic (0, "no log capability provided")
|
||||
break
|
||||
break
|
||||
if dbg_cap:
|
||||
dbg_log_char (current->arch.a1)
|
||||
break
|
||||
break
|
||||
#endif
|
||||
case 10:
|
||||
// Reserved instruction.
|
||||
panic (0xa1223344, "Reserved instruction.")
|
||||
current->raise (ERR_RESERVED_INSTRUCTION, 0)
|
||||
break
|
||||
case 11:
|
||||
// Coprocessor unusable.
|
||||
panic (0xb1223344, "Coprocessor unusable.")
|
||||
current->raise (ERR_COPROCESSOR_UNUSABLE, 0)
|
||||
break
|
||||
case 12:
|
||||
// Arithmetic overflow.
|
||||
panic (0xc1223344, "Arithmetic overflow.")
|
||||
current->raise (ERR_OVERFLOW, 0)
|
||||
break
|
||||
case 13:
|
||||
// Trap.
|
||||
panic (0xd1223344, "Trap.")
|
||||
current->raise (ERR_TRAP, 0)
|
||||
break
|
||||
case 15:
|
||||
// Floating point exception.
|
||||
@ -259,7 +248,7 @@ Thread *exception ():
|
||||
break
|
||||
case 23:
|
||||
// Reference to WatchHi/WatchLo address.
|
||||
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
|
||||
current->raise (ERR_WATCHPOINT, 0)
|
||||
break
|
||||
case 24:
|
||||
// Machine check.
|
||||
|
@ -2837,6 +2837,66 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
|
||||
#define GPIO_CHARG_STAT 29
|
||||
#define GPIO_TS_PENIRQ_PORT 2
|
||||
#define GPIO_TS_PENIRQ 4
|
||||
#define GPIO_CAPS_PORT 0
|
||||
#define GPIO_CAPS 27
|
||||
#define GPIO_SCROLL_PORT 0
|
||||
#define GPIO_SCROLL 9
|
||||
#define GPIO_NUM_PORT 2
|
||||
#define GPIO_NUM 22
|
||||
#define GPIO_TP_LEFT_PORT 0
|
||||
#define GPIO_TP_LEFT 16
|
||||
#define GPIO_TP_RIGHT_PORT 0
|
||||
#define GPIO_TP_RIGHT 13
|
||||
|
||||
#define GPIO_HALF(x) (((x) & 0xf) << 1)
|
||||
|
||||
static __inline__ void gpio_as_gpio (unsigned port, unsigned pin):
|
||||
unsigned mask = 3 << GPIO_HALF (pin)
|
||||
if pin < 16:
|
||||
GPIO_GPALR (port) &= ~mask
|
||||
else:
|
||||
GPIO_GPAUR (port) &= ~mask
|
||||
|
||||
static __inline__ void gpio_as_input (unsigned port, unsigned pin):
|
||||
#if 0
|
||||
unsigned mask = 3 << GPIO_HALF (pin)
|
||||
if pin < 16:
|
||||
GPIO_GPIDLR (port) &= ~mask
|
||||
else:
|
||||
GPIO_GPIDUR (port) &= ~mask
|
||||
#else
|
||||
GPIO_GPDIR (port) &= ~(1 << pin)
|
||||
#endif
|
||||
|
||||
static __inline__ void gpio_as_output (unsigned port, unsigned pin):
|
||||
#if 0
|
||||
unsigned half = 1 << GPIO_HALF (pin)
|
||||
if pin < 16:
|
||||
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | half
|
||||
else:
|
||||
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | half
|
||||
#else
|
||||
GPIO_GPDIR (port) |= 1 << pin
|
||||
#endif
|
||||
|
||||
static __inline__ void gpio_irq (unsigned port, unsigned pin, unsigned how):
|
||||
unsigned half = 1 << GPIO_HALF (pin)
|
||||
if pin < 16:
|
||||
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | (how * half)
|
||||
else:
|
||||
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | (how * half)
|
||||
|
||||
static __inline__ void gpio_irq_low (unsigned port, unsigned pin):
|
||||
gpio_irq (port, pin, GPIO_IRQ_LOLEVEL)
|
||||
|
||||
static __inline__ void gpio_irq_high (unsigned port, unsigned pin):
|
||||
gpio_irq (port, pin, GPIO_IRQ_HILEVEL)
|
||||
|
||||
static __inline__ void gpio_irq_fall (unsigned port, unsigned pin):
|
||||
gpio_irq (port, pin, GPIO_IRQ_FALLEDG)
|
||||
|
||||
static __inline__ void gpio_irq_rise (unsigned port, unsigned pin):
|
||||
gpio_irq (port, pin, GPIO_IRQ_RAISEDG)
|
||||
|
||||
/* Init the alternate function pins */
|
||||
|
||||
|
27
panic.ccp
27
panic.ccp
@ -36,20 +36,13 @@ void dbg_log (char const *str):
|
||||
while *str:
|
||||
dbg_log_char (*str++)
|
||||
|
||||
void dbg_send (unsigned code, unsigned bits):
|
||||
if bits > 32:
|
||||
bits = 32
|
||||
void dbg_log_num (unsigned num):
|
||||
char const *encode = "0123456789abcdef"
|
||||
dbg_log_char ('[')
|
||||
dbg_log_char (encode[(bits >> 4) & 0xf])
|
||||
dbg_log_char (encode[bits & 0xf])
|
||||
dbg_log_char (':')
|
||||
for unsigned i = 0; i < 8; ++i:
|
||||
dbg_log_char (encode[(code >> (4 * (7 - i))) & 0xf])
|
||||
dbg_log_char (']')
|
||||
dbg_log_char (encode[(num >> (4 * (7 - i))) & 0xf])
|
||||
return
|
||||
|
||||
void panic (unsigned n, char const *message):
|
||||
void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
|
||||
Thread *who = current
|
||||
// Stop all threads.
|
||||
while first_scheduled:
|
||||
@ -64,8 +57,18 @@ void panic (unsigned n, char const *message):
|
||||
if dbg_cap && dbg_cap->target->owner:
|
||||
dbg_cap->target->owner->run ()
|
||||
// Use the (now running) log thread to display the message.
|
||||
dbg_log ("Panic: ")
|
||||
dbg_send (n)
|
||||
dbg_log ("Panic: current = ")
|
||||
dbg_log_num ((unsigned)who)
|
||||
if who:
|
||||
dbg_log_char ('@')
|
||||
dbg_log_num ((unsigned)who->pc)
|
||||
dbg_log ("; ")
|
||||
dbg_log (name)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (line)
|
||||
dbg_log (": ")
|
||||
dbg_log (message)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (n)
|
||||
dbg_log_char ('\n')
|
||||
// If no log capability is registered, the machine just hangs.
|
||||
|
@ -71,7 +71,7 @@ static void alarm_tick (Receiver *recv):
|
||||
first_alarm = recv->next_alarm
|
||||
if recv->next_alarm:
|
||||
recv->next_alarm->prev_alarm = recv->prev_alarm
|
||||
return
|
||||
// Fall through to let alarm_count be ~0. This is required, because it is the indicator for no running alarm.
|
||||
--recv->alarm_count
|
||||
|
||||
void Thread::wait ():
|
||||
|
Loading…
Reference in New Issue
Block a user