1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2025-04-21 12:27:27 +03:00

new stuff almost working

This commit is contained in:
Bas Wijnen
2009-08-24 21:02:35 +02:00
parent ebdc68a9d8
commit 418f6c6594
18 changed files with 651 additions and 495 deletions

View File

@@ -31,10 +31,8 @@ static list *__first_free_slot, *__first_free_cap
Receiver __my_receiver
Thread __my_thread
Memory __my_memory
Caps __my_caps
Cap __my_call
Cap __my_parent
Caps __tmp_caps
void free_slot (unsigned slot):
__slot_admin[slot].prev = NULL
@@ -59,16 +57,17 @@ unsigned alloc_slot ():
__first_free_slot = ret->next
if ret->next:
ret->next->prev = NULL
return ret - __slot_admin
unsigned alloc_cap ():
if !__first_free_cap:
// Out of caps... Probably best to raise an exception. For now, just return NO_SLOT.
// Out of caps... Probably best to raise an exception. For now, just return NO_CAPABILITY.
return ~0
list *ret = __first_free_cap
__first_free_cap = ret->next
if ret->next:
ret->next->prev = NULL
return ret - __slot_admin
return ret - __cap_admin
extern "C":
void __main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
@@ -77,7 +76,7 @@ extern "C":
__slot_admin = slot_admin
__cap_admin = cap_admin
__first_free_slot = NULL
for unsigned i = 1; i < __slots; ++i:
for unsigned i = 2; i < __slots; ++i:
free_slot (i)
__first_free_cap = NULL
for unsigned i = 7; i < __caps; ++i:
@@ -85,10 +84,8 @@ extern "C":
__my_receiver = Cap (0, __receiver_num)
__my_thread = Cap (0, __thread_num)
__my_memory = Cap (0, __memory_num)
__my_caps = Cap (0, __caps_num)
__my_call = Cap (0, __call_num)
__my_parent = Cap (0, __parent_num)
__tmp_caps = Cap (0, __tmp_num)
Num ret = start ()
__my_parent.invoke (~0, ret)
__my_memory.destroy (__my_thread)

View File

@@ -48,10 +48,11 @@ struct Keyboard : public Cap:
RELEASE = 1 << 31
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events.
void set_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | SET_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.
void get_keys (List <String> ret):
call (ret, CAP_MASTER_DIRECT | GET_KEYS)
List <String> get_keys (List <String> ret = Cap (0, alloc_cap ())):
icall (ret, CAP_MASTER_DIRECT | GET_KEYS)
return ret
// Display interface.
struct Display : public Cap:
@@ -64,18 +65,18 @@ struct Display : public Cap:
// Register an end-of-frame callback.
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
void set_eof_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | EOF_CB)
ocall (cb, CAP_MASTER_DIRECT | EOF_CB)
// Create a framebuffer for the display. When not in use, it can be freed by the user.
// The pages must be cappages holding Page capabilities. They are filled by the display.
// The passed numbers must be 0 or match a mode that the device can use.
// The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
unsigned create_framebuffer (Caps pages, unsigned w = 0, unsigned h = 0, unsigned mode = 0):
return call (pages, Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Num ((w << 16) | h, mode)).l
return icall (pages, Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Num ((w << 16) | h, mode)).l
// Use a framebuffer. The address must have been returned from display_create_framebuffer.
// w, h and mode must match the values given at creation time.
// unuse_cb is called the next time this operation is requested for this display.
void use_framebuffer (unsigned addr, Cap unuse_cb = Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0):
invoke (unuse_cb, Num (CAP_MASTER_DIRECT | USE_FB, addr), Num ((w << 16) | h, mode))
ocall (unuse_cb, Num (CAP_MASTER_DIRECT | USE_FB, addr), Num ((w << 16) | h, mode))
// Get information about the display.
void get_info ():
// TODO: Interface is to be designed.
@@ -93,13 +94,13 @@ struct File : public Cap:
MAP_HANDLE
// Get information about the file.
Num get_info (unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | INFO, type))
return icall (ret, Num (CAP_MASTER_DIRECT | INFO, type))
// Close a file. If this is a directory, it implicitly closes all files opened from it.
void close ():
invoke (CAP_MASTER_DIRECT | CLOSE)
call (CAP_MASTER_DIRECT | CLOSE)
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
File map_handle (File ret):
call (ret, CAP_MASTER_DIRECT | MAP_HANDLE)
icall (ret, CAP_MASTER_DIRECT | MAP_HANDLE)
// Directory interface.
struct Directory : public File:
@@ -116,19 +117,19 @@ struct Directory : public File:
return call (CAP_MASTER_DIRECT | GET_SIZE)
// Get the filename. The return value is the size of the string, the page is filled with the string itself.
void get_name (Num idx, String target):
call (target, CAP_MASTER_DIRECT | GET_NAME, idx)
icall (target, CAP_MASTER_DIRECT | GET_NAME, idx)
// Get the file.
void get_file (Num idx, File ret):
call (ret, CAP_MASTER_DIRECT | GET_FILE, idx)
icall (ret, CAP_MASTER_DIRECT | GET_FILE, idx)
// Get file info. This returns the same information as file_get_info, without opening the file.
Num get_file_info (Num idx, unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
return icall (ret, Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
// Create a new file. After this, any index may map to a different file.
void create_file (String name, File ret):
call (ret, CAP_MASTER_DIRECT | CREATE_FILE)
icall (ret, CAP_MASTER_DIRECT | CREATE_FILE)
// Delete a file. After this, any index may map to a different file.
void delete_file (Num idx):
invoke (CAP_MASTER_DIRECT | DELETE_FILE, idx)
call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
// Stream interface.
struct Stream : public File:
@@ -138,10 +139,10 @@ struct Stream : public File:
WRITE
// Try to read size bytes. Returns the number of bytes successfully read.
Num read (Num size, String ret):
return call (ret, CAP_MASTER_DIRECT | READ, size)
return icall (ret, CAP_MASTER_DIRECT | READ, size)
// Try to write size bytes. Returns the number of bytes successfully written.
Num write (String s, Num size):
return call (s, CAP_MASTER_DIRECT | WRITE, size)
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
// Seekable file interface.
struct Seekable : public File:
@@ -152,13 +153,13 @@ struct Seekable : public File:
TRUNCATE
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
Num read (Num idx, unsigned size, String ret):
return call (ret, Num (CAP_MASTER_DIRECT | READ, size), idx)
return icall (ret, Num (CAP_MASTER_DIRECT | READ, size), idx)
// Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written.
Num write (Num idx, String s):
return call (s, CAP_MASTER_DIRECT | WRITE, idx)
return ocall (s, CAP_MASTER_DIRECT | WRITE, idx)
// Truncate file to size idx. The file is extended with zeroes if it gets longer.
void truncate (Num idx):
invoke (CAP_MASTER_DIRECT | TRUNCATE, idx)
call (CAP_MASTER_DIRECT | TRUNCATE, idx)
// Mappable file interface.
struct Mappable : public Seekable:

View File

@@ -58,15 +58,30 @@ enum cap_type:
CAP_TOUCHPAD
CAP_LOCKLEDS
CAP_PWM
NUM_EVENT_TYPES
static unsigned events
static Caps event_caps
static void event (event_type type, unsigned data):
Cap (events, type - 32).invoke (data)
kdebug ("event t/d/e=")
kdebug_num (type)
kdebug_char ('/')
kdebug_num (data)
kdebug_char ('/')
kdebug_num (events)
kdebug_char ('\n')
Cap (events, type).invoke (data)
static void set_cb (Cap cap, event_type type):
cap.clone (Cap (events, type - 32))
kdebug ("gpio set cb ")
kdebug_num (type)
kdebug_char ('\n')
for unsigned i = 0; i < NUM_EVENTS; ++i:
event_caps.print (i)
cap.clone (Cap (events, type))
kdebug ("after:\n")
for unsigned i = 0; i < NUM_EVENTS; ++i:
event_caps.print (i)
class DevKeyboard:
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
@@ -188,7 +203,7 @@ class Touchpad:
else:
gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
event (TOUCHPAD_EVENT, 0x10000)
event (TOUCHPAD_EVENT, 0 | Keyboard::RELEASE)
if state & (1 << GPIO_TP_RIGHT):
gpio_irq_low (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
@@ -196,7 +211,7 @@ class Touchpad:
else:
gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
event (TOUCHPAD_EVENT, 0x10001)
event (TOUCHPAD_EVENT, 1 | Keyboard::RELEASE)
old_state = state
// Ack interrupts.
//GPIO_GPFR (GPIO_TP_LEFT_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
@@ -255,22 +270,18 @@ class Pwm:
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
Num start ():
Kernel::schedule ()
map_gpio ()
map_pwm0 ()
Caps e = __my_memory.create_caps (NUM_EVENT_TYPES - 32)
events = e.use ()
free_cap (e)
event_caps = __my_memory.create_caps (NUM_EVENTS)
events = event_caps.use ()
DevKeyboard kbd
Touchpad tp
Lockleds leds
Pwm pwm
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
Kernel::register_interrupt (IRQ_GPIO0)
Caps c = __my_memory.create_caps (4)
unsigned init_slot = c.use ()
__my_receiver.create_capability (CAP_KEYBOARD, Cap (init_slot, 0))
@@ -278,15 +289,23 @@ Num start ():
__my_receiver.create_capability (CAP_LOCKLEDS, Cap (init_slot, 2))
__my_receiver.create_capability (CAP_PWM, Cap (init_slot, 3))
__my_parent.invoke (c, INIT_SET_GPIO)
__my_parent.ocall (c, INIT_SET_GPIO)
free_cap (c)
free_slot (init_slot)
if kbd.is_scanning ():
__my_receiver.set_alarm (ALARM_INTERVAL)
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
Kernel::register_interrupt (IRQ_GPIO0)
kdebug ("gpio ready\n")
unsigned slot = alloc_slot ()
while true:
Kernel::schedule ()
Cap::OMessage msg
Kernel::wait (&msg)
Kernel::wait (&msg, slot)
switch (unsigned)msg.cap_protected.value ():
case ~0:
// Alarm.
@@ -302,16 +321,20 @@ Num start ():
Kernel::register_interrupt (IRQ_GPIO0)
break
case CAP_KEYBOARD:
set_cb (Cap (__tmp_slot, 0), KEYBOARD_EVENT)
set_cb (Cap (slot, 1), KEYBOARD_EVENT)
Cap (slot, 0).invoke ()
kbd.send_initial ()
break
case CAP_TOUCHPAD:
set_cb (Cap (__tmp_slot, 0), TOUCHPAD_EVENT)
set_cb (Cap (slot, 1), TOUCHPAD_EVENT)
Cap (slot, 0).invoke ()
tp.send_initial ()
break
case CAP_LOCKLEDS:
leds.set (msg.data[0].l)
Cap (slot, 0).invoke ()
break
case CAP_PWM:
pwm.set_backlight (msg.data[0].l)
Cap (slot, 0).invoke ()
break

View File

@@ -30,31 +30,37 @@ enum type:
static void setup ():
unsigned state = 0
unsigned slot = 2
unsigned slot = alloc_slot ()
while true:
Cap::OMessage msg
Kernel::wait (&msg, slot)
switch msg.data[0].value ():
case INIT_SET_GPIO:
kdebug ("gpio\n")
kbd = Cap (slot, 0)
tp = Cap (slot, 1)
lockleds = Cap (slot, 2)
pwm = Cap (slot, 3)
++slot
Caps caps = Cap (slot, 1)
unsigned gpio_slot = caps.use ()
Cap (slot, 0).invoke ()
kbd = Cap (gpio_slot, 0)
tp = Cap (gpio_slot, 1)
lockleds = Cap (gpio_slot, 2)
pwm = Cap (gpio_slot, 3)
++state
break
case INIT_SET_LCD:
kdebug ("lcd\n")
lcd = Cap (slot, 0)
++slot
lcd = Cap (slot, 1).clone ()
Cap (slot, 0).invoke ()
++state
break
if state == 2:
break
kbd.set_cb (__my_receiver.create_capability (KBD).copy ())
tp.set_cb (__my_receiver.create_capability (TP).copy ())
pwm.invoke (1)
Caps caps = __my_memory.create_caps (2)
caps.use (slot)
Cap kc = __my_receiver.create_capability (KBD, Cap (slot, 1))
kbd.set_cb (kc)
Cap tc = __my_receiver.create_capability (TP, Cap (slot, 0))
tp.set_cb (tc)
pwm.call (1)
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
@@ -82,5 +88,5 @@ Num start ():
leds |= 0x4
if !(msg.data[0].l & Keyboard::RELEASE):
leds |= 0x2
lockleds.invoke (leds)
lockleds.call (leds)
break

View File

@@ -20,9 +20,9 @@
#define ARCH
#include "arch.hh"
__asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"")
// I'm too lazy to do this right. The address of charset is really the address of the array.
extern unsigned charset
__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"\n.section .text")
// charset is really the first character in the array. Its address is used as the start of the array.
extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
@@ -32,16 +32,18 @@ enum types:
// For now, support only 16 bpp.
// Screen is 800x480 tft.
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#define frame_size (v * h * Bpp)
static unsigned physical_descriptor
struct Descriptor:
unsigned next
unsigned frame
unsigned id
unsigned cmd
static void reset (unsigned physical_descriptor):
static void reset ():
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
LCD_VSYNC = vs
LCD_HSYNC = hs
@@ -74,11 +76,10 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
if ch < 32 || ch > 126:
ch = 127
ch -= 32
unsigned char *c = &((unsigned char *)&charset)[ch * 6]
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[c[k] & (1 << r) ? 1 : 0]
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
static unsigned log_x = 1, log_y = 1
static void inc_logx ():
@@ -126,12 +127,12 @@ Num start ():
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
unsigned physical = Kernel::alloc_range (__my_memory, pages)
assert (physical)
unsigned physical = __my_memory.alloc_range (pages)
assert (physical & PAGE_MASK && ~physical)
for unsigned i = 0; i < pages; ++i:
Page p = __my_memory.create_page ()
p.alloc_physical (physical + i * PAGE_SIZE, false, true)
__my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, true)
__my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
free_cap (p)
for unsigned y = 0; y < 480; ++y:
unsigned g = (y << 6) / 480
@@ -150,7 +151,7 @@ Num start ():
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
Page p = __my_memory.mapping (&descriptor)
unsigned physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
free_cap (p)
descriptor.next = physical_descriptor
descriptor.frame = physical
@@ -158,15 +159,16 @@ Num start ():
descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
unsigned dptr = (unsigned)&descriptor
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset (physical_descriptor)
Cap set_eof_cb = __my_receiver.create_capability (LCD_EOF_CB)
__my_parent.invoke (set_eof_cb.copy (), INIT_SET_LCD)
reset ()
Cap logcap = __my_receiver.create_capability (LCD_LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
Cap set_eof_cb = __my_receiver.create_capability (LCD_EOF_CB)
__my_parent.ocall (set_eof_cb, INIT_SET_LCD)
unsigned slot = alloc_slot ()
Cap eof_cb (0, alloc_cap ())
while true:
Cap::OMessage msg
Kernel::wait (&msg, slot)
@@ -174,10 +176,11 @@ Num start ():
switch msg.cap_protected.value ():
case IRQ_LCD:
lcd_clr_eof ()
Cap (slot, 0).invoke ()
Cap (slot, 0) = Cap ()
eof_cb.invoke ()
break
case LCD_EOF_CB:
Cap (slot, 1).clone (eof_cb)
Cap (slot, 0).invoke ()
Kernel::register_interrupt (IRQ_LCD)
break
case LCD_LOG: