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:
@@ -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")
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user