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

towards a usb file system

This commit is contained in:
Bas Wijnen
2010-01-14 18:14:37 +01:00
parent 3debf99082
commit 0c1dfe719b
20 changed files with 690 additions and 507 deletions

View File

@@ -1,134 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/buzzer.ccp: Piezo buzzer driver.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "devices.hh"
#define ARCH
#include "arch.hh"
class DevBuzzer:
static unsigned const pwm = 4
Kernel::Cap event
bool is_beeping
public:
DevBuzzer ():
is_beeping = false
tcu_stop_counter (pwm)
tcu_select_extalclk (pwm)
tcu_select_clk_div64 (pwm)
tcu_enable_pwm_output (pwm)
void stop ():
if !is_beeping:
return
tcu_stop_counter (pwm)
event.invoke ()
Kernel::free_cap (event)
is_beeping = false
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
stop ()
event = cb
unsigned full = JZ_EXTAL / 64 / freq
tcu_set_full_data (pwm, full)
tcu_set_half_data (pwm, full / 2)
tcu_set_count (pwm, 0)
tcu_start_counter (pwm)
Kernel::my_receiver.set_alarm (ms * HZ / 1000)
is_beeping = true
enum codes:
BUZZER = 32
Kernel::Num start ():
Kernel::schedule ()
map_tcu ()
DevBuzzer buzzer
Device dev = Kernel::my_receiver.create_capability (BUZZER)
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
Kernel::free_cap (dev)
unsigned user (~0)
unsigned next_user (0)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.h:
case ~0:
// Alarm.
buzzer.stop ()
break
case 0:
switch Kernel::recv.protected_data.l:
case BUZZER:
// Buzzer device control request.
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, BUZZER))
reply.invoke (0, 0, cap.copy ())
Kernel::free_cap (cap)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::UNUSE:
buzzer.stop ()
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("invalid buzzer control command: ")
kdebug_num (Kernel::recv.data[0].l)
kdebug ("\n")
break
break
default:
kdebug ("invalid buzzer request\n")
break
break
case BUZZER:
// Buzzer device user request.
if Kernel::recv.protected_data.l != user:
kdebug ("invalid user requesting buzzer\n")
Kernel::recv.reply.invoke ()
break
switch Kernel::recv.data[0].l:
case Buzzer::BEEP:
// 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 (reply)
break
case Buzzer::STOP:
buzzer.stop ()
Kernel::recv.reply.invoke ()
break
default:
kdebug ("Buzzer: other\n")
break
break
default:
kdebug ("Buzzer: unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)
kdebug ("\n")

View File

@@ -1,887 +0,0 @@
#!/usr/bin/env python
data = """
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . . . . .
. # . . . .
. . . . . .
. # # . # #
. . # . . #
+ # . + # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # . # .
. # # # # #
. # . # . .
# # # # # .
# . # . . .
. . . . . .
. . . . # .
. . # # # #
. # . # . .
. . # # # .
. . # . # .
. # # # # .
. # . . . .
. . . . . .
. . . . . .
. # # . # .
. # . # . .
. . . # . .
. . # . . .
. . # . # .
. # . # # .
. . . . . .
. # # . . .
. # . # . .
. # # . . .
. . # . . .
. # # . # .
. # . # # .
. # # # # .
. . . . . .
. . # # . .
. . . # . .
. + # . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . + # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . # . . .
. . # # . .
. . . . . .
. . # # . .
. . . . # .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
# # + . . .
. . . . . .
. # . . # .
. . # . # .
. . # # . .
. # # # # #
. . # # . .
. . # . # .
. # . . # .
. . . . . .
. . . . . .
. . . . . .
. . . # . .
. . . # . .
# # # # # .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # # . .
. . # . . .
. + # . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. # # # # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . + # # .
. # + . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. . . . . .
. . . . # .
. . # # . .
. . . # . .
. . # . . .
. . # . . .
# # # . . .
. . . . . .
. . . . . .
. . + # # .
. + + . # .
. . . . # .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . . . .
. . # # # .
. . . . # .
. . . + # .
. + # . . .
. . . # . .
# # # . . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. # # # # .
. . . # . .
. . . # . .
. . # . . .
. . . . . .
. . . . . .
. . # # # #
. # . . . .
. # # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. . . + # .
. . . # . .
. . # . . .
. . # # # .
. # . . # .
. # . . # .
. # # # . .
. . . . . .
. . . . . .
. . # # # #
. . . . # .
. . . . # .
. . + + . .
. . + + . .
. # . . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. + # # + .
# . . # . .
# . . # . .
# # + . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. # . + # .
. # + # . .
. . . # . .
# # # . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. # # . . .
. # . . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. # # . . .
. # . . . .
+ # . . . .
. . . . . .
. . . # + .
. + + . . .
. # . . . .
. # . . . .
. . # . . .
. . # . . .
. . . . . .
. . . . . .
. . . . . .
. # # # # .
. . . . . .
. . . . . .
# # # # . .
. . . . . .
. . . . . .
. . . . . .
. . # . . .
. . # . . .
. . . # . .
. . . # . .
. . + + . .
+ # . . . .
. . . . . .
. . # # . .
. . # . # .
. . . . # .
. . . + # .
. . # . . .
. . . . . .
. # . . . .
. . . . . .
. . # # # .
. . # . . #
. # . # . #
. # . # + #
# . # # # .
. # . . . .
. # # # . .
. . . . . .
. . . + # .
. . . # . #
. . # . . #
. . # # # #
. # . . # .
. # . . # .
# . . # . .
. . . . . .
. . . # # .
. . . # . #
. . # . # .
. . # # # .
. # . . # .
. # . + # .
# # # + . .
. . . . . .
. . + # # .
. . # + . #
. # . . . .
. # . . . .
# . . . . .
+ + . + + .
# # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . . #
. # . . # .
. # . + # .
# # # + . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # # . .
. # . . . .
. # . . . .
# # # . . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # # . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . + # # .
. . # + . #
. # . . . .
. # . . . .
# . # # . .
+ + . # . .
+ # # . . .
. . . . . .
. . . # . #
. . . # . #
. . # . # .
. . # # # .
. # . # . .
. # . # . .
# . # . . .
. . . . . .
. . . # # #
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
# # # . . .
. . . . . .
. . . # # #
. . . . # .
. . . # . .
. . . # . .
. . # . . .
# . # . . .
# # . . . .
. . . . . .
. . . # . #
. . . # . #
. . # . # .
. . # # + .
. # + . . .
. # . # . .
# . . # . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# # # # . .
. . . . . .
. . # . # #
. . # + # +
. # . # . #
. # . . . #
# . . . # .
# . . . # .
+ . . # . .
. . . . . .
. . # . . #
. . # # . +
. # + + . #
. # . # . #
# . + + # .
# . . # # .
+ . . # . .
. . . . . .
. . . # # .
. . # + . #
. # . . . #
. # . . . #
# . . . # .
# . . + # .
# # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . + #
. # # # + .
. # . . . .
# . . . . .
. . . . . .
. . . # # .
. . # + . #
. # . . . #
. # . . . #
# . . # # .
# . . . # .
# # # . # .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . + #
. # # # + .
. # . # . .
# . . # . .
. . . . . .
. . + # # #
. . # + . .
. # . . . .
. . # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. # # # # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . # . . #
. . # . . #
. # . . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. + . . . #
. # . . . #
+ . . . # .
. # . . # .
+ . . # . .
. # + + . .
. # . . . .
. . . . . .
. . # . . +
. . # . . +
. # . . . #
. # . . . #
# . # . # .
# + # . # .
# + # # . .
. . . . . .
. # . . . #
. . # . . #
. . # # + .
. . . # . .
. + # # . .
. # . . # .
# . . . # .
. . . . . .
. # . . . #
. . # . . #
. . # # + .
. . . # . .
. + # . . .
. # . . . .
# . . . . .
. . . . . .
. . # # # #
. . . . . #
. . . # + .
. . . # . .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# # # . . .
. . . . . .
. # . . . .
. . # . . .
. . # . . .
. . . # . .
. . . # . .
. . . . # .
. . . . # .
. . . . . .
. . . # # #
. . . . . #
. . . . # .
. . . . # .
. . . # . .
. . . # . .
# # # . . .
. . . . . .
. . . + # .
. . + # . #
. # . . . #
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
# # # # # .
. . . . . .
. . # # . .
. . . # . .
. . + # . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # # + #
. # . # # .
. # . . # .
# . . # . .
. # + # . .
. # # . . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # # # .
. # . . # .
. # . . # .
# # # # . .
. . . . . .
. . . . . .
. . . # # .
. # + . # .
. # . . . .
# . . . . .
. # . # . .
. # + . . .
. . . . . .
. . . . . #
. . . . . #
. . # # # .
. # + . # .
# . . # . .
# . . # . .
# # # . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. # # # + .
# . . . . .
. # . . . .
. # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . .
. # # # . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . . # # #
. . # . . #
. . . # # #
. . . . # .
. . . + # .
. # # . . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # # # . .
. # . . # .
# . . # . .
. . . . . .
. . . . # .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . # .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
# # . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # + # . .
. # # + . .
# . # + . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . . # # #
. . # + + #
. . # + + #
. # + + # .
. # + + # .
# + + # . .
. . . . . .
. . . . . .
. . . # + #
. . # # + #
. . # . . #
. # . . # .
. # . . # .
# . . # . .
. . . # . .
. . . . . .
. . + # # .
. # + . # .
. # . . . #
# . . . # .
. # . + # .
. # # + . .
. . . . . .
. . . . . .
. . . # # #
. . # . . #
. . # . . #
. # # # + .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . + # # #
. # . . # .
. # . . # .
. # # # . .
. . . # . .
. . # . . .
. . # . . .
. . . . . .
. . . # + #
. . # # . #
. . # . . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . # # # #
. # . . . .
. . # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. . . . . .
. . . # . .
. # # # . .
. . # . . .
. # . . . .
. # . # . .
. # + . . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. . . . . .
. + # . . +
. # . . . #
. + + . + #
. # . # + .
. # . # . .
. # . . . .
. . . . . .
. . . . . .
. . # . . +
. # . . . #
. # . # . #
# . # . # .
# . # . # .
# # # + . .
. . . . . .
. . . . . .
. . # . . #
. . # . # .
. . + # + .
. + # + . .
. # . # . .
# . . # . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. . # # # .
. . . # . .
. . + # . .
# # + . . .
. . . . . .
. . . . . .
. . # # # #
. . . . # .
. . . # + .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . + # #
. . . # . .
. . # . . .
. # + . . .
. # . . . .
. # . . . .
+ # # . . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . # # +
. . . . . #
. . . . # .
. . . . + #
. . . # . .
. . . # . .
# # + . . .
. . . . . .
. # # . . .
. # . # . #
. . . # # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. # + # + .
. # + # + .
. + # + # .
. + # + # .
. # + # + .
. # + # + .
. . . . . .
"""
# """ # add quotes, because vim thinks the qotes on the previous line start a string.
import sys
charsize = 25 * 4 + 1
for c in range (128 - 32):
line = []
for l in range (8):
offset = 2 + c * charsize + 25 * (l >> 1) + 12 * (l & 1)
ln = ""
for x in range (6):
char = data[offset + x * 2]
if char == '.':
sys.stdout.write (chr (0))
elif char == '+':
sys.stdout.write (chr (128))
elif char == '#':
sys.stdout.write (chr (255))
else:
raise "invalid character in " + str (c)

View File

@@ -97,7 +97,7 @@ namespace Kernel:
return Cap (0, ret - __cap_admin)
extern "C":
void __main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
__slots = slots
__caps = caps
__slot_admin = slot_admin
@@ -137,7 +137,7 @@ __asm__ volatile ("\t.globl __start\n"
"\tmove $a2, $sp\n"
"\tsubu $sp, $sp, $v1\n"
"\tmove $a3, $sp\n"
"\tla $t9, __main\n"
"\tla $t9, run__main\n"
"\tjr $t9\n"
"\tnop\n"
"\t.set reorder")

View File

@@ -1,323 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/gpio.ccp: GPIO driver, controlling all devices without special hardware.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "devices.hh"
#define ARCH
#include "arch.hh"
// Interval between polls for keyboard events (when keys are pressed)
#define ALARM_INTERVAL (HZ / 50)
// GPIO pins for the devices (port.pin)
// keyboard
// Cols = 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15, 3.29
// Rows = 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7
// For some reason, it only works if the rows are input and the columns are output.
// interrupts: yes, with all columns set to output 0, the first key press can be detected as an interrupt; some other events also trigger interrupts.
// touchpad buttons
// Left: 0.16
// Right: 0.13
// interrupts: yes, for any change.
// Lock leds
// Num lock: 2.22
// Caps lock: 0.27
// Scroll lock: 0.9
// interrupts: no, output only.
// interrupt summary
// Port 0: pin 0, 1, 2, 3, 4, 5, 6, 7: keyboard; 13, 16: touchpad
// Port 1: None.
// Port 2: None.
// Port 3: None.
enum event_type:
KEYBOARD_EVENT
TOUCHPAD_EVENT
NUM_EVENTS
static Kernel::Cap events[NUM_EVENTS]
static void event (event_type type, unsigned data):
events[type].invoke (data)
static void set_cb (event_type type):
Kernel::free_cap (events[type])
events[type] = Kernel::get_arg ()
class DevKeyboard:
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
unsigned keys[GPIO_KBD_NUM_COLS]
bool scanning
void parse (unsigned col, unsigned data):
for unsigned row = 0; row < GPIO_KBD_NUM_ROWS; ++row:
if (data ^ keys[col]) & (1 << row):
unsigned code = encode[col][row]
if data & (1 << row):
code |= Keyboard::RELEASE
event (KEYBOARD_EVENT, code)
keys[col] = data
// If any keys are pressed, scanning is required.
if data != GPIO_KBD_ROW_MASK:
scanning = true
public:
bool is_scanning ():
return scanning
void scan ():
// Disable interrupts during scan.
GPIO_GPIER (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
// All columns are input.
GPIO_GPDIR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
int const cols[GPIO_KBD_NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
unsigned dir = GPIO_GPDIR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
unsigned dat = GPIO_GPDR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
// Set scanning to false before first parse.
scanning = false
// Clear all pins. This is only required once, because it's done at the end of the loop as well.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
// Set pin to output.
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Delay for stabalization.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Read the result.
unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT) & GPIO_KBD_ROW_MASK
// Generate events.
parse (col, data)
// Set pin to get rid of capacitance effects.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat | (1 << cols[col])
// Delay to make the above trick work.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Pin is set to input at the start of the loop.
// set all to 0.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
// set all to output.
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
// Delay for stabalization.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
// Set interrupts.
unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT)
for unsigned i = 0; i < 8; ++i:
if data & (1 << i):
gpio_irq_low (GPIO_KBD_ROW_PORT, i)
else:
gpio_irq_high (GPIO_KBD_ROW_PORT, i)
// Reenable interrupts.
GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
DevKeyboard ():
// Set all columns to output without pull-ups when set as input.
GPIO_GPPUR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
GPIO_GPDIR (GPIO_KBD_COL_PORT) |= GPIO_KBD_COL_MASK
// Set all rows to input and enable the pull-ups.
GPIO_GPPUR (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
GPIO_GPDIR (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
// Initialize things in the same way as when a new callback is set up.
send_initial ()
void send_initial ():
for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
keys[col] = 0xff
scan ()
enum Keys:
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, F5, F6, F7, F8, F9, F10
SPACE, TAB, ENTER, LBRACE, RBRACE, COMMA, PERIOD, MINUS, EQUAL, SLASH, BACKSLASH, SEMICOLON, EXTRA, BACKQUOTE, QUOTE
UP, DOWN, LEFT, RIGHT
ESC, INSERT, DELETE, BACKSPACE, PAUSE, FN, ZZZ, MENU, SYSRQ
LSHIFT, RSHIFT, CTRL, ALT
CAPS, NUM
NONE = ~Keyboard::RELEASE
unsigned const DevKeyboard::encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] = {
{ PAUSE, NONE, NONE, NONE, NONE, NONE, CTRL, F5 },
{ Q, TAB, A, ESC, Z, NONE, BACKQUOTE, N1 },
{ W, CAPS, S, EXTRA, X, NONE, NONE, N2 },
{ E, F3, D, F4, C, NONE, NONE, N3 },
{ R, T, F, G, V, B, N5, N4 },
{ U, Y, J, H, M, N, N6, N7 },
{ I, RBRACE, K, F6, COMMA, NONE, EQUAL, N8 },
{ O, F7, L, NONE, PERIOD, MENU, F8, N9 },
{ NONE, NONE, NONE, SPACE, NUM, NONE, DELETE, NONE },
{ NONE, BACKSPACE, NONE, NONE, ENTER, NONE, F9, NONE },
{ NONE, NONE, NONE, ALT, NONE, NONE, NONE, SYSRQ },
{ P, LBRACE, SEMICOLON, QUOTE, BACKSLASH, SLASH, MINUS, N0 },
{ NONE, ZZZ, NONE, NONE, NONE, NONE, NONE, F10 },
{ NONE, NONE, NONE, NONE, NONE, NONE, F2, NONE },
{ NONE, NONE, NONE, NONE, NONE, NONE, INSERT, NONE },
{ NONE, NONE, UP, DOWN, LEFT, RIGHT, NONE, NONE },
{ NONE, LSHIFT, RSHIFT, NONE, NONE, NONE, F1, FN }}
class Touchpad:
unsigned old_state
public:
void check_events ():
unsigned state = GPIO_GPDR (GPIO_TP_LEFT_PORT)
if state & (1 << GPIO_TP_LEFT):
gpio_irq_low (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
event (TOUCHPAD_EVENT, 0)
else:
gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
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):
event (TOUCHPAD_EVENT, 1)
else:
gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
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)
Touchpad ():
// Set pins to input with pull-ups.
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)
// See if they are already pressed. Also set up interrupts. This is done like when a new callback is registered.
send_initial ()
void send_initial ():
old_state = 0
check_events ()
class Lockleds:
// Note that num lock is in port 2. The others are in port 0.
public:
Lockleds ():
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 (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
else:
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
if state & 2:
GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
else:
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
if state & 1:
GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
else:
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
class Pwm:
public:
Pwm ():
GPIO_GPDIR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
PWM_PER (0) = 300
void set_backlight (unsigned level):
if level > 300:
level = 300
PWM_DUT (0) = level
if level:
PWM_CTR (0) = 0x80
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
else:
PWM_CTR (0) = 0x00
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
enum codes:
KEYBOARD = 32
TOUCHPAD
LOCKLEDS
PWM
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
map_pwm0 ()
for unsigned i = 0; i < NUM_EVENTS; ++i:
events[i] = Kernel::alloc_cap ()
DevKeyboard kbd
Touchpad tp
Lockleds leds
Pwm pwm
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
Kernel::free_cap (c)
c = Kernel::my_receiver.create_capability (TOUCHPAD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
Kernel::free_cap (c)
if kbd.is_scanning ():
Kernel::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)
while true:
Kernel::schedule ()
Kernel::wait ()
switch Kernel::recv.protected_data.l:
case ~0:
// Alarm.
kbd.scan ()
if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
break
case IRQ_GPIO0:
// Always scan keyboard and touchpad on any interrupt.
kbd.scan ()
tp.check_events ()
// Reregister the interrupt.
Kernel::register_interrupt (IRQ_GPIO0)
break
case KEYBOARD:
set_cb (KEYBOARD_EVENT)
Kernel::recv.reply.invoke ()
kbd.send_initial ()
event (KEYBOARD_EVENT, ~0)
break
case TOUCHPAD:
set_cb (TOUCHPAD_EVENT)
Kernel::recv.reply.invoke ()
tp.send_initial ()
event (TOUCHPAD_EVENT, ~0)
break
case LOCKLEDS:
leds.set (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
case PWM:
pwm.set_backlight (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
default:
kdebug ("invalid gpio operation ")
kdebug_num (Kernel::recv.protected_data.l)
kdebug ("\n")
break

View File

@@ -1,350 +0,0 @@
GPIO control:
#define GPIO_BASE 0xB0010000
#define IRQ_GPIO3 25
#define IRQ_GPIO2 26
#define IRQ_GPIO1 27
#define IRQ_GPIO0 28
#define GPIO_IRQ_LOLEVEL 0
#define GPIO_IRQ_HILEVEL 1
#define GPIO_IRQ_FALLEDG 2
#define GPIO_IRQ_RAISEDG 3
// GP ... Registers: one set for each port of 32 pins; total 128 pins means 4 groups. Total size: 4 * 0x30 == 0xc0.
#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) // D: data
#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) // DI: data in: 0 is input; 1 is output. Disable interrupts on the pin before touching this.
#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) // OD:
#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) // PU: pull-up (1 is enable)
#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) // AL: alternate lower: per 2 bit; 00 means use as gpio; other values mean use as alternate function
#define GPIO_GPAUR(n) (GPIO_BASE + (0x14 + (n)*0x30)) // AU: alternate upper: same thing, needs 2 registers because it's 2 bits per pin.
#define GPIO_GPIDLR(n) (GPIO_BASE + (0x18 + (n)*0x30)) // IDL: interrupt detect lower: per 2 bit (GPIO_IRQ_*)
#define GPIO_GPIDUR(n) (GPIO_BASE + (0x1c + (n)*0x30)) // IDU: interrupt detect upper: same thing, upper 16 bit
#define GPIO_GPIER(n) (GPIO_BASE + (0x20 + (n)*0x30)) // IE: interrupt enable (0 is disable)
#define GPIO_GPIMR(n) (GPIO_BASE + (0x24 + (n)*0x30)) // IM:
#define GPIO_GPFR(n) (GPIO_BASE + (0x28 + (n)*0x30)) // F: flag: set on interrupt; cleared by user.
#define IRQ_GPIO_0 48
#define NUM_GPIO 128
// Pins for alternate functions:
#define __gpio_as_ssi() \
do { \
REG_GPIO_GPALR(2) &= 0xFC00FFFF; \
REG_GPIO_GPALR(2) |= 0x01550000; \
} while (0)
#define __gpio_as_uart3() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFFF0000; \
REG_GPIO_GPAUR(0) |= 0x00005555; \
} while (0)
#define __gpio_as_uart2() \
do { \
REG_GPIO_GPALR(3) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(3) |= 0x40000000; \
REG_GPIO_GPAUR(3) &= 0xF3FFFFFF; \
REG_GPIO_GPAUR(3) |= 0x04000000; \
} while (0)
#define __gpio_as_uart1() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFF0FFFF; \
REG_GPIO_GPAUR(0) |= 0x00050000; \
} while (0)
#define __gpio_as_uart0() \
do { \
REG_GPIO_GPAUR(3) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(3) |= 0x50000000; \
} while (0)
#define __gpio_as_scc0() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFFCC; \
REG_GPIO_GPALR(2) |= 0x00000011; \
} while (0)
#define __gpio_as_scc1() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFF33; \
REG_GPIO_GPALR(2) |= 0x00000044; \
} while (0)
#define __gpio_as_scc() \
do { \
__gpio_as_scc0(); \
__gpio_as_scc1(); \
} while (0)
#define __gpio_as_dma() \
do { \
REG_GPIO_GPALR(0) &= 0x00FFFFFF; \
REG_GPIO_GPALR(0) |= 0x55000000; \
REG_GPIO_GPAUR(0) &= 0xFF0FFFFF; \
REG_GPIO_GPAUR(0) |= 0x00500000; \
} while (0)
#define __gpio_as_msc() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFF000F; \
REG_GPIO_GPALR(1) |= 0x00005550; \
} while (0)
#define __gpio_as_pcmcia() \
do { \
REG_GPIO_GPAUR(2) &= 0xF000FFFF; \
REG_GPIO_GPAUR(2) |= 0x05550000; \
} while (0)
#define __gpio_as_emc(csmask) \
do { \
REG_GPIO_GPALR(2) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(2) |= 0x40000000; \
REG_GPIO_GPAUR(2) &= 0xFFFF0000; \
REG_GPIO_GPAUR(2) |= 0x00005555; \
} while (0)
#define __gpio_as_lcd_slave() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x55555555; \
} while (0)
#define __gpio_as_lcd_master() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x556A5555; \
} while (0)
#define __gpio_as_usb() \
do { \
REG_GPIO_GPAUR(0) &= 0x00FFFFFF; \
REG_GPIO_GPAUR(0) |= 0x55000000; \
} while (0)
#define __gpio_as_ac97() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF03FF; \
REG_GPIO_GPALR(2) |= 0x24005400; \
} while (0)
#define __gpio_as_i2s_slave() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x14005100; \
} while (0)
#define __gpio_as_i2s_master() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x28005100; \
} while (0)
#define __gpio_as_eth() \
do { \
REG_GPIO_GPAUR(3) &= 0xFC000000; \
REG_GPIO_GPAUR(3) |= 0x01555555; \
} while (0)
#define __gpio_as_pwm() \
do { \
REG_GPIO_GPAUR(2) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(2) |= 0x50000000; \
} while (0)
#define __gpio_as_ps2() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFFFFF0; \
REG_GPIO_GPALR(1) |= 0x00000005; \
} while (0)
#define __gpio_as_uprt() \
do { \
REG_GPIO_GPALR(1) &= 0x0000000F; \
REG_GPIO_GPALR(1) |= 0x55555550; \
REG_GPIO_GPALR(3) &= 0xC0000000; \
REG_GPIO_GPALR(3) |= 0x15555555; \
} while (0)
#define __gpio_as_cim() \
do { \
REG_GPIO_GPALR(0) &= 0xFF000000; \
REG_GPIO_GPALR(0) |= 0x00555555; \
} while (0)
// Pins on the trendtac:
0.00 keyboard
0.01 keyboard
0.02 keyboard
0.03 keyboard
0.04 keyboard
0.05 keyboard
0.06 keyboard
0.07 keyboard
0.08 keyboard interrupt?
0.09
0.10
0.11
0.12
0.13 touchpad right button
0.14
0.15
0.16 touchpad left button
0.17
0.18
0.19
0.20
0.21
0.22
0.23
0.24
0.25
0.26
0.27
0.28
0.29
0.30
0.31
1.00
1.01
1.02
1.03
1.04
1.05
1.06
1.07
1.08
1.09
1.10
1.11
1.12
1.13
1.14
1.15
1.16
1.17
1.18
1.19
1.20
1.21
1.22
1.23
1.24
1.25
1.26
1.27
1.28
1.29
1.30
1.31
2.00 SPEN: lcd enable
2.01 SPCK: lcd clock
2.02 SPDA: lcd data
2.03 LCD_RET: lcd reset
2.04
2.05
2.06
2.07
2.08
2.09
2.10
2.11
2.12
2.13
2.14
2.15
2.16
2.17
2.18
2.19
2.20
2.21
2.22
2.23
2.24
2.25
2.26
2.27
2.28
2.29
2.30 PWM enable (for lcd backlight)
2.31
3.00 keyboard
3.01 keyboard
3.02 keyboard
3.03 keyboard
3.04 keyboard
3.05 keyboard
3.06 keyboard
3.07 keyboard
3.08 keyboard
3.09 keyboard
3.10 keyboard
3.11 keyboard
3.12 keyboard
3.13 keyboard
3.14 keyboard
3.15 keyboard
3.16
3.17
3.18
3.19
3.20
3.21
3.22
3.23
3.24
3.25
3.26
3.27
3.28
3.29 keyboard
3.30
3.31
Devices enabled in linux:
+ __harb_usb0_uhc();
+ __gpio_as_emc();
+ __gpio_as_uart0();
+ __gpio_as_dma();
+ __gpio_as_eth();
+ __gpio_as_usb();
+ __gpio_as_lcd_master();
+#if defined(CONFIG_I2S_AK4642EN)
+//wjx __gpio_as_scc1();
+ __gpio_as_i2s_master(); //wjx
+#endif
+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23)
+ __gpio_as_ssi();
+#endif
+ //__gpio_as_ac97();
+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) || defined(CONFIG_I2S_CS42L51)
+ __gpio_as_i2s_slave();
+#endif
+//wjx __gpio_as_cim();
+ __gpio_as_msc();
+
+/* wjx
+ __gpio_as_output(GPIO_LED_EN);
+ __gpio_set_pin(GPIO_LED_EN);
+
+ __gpio_as_output(GPIO_DISP_OFF_N);
+ __gpio_set_pin(GPIO_DISP_OFF_N);
+*/
+ __gpio_as_output(GPIO_PWM0);
+ __gpio_set_pin(GPIO_PWM0);
+
+
+//wjx __gpio_as_input(GPIO_RTC_IRQ);
+ __gpio_as_output(GPIO_USB_CLK_EN);
+ __gpio_set_pin(GPIO_USB_CLK_EN);

View File

@@ -1,6 +1,6 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/init.ccp: System boot manager.
// bootstrap/init.ccp: Bootstrapping code.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// This program is free software: you can redistribute it and/or modify
@@ -18,136 +18,288 @@
#include "devices.hh"
#include "iris.hh"
#include <elf.h>
static Keyboard sysreq
static Device kbd_dev, buz_dev, backlight_dev, rootfs_dev
#define NUM_SLOTS 4
#define NUM_CAPS 16
static unsigned _free
extern unsigned _end
void init_alloc ():
_free = _end
char *alloc_space (unsigned pages):
unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK
_free = ret + pages * PAGE_SIZE
return (char *)ret
void *operator new[] (unsigned size):
void *ret = (void *)_free
size = (size + 3) & ~3
unsigned rest = PAGE_SIZE - (size & ~PAGE_MASK)
if rest <= size:
_free += size
return ret
unsigned pages = ((size - rest) + PAGE_SIZE - 1) & PAGE_MASK
char *space = alloc_space (pages)
for unsigned p = 0; p < pages; ++p:
Kernel::Page page = Kernel::my_memory.create_page ()
page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
Kernel::my_memory.map (page, (unsigned)&space[p << PAGE_BITS])
Kernel::free_cap (page)
_free += size
return ret
struct file:
unsigned size
// Only the first 16 characters of the name are used, because that's much easier.
// This means that file names must be different in the first 16 characters if sort order matters.
char name[16]
String string
static unsigned num_files
static file *files
static unsigned *index
static Kernel::Memory top_memory
static unsigned slot
static unsigned max_pages
static char *mapping
static unsigned current_thread
// Event types.
enum type:
SYSREQ
KBDDEV
BUZDEV
BACKLIGHTDEV
ROOTFSDEV
static void user_reply (Kernel::Cap target, unsigned dev):
switch dev:
case Keyboard::ID:
// keyboard user
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
Kernel::Cap buzzer = buz_dev.create_user (Kernel::Cap ())
buz_dev.use (buzzer)
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::Cap user
unsigned device
while true:
// Get the initial block device and filesystem.
static Directory receive_devices ():
String data
Filesystem fs
bool have_data = false, have_fs = false
for unsigned i = 0; i < 2; ++i:
Device dev
Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
switch Kernel::recv.data[0].l:
case Parent::PROVIDE_DEVICE:
switch Kernel::recv.data[1].l:
case Keyboard::ID:
switch Kernel::recv.data[0].h:
case 0:
caps.set (KBDDEV, arg.copy ())
kbd_dev = Kernel::Cap (slot, KBDDEV)
break
case 1:
caps.set (SYSREQ, arg.copy ())
sysreq = Kernel::Cap (slot, SYSREQ)
break
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 Setting::ID:
caps.set (BACKLIGHTDEV, arg.copy ())
backlight_dev = Kernel::Cap (slot, BACKLIGHTDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
case Directory::ID:
caps.set (ROOTFSDEV, arg.copy ())
rootfs_dev = Kernel::Cap (slot, ROOTFSDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("unexpected device: ")
kdebug_num (Kernel::recv.data[1].l)
kdebug_char ('\n')
break
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
kdebug ("Invalid bootstrap request.\n")
Kernel::panic (0)
switch Kernel::recv.data[1].l:
case String::ID:
if have_data:
kdebug ("duplicate device.\n")
Kernel::panic (0)
dev = Kernel::get_arg ()
have_data = true
Kernel::recv.reply.invoke ()
data = dev.create_user (Kernel::my_memory)
dev.use (data)
Kernel::free_cap (dev)
break
case Parent::GET_DEVICE:
user = reply
device = Kernel::recv.data[1].l
case Filesystem::ID:
if have_fs:
kdebug ("duplicate filesystem.\n")
Kernel::panic (0)
dev = Kernel::get_arg ()
have_fs = true
fs = dev.create_user (Kernel::my_memory)
dev.use (fs)
Kernel::free_cap (dev)
Kernel::recv.reply.invoke ()
break
default:
kdebug ("unknown setup request for init\n")
reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg)
continue
Kernel::free_cap (arg)
if ++state == 6:
break
// sysreq
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
sysreq.set_cb (cb.copy ())
Kernel::free_cap (cb)
// First user reply.
user_reply (user, device)
Kernel::free_cap (user)
kdebug ("unexpected device: ")
kdebug_num (Kernel::recv.data[1].l)
kdebug_char ('\n')
Kernel::panic (0)
// Initialize the root file system.
Directory root = fs.use_device_ro (data.copy ())
Kernel::free_cap (data)
Kernel::free_cap (fs)
return root
// Make a list of all files.
static void list_files (Directory root):
Kernel::Num fullsize = root.get_size ()
if fullsize.h != 0:
kdebug ("Too many files in bootstrap directory.\n")
Kernel::panic (0)
num_files = fullsize.l
files = new file[num_files]
Kernel::Caps caps = Kernel::my_memory.create_caps (num_files * 2)
unsigned slot = Kernel::alloc_slot ()
caps.use (slot)
for unsigned i = 0; i < num_files; ++i:
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2))
String n = root.get_name (i)
n.get_chars (0, files[i].name)
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2 + 1))
files[i].string = root.get_file_ro (i)
Kernel::Num fullsize = files[i].string.get_size ()
if fullsize.h != 0:
kdebug ("initial file size too large.\n")
Kernel::panic (0)
files[i].size = fullsize.l
if max_pages < (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK:
max_pages = (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK
// Sort the list of files.
static bool is_less (file *f1, file *f2):
for unsigned i = 0; i < 16; ++i:
if f1->name[i] < f2->name[i]:
return true
if f1->name[i] > f2->name[i]:
return false
return false
// Bubble sort.
static void sort ():
index = new unsigned[num_files]
index[0] = 0
// Invariant: index[0...f-1] is sorted.
for unsigned f = 1; f < num_files; ++f:
// Bubble up until top. Test for less-than, because it wraps to maxunsigned.
unsigned i
// Invariant: index[0...f] \ index[i+1] is sorted and index[i+1...f] is sorted.
for i = f - 1; i < f; --i:
if is_less (&files[index[i]], &files[f]):
break
index[i + 1] = index[i]
index[i + 1] = f
static void run (file *f, bool priv):
Kernel::Memory mem = top_memory.create_memory ()
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
for unsigned p = 0; p < num_pages; ++p:
Kernel::set_recv_arg (Kernel::Cap (slot, p))
mem.create_page ()
f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p))
Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS])
Kernel::Thread thread = mem.create_thread (NUM_SLOTS)
if priv:
thread.make_priv ()
Elf32_Ehdr *header = (Elf32_Ehdr *)mapping
for unsigned j = 0; j < SELFMAG; ++j:
if header->e_ident[j] != ELFMAG[j]:
kdebug ("invalid ELF magic\n")
Kernel::panic (0)
return
if header->e_ident[EI_CLASS] != ELFCLASS32:
kdebug ("invalid ELF class\n")
Kernel::panic (0)
return
if header->e_ident[EI_DATA] != ELFDATA2LSB:
kdebug ("invalid ELF data\n")
Kernel::panic (0)
return
if header->e_ident[EI_VERSION] != EV_CURRENT:
kdebug ("invalid ELF version\n")
Kernel::panic (0)
return
if header->e_type != ET_EXEC:
kdebug ("invalid ELF type\n")
Kernel::panic (0)
return
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
kdebug ("invalid ELF machine\n")
Kernel::panic (0)
return
thread.set_pc (header->e_entry)
thread.set_sp (0x80000000)
for unsigned section = 0; section < header->e_shnum; ++section:
Elf32_Shdr *shdr = (Elf32_Shdr *)((unsigned)mapping + header->e_shoff + section * header->e_shentsize)
if ~shdr->sh_flags & SHF_ALLOC:
continue
bool readonly = !(shdr->sh_flags & SHF_WRITE)
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
if shdr->sh_type != SHT_NOBITS:
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
kdebug ("thread too large\n")
Kernel::panic (0)
return
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
unsigned idx = file_offset + section_offset
Kernel::Page page = mem.mapping ((void *)p)
if Kernel::recv.data[0].l == Kernel::NO_ERROR:
// The address already has a mapping; assume that it is correct.
Kernel::free_cap (page)
continue
page = mem.create_page ()
Kernel::Page (slot, idx).share (page, 0)
if !mem.map (page, p, readonly):
kdebug ("unable to map page\n")
Kernel::panic (0)
return
Kernel::free_cap (page)
else:
if readonly:
kdebug ("unwritable bss section\n")
Kernel::panic (0)
return
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
Kernel::Page page = mem.mapping ((void *)p)
if Kernel::recv.data[0].l == Kernel::NO_ERROR:
// No error means there is no mapping.
page = mem.create_page ()
if Kernel::recv.data[0].l != Kernel::NO_ERROR:
kdebug ("out of memory\n")
Kernel::panic (0)
return
if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME):
kdebug ("out of memory\n")
Kernel::panic (0)
return
if !mem.map (page, p):
kdebug ("unable to map bss page\n")
Kernel::panic (0)
return
Kernel::free_cap (page)
else:
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
if a >= shdr->sh_addr + shdr->sh_size:
break
if a < shdr->sh_addr:
continue
((unsigned *)&mapping[p])[(a & ~PAGE_MASK) >> 2] = 0
for unsigned p = 0; p <= num_pages; ++p:
mem.destroy (Kernel::Page (slot, p))
Kernel::Page stackpage = mem.create_page ()
stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME)
if Kernel::recv.data[0].l != Kernel::NO_ERROR || !mem.map (stackpage, 0x7ffff000):
kdebug ("unable to map initial stack page\n")
Kernel::panic (0)
return
Kernel::free_cap (stackpage)
Kernel::Caps caps = mem.create_caps (NUM_CAPS)
thread.use (caps, 0)
thread.set_info (Kernel::Thread::A0, NUM_SLOTS)
thread.set_info (Kernel::Thread::A1, NUM_CAPS)
Kernel::Receiver receiver = mem.create_receiver ()
receiver.set_owner (thread.copy ())
Kernel::Cap call = receiver.create_call_capability ()
Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread)
caps.set (__receiver_num, receiver.copy ())
caps.set (__thread_num, thread.copy ())
caps.set (__memory_num, mem.copy ())
caps.set (__call_num, call.copy ())
caps.set (__parent_num, parent.copy ())
thread.run ()
Kernel::free_cap (receiver)
Kernel::free_cap (thread)
Kernel::free_cap (mem)
Kernel::free_cap (call)
Kernel::free_cap (parent)
Kernel::Num start ():
// Wait for the debugging device to be active, in case there is one.
Kernel::schedule ()
setup ()
// claim backlight
Setting backlight = backlight_dev.create_user (Kernel::Cap ())
backlight_dev.use (backlight)
bool backlight_state = true
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.value ():
case SYSREQ:
unsigned code = Kernel::recv.data[0].l
if !(code & Keyboard::RELEASE):
backlight_state = !backlight_state
backlight.set (backlight_state ? ~0 : 0)
break
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
top_memory = Kernel::get_top_memory ()
Directory root = receive_devices ()
root.lock_ro ()
list_files (root)
sort ()
Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages)
slot = caps.use ()
mapping = alloc_space (max_pages)
for unsigned i = 0; i < num_files; ++i:
run (&files[index[i]], files[index[i]].name[0] == '#')
root.unlock_ro ()
Kernel::free_slot (slot)
Kernel::my_memory.destroy (caps)
return 0

View File

@@ -1,421 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/lcd.ccp: Display driver.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "devices.hh"
#define ARCH
#include "arch.hh"
__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"\n.section .text")
extern unsigned char const charset[127-32][8][6]
#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
#if defined (TRENDTAC)
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
#define LOG_X_BASE 1
#define LOG_Y_BASE 1
#elif defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 60, Bpp = 4
#define LOG_X_BASE 0
#define LOG_Y_BASE 0
#else
#error unknown board
#endif
#define frame_size (v * h * Bpp)
static unsigned physical_descriptor
/**/struct Descriptor {
unsigned next;
unsigned frame;
unsigned id;
unsigned cmd;
} __attribute__ ((packed))
#if defined (NANONOTE)
#define SP_PORT 2
#define SPEN 21
#define SPDA 22
#define SPCK 23
static void udelay (unsigned num):
for unsigned i = 0; i < num * (JZ_EXTAL / 1000000); ++i:
// set 0 does nothing, but costs at least one clock pulse.
gpio_set (SP_PORT, 0)
// Register names. The registers are not named in the datasheet, and in some cases the name only describes a part of the bits in it.
// The registers with bit 6 set have bit 7 set instead, because of the transfer method.
enum spi_reg:
AC = 0x00
DC = 0x01
BRIGHTNESS = 0x03
FORMAT = 0x04
BACKLIGHT1 = 0x05
VBLANK = 0x06
HBLANK = 0x07
BACKLIGHT2 = 0x08
SYNC = 0x0b
POLARITY = 0x0c
CONTRAST_RGB = 0x0d
SUB_CONTRAST_R = 0x0e
SUB_BRIGHTNESS_R= 0x0f
SUB_CONTRAST_B = 0x10
SUB_BRIGHTNESS_B= 0x11
TRIM = 0x12
COLOR = 0x13
GAMMA = 0x16
GAMMA1 = 0x17
GAMMA2 = 0x18
GAMMA3 = 0x19
GAMMA4 = 0x1a
INVERSION = 0xa5
HLEVEL = 0xa6
LLEVEL = 0xa7
FB = 0xb1
static void write_reg (unsigned reg, unsigned val):
unsigned value = (reg << 8) | (val & 0xff)
gpio_clear (SP_PORT, 1 << SPEN)
udelay (1)
for unsigned i = 0; i < 16; ++i, value <<= 1:
gpio_clear (SP_PORT, 1 << SPCK)
if value & 0x8000:
gpio_set (SP_PORT, 1 << SPDA)
else:
gpio_clear (SP_PORT, 1 << SPDA)
udelay (4)
gpio_set (SP_PORT, 1 << SPCK)
udelay (4)
gpio_set (SP_PORT, 1 << SPEN)
udelay(4)
#endif
static void reset ():
#if defined (TRENDTAC)
// Note that the sync pulse is part of the pre-display region.
// Vertical timings.
unsigned vsync = 20, vpre = 20, vpost = 0
// Horizontal timings.
unsigned hsync = 80, hpre = 80, hpost = 0
// One clock pulse per pixel.
unsigned cpp = 1
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16
// Configuration.
#define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8)
unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE)
// Note that the sync pulse is part of the pre-display region.
// Horizontal timings.
unsigned hsync = 1, hpre = 70, hpost = 273
// Vertical timings.
unsigned vsync = 1, vpre = 21, vpost = 2
// 3 clocks per pixel.
unsigned cpp = 3
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration.
unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP | LCD_CFG_PCP
// Set up SPI pins.
gpio_as_output (SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
gpio_set (SP_PORT, (1 << SPEN) | (1 << SPCK))
#else
#error unknown board
#endif
// Note that the sync pulse is part of the pre-display region.
unsigned vpe = vsync, vds = vpre, vde = vds + v, vt = vde + vpost
unsigned hpe = hsync, hds = hpre, hde = hds + h, ht = hde + hpost
cpm_stop_lcd ()
unsigned pixclock = fps * ht * vt
#if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout ()
CPM_CFCR2 = pllout / pixclock - 1
unsigned val = pllout / (pixclock * 4) - 1
assert (pllout / (val + 1) <= 150000000)
assert (val <= 0xf)
cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pixclock - 1
//assert (val < 0x400)
//cpm_set_pixdiv (val)
//cpm_set_pixdiv (12)
val = cpm_get_pllout2 () / (pixclock * 3) - 1
assert (val < 0x20)
//cpm_set_ldiv (val)
// Update dividers.
//CPM_CPCCR |= CPM_CPCCR_CE
#else
#error "Unknown board"
#endif
cpm_start_lcd ()
#ifdef NANONOTE
// Reset the controller.
write_reg (BACKLIGHT1, 0x1e)
// Enable display.
write_reg (BACKLIGHT1, 0x5f)
// Set data to rgbrgbrgb input, with a delta color filter.
write_reg (COLOR, 0x01)
#endif
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
LCD_CFG = cfg
LCD_HSYNC = hpe
LCD_VSYNC = vpe
LCD_VAT = (ht << 16) | vt
LCD_DAH = (hds << 16) | hde
LCD_DAV = (vds << 16) | vde
LCD_DA0 = physical_descriptor
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_ENA
//lcd_enable_eof_intr ()
static void putchar (unsigned x, unsigned y, unsigned ch):
if ch < 32 || ch > 126:
ch = 127
ch -= 32
for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = charset[ch][r][k] * 0x00010101
static unsigned log_x = LOG_X_BASE, log_y = LOG_Y_BASE
static void inc_logx ():
if ++log_x >= h / 6:
log_x = LOG_X_BASE
if ++log_y >= v / 8:
log_y = LOG_Y_BASE
static void log_char (unsigned ch):
switch ch:
case '\n':
while log_x < h / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
default:
putchar (log_x, log_y, ch)
inc_logx ()
static void log_str (char const *str):
while *str:
log_char (*str++)
static void log_num (Kernel::Num n):
char const *encode = "0123456789abcdef"
log_char ('[')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n.h >> (4 * (7 - i))) & 0xf])
log_char (' ')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n.l >> (4 * (7 - i))) & 0xf])
log_char (']')
static void log_msg ():
log_str ("prot:")
log_num (Kernel::recv.protected_data)
log_str ("data:")
for unsigned i = 0; i < 2; ++i:
log_num (Kernel::recv.data[i])
log_char ('\n')
enum captype:
LOG = 32
SET_EOF_CB
BACKLIGHT
static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
unsigned dx2 = (x - cx) * (x - cx)
unsigned dy2 = (y - cy) * (y - cy)
unsigned d2 = dx2 + dy2
unsigned l = 120
if d2 >= l * l:
return 0
return ((l * l - d2 - 1) << 8) / (l * l)
Kernel::Num start ():
Kernel::schedule ()
map_lcd ()
map_cpm ()
#ifdef NANONOTE
map_gpio ()
#endif
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
unsigned physical = Kernel::my_memory.alloc_range (pages)
assert (physical & PAGE_MASK && ~physical)
for unsigned i = 0; i < pages; ++i:
Kernel::Page p = Kernel::my_memory.create_page ()
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
Kernel::free_cap (p)
for unsigned y = 0; y < v; ++y:
for unsigned x = 0; x < h; ++x:
unsigned r = spot (x, y, 100, 160)
unsigned g = spot (x, y, 160, 60)
unsigned b = spot (x, y, 220, 160)
#if defined (TRENDTAC)
LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
#elif defined (NANONOTE)
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 16) | (g << 8) | b
#else
#error "Define your framebuffer format."
#endif
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
unsigned paddr = p.physical_address ()
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p)
descriptor.next = physical_descriptor
descriptor.frame = physical
descriptor.id = 0xdeadbeef
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 ()
#if defined (TRENDTAC)
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
#endif
// Register the backlight device.
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
Kernel::my_parent.provide_device <Setting> (backlight)
Kernel::Cap eof_cb
bool have_eof = false
bool is_on = true
unsigned backlight_user = 0
Kernel::Num current_backlight = 0
while true:
//log_str ("Wachten...\n")
Kernel::wait ()
//log_msg ()
switch Kernel::recv.protected_data.h:
case 0:
switch Kernel::recv.protected_data.l:
case IRQ_LCD:
lcd_clr_eof ()
eof_cb.invoke ()
have_eof = false
Kernel::free_cap (eof_cb)
break
#if defined (TRENDTAC)
case LOG:
log_char (Kernel::recv.data[0].l)
break
#endif
case BACKLIGHT:
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (backlight_user++, BACKLIGHT))
reply.invoke (0, 0, c.copy ())
Kernel::free_cap (c)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
current_backlight = Kernel::my_receiver.get_protected (arg)
reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
case Device::UNUSE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
if current_backlight.value () == Kernel::my_receiver.get_protected (arg).value ():
current_backlight = 0
reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
default:
log_char ('@')
break
break
default:
log_char ('#')
log_num (Kernel::recv.protected_data)
log_char ('\n')
break
break
case BACKLIGHT:
if current_backlight.value () != Kernel::recv.protected_data.value ():
log_char ('&')
log_num (current_backlight)
log_num (Kernel::recv.protected_data)
log_char ('\n')
break
switch Kernel::recv.data[0].l:
case Setting::SET:
// TODO
unsigned state = Kernel::recv.data[1].l
if !state:
#if defined (NANONOTE)
if is_on:
write_reg (BACKLIGHT1, 0x5e)
is_on = false
#else
#endif
else:
#if defined (NANONOTE)
if !is_on:
write_reg (BACKLIGHT1, 0x5f)
is_on = true
#else
#endif
Kernel::recv.reply.invoke ()
break
case Setting::GET_RANGE:
Kernel::recv.reply.invoke (~0)
break
default:
log_char ('$')
break
break
case SET_EOF_CB:
Kernel::Cap reply = Kernel::get_reply ()
if have_eof:
Kernel::free_cap (eof_cb)
else:
Kernel::register_interrupt (IRQ_LCD)
have_eof = true
eof_cb = Kernel::get_arg ()
reply.invoke ()
Kernel::free_cap (reply)
break
default:
log_char ('~')
log_num (Kernel::recv.protected_data)
log_char ('\n')
break

View File

@@ -1,71 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/metronome.ccp: Userspace program.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "devices.hh"
#include "keys.hh"
Kernel::Num start ():
Kernel::schedule ()
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
kbd.set_cb (key)
// Frequency of the pulse train in millihertz.
unsigned mHz = 1000
// Frequency of single pulses in hertz.
unsigned freq = 1000
bool running (false)
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 * 99 / 100
break
case Key::RIGHT:
mHz = mHz * 101 / 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 (0)
break
break
default:
kdebug ("metronome: huh?\n")
break

View File

@@ -1,303 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/nanonote-gpio.ccp: gpio devices on the nanonote.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "devices.hh"
#define ARCH
#include "arch.hh"
#include "keys.hh"
//#define QI
#define SCAN_INTERVAL HZ / 50
class DevKbd:
static unsigned const NUM_COLS = 8
static unsigned const NUM_ROWS = 8
static unsigned const COLS_PORT = 2
static unsigned const ROWS_PORT = 3
static unsigned const ALL_COLS = 0x0003fc00
static unsigned const ALL_ROWS = 0x05fc0000
static unsigned const COLS[NUM_COLS]
static unsigned const ROWS[NUM_ROWS]
static unsigned const encode[NUM_ROWS][NUM_COLS]
static unsigned const NUM_KEYS = 58
static unsigned const keys[NUM_KEYS]
unsigned state[NUM_COLS]
Kernel::Cap event
bool is_active
bool is_scanning
public:
unsigned size ():
return NUM_KEYS
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 ():
if is_active:
Kernel::free_cap (event)
is_active = false
void check (unsigned col, unsigned rowdata):
for unsigned r = 0; r < NUM_ROWS; ++r:
if !((rowdata ^ state[col]) & (1 << ROWS[r])):
continue
unsigned code = encode[r][col]
if rowdata & (1 << ROWS[r]):
code |= Keyboard::RELEASE
if is_active:
event.invoke (code)
state[col] = rowdata
void delay ():
for unsigned i = 0; i < 10000; ++i:
gpio_set (0, 0)
void scan ():
unsigned r
gpio_mask_irq (ROWS_PORT, ALL_ROWS)
is_scanning = false
if !is_active:
return
for unsigned c = 0; c < NUM_COLS; ++c:
gpio_as_input (COLS_PORT, ALL_COLS & ~(1 << COLS[c]))
gpio_as_output (COLS_PORT, 1 << COLS[c])
if c > 0:
check (c - 1, r)
delay ()
else:
check (0, state[0])
delay ()
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
if r != ALL_ROWS:
is_scanning = true
gpio_as_output (COLS_PORT, ALL_COLS)
check (NUM_COLS - 1, r)
delay ()
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
unsigned high = 0, low = 0
for unsigned i = 0; i < NUM_ROWS; ++i:
if r & (1 << ROWS[i]):
low |= 1 << ROWS[i]
else:
high |= 1 << ROWS[i]
gpio_as_interrupt (ROWS_PORT, high, true, true)
gpio_as_interrupt (ROWS_PORT, low, false, true)
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
void active (Kernel::Cap cb):
inactive ()
event = cb
is_active = true
for unsigned c = 0; c < NUM_COLS; ++c:
state[c] = ALL_ROWS
scan ()
DevKbd ():
is_active = false
gpio_as_gpio (COLS_PORT, ALL_COLS)
gpio_as_gpio (ROWS_PORT, ALL_ROWS)
gpio_clear (COLS_PORT, ALL_COLS)
gpio_as_output (COLS_PORT, ALL_COLS)
gpio_as_input (ROWS_PORT, ALL_ROWS)
gpio_enable_pull (ROWS_PORT, ALL_ROWS)
for unsigned i = 0; i < NUM_COLS; ++i:
state[i] = ALL_ROWS
scan ()
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
{ 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
{ 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
}
unsigned const DevKbd::keys[NUM_KEYS] = {
#ifdef QI
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
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
}
class PowerButton:
bool state, started
Kernel::Cap cb
public:
void scan ():
gpio_mask_irq (3, 1 << 29)
bool s = gpio_get_port (3) & (1 << 29)
if s != state:
state = s
cb.invoke (state ? Keyboard::RELEASE : 0)
gpio_as_interrupt (3, 1 << 29, !state, true)
gpio_unmask_irq (3, 1 << 29)
PowerButton ():
gpio_as_gpio (3, 29)
state = true
started = false
void set_cb (Kernel::Cap c):
if started:
Kernel::free_cap (cb)
else:
started = true
cb = c
state = true
scan ()
enum codes:
KBD_DEV = 32
PWR
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
DevKbd kbd
PowerButton pwr
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
Kernel::free_cap (dev)
Kernel::free_cap (pw)
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
unsigned user (~0)
unsigned next_user (0)
Kernel::register_interrupt (IRQ_GPIO3)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.h:
case ~0:
// Alarm.
kbd.scan ()
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
break
case 0:
switch Kernel::recv.protected_data.l:
case IRQ_GPIO3:
// Interrupt.
pwr.scan ()
kbd.scan ()
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
Kernel::register_interrupt (IRQ_GPIO3)
break
case PWR:
// Power button request.
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
pwr.set_cb (Kernel::get_arg ())
Kernel::recv.reply.invoke ()
break
default:
kdebug ("power button invalid request\n")
break
break
case KBD_DEV:
// Keyboard device control request.
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, KBD_DEV))
reply.invoke (0, 0, cap.copy ())
Kernel::free_cap (cap)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::UNUSE:
kbd.inactive ()
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("gpio other dev:")
kdebug_num (Kernel::recv.data[0].l)
kdebug ("\n")
break
break
default:
break
break
case KBD_DEV:
// Keyboard device user request.
if Kernel::recv.protected_data.l != user:
kdebug ("invalid user requesting\n")
Kernel::recv.reply.invoke ()
break
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
Kernel::Cap reply = Kernel::get_reply ()
kbd.active (Kernel::get_arg ())
reply.invoke ()
Kernel::free_cap (reply)
break
case Keyboard::GET_NUM_KEYS:
Kernel::recv.reply.invoke (kbd.size ())
break
case Keyboard::GET_KEYS:
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
break
default:
kdebug ("keyboard other\n")
break
break
default:
kdebug ("keyboard unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)
kdebug ("\n")

View File

@@ -150,17 +150,19 @@ class Udc:
char configuration
unsigned size
char const *ptr
unsigned cmd_code, cmd_arg
bool rebooting
bool vendor (Setup *s)
bool vendor (Setup *s, unsigned cmd)
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
bool handle_setup (Setup *s)
bool handle_setup (Setup *s, unsigned cmd)
char log_buffer[1000]
unsigned log_buffer_size
unsigned log_buffer_start
public:
void init ()
void log (unsigned c)
void interrupt ()
void interrupt (unsigned cmd)
void send (unsigned code, unsigned arg)
Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
Udc::my_config Udc::config_descriptor = {
@@ -198,6 +200,8 @@ void Udc::init ():
s_product = (String <16>){ sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
log_buffer_size = 0
log_buffer_start = 0
cmd_code = ~0
cmd_arg = 0
// Disconnect from the bus and don't try to get high-speed.
UDC_POWER &= ~(UDC_POWER_SOFTCONN | UDC_POWER_HSENAB)
@@ -221,21 +225,35 @@ void Udc::init ():
// Connect to the host.
UDC_POWER |= UDC_POWER_SOFTCONN
bool Udc::vendor (Setup *s):
bool Udc::vendor (Setup *s, unsigned cmd):
if !(s->request_type & 0x80):
switch s->request:
case Directory::GET_SIZE:
//TODO
case Directory::GET_NAME:
//TODO
default:
kdebug ("invalid vendor request\n")
Kernel::panic (0)
return true
if s->request == 10:
static char b[2]
ptr = b
size = s->length < 2 ? s->length : 2
b[0] = '#'
if log_buffer_start == log_buffer_size:
size = 1
static unsigned b[2]
ptr = (char *)b
size = s->length < 8 ? s->length : 8
if cmd_code != ~0:
b[0] = cmd_code
b[1] = cmd_arg
cmd_code = ~0
else:
b[1] = log_buffer[log_buffer_start++]
if log_buffer_start == log_buffer_size:
log_buffer_start = 0
log_buffer_size = 0
if log_buffer_start == log_buffer_size:
b[0] = ~1
b[1] = 0
else:
b[0] = ~0
b[1] = (log_buffer[log_buffer_start++] & 0xff) * 0x01010101
if log_buffer_start == log_buffer_size:
log_buffer_start = 0
log_buffer_size = 0
else:
static char const *name = "Reboot"
ptr = name
@@ -244,6 +262,13 @@ bool Udc::vendor (Setup *s):
state = TX
return true
void Udc::send (unsigned code, unsigned arg):
if code != ~0:
kdebug ("new code sent while old one wasn't finished.\n")
Kernel::panic (0)
cmd_code = code
cmd_arg = arg
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
switch type:
case Configuration::Type:
@@ -265,7 +290,7 @@ bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
//size = (len < sizeof (device_qualifier_descriptor) ? len : sizeof (device_qualifier_descriptor))
//break
return false
// The 6 is an arbitrary number, except that String <6> in instantiated already.
// The 6 is an arbitrary number, except that String <6> is instantiated already.
case String <6>::Type:
switch idx:
case 0:
@@ -288,7 +313,7 @@ bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
state = TX
return true
bool Udc::handle_setup (Setup *s):
bool Udc::handle_setup (Setup *s, unsigned cmd):
switch s->request_type:
case STANDARD_TO_DEVICE:
switch s->request:
@@ -331,12 +356,12 @@ bool Udc::handle_setup (Setup *s):
break
case VENDOR_TO_DEVICE:
case VENDOR_FROM_DEVICE:
return vendor (s)
return vendor (s, cmd)
default:
return false
return true
void Udc::interrupt ():
void Udc::interrupt (unsigned cmd):
unsigned i = UDC_INTRUSB
if i & UDC_INTR_RESET:
state = IDLE
@@ -361,7 +386,7 @@ void Udc::interrupt ():
packet.d[0] = UDC_FIFO (0)
packet.d[1] = UDC_FIFO (0)
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
if !handle_setup (&packet.s):
if !handle_setup (&packet.s, cmd):
csr |= UDC_CSR0_SENDSTALL
break
if size == 0:
@@ -395,6 +420,8 @@ void Udc::log (unsigned c):
enum pdata:
LOG = 32
FS
DATA
DIRECTORY
Kernel::Num start ():
map_udc ()
@@ -408,52 +435,28 @@ Kernel::Num start ():
Kernel::register_interrupt (IRQ_UDC)
Device fs_dev = Kernel::my_receiver.create_capability (FS)
Kernel::my_parent.provide_device <Directory> (fs_dev)
Kernel::Num current_user = 0
unsigned data_current_user = 0, fs_current_user = 0
unsigned next_user
unsigned state = 0
while true:
Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply ()
switch Kernel::recv.protected_data.h:
case 0:
switch Kernel::recv.protected_data.l:
case IRQ_UDC:
udc.interrupt ()
udc.interrupt (state)
Kernel::register_interrupt (IRQ_UDC)
break
case LOG:
udc.log (Kernel::recv.data[0].l)
break
case FS:
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, FS))
reply.invoke (0, 0, c.copy ())
Kernel::free_cap (c)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::Cap reply = Kernel::get_reply ()
reply.invoke ()
Kernel::free_cap (reply)
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
current_user = Kernel::my_receiver.get_protected (arg)
reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg)
break
case Device::UNUSE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
if current_user.value () == Kernel::my_receiver.get_protected (arg).value ():
current_user = 0
reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg)
break
break
Device::host (FS, fs_current_user, reply)
continue
case DATA:
Device::host (DATA, data_current_user, reply)
continue
default:
udc.log ('~')
char digit[] = "0123456789abcdef"
@@ -461,18 +464,55 @@ Kernel::Num start ():
udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
udc.log ('\n')
break
case FS:
if current_user.value () != Kernel::recv.protected_data.value ():
case DATA:
if data_current_user != Kernel::recv.protected_data.l:
break
switch Kernel::recv.data[0].l:
case String::GET_SIZE:
case String::GET_CHARS:
reply.invoke (0)
Kernel::free_cap (reply)
continue
case String::GET_PAGE:
default:
reply.invoke (Kernel::ERR_INVALID_OPERATION)
Kernel::free_cap (reply)
continue
break
case FS:
if fs_current_user != Kernel::recv.protected_data.l:
break
switch Kernel::recv.data[0].l:
case Filesystem::USE_DEVICE:
case Filesystem::USE_DEVICE_RO:
Directory dir = Kernel::my_receiver.create_capability (Kernel::Num (0, DIRECTORY))
reply.invoke (0, 0, dir.copy ())
Kernel::free_cap (dir)
Kernel::free_cap (reply)
continue
default:
reply.invoke (Kernel::ERR_INVALID_OPERATION)
Kernel::free_cap (reply)
continue
case DIRECTORY:
switch Kernel::recv.data[0].l:
case Directory::GET_SIZE:
case Directory::GET_NAME:
case Directory::GET_FILE_RO:
case Directory::LOCK_RO:
case Directory::UNLOCK_RO:
Kernel::recv.reply.invoke ()
break
state = Kernel::recv.data[0].l
if Kernel::recv.data[1].h != 0:
kdebug ("index out of supported range\n")
Kernel::panic (0)
udc.send (Kernel::recv.data[0].l, Kernel::recv.data[1].l)
Kernel::free_cap (reply)
continue
case Directory::GET_FILE_RO:
//TODO
case Directory::GET_FILE_INFO:
default:
Kernel::recv.reply.invoke (~0)
break
reply.invoke (Kernel::ERR_INVALID_OPERATION)
Kernel::free_cap (reply)
continue
reply.invoke ()
Kernel::free_cap (reply)