/branches/dd/contrib/toolchain/toolchain.ppc32.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="ppc" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.amd64.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="amd64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.ppc64.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="ppc64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.ia32.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="i686" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-pc-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.mipsel32.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="mipsel" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.sparc64.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.3" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="sparc64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.ia64.sh |
---|
15,16 → 15,18 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
INCLUDES="ia64-pc-gnu-linux_includes.tar.bz2" |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
GCC_CPP="gcc-g++-${GCC_VERSION}.tar.bz2" |
INCLUDES_SOURCE="http://download.decky.cz/" |
BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/" |
GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/" |
31,7 → 33,7 |
PLATFORM="ia64" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-pc-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
INCLUDESDIR="${WORKDIR}/include" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
39,10 → 41,6 |
echo ">>> Downloading tarballs" |
if [ ! -f "${INCLUDES}" ]; then |
wget -c "${INCLUDES_SOURCE}${INCLUDES}" |
check_error $? "Error downloading includes." |
fi |
if [ ! -f "${BINUTILS}" ]; then |
wget -c "${BINUTILS_SOURCE}${BINUTILS}" |
check_error $? "Error downloading binutils." |
75,8 → 73,6 |
fi |
echo ">>> Unpacking tarballs" |
tar -xvjf "${INCLUDES}" |
check_error $? "Error unpacking includes." |
tar -xvzf "${BINUTILS}" |
check_error $? "Error unpacking binutils." |
tar -xvjf "${GCC_CORE}" |
97,7 → 93,7 |
echo ">>> Compiling and installing GCC" |
cd "${OBJDIR}" |
check_error $? "Change directory failed." |
"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj "--with-headers=${INCLUDESDIR}" --disable-shared |
"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj --disable-shared |
check_error $? "Error configuring GCC." |
PATH="${PATH}:${PREFIX}/bin" make all-gcc install-gcc |
check_error $? "Error compiling/installing GCC." |
/branches/dd/contrib/toolchain/toolchain.arm32.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="arm" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-linux-gnu" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
/branches/dd/contrib/toolchain/toolchain.mipseb32.sh |
---|
15,9 → 15,13 |
fi |
} |
BINUTILS_VERSION="2.18" |
GCC_VERSION="4.2.2" |
if [ -z "${CROSS_PREFIX}" ] ; then |
CROSS_PREFIX="/usr/local" |
fi |
BINUTILS_VERSION="2.19" |
GCC_VERSION="4.3.2" |
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz" |
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2" |
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2" |
29,7 → 33,7 |
PLATFORM="mips" |
WORKDIR=`pwd` |
TARGET="${PLATFORM}-sgi-irix5" |
PREFIX="/usr/local/${PLATFORM}" |
PREFIX="${CROSS_PREFIX}/${PLATFORM}" |
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}" |
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}" |
OBJDIR="${WORKDIR}/gcc-obj" |
80,6 → 84,21 |
echo ">>> Compiling and installing binutils" |
cd "${BINUTILSDIR}" |
check_error $? "Change directory failed." |
patch -p1 <<EOF |
diff -Naur binutils-2.19.orig/bfd/elfxx-mips.c binutils-2.19/bfd/elfxx-mips.c |
--- binutils-2.19.orig/bfd/elfxx-mips.c 2008-08-18 20:14:04.000000000 +0200 |
+++ binutils-2.19/bfd/elfxx-mips.c 2009-01-18 18:14:47.292011299 +0100 |
@@ -1409,7 +1409,7 @@ |
function, or 0 if we can't decide which function that is. */ |
static unsigned long |
-mips16_stub_symndx (asection *sec, const Elf_Internal_Rela *relocs, |
+mips16_stub_symndx (asection *sec __attribute__((unused)), const Elf_Internal_Rela *relocs, |
const Elf_Internal_Rela *relend) |
{ |
const Elf_Internal_Rela *rel; |
EOF |
check_error $? "Error patching binutils" |
./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" "--disable-nls" |
check_error $? "Error configuring binutils." |
make all install |
/branches/dd/contrib/default/sparc64/Makefile.config |
---|
0,0 → 1,62 |
# Platform |
PLATFORM = sparc64 |
# CPU type |
MACHINE = us |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for SMP |
CONFIG_SMP = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
# Use TSB |
CONFIG_TSB = y |
# Support for Z8530 serial port |
CONFIG_Z8530 = y |
# Support for NS16550 serial port |
CONFIG_NS16550 = y |
# Support for Serengeti console |
CONFIG_SGCN = y |
# Interrupt-driven driver for NS16550? |
CONFIG_NS16550_INTERRUPT_DRIVEN = y |
# Virtually indexed D-cache support |
CONFIG_VIRT_IDX_DCACHE = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Deadlock detection support for spinlocks |
CONFIG_DEBUG_SPINLOCK = y |
# Compile kernel tests |
CONFIG_TEST = y |
# Start AP processors by the loader |
CONFIG_AP = y |
# Preserve A.OUT header in isofs.b |
CONFIG_AOUT_ISOFS_B = y |
# External ramdisk |
CONFIG_RD_EXTERNAL = n |
/branches/dd/contrib/default/sparc64/output |
---|
0,0 → 1,0 |
image.iso |
/branches/dd/contrib/default/ia64/output |
---|
0,0 → 1,0 |
image.boot |
/branches/dd/contrib/default/ia64/Makefile.config |
---|
0,0 → 1,47 |
# Platform |
PLATFORM = ia64 |
# Machine type |
MACHINE = i460GX |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for SMP |
CONFIG_SMP = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
# Use VHPT |
CONFIG_VHPT = n |
# Support for NS16550 serial port |
CONFIG_NS16550 = y |
# IOSapic on default address support |
CONFIG_IOSAPIC = y |
# Interrupt-driven driver for NS16550? |
CONFIG_NS16550_INTERRUPT_DRIVEN = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Deadlock detection support for spinlocks |
CONFIG_DEBUG_SPINLOCK = y |
# Compile kernel tests |
CONFIG_TEST = y |
/branches/dd/contrib/default/arm32/output |
---|
0,0 → 1,0 |
image.boot |
/branches/dd/contrib/default/arm32/Makefile.config |
---|
0,0 → 1,26 |
# Platform |
PLATFORM = arm32 |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Compile kernel tests |
CONFIG_TEST = y |
# Framebuffer support |
CONFIG_FB = y |
/branches/dd/contrib/default/ppc32/output |
---|
0,0 → 1,0 |
image.boot |
/branches/dd/contrib/default/ppc32/Makefile.config |
---|
0,0 → 1,26 |
# Platform |
PLATFORM = ppc32 |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Compile kernel tests |
CONFIG_TEST = y |
# Use Block Address Translation by the loader |
CONFIG_BAT = y |
/branches/dd/contrib/default/mips32/output |
---|
0,0 → 1,0 |
image.boot |
/branches/dd/contrib/default/mips32/Makefile.config |
---|
0,0 → 1,35 |
# Platform |
PLATFORM = mips32 |
# Machine type |
MACHINE = lgxemul |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Save all interrupt registers |
CONFIG_DEBUG_ALLREGS = y |
# Compile kernel tests |
CONFIG_TEST = y |
# Framebuffer support |
CONFIG_FB = y |
/branches/dd/contrib/default/ia32/output |
---|
0,0 → 1,0 |
image.iso |
/branches/dd/contrib/default/ia32/Makefile.config |
---|
0,0 → 1,59 |
# Platform |
PLATFORM = ia32 |
# CPU type |
MACHINE = pentium4 |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for SMP |
CONFIG_SMP = y |
# Improved support for hyperthreading |
CONFIG_HT = y |
# Simics BIOS AP boot fix |
CONFIG_SIMICS_FIX = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Deadlock detection support for spinlocks |
CONFIG_DEBUG_SPINLOCK = y |
# Watchpoint on rewriting AS with zero |
CONFIG_DEBUG_AS_WATCHPOINT = y |
# Save all interrupt registers |
CONFIG_DEBUG_ALLREGS = y |
# Compile kernel tests |
CONFIG_TEST = y |
# Framebuffer support |
CONFIG_FB = y |
# Framebuffer width |
CONFIG_VESA_WIDTH = 1024 |
# Framebuffer height |
CONFIG_VESA_HEIGHT = 768 |
# Framebuffer depth |
CONFIG_VESA_BPP = 24 |
/branches/dd/contrib/default/amd64/output |
---|
0,0 → 1,0 |
image.iso |
/branches/dd/contrib/default/amd64/Makefile.config |
---|
0,0 → 1,59 |
# Platform |
PLATFORM = amd64 |
# CPU type |
MACHINE = opteron |
# Ramdisk format |
RDFMT = tmpfs |
# Compiler |
COMPILER = gcc_cross |
# Debug build |
CONFIG_DEBUG = y |
# Support for SMP |
CONFIG_SMP = y |
# Improved support for hyperthreading |
CONFIG_HT = y |
# Simics BIOS AP boot fix |
CONFIG_SIMICS_FIX = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
# Support for userspace debuggers |
CONFIG_UDEBUG = n |
# Kernel console support |
CONFIG_KCONSOLE = y |
# Detailed kernel logging |
CONFIG_LOG = n |
# Deadlock detection support for spinlocks |
CONFIG_DEBUG_SPINLOCK = y |
# Watchpoint on rewriting AS with zero |
CONFIG_DEBUG_AS_WATCHPOINT = y |
# Save all interrupt registers |
CONFIG_DEBUG_ALLREGS = y |
# Compile kernel tests |
CONFIG_TEST = y |
# Framebuffer support |
CONFIG_FB = y |
# Framebuffer width |
CONFIG_VESA_WIDTH = 1024 |
# Framebuffer height |
CONFIG_VESA_HEIGHT = 768 |
# Framebuffer depth |
CONFIG_VESA_BPP = 24 |
/branches/dd/contrib/conf/SPMIPS.simics |
---|
File deleted |
/branches/dd/contrib/conf/HelenOS.amd64.simics |
---|
File deleted |
/branches/dd/contrib/conf/spmips.conf |
---|
File deleted |
/branches/dd/contrib/conf/HelenOS.sparc64.simics |
---|
File deleted |
/branches/dd/contrib/conf/bootindy |
---|
File deleted |
/branches/dd/contrib/conf/simics.conf |
---|
File deleted |
/branches/dd/contrib/conf/dot.bochsrc |
---|
File deleted |
/branches/dd/contrib/conf/gxemul.sh |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/contrib/conf/vmware.conf |
---|
File deleted |
/branches/dd/contrib/conf/HelenOS.ppc32.simics |
---|
File deleted |
/branches/dd/contrib/conf/mips32-gx.sh |
---|
0,0 → 1,3 |
#!/bin/sh |
gxemul $@ -E testmips -C R4000 -X image.boot |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
Added: svn:mergeinfo |
/branches/dd/contrib/conf/msim.conf |
---|
2,13 → 2,16 |
# MSIM configuration script |
# |
add dcpu mips1 |
add dcpu cpu0 |
add dcpu cpu1 |
add rwm mainmem 0x00000000 8M |
add rwm mainmem 0x00000000 |
mainmem generic 16M |
mainmem load "/dev/zero" |
add rom bootmem 0x1fc00000 2048k |
bootmem load "image.boot" |
add rom bootmem 0x1fc00000 |
bootmem generic 4096k |
bootmem load "image.boot" |
add dprinter printer 0x10000000 |
add dkeyboard keyboard 0x10000000 2 |
/branches/dd/contrib/conf/arm32-gx.sh |
---|
0,0 → 1,3 |
#!/bin/sh |
gxemul $@ -E testarm -X image.boot |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/contrib/util/DownloadAndPatchSILO.sh |
---|
0,0 → 1,74 |
#!/bin/bash |
# Download SILO and patch it so that it can be used to create a bootable CD |
# for the Serengeti machine |
# by Pavel Rimsky <rimskyp@seznam.cz> |
# portions by Martin Decky <martin@decky.cz> |
# |
# GPL'ed, copyleft |
# |
# stuff to be downloaded |
SILO_DOWNLOAD_FILE='silo-loaders-1.4.11.tar.gz' |
SILO_DOWNLOAD_URL='http://silo.auxio.org/pub/silo/old/'$SILO_DOWNLOAD_FILE |
# check whether the last command failed, if so, write an error message and exit |
check_error() { |
if [ "$1" -ne "0" ]; then |
echo |
echo "Script failed: $2" |
exit |
fi |
} |
# temporary files are to be stored in /tmp |
# the resulting file in the current directory |
WD=`pwd` |
cd /tmp |
# download SILO from its official website |
echo ">>> Downloading SILO" |
wget $SILO_DOWNLOAD_URL |
check_error $? "Error downloading SILO." |
# unpack the downloaded file |
echo ">>> Unpacking tarball" |
tar xvzf $SILO_DOWNLOAD_FILE |
check_error $? "Error unpacking tarball." |
# CD to the unpacked directory |
echo ">>> Changing to the unpacked SILO directory" |
cd boot |
check_error $? "Changing directory failed." |
# patch it - remove bytes 512 to 512 + 32 (counted from 0), which belong to |
# the ELF header which is not recognized by the Serengeti firmware |
echo ">>> Patching SILO" |
(((xxd -p -l 512 isofs.b) && (xxd -p -s 544 isofs.b)) | xxd -r -p) \ |
> isofs.b.patched |
check_error $? "Patching SILO failed" |
mv isofs.b.patched isofs.b |
# get rid of files which are not needed for creating the bootable CD |
echo ">>> Purging SILO directory" |
for file in `ls`; do |
if [ \( -f $file \) -a \( $file != "isofs.b" \) -a \( $file != "second.b" \) ]; |
then |
rm -fr $file; |
fi |
done |
check_error $? "Purging SILO directory failed" |
# create the gzipped tarball with patched SILO |
echo ">>> Creating tarball with patched SILO" |
tar cvzf silo.patched.tar.gz *.b |
check_error $? "Creating tarball with patched SILO failed" |
# and move it to the directory where the user expects it to be |
echo ">>> Moving the tarball with patched SILO to the current directory" |
mv silo.patched.tar.gz $WD |
check_error $? "Moving the tarball with patched SILO failed" |
# move back to the working directory from /tmp |
cd $WD |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/kernel/kernel.config |
---|
File deleted |
/branches/dd/kernel/test/avltree/avltree1.def |
---|
1,6 → 1,6 |
{ |
"avltree1", |
"Test Avl tree operations", |
"Test AVL tree operations", |
&test_avltree1, |
true |
}, |
/branches/dd/kernel/test/avltree/avltree1.c |
---|
48,7 → 48,8 |
static int test_tree_balance(avltree_node_t *node); |
static avltree_node_t *test_tree_parents(avltree_node_t *node); |
static void print_tree_structure_flat (avltree_node_t *node, int level); |
static void print_tree_structure_flat (avltree_node_t *node, int level) |
__attribute__ ((used)); |
static avltree_node_t *alloc_avltree_node(void); |
static avltree_node_t *test_tree_parents(avltree_node_t *node) |
61,14 → 62,15 |
if (node->lft) { |
tmp = test_tree_parents(node->lft); |
if (tmp != node) { |
printf("Bad parent pointer key: %d, address: %p\n", |
tmp->key, node->lft); |
printf("Bad parent pointer key: %" PRIu64 |
", address: %p\n", tmp->key, node->lft); |
} |
} |
if (node->rgt) { |
tmp = test_tree_parents(node->rgt); |
if (tmp != node) { |
printf("Bad parent pointer key: %d, address: %p\n", |
printf("Bad parent pointer key: %" PRIu64 |
", address: %p\n", |
tmp->key,node->rgt); |
} |
} |
94,7 → 96,8 |
* Prints the structure of the node, which is level levels from the top of the |
* tree. |
*/ |
static void print_tree_structure_flat(avltree_node_t *node, int level) |
static void |
print_tree_structure_flat(avltree_node_t *node, int level) |
{ |
/* |
* You can set the maximum level as high as you like. |
109,7 → 112,7 |
if (node == NULL) |
return; |
printf("%d[%d]", node->key, node->balance); |
printf("%" PRIu64 "[%" PRIu8 "]", node->key, node->balance); |
if (node->lft != NULL || node->rgt != NULL) { |
printf("("); |
130,6 → 133,7 |
for (i = 0; i < NODE_COUNT - 1; i++) { |
avltree_nodes[i].par = &avltree_nodes[i + 1]; |
} |
avltree_nodes[i].par = NULL; |
/* |
* Node keys which will be used for insertion. Up to NODE_COUNT size of |
169,7 → 173,6 |
for (i = 21; i < NODE_COUNT; i++) |
avltree_nodes[i].key = i * 3; |
avltree_nodes[i].par = NULL; |
first_free_node = &avltree_nodes[0]; |
} |
191,7 → 194,7 |
avltree_create(tree); |
if (!quiet) |
printf("Inserting %d nodes...", node_count); |
printf("Inserting %" PRIc " nodes...", node_count); |
for (i = 0; i < node_count; i++) { |
newnode = alloc_avltree_node(); |
/branches/dd/kernel/test/synch/rwlock3.c |
---|
45,14 → 45,14 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("cpu%d, tid %llu: trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for reading....\n", CPU->id, THREAD->tid); |
rwlock_read_lock(&rwlock); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) { |
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid); |
printf("cpu%d, tid %llu: trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": trying to lock rwlock for writing....\n", CPU->id, THREAD->tid); |
} |
rwlock_write_lock(&rwlock); |
59,7 → 59,7 |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu: success\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 ": success\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
88,7 → 88,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dd/kernel/test/synch/rwlock4.c |
---|
60,7 → 60,7 |
spinlock_lock(&rw_lock); |
rc = seed % max; |
seed = (((seed<<2) ^ (seed>>2)) * 487) + rc; |
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc; |
spinlock_unlock(&rw_lock); |
return rc; |
} |
74,18 → 74,18 |
to = random(40000); |
if (!sh_quiet) |
printf("cpu%d, tid %llu w+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " w+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_write_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%d, tid %llu w!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %llu w=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w=\n", CPU->id, THREAD->tid); |
if (rwlock.readers_in) { |
if (!sh_quiet) |
106,7 → 106,7 |
rwlock_write_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu w-\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " w-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
119,24 → 119,24 |
to = random(2000); |
if (!sh_quiet) |
printf("cpu%d, tid %llu r+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " r+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = rwlock_read_lock_timeout(&rwlock, to); |
if (SYNCH_FAILED(rc)) { |
if (!sh_quiet) |
printf("cpu%d, tid %llu r!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r!\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
return; |
} |
if (!sh_quiet) |
printf("cpu%d, tid %llu r=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r=\n", CPU->id, THREAD->tid); |
thread_usleep(30000); |
rwlock_read_unlock(&rwlock); |
if (!sh_quiet) |
printf("cpu%d, tid %llu r-\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " r-\n", CPU->id, THREAD->tid); |
atomic_dec(&thread_count); |
} |
159,8 → 159,8 |
context_save(&ctx); |
if (!quiet) { |
printf("sp=%#x, readers_in=%d\n", ctx.sp, rwlock.readers_in); |
printf("Creating %d readers\n", rd); |
printf("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in); |
printf("Creating %" PRIu32 " readers\n", rd); |
} |
for (i = 0; i < rd; i++) { |
168,11 → 168,11 |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create reader %d\n", i); |
printf("Could not create reader %" PRIu32 "\n", i); |
} |
if (!quiet) |
printf("Creating %d writers\n", wr); |
printf("Creating %" PRIu32 " writers\n", wr); |
for (i = 0; i < wr; i++) { |
thrd = thread_create(writer, NULL, TASK, 0, "writer", false); |
179,7 → 179,7 |
if (thrd) |
thread_ready(thrd); |
else if (!quiet) |
printf("Could not create writer %d\n", i); |
printf("Could not create writer %" PRIu32 "\n", i); |
} |
thread_usleep(20000); |
187,7 → 187,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dd/kernel/test/synch/semaphore2.c |
---|
53,7 → 53,7 |
spinlock_lock(&sem_lock); |
rc = seed % max; |
seed = (((seed<<2) ^ (seed>>2)) * 487) + rc; |
seed = (((seed << 2) ^ (seed >> 2)) * 487) + rc; |
spinlock_unlock(&sem_lock); |
return rc; |
} |
67,18 → 67,18 |
waitq_sleep(&can_start); |
to = random(20000); |
printf("cpu%d, tid %llu down+ (%d)\n", CPU->id, THREAD->tid, to); |
printf("cpu%u, tid %" PRIu64 " down+ (%d)\n", CPU->id, THREAD->tid, to); |
rc = semaphore_down_timeout(&sem, to); |
if (SYNCH_FAILED(rc)) { |
printf("cpu%d, tid %llu down!\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " down!\n", CPU->id, THREAD->tid); |
return; |
} |
printf("cpu%d, tid %llu down=\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " down=\n", CPU->id, THREAD->tid); |
thread_usleep(random(30000)); |
semaphore_up(&sem); |
printf("cpu%d, tid %llu up\n", CPU->id, THREAD->tid); |
printf("cpu%u, tid %" PRIu64 " up\n", CPU->id, THREAD->tid); |
} |
char * test_semaphore2(bool quiet) |
91,7 → 91,7 |
thread_t *thrd; |
k = random(7) + 1; |
printf("Creating %d consumers\n", k); |
printf("Creating %" PRIu32 " consumers\n", k); |
for (i = 0; i < k; i++) { |
thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false); |
if (thrd) |
/branches/dd/kernel/test/synch/rwlock5.c |
---|
108,7 → 108,7 |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while ((items_read.count != readers) || (items_written.count != writers)) { |
printf("%zd readers remaining, %zd writers remaining, readers_in=%zd\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
printf("%d readers remaining, %d writers remaining, readers_in=%d\n", readers - items_read.count, writers - items_written.count, rwlock.readers_in); |
thread_usleep(100000); |
} |
} |
/branches/dd/kernel/test/test.h |
---|
36,12 → 36,13 |
#define KERN_TEST_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
typedef char * (* test_entry_t)(bool); |
typedef char *(*test_entry_t)(bool); |
typedef struct { |
char * name; |
char * desc; |
char *name; |
char *desc; |
test_entry_t entry; |
bool safe; |
} test_t; |
/branches/dd/kernel/test/debug/mips1_skip.c |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <test.h> |
char *test_mips1(bool quiet) |
{ |
return NULL; |
} |
/branches/dd/kernel/test/debug/mips1.def |
---|
1,4 → 1,3 |
#ifdef mips32 |
{ |
"mips1", |
"MIPS debug test", |
5,4 → 4,3 |
&test_mips1, |
false |
}, |
#endif |
/branches/dd/kernel/test/debug/mips1.c |
---|
25,8 → 25,6 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef mips32 |
#include <print.h> |
#include <debug.h> |
38,10 → 36,10 |
#include <arch.h> |
char * test_mips1(bool quiet) |
char *test_mips1(bool quiet) |
{ |
if (!quiet) |
printf("You should enter kconsole debug mode now.\n"); |
printf("If kconsole is compiled in, you should enter debug mode now.\n"); |
asm volatile ( |
"break\n" |
49,5 → 47,3 |
return "Back from debug mode"; |
} |
#endif |
/branches/dd/kernel/test/thread/thread1.c |
---|
48,7 → 48,7 |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", THREAD->tid); |
printf("%" PRIu64 " ", THREAD->tid); |
thread_usleep(100000); |
} |
atomic_inc(&threads_finished); |
/branches/dd/kernel/test/mm/purge1.def |
---|
1,4 → 1,3 |
#ifdef ia64 |
{ |
"purge1", |
"Itanium TLB purge test", |
5,4 → 4,3 |
&test_purge1, |
true |
}, |
#endif |
/branches/dd/kernel/test/mm/falloc2.c |
---|
55,10 → 55,10 |
uint8_t val = THREAD->tid % THREADS; |
index_t k; |
uintptr_t * frames = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), FRAME_ATOMIC); |
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC); |
if (frames == NULL) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Unable to allocate frames\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id); |
atomic_inc(&thread_fail); |
atomic_dec(&thread_count); |
return; |
69,11 → 69,11 |
for (run = 0; run < THREAD_RUNS; run++) { |
for (order = 0; order <= MAX_ORDER; order++) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
printf("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order); |
allocated = 0; |
for (i = 0; i < (MAX_FRAMES >> order); i++) { |
frames[allocated] = (uintptr_t)frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
frames[allocated] = frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
if (frames[allocated]) { |
memsetb(frames[allocated], FRAME_SIZE << order, val); |
allocated++; |
82,16 → 82,16 |
} |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
printf("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated); |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Deallocating ... \n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id); |
for (i = 0; i < allocated; i++) { |
for (k = 0; k <= (((index_t) FRAME_SIZE << order) - 1); k++) { |
if (((uint8_t *) frames[i])[k] != val) { |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Unexpected data (%d) in block %p offset %#zx\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
printf("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k); |
atomic_inc(&thread_fail); |
goto cleanup; |
} |
100,7 → 100,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Finished run.\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id); |
} |
} |
108,7 → 108,7 |
free(frames); |
if (!sh_quiet) |
printf("Thread #%llu (cpu%d): Exiting\n", THREAD->tid, CPU->id); |
printf("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id); |
atomic_dec(&thread_count); |
} |
124,7 → 124,7 |
thread_t * thrd = thread_create(falloc, NULL, TASK, 0, "falloc", false); |
if (!thrd) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
printf("Could not create thread %u\n", i); |
break; |
} |
thread_ready(thrd); |
132,7 → 132,7 |
while (atomic_get(&thread_count) > 0) { |
if (!quiet) |
printf("Threads left: %d\n", atomic_get(&thread_count)); |
printf("Threads left: %ld\n", atomic_get(&thread_count)); |
thread_sleep(1); |
} |
/branches/dd/kernel/test/mm/slab1.c |
---|
53,7 → 53,7 |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
71,7 → 71,7 |
for (i = 0; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
89,7 → 89,7 |
for (i = count / 2; i < count; i++) { |
data[i] = slab_alloc(cache, 0); |
memsetb((uintptr_t) data[i], size, 0); |
memsetb(data[i], size, 0); |
} |
if (!quiet) { |
137,7 → 137,7 |
thread_detach(THREAD); |
if (!sh_quiet) |
printf("Starting thread #%llu...\n", THREAD->tid); |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
for (j = 0; j < 10; j++) { |
for (i = 0; i < THR_MEM_COUNT; i++) |
151,7 → 151,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu finished\n", THREAD->tid); |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
semaphore_up(&thr_sem); |
} |
/branches/dd/kernel/test/mm/purge1.c |
---|
26,8 → 26,6 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef ia64 |
#include <print.h> |
#include <test.h> |
#include <mm/page.h> |
47,10 → 45,10 |
tlb_entry_t entryd; |
int i; |
entryd.word[0] = 0; |
entryd.word[1] = 0; |
entryd.p = true; /* present */ |
entryd.ma = MA_WRITEBACK; |
entryd.a = true; /* already accessed */ |
77,11 → 75,9 |
dtc_mapping_insert(0 + i * (1 << PAGE_WIDTH), 9, entryd); |
} |
tlb_invalidate_pages(8,0x0c000,14); |
tlb_invalidate_pages(8, 0x0c000, 14); |
/*tlb_invalidate_all();*/ |
/* tlb_invalidate_all(); */ |
return NULL; |
} |
#endif |
/branches/dd/kernel/test/mm/slab2.c |
---|
68,8 → 68,8 |
slab_free(cache2, data2); |
break; |
} |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb((uintptr_t) data2, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
memsetb(data2, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
*((void **) data2) = olddata2; |
olddata1 = data1; |
100,7 → 100,7 |
printf("Incorrect memory size - use another test."); |
return; |
} |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
olddata1 = data1; |
} |
108,7 → 108,7 |
data1 = slab_alloc(cache1, FRAME_ATOMIC); |
if (!data1) |
break; |
memsetb((uintptr_t) data1, ITEM_SIZE, 0); |
memsetb(data1, ITEM_SIZE, 0); |
*((void **) data1) = olddata1; |
olddata1 = data1; |
} |
150,11 → 150,11 |
mutex_unlock(&starter_mutex); |
if (!sh_quiet) |
printf("Starting thread #%llu...\n",THREAD->tid); |
printf("Starting thread #%" PRIu64 "...\n", THREAD->tid); |
/* Alloc all */ |
if (!sh_quiet) |
printf("Thread #%llu allocating...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
166,7 → 166,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu releasing...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
176,7 → 176,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu allocating...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " allocating...\n", THREAD->tid); |
while (1) { |
/* Call with atomic to detect end of memory */ |
188,7 → 188,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu releasing...\n", THREAD->tid); |
printf("Thread #%" PRIu64 " releasing...\n", THREAD->tid); |
while (data) { |
new = *((void **)data); |
198,7 → 198,7 |
} |
if (!sh_quiet) |
printf("Thread #%llu finished\n", THREAD->tid); |
printf("Thread #%" PRIu64 " finished\n", THREAD->tid); |
slab_print_list(); |
semaphore_up(&thr_sem); |
216,7 → 216,7 |
printf("Running stress test with size %d\n", size); |
condvar_initialize(&thread_starter); |
mutex_initialize(&starter_mutex); |
mutex_initialize(&starter_mutex, MUTEX_PASSIVE); |
thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0); |
semaphore_initialize(&thr_sem,0); |
/branches/dd/kernel/test/mm/purge1_skip.c |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <test.h> |
char *test_purge1(bool quiet) |
{ |
return NULL; |
} |
/branches/dd/kernel/test/fpu/fpu1.c |
---|
File deleted |
/branches/dd/kernel/test/fpu/fpu1_ia64.c |
---|
0,0 → 1,179 |
/* |
* Copyright (c) 2005 Jakub Vana |
* Copyright (c) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <print.h> |
#include <debug.h> |
#include <test.h> |
#include <atomic.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <arch/arch.h> |
#define THREADS 150 |
#define ATTEMPTS 100 |
#define E_10e8 271828182 |
#define PI_10e8 3141592 |
static inline long double sqrt(long double a) |
{ |
long double x = 1; |
long double lx = 0; |
if (a < 0.00000000000000001) |
return 0; |
while (x != lx) { |
lx = x; |
x = (x + (a / x)) / 2; |
} |
return x; |
} |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void e(void *data) |
{ |
int i; |
double e, d, le, f; |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i<ATTEMPTS; i++) { |
le = -1; |
e = 0; |
f = 1; |
for (d = 1; e != le; d *= f, f += 1) { |
le = e; |
e = e + 1 / d; |
} |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
} |
atomic_inc(&threads_ok); |
} |
static void pi(void *data) |
{ |
int i; |
double lpi, pi; |
double n, ab, ad; |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
lpi = -1; |
pi = 0; |
for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) { |
double sc, cd; |
sc = sqrt(1 - (ab * ab / 4)); |
cd = 1 - sc; |
ad = sqrt(ab * ab / 4 + cd * cd); |
lpi = pi; |
pi = 2 * n * ad; |
} |
if ((int) (1000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (1000000 * pi), (unative_t) (PI_10e8 / 100)); |
atomic_inc(&threads_fault); |
break; |
} |
} |
atomic_inc(&threads_ok); |
} |
char * test_fpu1(bool quiet) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
total++; |
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
if (atomic_get(&threads_fault) == 0) |
return NULL; |
return "Test failed"; |
} |
/branches/dd/kernel/test/fpu/fpu1_x86.c |
---|
0,0 → 1,176 |
/* |
* Copyright (c) 2005 Jakub Vana |
* Copyright (c) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <print.h> |
#include <debug.h> |
#include <test.h> |
#include <atomic.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <arch/arch.h> |
#define THREADS 150 |
#define ATTEMPTS 100 |
#define E_10e8 271828182 |
#define PI_10e8 314159265 |
static inline double sqrt(double x) |
{ |
double v; |
asm ( |
"fsqrt\n" |
: "=t" (v) |
: "0" (x) |
); |
return v; |
} |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
static waitq_t can_start; |
static bool sh_quiet; |
static void e(void *data) |
{ |
int i; |
double e, d, le, f; |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i<ATTEMPTS; i++) { |
le = -1; |
e = 0; |
f = 1; |
for (d = 1; e != le; d *= f, f += 1) { |
le = e; |
e = e + 1 / d; |
} |
if ((int) (100000000 * e) != E_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * e), (unative_t) E_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
} |
atomic_inc(&threads_ok); |
} |
static void pi(void *data) |
{ |
int i; |
double lpi, pi; |
double n, ab, ad; |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
lpi = -1; |
pi = 0; |
for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) { |
double sc, cd; |
sc = sqrt(1 - (ab * ab / 4)); |
cd = 1 - sc; |
ad = sqrt(ab * ab / 4 + cd * cd); |
lpi = pi; |
pi = 2 * n * ad; |
} |
if ((int) (100000000 * pi) != PI_10e8) { |
if (!sh_quiet) |
printf("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (unative_t) (100000000 * pi), (unative_t) PI_10e8); |
atomic_inc(&threads_fault); |
break; |
} |
} |
atomic_inc(&threads_ok); |
} |
char * test_fpu1(bool quiet) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
waitq_initialize(&can_start); |
atomic_set(&threads_ok, 0); |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
total++; |
if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) { |
if (!quiet) |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
total++; |
} |
if (!quiet) |
printf("ok\n"); |
thread_sleep(1); |
waitq_wakeup(&can_start, WAKEUP_ALL); |
while (atomic_get(&threads_ok) != (long) total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_ok)); |
thread_sleep(1); |
} |
if (atomic_get(&threads_fault) == 0) |
return NULL; |
return "Test failed"; |
} |
/branches/dd/kernel/test/fpu/mips2_skip.c |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <test.h> |
char * test_mips2(bool quiet) |
{ |
return NULL; |
} |
/branches/dd/kernel/test/fpu/fpu1_skip.c |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <test.h> |
char * test_fpu1(bool quiet) |
{ |
return NULL; |
} |
/branches/dd/kernel/test/fpu/sse1_skip.c |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <test.h> |
char * test_sse1(bool quiet) |
{ |
return NULL; |
} |
/branches/dd/kernel/test/fpu/mips2.def |
---|
1,4 → 1,3 |
#ifdef mips32 |
{ |
"mips2", |
"MIPS FPU test", |
5,4 → 4,3 |
&test_mips2, |
true |
}, |
#endif |
/branches/dd/kernel/test/fpu/fpu1.def |
---|
1,4 → 1,3 |
#if (defined(ia32) || defined(amd64) || defined(ia64) || defined(ia32xen)) |
{ |
"fpu1", |
"Intel FPU test", |
5,4 → 4,3 |
&test_fpu1, |
true |
}, |
#endif |
/branches/dd/kernel/test/fpu/sse1.def |
---|
1,4 → 1,3 |
#if (defined(ia32) || defined(amd64) || defined(ia32xen)) |
{ |
"sse1", |
"Intel SEE test", |
5,4 → 4,3 |
&test_sse1, |
true |
}, |
#endif |
/branches/dd/kernel/test/fpu/mips2.c |
---|
26,8 → 26,6 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef mips32 |
#include <print.h> |
#include <debug.h> |
38,9 → 36,9 |
#include <arch.h> |
#define THREADS 50 |
#define DELAY 10000L |
#define ATTEMPTS 5 |
#define THREADS 50 |
#define DELAY 10000L |
#define ATTEMPTS 5 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
56,7 → 54,7 |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"mtc1 %0,$1" |
72,7 → 70,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
89,13 → 87,13 |
thread_detach(THREAD); |
waitq_sleep(&can_start); |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"mtc1 %0,$1" |
: "=r" (arg) |
); |
scheduler(); |
asm volatile ( |
"mfc1 %0,$1" |
104,7 → 102,7 |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("General reg tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
123,14 → 121,14 |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %d threads... ", 2 * THREADS); |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i); |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
138,7 → 136,7 |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i + 1); |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
162,5 → 160,3 |
return "Test failed"; |
} |
#endif |
/branches/dd/kernel/test/fpu/sse1.c |
---|
26,8 → 26,6 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#if (defined(ia32) || defined(amd64) || defined(ia32xen)) |
#include <print.h> |
#include <debug.h> |
38,9 → 36,9 |
#include <arch.h> |
#define THREADS 25 |
#define DELAY 10000L |
#define ATTEMPTS 5 |
#define THREADS 25 |
#define DELAY 10000L |
#define ATTEMPTS 5 |
static atomic_t threads_ok; |
static atomic_t threads_fault; |
60,19 → 58,19 |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"movlpd %0, %%xmm2\n" |
: "=m" (arg) |
"movlpd %[arg], %%xmm2\n" |
: [arg] "=m" (arg) |
); |
delay(DELAY); |
asm volatile ( |
"movlpd %%xmm2, %0\n" |
: "=m" (after_arg) |
"movlpd %%xmm2, %[after_arg]\n" |
: [after_arg] "=m" (after_arg) |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
92,19 → 90,19 |
for (i = 0; i < ATTEMPTS; i++) { |
asm volatile ( |
"movlpd %0, %%xmm2\n" |
: "=m" (arg) |
"movlpd %[arg], %%xmm2\n" |
: [arg] "=m" (arg) |
); |
scheduler(); |
asm volatile ( |
"movlpd %%xmm2, %0\n" |
: "=m" (after_arg) |
"movlpd %%xmm2, %[after_arg]\n" |
: [after_arg] "=m" (after_arg) |
); |
if (arg != after_arg) { |
if (!sh_quiet) |
printf("tid%llu: arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
printf("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg); |
atomic_inc(&threads_fault); |
break; |
} |
123,7 → 121,7 |
atomic_set(&threads_fault, 0); |
if (!quiet) |
printf("Creating %d threads... ", 2 * THREADS); |
printf("Creating %u threads... ", 2 * THREADS); |
for (i = 0; i < THREADS; i++) { |
thread_t *t; |
130,7 → 128,7 |
if (!(t = thread_create(testit1, (void *) ((unative_t) 2 * i), TASK, 0, "testit1", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i); |
printf("could not create thread %u\n", 2 * i); |
break; |
} |
thread_ready(t); |
138,7 → 136,7 |
if (!(t = thread_create(testit2, (void *) ((unative_t) 2 * i + 1), TASK, 0, "testit2", false))) { |
if (!quiet) |
printf("could not create thread %d\n", 2 * i + 1); |
printf("could not create thread %u\n", 2 * i + 1); |
break; |
} |
thread_ready(t); |
162,5 → 160,3 |
return "Test failed"; |
} |
#endif |
/branches/dd/kernel/test/print/print1.c |
---|
44,12 → 44,12 |
printf(" text 8.10s %8.10s \n", "text"); |
printf(" very long text 8.10s %8.10s \n", "very long text"); |
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n",'a', 'b', 'c', 'd', 'e' ); |
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",1, 1, 1, 1, 1 ); |
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 ); |
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 ); |
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n", 'a', 'b', 'c', 'd', 'e'); |
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n", 1, 1, 1, 1, 1); |
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n", -1, -1, -1, -1, -1); |
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n", 17, 17, 17, 17, 17); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#" PRIxn "'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" ); |
printf(" Print to NULL '%s'\n", NULL); |
/branches/dd/kernel/doc/BUGS_FOUND |
---|
File deleted |
/branches/dd/kernel/doc/AUTHORS |
---|
1,12 → 1,12 |
Jakub Jermar <jermar@helenos.eu> |
Martin Decky <decky@helenos.eu> |
Ondrej Palkovsky <palkovsky@helenos.eu> |
Jakub Vana <vana@helenos.eu> |
Josef Cejka <cejka@helenos.eu> |
Michal Kebrt <michalek.k@seznam.cz> |
Sergey Bondari <bondari@helenos.eu> |
Pavel Jancik <alfik.009@seznam.cz> |
Petr Stepan <stepan.petr@volny.cz> |
Michal Konopa <mkonopa@seznam.cz> |
Jakub Jermar |
Martin Decky |
Ondrej Palkovsky |
Jiri Svoboda |
Jakub Vana |
Josef Cejka |
Michal Kebrt |
Sergey Bondari |
Pavel Jancik |
Petr Stepan |
Michal Konopa |
Vojtech Mencl |
/branches/dd/kernel/doc/arch/mips32 |
---|
3,11 → 3,9 |
mips32 is the second port of SPARTAN kernel originally written by Jakub Jermar. |
It was first developed to run on MIPS R4000 32-bit simulator. |
Now it can run on real hardware as well. |
It can be compiled and run either as little- or big-endian. |
HARDWARE REQUIREMENTS |
o SGI Indy R4600 |
o emulated MIPS 4K CPU |
CPU |
/branches/dd/kernel/genarch/include/kbd/key.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/scanc_pc.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/z8530.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/scanc_sun.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/ns16550.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/i8042.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbd/scanc.h |
---|
File deleted |
/branches/dd/kernel/genarch/include/kbrd/kbrd.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef KERN_KBD_H_ |
#define KERN_KBD_H_ |
#include <console/chardev.h> |
extern chardev_t kbrdin; |
extern void kbrd_init(chardev_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/kbrd/scanc_pc.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pc keyboards. |
*/ |
#ifndef KERN_SCANC_PC_H_ |
#define KERN_SCANC_PC_H_ |
#define SC_ESC 0x01 |
#define SC_BACKSPACE 0x0e |
#define SC_LSHIFT 0x2a |
#define SC_RSHIFT 0x36 |
#define SC_CAPSLOCK 0x3a |
#define SC_SPEC_ESCAPE 0xe0 |
#define SC_LEFTARR 0x4b |
#define SC_RIGHTARR 0x4d |
#define SC_UPARR 0x48 |
#define SC_DOWNARR 0x50 |
#define SC_DELETE 0x53 |
#define SC_HOME 0x47 |
#define SC_END 0x4f |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/include/kbrd/scanc_sun.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for sun keyboards. |
*/ |
#ifndef KERN_SCANC_SUN_H_ |
#define KERN_SCANC_SUN_H_ |
#define SC_ESC 0x1d |
#define SC_BACKSPACE 0x2b |
#define SC_LSHIFT 0x63 |
#define SC_RSHIFT 0x6e |
#define SC_CAPSLOCK 0x77 |
#define SC_SPEC_ESCAPE 0xe0 /* ??? */ |
#define SC_LEFTARR 0x18 |
#define SC_RIGHTARR 0x1c |
#define SC_UPARR 0x14 |
#define SC_DOWNARR 0x1b |
#define SC_DELETE 0x42 |
#define SC_HOME 0x34 |
#define SC_END 0x4a |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/include/kbrd/scanc.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef KERN_SCANC_H_ |
#define KERN_SCANC_H_ |
#define SPECIAL '?' |
extern char sc_primary_map[]; |
extern char sc_secondary_map[]; |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/include/kbrd |
---|
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/fb/font-8x16.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
35,11 → 35,14 |
#ifndef KERN_FONT_8X16_H_ |
#define KERN_FONT_8X16_H_ |
#define FONT_GLIPHS 256 |
#define FONT_SCANLINES 16 |
#define FONT_GLYPHS 256 |
#define FONT_WIDTH 8 |
#define FONT_SCANLINES 16 |
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES]; |
#include <arch/types.h> |
extern uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES]; |
#endif |
/** @} |
/branches/dd/kernel/genarch/include/fb/logo-196x66.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_LOGO_196X66_H_ |
#define KERN_LOGO_196X66_H_ |
#define LOGO_WIDTH 196 |
#define LOGO_HEIGHT 66 |
#define LOGO_COLOR 0xffffff |
#include <arch/types.h> |
extern uint32_t fb_logo[LOGO_WIDTH * LOGO_HEIGHT]; |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/fb/visuals.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
35,15 → 35,16 |
#ifndef KERN_VISUALS_H_ |
#define KERN_VISUALS_H_ |
#define VISUAL_INDIRECT_8 0 |
#define VISUAL_INDIRECT_8 0 |
#define VISUAL_RGB_5_5_5 1 |
#define VISUAL_RGB_5_6_5 2 |
#define VISUAL_RGB_8_8_8 3 |
#define VISUAL_RGB_8_8_8_0 4 |
#define VISUAL_RGB_0_8_8_8 5 |
#define VISUAL_RGB_5_5_5 1 |
#define VISUAL_RGB_5_6_5 2 |
#define VISUAL_RGB_8_8_8 3 |
#define VISUAL_RGB_8_8_8_0 4 |
#define VISUAL_RGB_0_8_8_8 5 |
#define VISUAL_BGR_0_8_8_8 6 |
#define VISUAL_BGR_0_8_8_8 6 |
#define VISUAL_BGR_8_8_8 7 |
#endif |
/branches/dd/kernel/genarch/include/fb/fb.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
38,9 → 38,37 |
#include <arch/types.h> |
#include <synch/spinlock.h> |
/** |
* Properties of the framebuffer device. |
*/ |
typedef struct fb_properties { |
/** Physical address of the framebuffer device. */ |
uintptr_t addr; |
/** |
* Address where the first (top left) pixel is mapped, |
* relative to "addr". |
*/ |
unsigned int offset; |
/** Screen width in pixels. */ |
unsigned int x; |
/** Screen height in pixels. */ |
unsigned int y; |
/** Bytes per one scanline. */ |
unsigned int scan; |
/** Color model. */ |
unsigned int visual; |
} fb_properties_t; |
SPINLOCK_EXTERN(fb_lock); |
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan, unsigned int visual); |
void fb_redraw(void); |
void fb_init(fb_properties_t *props); |
#endif |
/** @} |
/branches/dd/kernel/genarch/include/mm/page_pt.h |
---|
116,9 → 116,7 |
#define PTE_WRITABLE(p) PTE_WRITABLE_ARCH((p)) |
#define PTE_EXECUTABLE(p) PTE_EXECUTABLE_ARCH((p)) |
#ifndef __OBJC__ |
extern as_operations_t as_pt_operations; |
#endif |
extern page_mapping_operations_t pt_mapping_operations; |
extern void page_mapping_insert_pt(as_t *as, uintptr_t page, uintptr_t frame, |
/branches/dd/kernel/genarch/include/ofw/ofw_tree.h |
---|
30,6 → 30,8 |
#define KERN_OFW_TREE_H_ |
#include <arch/types.h> |
#include <ddi/irq.h> |
#include <typedefs.h> |
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32 |
42,11 → 44,11 |
ofw_tree_node_t *peer; |
ofw_tree_node_t *child; |
uint32_t node_handle; /**< Old OpenFirmware node handle. */ |
uint32_t node_handle; /**< Old OpenFirmware node handle. */ |
char *da_name; /**< Disambigued name. */ |
char *da_name; /**< Disambigued name. */ |
unsigned properties; /**< Number of properties. */ |
unsigned properties; /**< Number of properties. */ |
ofw_tree_property_t *property; |
/** |
104,7 → 106,7 |
uint32_t child_space; |
uint32_t child_base; |
uint32_t parent_space; |
uint64_t parent_base; /* group phys.mid and phys.lo together */ |
uint64_t parent_base; /* group phys.mid and phys.lo together */ |
uint32_t size; |
} __attribute__ ((packed)); |
typedef struct ofw_ebus_range ofw_ebus_range_t; |
126,8 → 128,8 |
typedef struct ofw_ebus_intr_mask ofw_ebus_intr_mask_t; |
struct ofw_pci_reg { |
uint32_t space; /* needs to be masked to obtain pure space id */ |
uint64_t addr; /* group phys.mid and phys.lo together */ |
uint32_t space; /* needs to be masked to obtain pure space id */ |
uint64_t addr; /* group phys.mid and phys.lo together */ |
uint64_t size; |
} __attribute__ ((packed)); |
typedef struct ofw_pci_reg ofw_pci_reg_t; |
134,7 → 136,7 |
struct ofw_pci_range { |
uint32_t space; |
uint64_t child_base; /* group phys.mid and phys.lo together */ |
uint64_t child_base; /* group phys.mid and phys.lo together */ |
uint64_t parent_base; |
uint64_t size; |
} __attribute__ ((packed)); |
159,27 → 161,43 |
} __attribute__ ((packed)); |
typedef struct ofw_upa_reg ofw_upa_reg_t; |
extern void ofw_tree_init(ofw_tree_node_t *root); |
extern void ofw_tree_init(ofw_tree_node_t *); |
extern void ofw_tree_print(void); |
extern const char *ofw_tree_node_name(const ofw_tree_node_t *node); |
extern ofw_tree_node_t *ofw_tree_lookup(const char *path); |
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name); |
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name); |
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *device_type); |
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *device_type); |
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle); |
extern const char *ofw_tree_node_name(const ofw_tree_node_t *); |
extern ofw_tree_node_t *ofw_tree_lookup(const char *); |
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *, |
const char *); |
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *, const char *); |
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *, |
const char *); |
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *, |
const char *); |
extern ofw_tree_node_t *ofw_tree_find_peer_by_name(ofw_tree_node_t *node, |
const char *name); |
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *, |
uint32_t); |
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa); |
extern bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa); |
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa); |
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa); |
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *node, ofw_sbus_reg_t *reg, uintptr_t *pa); |
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *node, ofw_upa_reg_t *reg, uintptr_t *pa); |
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *, ofw_fhc_reg_t *, |
uintptr_t *); |
extern bool ofw_central_apply_ranges(ofw_tree_node_t *, ofw_central_reg_t *, |
uintptr_t *); |
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *, ofw_ebus_reg_t *, |
uintptr_t *); |
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *, ofw_pci_reg_t *, |
uintptr_t *); |
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *, ofw_sbus_reg_t *, |
uintptr_t *); |
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *, ofw_upa_reg_t *, |
uintptr_t *); |
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out); |
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *, ofw_pci_reg_t *, |
ofw_pci_reg_t *); |
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr); |
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr); |
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr); |
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *, ofw_fhc_reg_t *, |
uint32_t, int *, cir_t *, void **); |
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *, ofw_ebus_reg_t *, |
uint32_t, int *, cir_t *, void **); |
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *, ofw_pci_reg_t *, |
int, int *, cir_t *, void **); |
#endif |
/branches/dd/kernel/genarch/include/drivers/ns16550/ns16550.h |
---|
0,0 → 1,80 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Headers for NS 16550 serial controller. |
*/ |
#ifndef KERN_NS16550_H_ |
#define KERN_NS16550_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */ |
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */ |
#define MCR_OUT2 0x08 /** OUT2. */ |
/** NS16550 registers. */ |
struct ns16550 { |
ioport8_t rbr; /**< Receiver Buffer Register. */ |
ioport8_t ier; /**< Interrupt Enable Register. */ |
union { |
ioport8_t iir; /**< Interrupt Ident Register (read). */ |
ioport8_t fcr; /**< FIFO control register (write). */ |
} __attribute__ ((packed)); |
ioport8_t lcr; /**< Line Control register. */ |
ioport8_t mcr; /**< Modem Control Register. */ |
ioport8_t lsr; /**< Line Status Register. */ |
} __attribute__ ((packed)); |
typedef struct ns16550 ns16550_t; |
/** Structure representing the ns16550 device. */ |
typedef struct ns16550_instance { |
devno_t devno; |
ns16550_t *ns16550; |
irq_t irq; |
chardev_t *devout; |
} ns16550_instance_t; |
extern bool ns16550_init(ns16550_t *, devno_t, inr_t, cir_t, void *, |
chardev_t *); |
extern irq_ownership_t ns16550_claim(irq_t *); |
extern void ns16550_irq_handler(irq_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/drivers/i8042/i8042.h |
---|
0,0 → 1,62 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_I8042_H_ |
#define KERN_I8042_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
#include <typedefs.h> |
struct i8042 { |
ioport8_t data; |
uint8_t pad[3]; |
ioport8_t status; |
} __attribute__ ((packed)); |
typedef struct i8042 i8042_t; |
typedef struct i8042_instance { |
devno_t devno; |
irq_t irq; |
i8042_t *i8042; |
chardev_t *devout; |
} i8042_instance_t; |
extern bool i8042_init(i8042_t *, devno_t, inr_t, chardev_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/drivers/z8530/z8530.h |
---|
0,0 → 1,131 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Headers for Zilog 8530 serial controller. |
*/ |
#ifndef KERN_Z8530_H_ |
#define KERN_Z8530_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
#define WR0 0 |
#define WR1 1 |
#define WR2 2 |
#define WR3 3 |
#define WR4 4 |
#define WR5 5 |
#define WR6 6 |
#define WR7 7 |
#define WR8 8 |
#define WR9 9 |
#define WR10 10 |
#define WR11 11 |
#define WR12 12 |
#define WR13 13 |
#define WR14 14 |
#define WR15 15 |
#define RR0 0 |
#define RR1 1 |
#define RR2 2 |
#define RR3 3 |
#define RR8 8 |
#define RR10 10 |
#define RR12 12 |
#define RR13 13 |
#define RR14 14 |
#define RR15 15 |
/** Reset pending TX interrupt. */ |
#define WR0_TX_IP_RST (0x5 << 3) |
#define WR0_ERR_RST (0x6 << 3) |
/** Receive Interrupts Disabled. */ |
#define WR1_RID (0x0 << 3) |
/** Receive Interrupt on First Character or Special Condition. */ |
#define WR1_RIFCSC (0x1 << 3) |
/** Interrupt on All Receive Characters or Special Conditions. */ |
#define WR1_IARCSC (0x2 << 3) |
/** Receive Interrupt on Special Condition. */ |
#define WR1_RISC (0x3 << 3) |
/** Parity Is Special Condition. */ |
#define WR1_PISC (0x1 << 2) |
/** Rx Enable. */ |
#define WR3_RX_ENABLE (0x1 << 0) |
/** 8-bits per character. */ |
#define WR3_RX8BITSCH (0x3 << 6) |
/** Master Interrupt Enable. */ |
#define WR9_MIE (0x1 << 3) |
/** Receive Character Available. */ |
#define RR0_RCA (0x1 << 0) |
/** z8530's registers. */ |
struct z8530 { |
union { |
ioport8_t ctl_b; |
ioport8_t status_b; |
} __attribute__ ((packed)); |
uint8_t pad1; |
ioport8_t data_b; |
uint8_t pad2; |
union { |
ioport8_t ctl_a; |
ioport8_t status_a; |
} __attribute__ ((packed)); |
uint8_t pad3; |
ioport8_t data_a; |
} __attribute__ ((packed)); |
typedef struct z8530 z8530_t; |
/** Structure representing the z8530 device. */ |
typedef struct { |
devno_t devno; |
irq_t irq; |
z8530_t *z8530; |
chardev_t *devout; |
} z8530_instance_t; |
extern bool z8530_init(z8530_t *, devno_t, inr_t, cir_t, void *, chardev_t *); |
extern irq_ownership_t z8530_claim(irq_t *); |
extern void z8530_irq_handler(irq_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/drivers/ega/ega.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch_drivers |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_EGA_H_ |
#define KERN_EGA_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#define EGA_COLS 80 |
#define EGA_ROWS 25 |
#define EGA_SCREEN (EGA_COLS * EGA_ROWS) |
#define EGA_VRAM_SIZE (2 * EGA_SCREEN) |
/* EGA device registers. */ |
#define EGA_INDEX_REG 0 |
#define EGA_DATA_REG 1 |
extern void ega_redraw(void); |
extern void ega_init(ioport8_t *, uintptr_t); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/drivers/legacy/ia32/io.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
* @brief This file contains definitions used by architectures with the |
* ia32 legacy I/O space (i.e. ia32, amd64 and ia64). |
*/ |
#ifndef KERN_LEGACY_IA32_IO_H |
#define KERN_LEGACY_IA32_IO_H |
#include <arch/types.h> |
#define I8042_BASE ((ioport8_t *) 0x60) |
#define EGA_BASE ((ioport8_t *) 0x3d4) |
#define NS16550_BASE ((ioport8_t *) 0x3f8) |
#define EGA_VIDEORAM 0xb8000 |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/include/multiboot/multiboot.h |
---|
0,0 → 1,100 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_MULTIBOOT_H_ |
#define KERN_MULTIBOOT_H_ |
#include <arch/types.h> |
#include <arch/boot/memmap.h> |
/** Multiboot 32-bit address. */ |
typedef uint32_t mbaddr_t; |
/** Multiboot mod structure */ |
typedef struct { |
mbaddr_t start; |
mbaddr_t end; |
mbaddr_t string; |
uint32_t reserved; |
} __attribute__ ((packed)) multiboot_mod_t; |
/** Multiboot mmap structure */ |
typedef struct { |
uint32_t size; |
e820memmap_t mm_info; |
} __attribute__ ((packed)) multiboot_mmap_t; |
/** Multiboot information structure */ |
typedef struct { |
uint32_t flags; |
uint32_t mem_lower; |
uint32_t mem_upper; |
uint32_t boot_device; |
uint32_t cmdline; |
uint32_t mods_count; |
mbaddr_t mods_addr; |
uint32_t syms[4]; |
uint32_t mmap_length; |
mbaddr_t mmap_addr; |
/* ... */ |
} __attribute__ ((packed)) multiboot_info_t; |
enum multiboot_info_flags { |
MBINFO_FLAGS_MEM = 0x01, |
MBINFO_FLAGS_BOOT = 0x02, |
MBINFO_FLAGS_CMDLINE = 0x04, |
MBINFO_FLAGS_MODS = 0x08, |
MBINFO_FLAGS_SYMS1 = 0x10, |
MBINFO_FLAGS_SYMS2 = 0x20, |
MBINFO_FLAGS_MMAP = 0x40 |
/* ... */ |
}; |
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002 |
/** Convert 32-bit multiboot address to a pointer. */ |
#define MULTIBOOT_PTR(mba) ((void *)(uintptr_t) (mba)) |
extern void multiboot_info_parse(uint32_t, const multiboot_info_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/srln/srln.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef KERN_SRLN_H_ |
#define KERN_SRLN_H_ |
#include <console/chardev.h> |
extern chardev_t srlnin; |
extern void srln_init(chardev_t *); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/Makefile.inc |
---|
33,68 → 33,75 |
genarch/src/acpi/acpi.c \ |
genarch/src/acpi/madt.c |
endif |
ifeq ($(CONFIG_PAGE_PT),y) |
GENARCH_SOURCES += \ |
genarch/src/mm/page_pt.c \ |
genarch/src/mm/as_pt.c |
endif |
ifeq ($(CONFIG_PAGE_HT),y) |
GENARCH_SOURCES += \ |
genarch/src/mm/page_ht.c \ |
genarch/src/mm/as_ht.c |
endif |
ifeq ($(CONFIG_ASID),y) |
GENARCH_SOURCES += \ |
genarch/src/mm/asid.c |
endif |
ifeq ($(CONFIG_ASID_FIFO),y) |
GENARCH_SOURCES += \ |
genarch/src/mm/asid_fifo.c |
endif |
ifeq ($(CONFIG_SOFTINT),y) |
GENARCH_SOURCES += \ |
genarch/src/softint/division.c |
endif |
## Framebuffer |
ifeq ($(CONFIG_FB),y) |
GENARCH_SOURCES += \ |
genarch/src/fb/font-8x16.c \ |
genarch/src/fb/logo-196x66.c \ |
genarch/src/fb/fb.c |
DEFS += -DCONFIG_FB |
endif |
## i8042 controller |
ifeq ($(CONFIG_I8042),y) |
GENARCH_SOURCES += \ |
genarch/src/kbd/i8042.c \ |
genarch/src/kbd/key.c \ |
genarch/src/kbd/scanc_pc.c |
genarch/src/drivers/i8042/i8042.c |
endif |
## Sun keyboard |
ifeq ($(CONFIG_SUN_KBD),y) |
ifeq ($(CONFIG_NS16550),y) |
GENARCH_SOURCES += \ |
genarch/src/kbd/key.c \ |
genarch/src/kbd/scanc_sun.c |
genarch/src/drivers/ns16550/ns16550.c |
endif |
## z8530 controller |
ifeq ($(CONFIG_Z8530),y) |
GENARCH_SOURCES += \ |
genarch/src/kbd/z8530.c |
genarch/src/drivers/z8530/z8530.c |
endif |
## ns16550 controller |
ifeq ($(CONFIG_NS16550),y) |
ifeq ($(CONFIG_PC_KBD),y) |
GENARCH_SOURCES += \ |
genarch/src/kbd/ns16550.c |
genarch/src/kbrd/kbrd.c \ |
genarch/src/kbrd/scanc_pc.c |
endif |
ifeq ($(CONFIG_SUN_KBD),y) |
GENARCH_SOURCES += \ |
genarch/src/kbrd/kbrd.c \ |
genarch/src/kbrd/scanc_sun.c |
endif |
## OpenFirmware Device Tree |
ifeq ($(CONFIG_OFW_TREE), y) |
ifeq ($(CONFIG_SRLN),y) |
GENARCH_SOURCES += \ |
genarch/src/srln/srln.c |
endif |
ifeq ($(CONFIG_OFW_TREE),y) |
GENARCH_SOURCES += \ |
genarch/src/ofw/ofw_tree.c \ |
genarch/src/ofw/ebus.c \ |
genarch/src/ofw/fhc.c \ |
102,3 → 109,13 |
genarch/src/ofw/sbus.c \ |
genarch/src/ofw/upa.c |
endif |
ifeq ($(CONFIG_MULTIBOOT), y) |
GENARCH_SOURCES += \ |
genarch/src/multiboot/multiboot.c |
endif |
ifeq ($(CONFIG_EGA), y) |
GENARCH_SOURCES += \ |
genarch/src/drivers/ega/ega.c |
endif |
/branches/dd/kernel/genarch/src/kbd/i8042.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbd/key.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbd/z8530.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbd/scanc_pc.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbd/scanc_sun.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbd/ns16550.c |
---|
File deleted |
/branches/dd/kernel/genarch/src/kbrd/kbrd.c |
---|
0,0 → 1,220 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Keyboard processing. |
*/ |
#include <genarch/kbrd/kbrd.h> |
#include <genarch/kbrd/scanc.h> |
#ifdef CONFIG_PC_KBD |
#include <genarch/kbrd/scanc_pc.h> |
#endif |
#ifdef CONFIG_SUN_KBD |
#include <genarch/kbrd/scanc_sun.h> |
#endif |
#include <synch/spinlock.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <macros.h> |
#ifdef CONFIG_SUN_KBD |
# define IGNORE_CODE 0x7f |
#endif |
#define KEY_RELEASE 0x80 |
#define PRESSED_SHIFT (1 << 0) |
#define PRESSED_CAPSLOCK (1 << 1) |
#define LOCKED_CAPSLOCK (1 << 0) |
chardev_t kbrdin; |
static chardev_t *kbdout; |
static void kbrdin_suspend(chardev_t *d) |
{ |
} |
static void kbrdin_resume(chardev_t *d) |
{ |
} |
chardev_operations_t kbrdin_ops = { |
.suspend = kbrdin_suspend, |
.resume = kbrdin_resume, |
}; |
SPINLOCK_INITIALIZE(keylock); /**< keylock protects keyflags and lockflags. */ |
static volatile int keyflags; /**< Tracking of multiple keypresses. */ |
static volatile int lockflags; /**< Tracking of multiple keys lockings. */ |
static void key_released(uint8_t); |
static void key_pressed(uint8_t); |
static void kkbrd(void *arg) |
{ |
chardev_t *in = (chardev_t *) arg; |
uint8_t sc; |
while (1) { |
sc = _getc(in); |
#ifdef CONFIG_SUN_KBD |
if (sc == IGNORE_CODE) |
continue; |
#endif |
if (sc & KEY_RELEASE) |
key_released(sc ^ KEY_RELEASE); |
else |
key_pressed(sc); |
} |
} |
void kbrd_init(chardev_t *devout) |
{ |
thread_t *t; |
chardev_initialize("kbrd", &kbrdin, &kbrdin_ops); |
kbdout = devout; |
t = thread_create(kkbrd, &kbrdin, TASK, 0, "kkbrd", false); |
ASSERT(t); |
thread_ready(t); |
} |
/** Process release of key. |
* |
* @param sc Scancode of the key being released. |
*/ |
void key_released(uint8_t sc) |
{ |
spinlock_lock(&keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags &= ~PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags &= ~PRESSED_CAPSLOCK; |
if (lockflags & LOCKED_CAPSLOCK) |
lockflags &= ~LOCKED_CAPSLOCK; |
else |
lockflags |= LOCKED_CAPSLOCK; |
break; |
default: |
break; |
} |
spinlock_unlock(&keylock); |
} |
/** Process keypress. |
* |
* @param sc Scancode of the key being pressed. |
*/ |
void key_pressed(uint8_t sc) |
{ |
char *map = sc_primary_map; |
char ascii = sc_primary_map[sc]; |
bool shift, capslock; |
bool letter = false; |
spinlock_lock(&keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags |= PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags |= PRESSED_CAPSLOCK; |
break; |
case SC_SPEC_ESCAPE: |
break; |
case SC_LEFTARR: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x5b); |
chardev_push_character(kbdout, 0x44); |
break; |
case SC_RIGHTARR: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x5b); |
chardev_push_character(kbdout, 0x43); |
break; |
case SC_UPARR: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x5b); |
chardev_push_character(kbdout, 0x41); |
break; |
case SC_DOWNARR: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x5b); |
chardev_push_character(kbdout, 0x42); |
break; |
case SC_HOME: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x4f); |
chardev_push_character(kbdout, 0x48); |
break; |
case SC_END: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x4f); |
chardev_push_character(kbdout, 0x46); |
break; |
case SC_DELETE: |
chardev_push_character(kbdout, 0x1b); |
chardev_push_character(kbdout, 0x5b); |
chardev_push_character(kbdout, 0x33); |
chardev_push_character(kbdout, 0x7e); |
break; |
default: |
letter = islower(ascii); |
capslock = (keyflags & PRESSED_CAPSLOCK) || |
(lockflags & LOCKED_CAPSLOCK); |
shift = keyflags & PRESSED_SHIFT; |
if (letter && capslock) |
shift = !shift; |
if (shift) |
map = sc_secondary_map; |
chardev_push_character(kbdout, map[sc]); |
break; |
} |
spinlock_unlock(&keylock); |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/kbrd/scanc_pc.c |
---|
0,0 → 1,200 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for pc keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
/** Primary meaning of scancodes. */ |
char sc_primary_map[] = { |
SPECIAL, /* 0x00 */ |
SPECIAL, /* 0x01 - Esc */ |
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', |
'\b', /* 0x0e - Backspace */ |
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', |
SPECIAL, /* 0x1d - LCtrl */ |
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', |
'`', |
SPECIAL, /* 0x2a - LShift */ |
'\\', |
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', |
SPECIAL, /* 0x36 - RShift */ |
'*', |
SPECIAL, /* 0x38 - LAlt */ |
' ', |
SPECIAL, /* 0x3a - CapsLock */ |
SPECIAL, /* 0x3b - F1 */ |
SPECIAL, /* 0x3c - F2 */ |
SPECIAL, /* 0x3d - F3 */ |
SPECIAL, /* 0x3e - F4 */ |
SPECIAL, /* 0x3f - F5 */ |
SPECIAL, /* 0x40 - F6 */ |
SPECIAL, /* 0x41 - F7 */ |
SPECIAL, /* 0x42 - F8 */ |
SPECIAL, /* 0x43 - F9 */ |
SPECIAL, /* 0x44 - F10 */ |
SPECIAL, /* 0x45 - NumLock */ |
SPECIAL, /* 0x46 - ScrollLock */ |
'7', '8', '9', '-', |
'4', '5', '6', '+', |
'1', '2', '3', |
'0', '.', |
SPECIAL, /* 0x54 - Alt-SysRq */ |
SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
SPECIAL, /* 0x57 - F11 */ |
SPECIAL, /* 0x58 - F12 */ |
SPECIAL, /* 0x59 */ |
SPECIAL, /* 0x5a */ |
SPECIAL, /* 0x5b */ |
SPECIAL, /* 0x5c */ |
SPECIAL, /* 0x5d */ |
SPECIAL, /* 0x5e */ |
SPECIAL, /* 0x5f */ |
SPECIAL, /* 0x60 */ |
SPECIAL, /* 0x61 */ |
SPECIAL, /* 0x62 */ |
SPECIAL, /* 0x63 */ |
SPECIAL, /* 0x64 */ |
SPECIAL, /* 0x65 */ |
SPECIAL, /* 0x66 */ |
SPECIAL, /* 0x67 */ |
SPECIAL, /* 0x68 */ |
SPECIAL, /* 0x69 */ |
SPECIAL, /* 0x6a */ |
SPECIAL, /* 0x6b */ |
SPECIAL, /* 0x6c */ |
SPECIAL, /* 0x6d */ |
SPECIAL, /* 0x6e */ |
SPECIAL, /* 0x6f */ |
SPECIAL, /* 0x70 */ |
SPECIAL, /* 0x71 */ |
SPECIAL, /* 0x72 */ |
SPECIAL, /* 0x73 */ |
SPECIAL, /* 0x74 */ |
SPECIAL, /* 0x75 */ |
SPECIAL, /* 0x76 */ |
SPECIAL, /* 0x77 */ |
SPECIAL, /* 0x78 */ |
SPECIAL, /* 0x79 */ |
SPECIAL, /* 0x7a */ |
SPECIAL, /* 0x7b */ |
SPECIAL, /* 0x7c */ |
SPECIAL, /* 0x7d */ |
SPECIAL, /* 0x7e */ |
SPECIAL, /* 0x7f */ |
}; |
/** Secondary meaning of scancodes. */ |
char sc_secondary_map[] = { |
SPECIAL, /* 0x00 */ |
SPECIAL, /* 0x01 - Esc */ |
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', |
SPECIAL, /* 0x0e - Backspace */ |
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', |
SPECIAL, /* 0x1d - LCtrl */ |
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', |
'~', |
SPECIAL, /* 0x2a - LShift */ |
'|', |
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', |
SPECIAL, /* 0x36 - RShift */ |
'*', |
SPECIAL, /* 0x38 - LAlt */ |
' ', |
SPECIAL, /* 0x3a - CapsLock */ |
SPECIAL, /* 0x3b - F1 */ |
SPECIAL, /* 0x3c - F2 */ |
SPECIAL, /* 0x3d - F3 */ |
SPECIAL, /* 0x3e - F4 */ |
SPECIAL, /* 0x3f - F5 */ |
SPECIAL, /* 0x40 - F6 */ |
SPECIAL, /* 0x41 - F7 */ |
SPECIAL, /* 0x42 - F8 */ |
SPECIAL, /* 0x43 - F9 */ |
SPECIAL, /* 0x44 - F10 */ |
SPECIAL, /* 0x45 - NumLock */ |
SPECIAL, /* 0x46 - ScrollLock */ |
'7', '8', '9', '-', |
'4', '5', '6', '+', |
'1', '2', '3', |
'0', '.', |
SPECIAL, /* 0x54 - Alt-SysRq */ |
SPECIAL, /* 0x55 - F11/F12/PF1/FN */ |
SPECIAL, /* 0x56 - unlabelled key next to LAlt */ |
SPECIAL, /* 0x57 - F11 */ |
SPECIAL, /* 0x58 - F12 */ |
SPECIAL, /* 0x59 */ |
SPECIAL, /* 0x5a */ |
SPECIAL, /* 0x5b */ |
SPECIAL, /* 0x5c */ |
SPECIAL, /* 0x5d */ |
SPECIAL, /* 0x5e */ |
SPECIAL, /* 0x5f */ |
SPECIAL, /* 0x60 */ |
SPECIAL, /* 0x61 */ |
SPECIAL, /* 0x62 */ |
SPECIAL, /* 0x63 */ |
SPECIAL, /* 0x64 */ |
SPECIAL, /* 0x65 */ |
SPECIAL, /* 0x66 */ |
SPECIAL, /* 0x67 */ |
SPECIAL, /* 0x68 */ |
SPECIAL, /* 0x69 */ |
SPECIAL, /* 0x6a */ |
SPECIAL, /* 0x6b */ |
SPECIAL, /* 0x6c */ |
SPECIAL, /* 0x6d */ |
SPECIAL, /* 0x6e */ |
SPECIAL, /* 0x6f */ |
SPECIAL, /* 0x70 */ |
SPECIAL, /* 0x71 */ |
SPECIAL, /* 0x72 */ |
SPECIAL, /* 0x73 */ |
SPECIAL, /* 0x74 */ |
SPECIAL, /* 0x75 */ |
SPECIAL, /* 0x76 */ |
SPECIAL, /* 0x77 */ |
SPECIAL, /* 0x78 */ |
SPECIAL, /* 0x79 */ |
SPECIAL, /* 0x7a */ |
SPECIAL, /* 0x7b */ |
SPECIAL, /* 0x7c */ |
SPECIAL, /* 0x7d */ |
SPECIAL, /* 0x7e */ |
SPECIAL, /* 0x7f */ |
}; |
/** @} |
*/ |
/branches/dd/kernel/genarch/src/kbrd/scanc_sun.c |
---|
0,0 → 1,304 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for Sun keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
/** Primary meaning of scancodes. */ |
char sc_primary_map[] = { |
[0x00] = SPECIAL, |
[0x01] = SPECIAL, |
[0x02] = SPECIAL, |
[0x03] = SPECIAL, |
[0x04] = SPECIAL, |
[0x05] = SPECIAL, /* F1 */ |
[0x06] = SPECIAL, /* F2 */ |
[0x07] = SPECIAL, /* F10 */ |
[0x08] = SPECIAL, /* F3 */ |
[0x09] = SPECIAL, /* F11 */ |
[0x0a] = SPECIAL, /* F4 */ |
[0x0b] = SPECIAL, /* F12 */ |
[0x0c] = SPECIAL, /* F5 */ |
[0x0d] = SPECIAL, /* RAlt */ |
[0x0e] = SPECIAL, /* F6 */ |
[0x0f] = SPECIAL, |
[0x10] = SPECIAL, /* F7 */ |
[0x11] = SPECIAL, /* F8 */ |
[0x12] = SPECIAL, /* F9 */ |
[0x13] = SPECIAL, /* LAlt */ |
[0x14] = SPECIAL, /* Up Arrow */ |
[0x15] = SPECIAL, /* Pause */ |
[0x16] = SPECIAL, |
[0x17] = SPECIAL, /* Scroll Lock */ |
[0x18] = SPECIAL, /* Left Arrow */ |
[0x19] = SPECIAL, |
[0x1a] = SPECIAL, |
[0x1b] = SPECIAL, /* Down Arrow */ |
[0x1c] = SPECIAL, /* Right Arrow */ |
[0x1d] = SPECIAL, /* Esc */ |
[0x1e] = '1', |
[0x1f] = '2', |
[0x20] = '3', |
[0x21] = '4', |
[0x22] = '5', |
[0x23] = '6', |
[0x24] = '7', |
[0x25] = '8', |
[0x26] = '9', |
[0x27] = '0', |
[0x28] = '-', |
[0x29] = '=', |
[0x2a] = '`', |
[0x2b] = '\b', /* Backspace */ |
[0x2c] = SPECIAL, /* Insert */ |
[0x2d] = SPECIAL, |
[0x2e] = '/', /* numeric keypad */ |
[0x2f] = '*', /* numeric keypad */ |
[0x30] = SPECIAL, |
[0x31] = SPECIAL, |
[0x32] = '.', /* numeric keypad */ |
[0x33] = SPECIAL, |
[0x34] = SPECIAL, /* Home */ |
[0x35] = '\t', /* Tab */ |
[0x36] = 'q', |
[0x37] = 'w', |
[0x38] = 'e', |
[0x39] = 'r', |
[0x3a] = 't', |
[0x3b] = 'y', |
[0x3c] = 'u', |
[0x3d] = 'i', |
[0x3e] = 'o', |
[0x3f] = 'p', |
[0x40] = '[', |
[0x41] = ']', |
[0x42] = SPECIAL, /* Del */ |
[0x43] = SPECIAL, |
[0x44] = '7', /* numeric keypad */ |
[0x45] = '8', /* numeric keypad */ |
[0x46] = '9', /* numeric keypad */ |
[0x47] = '-', /* numeric keypad */ |
[0x48] = SPECIAL, |
[0x49] = SPECIAL, |
[0x4a] = SPECIAL, /* End */ |
[0x4b] = SPECIAL, |
[0x4c] = SPECIAL, /* Control */ |
[0x4d] = 'a', |
[0x4e] = 's', |
[0x4f] = 'd', |
[0x50] = 'f', |
[0x51] = 'g', |
[0x52] = 'h', |
[0x53] = 'j', |
[0x54] = 'k', |
[0x55] = 'l', |
[0x56] = ';', |
[0x57] = '\'', |
[0x58] = '\\', |
[0x59] = '\n', /* Enter */ |
[0x5a] = '\n', /* Enter on numeric keypad */ |
[0x5b] = '4', /* numeric keypad */ |
[0x5c] = '5', /* numeric keypad */ |
[0x5d] = '6', /* numeric keypad */ |
[0x5e] = '0', /* numeric keypad */ |
[0x5f] = SPECIAL, |
[0x60] = SPECIAL, /* Page Up */ |
[0x61] = SPECIAL, |
[0x62] = SPECIAL, /* Num Lock */ |
[0x63] = SPECIAL, /* LShift */ |
[0x64] = 'z', |
[0x65] = 'x', |
[0x66] = 'c', |
[0x67] = 'v', |
[0x68] = 'b', |
[0x69] = 'n', |
[0x6a] = 'm', |
[0x6b] = ',', |
[0x6c] = '.', |
[0x6d] = '/', |
[0x6e] = SPECIAL, /* RShift */ |
[0x6f] = SPECIAL, |
[0x70] = '1', /* numeric keypad */ |
[0x71] = '2', /* numeric keypad */ |
[0x72] = '3', /* numeric keypad */ |
[0x73] = SPECIAL, |
[0x74] = SPECIAL, |
[0x75] = SPECIAL, |
[0x76] = SPECIAL, |
[0x77] = SPECIAL, /* Caps Lock */ |
[0x78] = SPECIAL, |
[0x79] = ' ', |
[0x7a] = SPECIAL, |
[0x7b] = SPECIAL, /* Page Down */ |
[0x7c] = SPECIAL, |
[0x7d] = '+', /* numeric key pad */ |
[0x7e] = SPECIAL, |
[0x7f] = SPECIAL |
}; |
/** Secondary meaning of scancodes. */ |
char sc_secondary_map[] = { |
[0x00] = SPECIAL, |
[0x01] = SPECIAL, |
[0x02] = SPECIAL, |
[0x03] = SPECIAL, |
[0x04] = SPECIAL, |
[0x05] = SPECIAL, /* F1 */ |
[0x06] = SPECIAL, /* F2 */ |
[0x07] = SPECIAL, /* F10 */ |
[0x08] = SPECIAL, /* F3 */ |
[0x09] = SPECIAL, /* F11 */ |
[0x0a] = SPECIAL, /* F4 */ |
[0x0b] = SPECIAL, /* F12 */ |
[0x0c] = SPECIAL, /* F5 */ |
[0x0d] = SPECIAL, /* RAlt */ |
[0x0e] = SPECIAL, /* F6 */ |
[0x0f] = SPECIAL, |
[0x10] = SPECIAL, /* F7 */ |
[0x11] = SPECIAL, /* F8 */ |
[0x12] = SPECIAL, /* F9 */ |
[0x13] = SPECIAL, /* LAlt */ |
[0x14] = SPECIAL, /* Up Arrow */ |
[0x15] = SPECIAL, /* Pause */ |
[0x16] = SPECIAL, |
[0x17] = SPECIAL, /* Scroll Lock */ |
[0x18] = SPECIAL, /* Left Arrow */ |
[0x19] = SPECIAL, |
[0x1a] = SPECIAL, |
[0x1b] = SPECIAL, /* Down Arrow */ |
[0x1c] = SPECIAL, /* Right Arrow */ |
[0x1d] = SPECIAL, /* Esc */ |
[0x1e] = '!', |
[0x1f] = '@', |
[0x20] = '#', |
[0x21] = '$', |
[0x22] = '%', |
[0x23] = '^', |
[0x24] = '&', |
[0x25] = '*', |
[0x26] = '(', |
[0x27] = ')', |
[0x28] = '_', |
[0x29] = '+', |
[0x2a] = '~', |
[0x2b] = SPECIAL, /* Backspace */ |
[0x2c] = SPECIAL, /* Insert */ |
[0x2d] = SPECIAL, |
[0x2e] = '/', /* numeric keypad */ |
[0x2f] = '*', /* numeric keypad */ |
[0x30] = SPECIAL, |
[0x31] = SPECIAL, |
[0x32] = '.', /* numeric keypad */ |
[0x33] = SPECIAL, |
[0x34] = SPECIAL, /* Home */ |
[0x35] = SPECIAL, /* Tab */ |
[0x36] = 'Q', |
[0x37] = 'W', |
[0x38] = 'E', |
[0x39] = 'R', |
[0x3a] = 'T', |
[0x3b] = 'Y', |
[0x3c] = 'U', |
[0x3d] = 'I', |
[0x3e] = 'O', |
[0x3f] = 'P', |
[0x40] = '{', |
[0x41] = '}', |
[0x42] = SPECIAL, /* Del */ |
[0x43] = SPECIAL, |
[0x44] = '7', /* numeric keypad */ |
[0x45] = '8', /* numeric keypad */ |
[0x46] = '9', /* numeric keypad */ |
[0x47] = '-', /* numeric keypad */ |
[0x48] = SPECIAL, |
[0x49] = SPECIAL, |
[0x4a] = SPECIAL, /* End */ |
[0x4b] = SPECIAL, |
[0x4c] = SPECIAL, /* Control */ |
[0x4d] = 'A', |
[0x4e] = 'S', |
[0x4f] = 'D', |
[0x50] = 'F', |
[0x51] = 'G', |
[0x52] = 'H', |
[0x53] = 'J', |
[0x54] = 'K', |
[0x55] = 'L', |
[0x56] = ':', |
[0x57] = '"', |
[0x58] = '|', |
[0x59] = SPECIAL, /* Enter */ |
[0x5a] = SPECIAL, /* Enter on numeric keypad */ |
[0x5b] = '4', /* numeric keypad */ |
[0x5c] = '5', /* numeric keypad */ |
[0x5d] = '6', /* numeric keypad */ |
[0x5e] = '0', /* numeric keypad */ |
[0x5f] = SPECIAL, |
[0x60] = SPECIAL, /* Page Up */ |
[0x61] = SPECIAL, |
[0x62] = SPECIAL, /* Num Lock */ |
[0x63] = SPECIAL, /* LShift */ |
[0x64] = 'Z', |
[0x65] = 'X', |
[0x66] = 'C', |
[0x67] = 'V', |
[0x68] = 'B', |
[0x69] = 'N', |
[0x6a] = 'M', |
[0x6b] = '<', |
[0x6c] = '>', |
[0x6d] = '?', |
[0x6e] = SPECIAL, /* RShift */ |
[0x6f] = SPECIAL, |
[0x70] = '1', /* numeric keypad */ |
[0x71] = '2', /* numeric keypad */ |
[0x72] = '3', /* numeric keypad */ |
[0x73] = SPECIAL, |
[0x74] = SPECIAL, |
[0x75] = SPECIAL, |
[0x76] = SPECIAL, |
[0x77] = SPECIAL, /* Caps Lock */ |
[0x78] = SPECIAL, |
[0x79] = ' ', |
[0x7a] = SPECIAL, |
[0x7b] = SPECIAL, /* Page Down */ |
[0x7c] = SPECIAL, |
[0x7d] = '+', /* numeric key pad */ |
[0x7e] = SPECIAL, |
[0x7f] = SPECIAL |
}; |
/** @} |
*/ |
/branches/dd/kernel/genarch/src/kbrd |
---|
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/fb/helenos.xbm |
---|
File deleted |
/branches/dd/kernel/genarch/src/fb/logo-196x66.c |
---|
0,0 → 1,13110 |
/* |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#include <genarch/fb/logo-196x66.h> |
uint32_t fb_logo[LOGO_WIDTH * LOGO_HEIGHT] = { |
/* Scanline 0 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 1 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 2 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 3 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xf9f9f8, |
0xf5f3f1, |
0xf3f1ee, |
0xf3f2ef, |
0xf7f7f6, |
0xfbfbfb, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 4 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefd, |
0xf9f9f8, |
0xf3f1ed, |
0xeeeae4, |
0xece8df, |
0xebe6de, |
0xeae5dd, |
0xeae5dd, |
0xeae5de, |
0xeae8e4, |
0xf1f1f0, |
0xfbfbfb, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 5 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefd, |
0xf9f9f8, |
0xf4f2ef, |
0xefebe5, |
0xf0ece5, |
0xeeeae4, |
0xe3e0db, |
0xdfdcd8, |
0xe2e0db, |
0xeeebe6, |
0xeeebe5, |
0xeae5dd, |
0xe8e4db, |
0xe5e1db, |
0xe9e9e8, |
0xfafafa, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 6 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefd, |
0xfaf9f9, |
0xf4f3ef, |
0xefece6, |
0xf0ece5, |
0xeeebe5, |
0xdfdcd7, |
0xc6c4bd, |
0xbebcb5, |
0xcfcdc8, |
0xd3d2cd, |
0xd1cfca, |
0xc0beb7, |
0xcccac3, |
0xeae7e3, |
0xe9e5dd, |
0xe7e3da, |
0xdedbd8, |
0xe8e8e7, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 7 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfafafa, |
0xf5f4f0, |
0xf1eee8, |
0xf0ece4, |
0xf0ede7, |
0xe1ded9, |
0xc9c7c1, |
0xbebcb4, |
0xd1cfca, |
0xecebe8, |
0xf9f9f7, |
0xfaf9f7, |
0xf8f6f4, |
0xf7f5f2, |
0xf4f3f1, |
0xdcdad6, |
0xc2c0b9, |
0xe6e4de, |
0xe5e2dc, |
0xe2ddd8, |
0xd7d5d4, |
0xf2f2f1, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 8 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfbfbfb, |
0xf6f5f2, |
0xf1eee9, |
0xf1ede5, |
0xf1ede6, |
0xe4e1db, |
0xcecbc4, |
0xbebcb5, |
0xcfcdc8, |
0xe7e6e4, |
0xf8f8f6, |
0xfafaf8, |
0xf9f7f5, |
0xf7f5f2, |
0xf5f3f0, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xd9d7d2, |
0xc8c5bf, |
0xe9e5e0, |
0xe4dfd8, |
0xd5d2ce, |
0xe1e1e1, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 9 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfbfbfb, |
0xf7f6f3, |
0xf2efea, |
0xf1ede6, |
0xf1eee7, |
0xe5e3de, |
0xd0cec7, |
0xbfbdb5, |
0xcdcbc5, |
0xe4e3e0, |
0xf7f7f6, |
0xfbfaf9, |
0xf9f8f6, |
0xf8f6f3, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf1efeb, |
0xc5c2bb, |
0xe2dfdb, |
0xe5e0da, |
0xded9d3, |
0xd3d2d1, |
0xf4f4f4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 10 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfcfcfb, |
0xf8f6f4, |
0xf3f0eb, |
0xf1eee7, |
0xf2efe8, |
0xe8e5df, |
0xd3d1cb, |
0xc0beb6, |
0xcbc9c3, |
0xe1e0dc, |
0xf5f4f3, |
0xfbfaf8, |
0xfaf9f7, |
0xf8f7f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ec, |
0xf2efec, |
0xdbd9d4, |
0xcdcbc4, |
0xe8e4de, |
0xe3ded7, |
0xd0cecb, |
0xe7e7e6, |
0xfdfdfc, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 11 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfcfcfb, |
0xf8f7f4, |
0xf4f1ed, |
0xf2eee8, |
0xf3efe9, |
0xeae7e1, |
0xd6d4cd, |
0xc3c1b9, |
0xcac8c2, |
0xdddcd8, |
0xf3f2f1, |
0xfafaf8, |
0xfbfaf7, |
0xf9f7f5, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf1efeb, |
0xf1eeeb, |
0xece9e5, |
0xc3c1ba, |
0xe5e3de, |
0xe3ded7, |
0xd9d5d0, |
0xd6d5d5, |
0xf7f7f7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 12 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfcfcfc, |
0xf9f8f5, |
0xf5f2ee, |
0xf3efe8, |
0xf4f0e9, |
0xece9e3, |
0xd9d7d1, |
0xc4c2bb, |
0xc8c6c0, |
0xd9d8d4, |
0xf1f0ef, |
0xfaf9f8, |
0xfbfaf8, |
0xfaf8f5, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xd2cfc9, |
0xd3d2cc, |
0xe4e0db, |
0xded9d3, |
0xcfccca, |
0xededec, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 13 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xf9f9f7, |
0xf5f3f0, |
0xf3efe8, |
0xf4f0e9, |
0xeeeae5, |
0xdddad4, |
0xc7c4bd, |
0xc7c6bf, |
0xd7d6d1, |
0xeeedeb, |
0xf9f9f8, |
0xfcfbfa, |
0xfaf9f6, |
0xf9f7f4, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf1efeb, |
0xf1eeeb, |
0xf1eeea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xe4e2dd, |
0xc4c2bb, |
0xe5e2de, |
0xdfdad3, |
0xd3d0cb, |
0xdbdbdb, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 14 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xfaf9f7, |
0xf6f4f0, |
0xf3f0e9, |
0xf4f0ea, |
0xefece6, |
0xdfddd7, |
0xcbc8c1, |
0xc7c5be, |
0xd4d3ce, |
0xebebe8, |
0xf8f8f6, |
0xfcfcfa, |
0xfbfaf7, |
0xfaf9f6, |
0xf9f7f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xc8c6bf, |
0xdcdad5, |
0xe1dcd6, |
0xdbd7d0, |
0xd0cfcd, |
0xf1f0f0, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 15 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfafaf9, |
0xf7f5f1, |
0xf4f1ea, |
0xf5f1ea, |
0xf1ede7, |
0xe2e0da, |
0xcccac3, |
0xc6c5be, |
0xd1cfca, |
0xe9e8e6, |
0xf8f7f6, |
0xfcfcfb, |
0xfbfaf8, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xedeae5, |
0xdedbd5, |
0xc7c6bf, |
0xe5e2dd, |
0xded9d3, |
0xcfcdc9, |
0xe2e2e2, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 16 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xfbfbf9, |
0xf6f3ed, |
0xf4f1e9, |
0xf4f1eb, |
0xe7e4df, |
0xcfcdc6, |
0xc7c5be, |
0xceccc7, |
0xe6e5e2, |
0xf7f6f5, |
0xfdfcfb, |
0xfcfbf9, |
0xfaf9f7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xe0dedb, |
0xb4b2b1, |
0xb6b5b4, |
0xe0dddb, |
0xf1eeeb, |
0xf1eeea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xece9e5, |
0xece9e4, |
0xe8e6e1, |
0xc3c1ba, |
0xdfddd9, |
0xddd9d3, |
0xd6d3cd, |
0xd3d2d1, |
0xf5f5f4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 17 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfafaf9, |
0xf4f0e8, |
0xf5f1ea, |
0xf3f1ed, |
0xcbc9c3, |
0xcac8c2, |
0xe3e2df, |
0xf5f4f3, |
0xfdfcfb, |
0xfdfbfa, |
0xfcfaf8, |
0xfbf9f7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xe1dedc, |
0x7f7e7e, |
0x706f6f, |
0x757374, |
0x8c8c8b, |
0xe1dedb, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xedeae5, |
0xece9e4, |
0xebe9e4, |
0xeae8e3, |
0xeae8e3, |
0xd4d2cb, |
0xcdcbc5, |
0xe1ded8, |
0xdad6cf, |
0xcdcbc8, |
0xe8e8e8, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 18 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0xf4f0eb, |
0xf4f0e7, |
0xf8f6f3, |
0xc6c4bd, |
0xdcdad7, |
0xfbfbfa, |
0xfdfcfb, |
0xfcfaf8, |
0xfcfaf8, |
0xfbfaf7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f7f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ed, |
0xb3b1af, |
0x716f70, |
0x7c7b7b, |
0x898989, |
0x8f8e8e, |
0xbdbbba, |
0xeeebe7, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xece9e5, |
0xece9e4, |
0xebe8e3, |
0xeae8e3, |
0xe9e7e2, |
0xe8e6e1, |
0xe2e0db, |
0xc1bfb8, |
0xe2dfdb, |
0xdad7d0, |
0xd2d0cb, |
0xd7d7d7, |
0xf8f8f7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 19 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf0f0ef, |
0xf1ede4, |
0xf8f6f0, |
0xdbd9d4, |
0xd3d2cd, |
0xfdfcfb, |
0xfcfbf9, |
0xfcfaf8, |
0xfcfaf8, |
0xfbfaf7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xaeacab, |
0x7a7979, |
0x8f8e8e, |
0xa3a2a2, |
0xabaaab, |
0xafaead, |
0xe8e5e1, |
0xeeebe7, |
0xedeae6, |
0xece9e4, |
0xebe8e4, |
0xeae8e3, |
0xe9e7e2, |
0xe9e7e2, |
0xe8e6e1, |
0xe7e5e0, |
0xe7e4df, |
0xcac8c1, |
0xd4d2cc, |
0xdcd9d3, |
0xd6d3ce, |
0xcdccca, |
0xeeeeed, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 20 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefd, |
0xe1e0dd, |
0xf0ebe2, |
0xfbfaf7, |
0xc3c1ba, |
0xf3f2f0, |
0xfcfbf9, |
0xfcfaf8, |
0xfcfaf8, |
0xfbf9f7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf7f5f2, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ec, |
0xf2f0ec, |
0xf1eeeb, |
0xd5d3d1, |
0x838282, |
0x9d9c9c, |
0xb4b3b3, |
0xbdbcbd, |
0xb6b5b5, |
0xd7d4d1, |
0xedeae6, |
0xece9e5, |
0xeae8e3, |
0xeae8e3, |
0xe9e7e2, |
0xe9e7e2, |
0xe7e5e0, |
0xe7e4df, |
0xe6e3de, |
0xe5e2dd, |
0xdbd8d3, |
0xc3c0ba, |
0xe1ded9, |
0xd8d4ce, |
0xcdcac6, |
0xdedddd, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 21 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0xd2d1cd, |
0xefeae1, |
0xfcfaf8, |
0xc3c1ba, |
0xf9f8f7, |
0xfcfaf8, |
0xfcfaf8, |
0xfbf9f7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f7f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf0eeeb, |
0xebe9e6, |
0xf3f1ee, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf1eeea, |
0xefece9, |
0x9c9b9a, |
0xa1a0a0, |
0xb9b7b8, |
0xc2c0c1, |
0xbfbdbe, |
0xc2c1c0, |
0xe9e6e2, |
0xeae8e3, |
0xe9e7e2, |
0xe9e7e2, |
0xe8e6e1, |
0xe7e5e0, |
0xe7e4df, |
0xe6e3de, |
0xe5e2dd, |
0xe4e1dc, |
0xe3dfda, |
0xc4c1ba, |
0xdbd9d4, |
0xd8d5ce, |
0xd4d0cb, |
0xcfcecd, |
0xf2f2f2, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xe3e3e3, |
0xbbbbbb, |
0x9d9d9d, |
0x989898, |
0xa4a4a4, |
0xbfbfbf, |
0xeaeaea, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf1f1f1, |
0xc4c4c4, |
0xa6a6a6, |
0x989898, |
0xa2a2a2, |
0xc5c5c5, |
0xf1f0f0, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 22 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfbfbfb, |
0xb9b8b6, |
0xeae5dd, |
0xf9f6f3, |
0xc4c2bb, |
0xf2f2f0, |
0xfbfaf7, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f5, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf6f4f1, |
0xd2d0ce, |
0x908f8e, |
0x888686, |
0xb3b1b0, |
0xedebe8, |
0xf3f1ee, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xc6c4c2, |
0x9c9b9b, |
0xb4b3b3, |
0xc1bfc0, |
0xc1c0c0, |
0xbab9b9, |
0xdeddd9, |
0xe9e7e2, |
0xe9e7e2, |
0xe7e5e0, |
0xe7e4df, |
0xe7e4df, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe4e0db, |
0xe3dfda, |
0xd4d1cb, |
0xc6c4bd, |
0xdfdcd7, |
0xd7d3cc, |
0xcbc9c6, |
0xe4e4e4, |
0xfcfcfc, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xcbcbcb, |
0x5f5f5f, |
0x343434, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x363636, |
0x737272, |
0xdedede, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf2f1f1, |
0x8e8e8e, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x393939, |
0x8a8a8a, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 23 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfbfbfb, |
0xbbbbba, |
0xc8c4bd, |
0xf4f1eb, |
0xd6d4cf, |
0xdbd9d5, |
0xfaf9f6, |
0xfaf9f6, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf7f5f3, |
0xf7f5f2, |
0xf6f4f1, |
0xe4e2df, |
0x7f7e7e, |
0x717071, |
0x7a7878, |
0x807f7f, |
0xbbbab9, |
0xf3f1ee, |
0xf2f0ec, |
0xf2f0ec, |
0xf1eeeb, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xe7e4e0, |
0x999897, |
0xacabab, |
0xbebcbd, |
0xc3c1c2, |
0xbebcbd, |
0xc9c8c7, |
0xe7e5e0, |
0xe7e5e0, |
0xe7e4df, |
0xe6e3de, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe3dfda, |
0xe3dfda, |
0xe2ded9, |
0xdedad5, |
0xc0beb6, |
0xdedad5, |
0xd6d2cb, |
0xd1cec8, |
0xd2d2d2, |
0xf6f6f6, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb0afaf, |
0x383838, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x414141, |
0xc8c8c8, |
0xffffff, |
0xefefef, |
0x626262, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x575656, |
0xefefef, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 24 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfc, |
0xd9d9d9, |
0x9a9893, |
0xede9e0, |
0xefede8, |
0xc3c1bb, |
0xf7f6f3, |
0xfaf9f6, |
0xf9f8f5, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf5f3f0, |
0xcac9c7, |
0x717071, |
0x7e7e7e, |
0x908f8f, |
0x9a9998, |
0xa5a4a3, |
0xebeae6, |
0xf2efec, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xb5b3b1, |
0xa2a1a1, |
0xb8b7b7, |
0xc2c0c1, |
0xc1bfc0, |
0xbcbaba, |
0xe1dfda, |
0xe7e4df, |
0xe6e3de, |
0xe5e1dc, |
0xe4e0db, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xe1ddd8, |
0xe1ddd8, |
0xe0dbd6, |
0xcbc8c1, |
0xceccc7, |
0xdad7d1, |
0xd4d0ca, |
0xcbc9c7, |
0xeaeae9, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xd6d6d6, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x555555, |
0xececec, |
0x919191, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x7e7e7e, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 25 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xe9e9e9, |
0x989694, |
0xd8d4cc, |
0xf5f3ed, |
0xc8c6bf, |
0xe8e6e2, |
0xf9f7f5, |
0xf9f7f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f4, |
0xf7f5f3, |
0xf7f5f2, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xd8d6d4, |
0x7d7d7c, |
0x8f8e8e, |
0xa6a5a6, |
0xb3b2b3, |
0xb1b0b0, |
0xd7d5d2, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xedeae6, |
0xece9e5, |
0xd3d0cd, |
0x999897, |
0xb1afb0, |
0xc0bebf, |
0xc3c1c2, |
0xbbbabb, |
0xd2d0cc, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe3dfda, |
0xe3dfda, |
0xe2ded9, |
0xe1ddd8, |
0xe0dcd7, |
0xe0dbd6, |
0xdfdad5, |
0xd9d5cf, |
0xbfbdb6, |
0xdedcd8, |
0xd4d0ca, |
0xcccac6, |
0xd9d8d8, |
0xf9f9f9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7a7a7a, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x494949, |
0x666565, |
0x3f3f3f, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x939392, |
0x4e4e4e, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x3f3f3f, |
0x686868, |
0x4c4c4c, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x343434, |
0xe8e7e7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 26 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf5f5f4, |
0xbcbbba, |
0xaaa7a2, |
0xbebcb6, |
0xa19f9c, |
0xa5a4a1, |
0xf4f2f0, |
0xf8f6f4, |
0xf8f6f4, |
0xf8f6f3, |
0xf7f5f2, |
0xf7f5f2, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xedebe8, |
0x9c9b9a, |
0x999898, |
0xb3b1b2, |
0xc0bebf, |
0xbebcbd, |
0xc2c0c0, |
0xefece9, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xedeae6, |
0xe4e1de, |
0xc7c5c2, |
0x9b9a99, |
0x8d8c8c, |
0xa9a8a8, |
0xbdbbbb, |
0xc3c1c2, |
0xc0bebe, |
0xc1bfbe, |
0xe1ded9, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xe1ddd9, |
0xe1ddd8, |
0xe0dbd6, |
0xe0dbd6, |
0xdedad5, |
0xdddad5, |
0xdcd8d3, |
0xc4c1bb, |
0xd5d3ce, |
0xd6d2cc, |
0xd2cec9, |
0xcbcac9, |
0xefefef, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf6f6f6, |
0x424242, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x565656, |
0xebebeb, |
0xffffff, |
0xd4d4d4, |
0x414141, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x414141, |
0x343434, |
0x323232, |
0x323232, |
0x323232, |
0x434343, |
0xe1e1e0, |
0xffffff, |
0xf1f1f1, |
0x575757, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0xaeaeae, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 27 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0xe0e0e0, |
0x8e8c89, |
0x696865, |
0x343434, |
0x343434, |
0xc8c7c7, |
0xf8f6f4, |
0xf7f5f3, |
0xf7f5f2, |
0xf6f4f1, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ed, |
0xc4c2c1, |
0x989797, |
0xb3b1b2, |
0xc1bfc0, |
0xc2c0c1, |
0xbcbabb, |
0xe1dfdc, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xebe8e4, |
0xdedbd8, |
0xb0aeac, |
0x828181, |
0x6f6e6f, |
0x797877, |
0x8c8c8c, |
0xa7a6a6, |
0xbab9ba, |
0xc3c1c2, |
0xc2c0c1, |
0xb9b8b8, |
0xd7d4d0, |
0xe3dfda, |
0xe2deda, |
0xe1ddd8, |
0xe0dcd7, |
0xe0dbd6, |
0xdfdad5, |
0xdedad5, |
0xddd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xd2cfca, |
0xc0beb7, |
0xdddad6, |
0xd4d0ca, |
0xcbc8c5, |
0xdfdfdf, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xdedede, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x929291, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0x616161, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x5c5c5c, |
0xffffff, |
0xffffff, |
0xfefefe, |
0x848484, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x858585, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 28 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xefefef, |
0xacaaaa, |
0x83807c, |
0x403f3f, |
0x323232, |
0x7d7c7c, |
0xf4f2f0, |
0xf7f5f2, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xe5e2e0, |
0x9e9d9d, |
0xacabab, |
0xbebcbd, |
0xc2c1c1, |
0xbdbcbc, |
0xcccac8, |
0xedeae6, |
0xe8e5e2, |
0xcdcbc9, |
0x9b9a98, |
0x767575, |
0x717070, |
0x777676, |
0x7e7e7d, |
0x8b8a8a, |
0x9c9b9b, |
0xafaeae, |
0xbdbcbc, |
0xc3c1c2, |
0xc3c1c2, |
0xbebdbd, |
0xc6c4c2, |
0xe1ddd9, |
0xe1dcd7, |
0xe0dbd6, |
0xe0dbd6, |
0xdfdad5, |
0xddd9d4, |
0xddd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xd9d6d1, |
0xd8d5cf, |
0xc0bdb6, |
0xdbd9d4, |
0xd4d0ca, |
0xd1cdc8, |
0xcecdcc, |
0xf3f3f3, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe0e0e0, |
0xbfbfbf, |
0xb4b4b4, |
0xc0c0c0, |
0xdfdfdf, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xebebeb, |
0xc8c8c8, |
0xb4b4b4, |
0xbababa, |
0xd5d4d4, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf1f1f1, |
0xc7c7c7, |
0xb4b4b4, |
0xbfbfbf, |
0xdddddd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x474747, |
0xebebeb, |
0xffffff, |
0xffffff, |
0xa3a3a3, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x747474, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 29 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf9f9f9, |
0xd0d0d0, |
0x8c8a85, |
0x595958, |
0x333333, |
0x414141, |
0xe0dfdc, |
0xf6f4f1, |
0xf6f4f1, |
0xf5f3f0, |
0xf5f3f0, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ed, |
0xf2f0ec, |
0xf2efec, |
0xf1eeeb, |
0xf0edea, |
0xb7b5b4, |
0xa2a1a1, |
0xb9b8b8, |
0xc2c0c1, |
0xc1c0c0, |
0xbbb9ba, |
0xcac8c5, |
0x999797, |
0x747373, |
0x737272, |
0x7a7979, |
0x848382, |
0x8f8e8e, |
0x9a9999, |
0xa6a5a5, |
0xb1b0b1, |
0xbbb9ba, |
0xc1bfc0, |
0xc4c2c3, |
0xc4c2c3, |
0xc1bfc0, |
0xbbb9b9, |
0xdad6d2, |
0xe0dbd6, |
0xdfdbd6, |
0xdedad5, |
0xddd9d4, |
0xdcd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd9d6d0, |
0xccc9c3, |
0xc6c4be, |
0xdbd8d3, |
0xd4d0ca, |
0xcac8c5, |
0xe6e6e6, |
0xfdfdfc, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfafafa, |
0xb1b0b0, |
0x505050, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0x5c5c5c, |
0xd1d1d1, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xffffff, |
0xcfcfcf, |
0x676767, |
0x363636, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x484847, |
0xacacac, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xe2e2e2, |
0x4d4d4d, |
0x4e4e4e, |
0xa4a4a4, |
0xfaf9f9, |
0x979797, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x585857, |
0xcbcbcb, |
0xffffff, |
0xffffff, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x757575, |
0xf4f4f4, |
0xffffff, |
0xf2f2f2, |
0xe3e3e3, |
0xe3e3e3, |
0xe3e3e3, |
0xe4e4e4, |
0xebebeb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 30 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe9e9e9, |
0x9f9d9a, |
0x787672, |
0x393939, |
0x323232, |
0xa2a1a0, |
0xf6f4f1, |
0xf5f3f0, |
0xf4f2ef, |
0xf3f1ee, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xf1efec, |
0xf1eeeb, |
0xf0edea, |
0xf0ede9, |
0xd8d6d3, |
0x999898, |
0xb1b0b0, |
0xbfbebe, |
0xc2c0c1, |
0xbbbabb, |
0xa9a8a8, |
0x929191, |
0x868585, |
0x8a8888, |
0x939292, |
0xa09f9f, |
0xabaaaa, |
0xb4b2b3, |
0xbbb9ba, |
0xc3c1c2, |
0xceccca, |
0xc3c1c2, |
0xc3c1c2, |
0xc3c1c2, |
0xc3c1c2, |
0xbcbbbb, |
0xcbc8c6, |
0xdfdad5, |
0xddd9d4, |
0xddd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd5d1cb, |
0xbdbbb3, |
0xdcd9d6, |
0xd4d0ca, |
0xd0cdc7, |
0xd3d3d3, |
0xf7f7f7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xf4f4f4, |
0x7b7a7a, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x373737, |
0xbcbcbc, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xa7a7a7, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x343434, |
0x888888, |
0xf9f9f9, |
0xffffff, |
0xdedede, |
0x323232, |
0x323232, |
0x8f8f8f, |
0x7f7f7f, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x353535, |
0xc4c4c4, |
0xffffff, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x424242, |
0x484848, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x595959, |
0xc7c7c7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 31 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f4f4, |
0xbdbcbb, |
0x898782, |
0x4b4a4a, |
0x323232, |
0x5d5d5d, |
0xebe9e7, |
0xf4f2ef, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xf1efec, |
0xf1eeeb, |
0xf0eeea, |
0xf0edea, |
0xf0ede9, |
0xefece8, |
0xe9e6e3, |
0xa7a6a5, |
0xa7a6a6, |
0xbcbabb, |
0xc3c1c2, |
0xc0bebf, |
0xb6b4b5, |
0xa8a7a7, |
0xa2a0a0, |
0xa5a5a5, |
0xafaeae, |
0xb8b6b6, |
0xbdbcbc, |
0xc9c7c6, |
0xd7d5d2, |
0xe2deda, |
0xe3dfda, |
0xc6c4c3, |
0xbdbbbc, |
0xc1bfc0, |
0xc3c1c2, |
0xc0bebf, |
0xbebcbc, |
0xdad7d2, |
0xdcd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d1, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xc4c2ba, |
0xd0cec8, |
0xd7d3cd, |
0xd3cfc9, |
0xc9c8c6, |
0xececec, |
0xfefefd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xfafafa, |
0x838383, |
0x323232, |
0x323232, |
0x424242, |
0x9f9f9f, |
0xdbdbdb, |
0xe3e3e3, |
0xcfcfcf, |
0x858585, |
0x353535, |
0x323232, |
0x3a3a39, |
0xe3e3e3, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xb6b6b6, |
0x383838, |
0x323232, |
0x363636, |
0x818181, |
0xcfcfcf, |
0xe4e4e4, |
0xd9d9d9, |
0xa1a0a0, |
0x454545, |
0x323232, |
0x353535, |
0xaaaaaa, |
0xffffff, |
0xdedede, |
0x323232, |
0x323232, |
0x444343, |
0x323232, |
0x4b4b4b, |
0xa9a8a8, |
0xdedede, |
0xe3e3e3, |
0xc3c3c2, |
0x5d5d5d, |
0x323232, |
0x323232, |
0x525252, |
0xfafafa, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x4f4f4f, |
0x6f6f6f, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x353535, |
0x777777, |
0xe7e7e7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 32 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfb, |
0xe0e0e0, |
0x92908b, |
0x6a6966, |
0x353535, |
0x343434, |
0xc7c6c6, |
0xf3f1ee, |
0xf2f0ed, |
0xf2f0ec, |
0xf1efec, |
0xf1eeeb, |
0xf0edea, |
0xf0edea, |
0xefece9, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xc8c7c4, |
0x9c9b9b, |
0xb5b4b4, |
0xc1bfc0, |
0xc3c1c2, |
0xbfbdbe, |
0xbab8b9, |
0xb8b6b7, |
0xbab9ba, |
0xc1c0c0, |
0xd0cecc, |
0xdfdcd8, |
0xe4e0db, |
0xe3dfda, |
0xe3dfda, |
0xe2deda, |
0xcfccc9, |
0xafaeae, |
0xbab8b9, |
0xc1c0c0, |
0xc2c0c1, |
0xbab9b9, |
0xcfcdc9, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd2cec8, |
0xbdbbb3, |
0xdedbd7, |
0xd4d0ca, |
0xcbc9c5, |
0xdbdbda, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0x515151, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x686868, |
0x454545, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xc6c6c6, |
0x363636, |
0x323232, |
0x4e4e4e, |
0xdddddd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xadacad, |
0x323232, |
0x323232, |
0x808080, |
0xfefefe, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xefefef, |
0x4c4c4c, |
0x323232, |
0x393939, |
0xb5b5b5, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xd6d6d6, |
0x464646, |
0x323232, |
0x525252, |
0xeeeeee, |
0xdedede, |
0x323232, |
0x323232, |
0x323232, |
0x575757, |
0xececec, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf3f3f3, |
0x464646, |
0x323232, |
0x323232, |
0xd5d5d5, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x525252, |
0xd3d3d3, |
0x4b4b4b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x3d3d3d, |
0x9f9f9f, |
0xfcfcfc, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 33 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xefefef, |
0xacaba9, |
0x83807c, |
0x424141, |
0x323232, |
0x7c7c7b, |
0xf0efec, |
0xf2f0ec, |
0xf1eeec, |
0xf1eeeb, |
0xf0edea, |
0xf0edea, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xedeae6, |
0xe2e0dc, |
0x9f9d9d, |
0xacabab, |
0xbebcbd, |
0xc3c1c2, |
0xc3c1c2, |
0xc3c1c2, |
0xc9c7c6, |
0xd8d6d3, |
0xe3e0dc, |
0xe5e2dd, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xe2deda, |
0xe1ddd8, |
0xdcd8d4, |
0xa3a1a1, |
0xadacac, |
0xbdbcbc, |
0xc2c0c1, |
0xbebcbd, |
0xc1bfbe, |
0xd9d6d1, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd8d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xc0bdb5, |
0xd6d4d0, |
0xd4d0cb, |
0xd2cfc9, |
0xcbcac9, |
0xf1f1f0, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xababab, |
0xfbfbfb, |
0x757575, |
0x323232, |
0x3c3c3c, |
0xc6c6c6, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfbfbfb, |
0x605f5f, |
0x323232, |
0x393938, |
0xf3f3f3, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xacacac, |
0x343434, |
0x323232, |
0x939393, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x9a9a9a, |
0x323232, |
0x353535, |
0xb8b8b8, |
0xdedede, |
0x323232, |
0x323232, |
0x3a3a3a, |
0xc6c6c6, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x8a8a8a, |
0x323232, |
0x323232, |
0xb2b2b2, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x525252, |
0xefefef, |
0xd4d4d4, |
0x505050, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0x6e6e6e, |
0xf9f9f9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 34 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf8f8f7, |
0xcecdcd, |
0x8d8b86, |
0x5c5b59, |
0x333333, |
0x434343, |
0xdcdbd9, |
0xf1eeeb, |
0xf0eeea, |
0xf0edea, |
0xefece9, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xece9e5, |
0xece9e5, |
0xeae8e3, |
0xb5b4b2, |
0xa1a0a0, |
0xb7b6b7, |
0xc2c1c1, |
0xc4c2c3, |
0xc6c4c5, |
0xe2dfdb, |
0xe5e2dd, |
0xe4e1dc, |
0xe3dfda, |
0xe3dfda, |
0xe2deda, |
0xe1ddd9, |
0xe0dcd7, |
0xe0dbd6, |
0xe0dbd6, |
0xb4b2b0, |
0xa09f9f, |
0xb7b6b7, |
0xc2c0c1, |
0xc1c0c0, |
0xbbb9b9, |
0xd3d1cc, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xcdcac3, |
0xc0beb7, |
0xdddad5, |
0xd4d0ca, |
0xc9c7c4, |
0xe1e1e1, |
0xfcfcfc, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xababab, |
0xe6e6e6, |
0x4b4b4b, |
0x323232, |
0x5b5b5b, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xa8a8a7, |
0x323232, |
0x323232, |
0xbebebe, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0x707070, |
0x323232, |
0x393939, |
0xdddddd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xdadada, |
0x3e3e3e, |
0x323232, |
0x808080, |
0xdedede, |
0x323232, |
0x323232, |
0x535353, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb0b0b0, |
0x323232, |
0x323232, |
0xacacac, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x525252, |
0xefefef, |
0xffffff, |
0xececec, |
0x7a7a7a, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0x8b8b8b, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 35 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe8e7e7, |
0x9c9a96, |
0x797873, |
0x3a3a3a, |
0x323232, |
0xa2a1a0, |
0xf2efec, |
0xf0edea, |
0xefece9, |
0xefece8, |
0xeeebe7, |
0xeeebe7, |
0xedeae6, |
0xece9e5, |
0xece9e5, |
0xebe8e4, |
0xe9e7e2, |
0xd6d5d1, |
0x999898, |
0xb0afaf, |
0xbfbebe, |
0xc4c2c3, |
0xc3c1c2, |
0xd6d3d0, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xe2deda, |
0xe1ddd8, |
0xe0dcd7, |
0xe0dbd6, |
0xdfdbd6, |
0xddd9d4, |
0xcecbc7, |
0x999999, |
0xaeadae, |
0xbebdbe, |
0xc3c1c2, |
0xbcbbbb, |
0xc9c7c3, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd3cfc9, |
0xbdbab3, |
0xdbd8d4, |
0xd4d0ca, |
0xd1cec8, |
0xcececd, |
0xf5f4f4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xcbcbcb, |
0x323232, |
0x323232, |
0x878686, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xcacaca, |
0x323232, |
0x323232, |
0x9c9c9b, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xeaeaea, |
0x454545, |
0x323232, |
0x575757, |
0xf0f0f0, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xeaeaea, |
0x515151, |
0x323232, |
0x5d5d5d, |
0xdedede, |
0x323232, |
0x323232, |
0x777777, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x525252, |
0xefefef, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xc1c1c1, |
0x525252, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x343434, |
0xe1e1e1, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 36 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f4f3, |
0xbabab9, |
0x898782, |
0x4e4d4c, |
0x323232, |
0x5e5e5e, |
0xe7e5e3, |
0xefece8, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xedeae6, |
0xece9e5, |
0xebe8e4, |
0xeae8e3, |
0xe9e7e2, |
0xe9e7e2, |
0xe4e3de, |
0xa8a7a5, |
0xa6a5a5, |
0xbbb9ba, |
0xc3c1c2, |
0xc3c1c2, |
0xc4c1c1, |
0xe1ded9, |
0xe2deda, |
0xe1ddd9, |
0xe1ddd8, |
0xe0dbd6, |
0xe0dbd6, |
0xdedad5, |
0xddd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xa4a3a2, |
0xa5a4a4, |
0xbab9b9, |
0xc2c0c1, |
0xc0bebf, |
0xcbc8c6, |
0xd8d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xc7c5be, |
0xc9c6c0, |
0xd9d5d0, |
0xd4d0ca, |
0xc9c8c5, |
0xe8e8e7, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xb3b3b3, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x7e7e7e, |
0xfefefe, |
0x565656, |
0x323232, |
0x494949, |
0xd6d6d6, |
0x404040, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x4e4e4e, |
0xcecece, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x525252, |
0xefefef, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf5f5f5, |
0x949494, |
0x373737, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x9d9d9d, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 37 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfbfbfb, |
0xdddddd, |
0x8f8d8a, |
0x6c6a68, |
0x363636, |
0x363636, |
0xc5c4c3, |
0xefece8, |
0xeeebe7, |
0xedeae6, |
0xece9e5, |
0xece9e5, |
0xebe8e4, |
0xeae7e3, |
0xe9e7e2, |
0xe8e6e1, |
0xe8e6e1, |
0xe7e5e0, |
0xc7c5c2, |
0x9a9a9a, |
0xb4b3b3, |
0xc1bfc0, |
0xc3c1c2, |
0xbdbbbc, |
0xd5d2ce, |
0xe1ddd9, |
0xe0dcd7, |
0xe0dbd6, |
0xdfdad5, |
0xdedad5, |
0xdcd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xc6c3c0, |
0x9f9d9d, |
0xb2b1b2, |
0xc1bfc0, |
0xc5c3c3, |
0xd4d0cc, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd1cec7, |
0xbbb8b1, |
0xdddad6, |
0xd4d0ca, |
0xcfcbc6, |
0xd4d4d4, |
0xf8f8f8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xa5a5a5, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x7a7a7a, |
0xfefefe, |
0x565656, |
0x323232, |
0x494949, |
0xcbcbcb, |
0x3d3d3d, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x4d4d4d, |
0xcccccc, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x424242, |
0xa4a4a4, |
0xb4b4b4, |
0xb4b4b4, |
0xb4b4b4, |
0xdadada, |
0xffffff, |
0xfefefe, |
0xc6c6c6, |
0x3d3d3d, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x7b7b7b, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 38 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xefeeee, |
0xaaa8a7, |
0x827f7b, |
0x434242, |
0x323232, |
0x7d7d7c, |
0xeeece9, |
0xedeae6, |
0xece9e5, |
0xebe8e4, |
0xeae8e3, |
0xe9e7e2, |
0xe9e7e2, |
0xe8e6e1, |
0xe8e5e0, |
0xe7e4df, |
0xe6e3de, |
0xdddad6, |
0x9d9c9b, |
0xabaaaa, |
0xbdbcbc, |
0xc3c1c2, |
0xbfbdbe, |
0xc3c1c0, |
0xe0dcd7, |
0xe0dbd6, |
0xdedad5, |
0xddd9d4, |
0xdbd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd8d5d0, |
0xcac8c3, |
0xc0bebc, |
0xc9c7c5, |
0xd4d0cc, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd2cfc8, |
0xc1beb8, |
0xc7c4be, |
0xd5d1cb, |
0xd4d0ca, |
0xc3c0b9, |
0xd3d1cc, |
0xd6d2cc, |
0xd3cfca, |
0xc8c7c6, |
0xeeeeed, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xa8a8a8, |
0x323232, |
0x323232, |
0x747474, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xe0e0e0, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xcecece, |
0x3e3e3e, |
0x323232, |
0x505050, |
0xc4c4c4, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xcfcfcf, |
0xd5d5d5, |
0xd9d9d9, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xd5d5d5, |
0x393939, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xb1b1b1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x787878, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x9a9a9a, |
0xffffff, |
0xffffff, |
0xfefefe, |
0x898988, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x696969, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 39 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf8f8f7, |
0xcbcbcb, |
0x8d8a86, |
0x5e5d5b, |
0x343433, |
0x454545, |
0xd9d8d6, |
0xece9e5, |
0xebe8e4, |
0xe9e7e2, |
0xe9e7e2, |
0xe8e6e1, |
0xe8e6e1, |
0xe7e5e0, |
0xe6e4df, |
0xe5e2dd, |
0xe5e2dd, |
0xe4e0db, |
0xb7b5b3, |
0xa09fa0, |
0xb7b6b6, |
0xc2c0c1, |
0xc1c0c0, |
0xbab8b8, |
0xd9d5d1, |
0xdedad5, |
0xdcd9d4, |
0xdbd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xacaaa3, |
0x817f7b, |
0x93918e, |
0xd7d4d0, |
0xd4d0ca, |
0xcecac4, |
0xc3c1ba, |
0xe1deda, |
0xd4d0ca, |
0xcac8c4, |
0xdcdcdc, |
0xfafafa, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xc1c1c1, |
0x323232, |
0x323232, |
0x7c7c7c, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xe1e1e1, |
0x434343, |
0x323232, |
0x505050, |
0xededed, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xdedede, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0xa3a3a3, |
0xffffff, |
0xffffff, |
0xffffff, |
0x6d6d6d, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x9a9a9a, |
0xffffff, |
0xffffff, |
0xffffff, |
0xa3a3a3, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x696969, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 40 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe7e7e7, |
0x9a9896, |
0x797773, |
0x3b3b3b, |
0x323232, |
0xa2a1a0, |
0xedeae6, |
0xe9e7e2, |
0xe8e6e1, |
0xe8e6e1, |
0xe8e5e0, |
0xe7e4df, |
0xe6e3de, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe3dfda, |
0xd3d0cd, |
0x999898, |
0xafaeae, |
0xbfbebe, |
0xc3c1c2, |
0xbcbbbb, |
0xc9c6c4, |
0xdcd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xdad7d1, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xb5b3ae, |
0xadaba4, |
0xd2d0ca, |
0xe6e4e2, |
0xd4d0ca, |
0xd1cdc7, |
0xc2c0b9, |
0xe9e6e4, |
0xd4d0ca, |
0xd2cfc9, |
0xcac9c9, |
0xf3f3f3, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xdfdfdf, |
0x414141, |
0x323232, |
0x535353, |
0xf8f8f8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xcfcfcf, |
0x7d7d7d, |
0x7d7d7d, |
0xcacaca, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0x5f5f5f, |
0x323232, |
0x353535, |
0xd7d7d7, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xebebeb, |
0x898989, |
0x7d7d7d, |
0xa2a2a2, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xf6f6f6, |
0x3e3e3e, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x747474, |
0xfbfbfb, |
0xffffff, |
0xefeeee, |
0x515151, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x717170, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0x7f7f7f, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x828282, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 41 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f4f3, |
0xb9b9b8, |
0x898781, |
0x4f4e4d, |
0x323232, |
0x5f5f5f, |
0xe5e3e1, |
0xe8e6e1, |
0xe8e6e1, |
0xe7e5e0, |
0xe7e4df, |
0xe6e3de, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xdedad7, |
0xa8a6a5, |
0xa5a4a4, |
0xbbb9ba, |
0xc2c0c1, |
0xc0bebf, |
0xc1bfbe, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd6d2cc, |
0xe5e3e0, |
0xecebe8, |
0xdad6d1, |
0xd4d0ca, |
0xcbc8c2, |
0xc7c5bf, |
0xeae8e6, |
0xd4d0ca, |
0xd3cfc9, |
0xbfbebc, |
0xeaeaea, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xf8f8f8, |
0x6a696a, |
0x323232, |
0x383838, |
0xb8b8b8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0x6c6c6c, |
0x323232, |
0x323232, |
0xe1e1e1, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xa1a0a0, |
0x333333, |
0x323232, |
0x848484, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xa8a8a7, |
0x323232, |
0x323232, |
0xa3a3a3, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xffffff, |
0x696969, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x373737, |
0x9b9b9a, |
0xcccccc, |
0x878686, |
0x353535, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x5c5c5c, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x393939, |
0x969595, |
0xcecece, |
0xa4a4a4, |
0x3b3b3b, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0xaeaeae, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 42 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfbfbfa, |
0xdbdbdb, |
0x918e8b, |
0x6d6c68, |
0x363636, |
0x363636, |
0xbfbebd, |
0xe9e7e2, |
0xe7e5e0, |
0xe6e4df, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e1dc, |
0xe3dfda, |
0xe2deda, |
0xe1ddd9, |
0xe1ddd9, |
0xe0dcd7, |
0xc5c2bf, |
0x9a9999, |
0xb3b2b3, |
0xc1bfc0, |
0xc3c1c2, |
0xcac8c6, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd3cfc9, |
0xbdbbb3, |
0xdeddd9, |
0xe3e0dc, |
0xd4d0ca, |
0xd3cfc9, |
0xb5b4b3, |
0xe4e4e4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xc3c3c3, |
0x363636, |
0x323232, |
0x494949, |
0xd4d4d4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf8f8f8, |
0x8f8f8f, |
0x323232, |
0x323232, |
0x767676, |
0xfefefe, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xececec, |
0x4b4b4b, |
0x323232, |
0x373736, |
0xacacac, |
0xfbfbfb, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xbababa, |
0x414141, |
0x323232, |
0x4f4f4f, |
0xe7e7e7, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xffffff, |
0xacacac, |
0x343434, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x3d3d3d, |
0xa3a3a3, |
0x3a3a3a, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x3b3b3b, |
0xefeeee, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 43 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xeeeeee, |
0xa9a8a7, |
0x82807b, |
0x454544, |
0x323232, |
0x787877, |
0xeae8e4, |
0xe6e3de, |
0xe5e2dd, |
0xe4e1dc, |
0xe4e0db, |
0xe3dfda, |
0xe2deda, |
0xe1ddd9, |
0xe1dcd8, |
0xe0dbd6, |
0xdfdad5, |
0xdbd7d2, |
0xb5b3b1, |
0xadabac, |
0xbdbcbc, |
0xc8c6c6, |
0xd7d4d0, |
0xdad7d2, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd2cec8, |
0xc1beb6, |
0xc5c4bd, |
0xf4f3f1, |
0xd7d3cd, |
0xd4d0ca, |
0xccc9c3, |
0xadacac, |
0xe4e4e4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xfbfbfb, |
0x8c8c8c, |
0x323232, |
0x323232, |
0x373737, |
0x777777, |
0xa9a9a9, |
0xb3b3b3, |
0x9b9b9b, |
0x545454, |
0x323232, |
0x323232, |
0x484848, |
0xe7e7e7, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xbfbfbf, |
0x3a3a3a, |
0x323232, |
0x323232, |
0x616161, |
0x9d9d9d, |
0xb4b4b4, |
0xa7a7a7, |
0x6c6b6b, |
0x353535, |
0x323232, |
0x3b3b3b, |
0xb6b6b6, |
0xffffff, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xffffff, |
0xf3f3f3, |
0x5c5c5c, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x868586, |
0xfafafa, |
0x8a8a8a, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x333333, |
0xa09f9f, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 44 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf7f7f7, |
0xcacaca, |
0x8b8984, |
0x5f5e5c, |
0x343434, |
0x454545, |
0xd5d4d2, |
0xe5e2dd, |
0xe4e1dc, |
0xe3e0db, |
0xe3dfda, |
0xe1ddd9, |
0xe1ddd9, |
0xe0dcd7, |
0xe0dbd6, |
0xdfdad5, |
0xddd9d4, |
0xddd9d4, |
0xdad7d2, |
0xd2d0cc, |
0xd4d2ce, |
0xd8d6d1, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd3cfc9, |
0xcecac3, |
0xc3c0b8, |
0xbbb9b1, |
0xcfcdc7, |
0xf2f1ef, |
0xdfdcd8, |
0xd4d0ca, |
0xd3cfc9, |
0x9c9a96, |
0xb4b3b3, |
0xeaeae9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7e7e7e, |
0x323232, |
0x323232, |
0xa9a9a9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0x7d7d7d, |
0x323232, |
0x323232, |
0xababab, |
0xffffff, |
0xffffff, |
0xf8f8f8, |
0x919191, |
0x373737, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x545454, |
0xe1e1e1, |
0xffffff, |
0xffffff, |
0xffffff, |
0x565656, |
0x323232, |
0x494949, |
0xf2f2f2, |
0xffffff, |
0xffffff, |
0xbcbbbb, |
0x444444, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x424242, |
0xb5b5b5, |
0xffffff, |
0xffffff, |
0xdedede, |
0x323232, |
0x323232, |
0x818181, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xb4b4b4, |
0x323232, |
0x323232, |
0xacacac, |
0xffffff, |
0xffffff, |
0xe6e6e6, |
0x626262, |
0x333333, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x343434, |
0x7f7e7e, |
0xf4f4f4, |
0xffffff, |
0xf7f7f7, |
0x898989, |
0x343434, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x323232, |
0x343434, |
0x9a9a9a, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 45 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe7e6e6, |
0x989795, |
0x797873, |
0x3c3c3c, |
0x323232, |
0x9c9c9b, |
0xe8e5e1, |
0xe3dfda, |
0xe2deda, |
0xe1ddd9, |
0xe1ddd8, |
0xe0dcd7, |
0xdfdbd6, |
0xdedad5, |
0xddd9d4, |
0xdcd8d3, |
0xdbd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xcecbc5, |
0xc5c3bb, |
0xbdbab2, |
0xc2c0ba, |
0xd7d6d1, |
0xecebe9, |
0xeeedea, |
0xdcd9d4, |
0xd4d0ca, |
0xd3cfc9, |
0x9d9b97, |
0x6f6f6e, |
0xc3c2c2, |
0xf2f2f1, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xbfbfbf, |
0x989898, |
0x989898, |
0xd4d4d4, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xbebebe, |
0x989898, |
0x989898, |
0xd5d5d5, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xd8d8d7, |
0x868585, |
0x535353, |
0x353535, |
0x333333, |
0x454545, |
0x666565, |
0xadadad, |
0xf9f9f9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xababab, |
0x989898, |
0xa4a4a4, |
0xf9f9f9, |
0xffffff, |
0xffffff, |
0xffffff, |
0xebebeb, |
0x9d9d9d, |
0x605f5f, |
0x3b3b3b, |
0x323232, |
0x3d3d3d, |
0x5a5959, |
0x949494, |
0xe8e8e8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xeeeeee, |
0x989898, |
0x989898, |
0xc0c0c0, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xd9d9d9, |
0x999999, |
0x989898, |
0xd5d5d5, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfc, |
0xc1c1c1, |
0x7a7a7a, |
0x555554, |
0x363636, |
0x323232, |
0x3a3a3a, |
0x595958, |
0x878787, |
0xd0d0d0, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xd5d5d5, |
0x8b8b8b, |
0x5b5a5a, |
0x3c3c3c, |
0x323232, |
0x383838, |
0x5b5b5b, |
0x898989, |
0xdddddd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 46 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f3f3, |
0xb9b8b8, |
0x878580, |
0x51514f, |
0x323232, |
0x5c5c5c, |
0xe2e0dd, |
0xe2deda, |
0xe1ddd9, |
0xe1dcd7, |
0xe0dbd6, |
0xdfdad5, |
0xded9d4, |
0xddd9d4, |
0xdcd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd0ccc6, |
0xc7c4be, |
0xbcbab2, |
0xc0bfb8, |
0xd1d0cb, |
0xe9e8e6, |
0xeeedeb, |
0xe7e5e1, |
0xdbd8d3, |
0xd5d1cb, |
0xd1cdc7, |
0xb5b2ae, |
0x7a7978, |
0x4b4b4b, |
0x969595, |
0xd6d6d6, |
0xf8f8f8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 47 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfafafa, |
0xdadada, |
0x8f8d8a, |
0x6e6c69, |
0x373636, |
0x373737, |
0xbebdbc, |
0xe4e0db, |
0xe0dcd7, |
0xdfdbd6, |
0xdedad5, |
0xddd9d4, |
0xdcd9d4, |
0xdbd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd1cdc7, |
0xcac6c0, |
0xbfbcb5, |
0xbebcb5, |
0xceccc7, |
0xe5e4e1, |
0xefeeec, |
0xeae8e4, |
0xdddad5, |
0xd6d2cc, |
0xd2cec8, |
0xbdbab4, |
0x94928f, |
0x626160, |
0x424141, |
0x444343, |
0x807f7f, |
0xbcbbbc, |
0xeaeaea, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 48 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xeeeeee, |
0xa8a7a5, |
0x817f7a, |
0x464544, |
0x333333, |
0xa6a5a5, |
0xe6e3e0, |
0xdfdbd6, |
0xded9d4, |
0xddd9d4, |
0xdcd8d3, |
0xdbd8d3, |
0xdbd8d3, |
0xdad7d2, |
0xdad7d2, |
0xd9d6d1, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d5cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd2cec8, |
0xcbc8c1, |
0xc0bdb5, |
0xbebcb5, |
0xc9c7c1, |
0xe2e1de, |
0xeeedeb, |
0xeceae8, |
0xdfdcd8, |
0xd7d3cd, |
0xd3cfc9, |
0xc2beb9, |
0x9f9d98, |
0x6b6a67, |
0x4a4948, |
0x3b3b3b, |
0x474746, |
0x626161, |
0x8b8a8a, |
0xb7b6b6, |
0xe0e0df, |
0xf8f8f8, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 49 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf7f7f7, |
0xc9c8c8, |
0x8b8884, |
0x5f5f5d, |
0x5d5c5c, |
0xd3d2d0, |
0xe2dfdb, |
0xddd9d4, |
0xddd9d4, |
0xdcd8d3, |
0xdbd8d3, |
0xd0cdc8, |
0xc7c4c0, |
0xd4d2cd, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d4ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd4d0ca, |
0xd4d0ca, |
0xd3cfc9, |
0xcdc9c3, |
0xc2bfb8, |
0xbdbbb3, |
0xc5c3bd, |
0xdddcd8, |
0xedecea, |
0xeeedeb, |
0xe1deda, |
0xd8d4cf, |
0xd3d0ca, |
0xc6c2bd, |
0xa8a5a1, |
0x747371, |
0x4f4f4f, |
0x3d3d3d, |
0x444444, |
0x5b5b5a, |
0x777777, |
0x939392, |
0xababab, |
0xc8c7c7, |
0xe4e4e4, |
0xf7f7f7, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 50 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xe6e6e6, |
0x989794, |
0x83817d, |
0xc4c3c2, |
0xcbc9c2, |
0xd5d3ce, |
0xdfdbd6, |
0xdbd8d3, |
0xdbd8d3, |
0xd5d2cd, |
0x94928d, |
0x85837e, |
0xaaa8a4, |
0xe1deda, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd3cfc9, |
0xcfcbc5, |
0xc5c2ba, |
0xbebbb3, |
0xc2c0b9, |
0xd8d7d3, |
0xebeae8, |
0xefeeec, |
0xe4e1dd, |
0xd9d6d0, |
0xd4d0ca, |
0xcac6c0, |
0xafaca8, |
0x807f7c, |
0x565655, |
0x3e3e3e, |
0x444343, |
0x555454, |
0x717070, |
0x8d8b8c, |
0xa6a5a5, |
0xbcbbbb, |
0xd0d0d0, |
0xe2e2e2, |
0xf1f1f1, |
0xfafafa, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 51 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f3f3, |
0xb8b8b7, |
0x9d9b96, |
0xd8d5d1, |
0xd3d0ca, |
0xc2c0ba, |
0xe1deda, |
0xdbd8d3, |
0xdad7d2, |
0xd5d3ce, |
0xa7a5a2, |
0xc2c0b9, |
0xd8d7d5, |
0xe3e1dd, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xcfccc5, |
0xc7c4be, |
0xbdbbb3, |
0xc0beb7, |
0xd3d2cd, |
0xe8e8e5, |
0xf1f0ef, |
0xe6e4e0, |
0xdbd8d3, |
0xd4d1cb, |
0xccc8c3, |
0xb8b5b0, |
0x898785, |
0x5f5e5c, |
0x444343, |
0x444443, |
0x515151, |
0x6b6b6a, |
0x868685, |
0xa09f9f, |
0xb6b5b5, |
0xcccbcb, |
0xdedede, |
0xececec, |
0xf6f6f6, |
0xfcfcfc, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 52 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfafafa, |
0xd9d9d9, |
0x8c8a87, |
0xbfbcb7, |
0xd8d4ce, |
0xc0beb7, |
0xdcd9d4, |
0xdbd8d3, |
0xdad7d2, |
0xd9d6d0, |
0xe0ddd9, |
0xebeae7, |
0xeae9e6, |
0xd9d5d0, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd6d2cc, |
0xd5d1cb, |
0xd2cec8, |
0xc9c7c0, |
0xbebbb4, |
0xbdbbb4, |
0xceccc7, |
0xe6e5e2, |
0xf1f0ee, |
0xe9e7e4, |
0xdcd9d4, |
0xd5d1cb, |
0xd0ccc6, |
0xbdbab4, |
0x95938f, |
0x656463, |
0x474747, |
0x444443, |
0x4f4f4e, |
0x646464, |
0x807f7e, |
0x9b9a9a, |
0xb1b0b0, |
0xc7c6c6, |
0xdadada, |
0xe9e9e9, |
0xf4f4f4, |
0xfbfbfb, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 53 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xeeeeed, |
0x9c9b9a, |
0x92908d, |
0xd5d2cc, |
0xceccc6, |
0xc4c2bb, |
0xdcd9d4, |
0xd9d6d0, |
0xd9d6d0, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3ce, |
0xd7d3cd, |
0xd7d3cd, |
0xd6d2cc, |
0xd3cfc9, |
0xcdc9c3, |
0xc0beb6, |
0xbdbbb3, |
0xc9c8c1, |
0xe2e1de, |
0xf1f1ef, |
0xebe9e6, |
0xdfdcd7, |
0xd5d1cb, |
0xd1cdc7, |
0xc2bfba, |
0x9d9a96, |
0x6f6e6b, |
0x4d4c4b, |
0x464544, |
0x4c4c4b, |
0x60605f, |
0x7a7a79, |
0x959595, |
0xababab, |
0xc1c1c1, |
0xd6d5d5, |
0xe7e7e6, |
0xf3f2f2, |
0xfafaf9, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 54 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf7f7f7, |
0xc7c7c6, |
0x787775, |
0xc8c4be, |
0xd7d4cf, |
0xc3c1b9, |
0xc4c2ba, |
0xd4d1cb, |
0xd8d5cf, |
0xd8d4cf, |
0xd7d3cd, |
0xd7d3cd, |
0xd5d1cb, |
0xcfcbc5, |
0xc3c0b8, |
0xbdbbb4, |
0xc3c1bb, |
0xdfdedb, |
0xefeeed, |
0xefedeb, |
0xe0deda, |
0xd7d3cd, |
0xd2cec8, |
0xc7c3bd, |
0xa6a39e, |
0x757371, |
0x525150, |
0x454544, |
0x4b4a49, |
0x5c5b5a, |
0x767575, |
0x909090, |
0xa7a6a6, |
0xbdbdbd, |
0xd1d1d1, |
0xe2e2e1, |
0xf0efef, |
0xf8f8f8, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 55 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfc, |
0xe6e6e5, |
0x848382, |
0xa5a39e, |
0xd6d2cc, |
0xd7d4ce, |
0xc8c5be, |
0xbcbab2, |
0xc4c1ba, |
0xcbc8c1, |
0xccc9c2, |
0xc4c1ba, |
0xbdbbb3, |
0xc1bfb8, |
0xd8d7d3, |
0xededeb, |
0xf1f0ee, |
0xe3e1dd, |
0xd8d4cf, |
0xd3cfca, |
0xcac6c1, |
0xafaca7, |
0x7d7b78, |
0x555452, |
0x454443, |
0x494847, |
0x575555, |
0x706f6f, |
0x8a8989, |
0xa2a1a1, |
0xb8b7b8, |
0xcecdcd, |
0xe0e0df, |
0xeeeeed, |
0xf7f7f7, |
0xfcfcfc, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 56 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf4f3f3, |
0xb2b2b2, |
0x797875, |
0xcdc9c3, |
0xd6d3cd, |
0xd9d6d0, |
0xdcd9d5, |
0xd8d7d2, |
0xcfcdc7, |
0xd0cec9, |
0xdcdad7, |
0xeae9e6, |
0xf3f2f1, |
0xe6e3e0, |
0xdad6d0, |
0xd4d0ca, |
0xcdc9c3, |
0xb5b2ad, |
0x878581, |
0x5d5c5a, |
0x464544, |
0x474645, |
0x515050, |
0x696968, |
0x848483, |
0x9d9c9c, |
0xb3b2b2, |
0xc8c8c8, |
0xdcdcdc, |
0xebebeb, |
0xf6f6f5, |
0xfbfbfb, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 57 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfafafa, |
0xd8d8d8, |
0x71706f, |
0x92908c, |
0xd1cec8, |
0xd6d2cc, |
0xd7d3cd, |
0xd8d4ce, |
0xdfdbd6, |
0xe2dfdb, |
0xe1deda, |
0xdbd7d2, |
0xd4d0ca, |
0xcfcbc5, |
0xbfbcb6, |
0x8e8c89, |
0x646260, |
0x494847, |
0x494847, |
0x504f4e, |
0x646362, |
0x7e7d7d, |
0x979696, |
0xadacac, |
0xc4c3c3, |
0xd8d7d7, |
0xe8e8e8, |
0xf3f3f3, |
0xfafafa, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 58 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfefefe, |
0xeeeeed, |
0x9f9e9e, |
0x5a5958, |
0x878683, |
0xc6c2bd, |
0xd3cfc9, |
0xd5d1cb, |
0xd5d1cb, |
0xd4d0ca, |
0xd1cdc7, |
0xc4c0bb, |
0x9a9894, |
0x6c6b68, |
0x4d4c4b, |
0x494847, |
0x4d4c4b, |
0x5f5e5d, |
0x777776, |
0x929292, |
0xa8a7a7, |
0xbebdbe, |
0xd4d3d2, |
0xe5e5e5, |
0xf1f1f1, |
0xf9f9f9, |
0xfdfdfd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 59 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xf8f8f7, |
0xd5d4d4, |
0x7c7c7b, |
0x555452, |
0x5f5e5c, |
0x82807c, |
0x989692, |
0x9a9894, |
0x92908c, |
0x747371, |
0x525251, |
0x4a4948, |
0x4e4d4c, |
0x5a5a59, |
0x717171, |
0x8c8b8c, |
0xa3a2a2, |
0xb9b9b9, |
0xd0cfcf, |
0xe1e1e1, |
0xeeeeee, |
0xf7f7f7, |
0xfcfcfc, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 60 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfdfdfd, |
0xefefef, |
0xc5c5c5, |
0x807f7e, |
0x585755, |
0x525150, |
0x51504f, |
0x4f4f4e, |
0x4e4e4d, |
0x4f4f4e, |
0x595857, |
0x6d6c6b, |
0x878787, |
0x9e9d9d, |
0xb4b3b4, |
0xcacaca, |
0xdddddd, |
0xededec, |
0xf7f7f6, |
0xfcfcfc, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 61 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfb, |
0xebebea, |
0xcacaca, |
0xa09f9f, |
0x7b7b7a, |
0x6b6b6a, |
0x686868, |
0x6f6f6e, |
0x838281, |
0x9a9999, |
0xafaeae, |
0xc5c5c5, |
0xdadad9, |
0xe9e9e9, |
0xf4f4f3, |
0xfbfbfb, |
0xfefefe, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 62 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xfcfcfb, |
0xf0f0f0, |
0xdcdcdb, |
0xc7c7c7, |
0xb8b7b7, |
0xb2b2b2, |
0xb6b6b6, |
0xc4c3c3, |
0xd5d5d5, |
0xe6e6e6, |
0xf3f3f2, |
0xfafafa, |
0xfefefd, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 63 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 64 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
/* Scanline 65 */ |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
0xffffff, |
}; |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/fb/fb.c |
---|
1,4 → 1,5 |
/* |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
26,7 → 27,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
33,6 → 34,7 |
*/ |
#include <genarch/fb/font-8x16.h> |
#include <genarch/fb/logo-196x66.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/fb/fb.h> |
#include <console/chardev.h> |
39,6 → 41,7 |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <mm/slab.h> |
#include <align.h> |
#include <panic.h> |
#include <memstr.h> |
#include <config.h> |
47,137 → 50,116 |
#include <ddi/ddi.h> |
#include <arch/types.h> |
#include "helenos.xbm" |
SPINLOCK_INITIALIZE(fb_lock); |
static parea_t fb_parea; /**< Physical memory area for fb. */ |
static uint8_t *fb_addr; |
static uint8_t *backbuf; |
static uint8_t *glyphs; |
static uint8_t *bgscan; |
SPINLOCK_INITIALIZE(fb_lock); |
static unsigned int xres; |
static unsigned int yres; |
static uint8_t *fbaddress = NULL; |
static unsigned int ylogo; |
static unsigned int ytrim; |
static unsigned int rowtrim; |
static uint8_t *blankline = NULL; |
static uint8_t *dbbuffer = NULL; /* Buffer for fast scrolling console */ |
static index_t dboffset; |
static unsigned int scanline; |
static unsigned int glyphscanline; |
static unsigned int xres = 0; |
static unsigned int yres = 0; |
static unsigned int scanline = 0; |
static unsigned int pixelbytes = 0; |
#ifdef FB_INVERT_COLORS |
static bool invert_colors = true; |
#else |
static bool invert_colors = false; |
#endif |
static unsigned int pixelbytes; |
static unsigned int glyphbytes; |
static unsigned int bgscanbytes; |
static unsigned int cols; |
static unsigned int rows; |
static unsigned int position = 0; |
static unsigned int columns = 0; |
static unsigned int rows = 0; |
#define COL_WIDTH 8 |
#define ROW_BYTES (scanline * FONT_SCANLINES) |
#define BG_COLOR 0x000080 |
#define FG_COLOR 0xffff00 |
#define BGCOLOR 0x000080 |
#define FGCOLOR 0xffff00 |
#define LOGOCOLOR 0x2020b0 |
#define CURSOR 219 |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
#define POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes) |
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
/***************************************************************/ |
/* Pixel specific fuctions */ |
#define X2COL(x) ((x) / FONT_WIDTH) |
#define Y2ROW(y) ((y) / FONT_SCANLINES) |
static void (*rgb2scr)(void *, int); |
static int (*scr2rgb)(void *); |
#define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes) |
#define BB_POS(col, row) ((row) * cols + (col)) |
#define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline) |
static inline int COLOR(int color) |
{ |
return invert_colors ? ~color : color; |
} |
/* Conversion routines between different color representations */ |
static void rgb_byte0888(void *dst, int rgb) |
{ |
*((int *) dst) = rgb; |
} |
static void (*rgb_conv)(void *, uint32_t); |
static int byte0888_rgb(void *src) |
{ |
return (*((int *) src)) & 0xffffff; |
} |
static void bgr_byte0888(void *dst, int rgb) |
/** ARGB 8:8:8:8 conversion |
* |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 | |
RED(rgb, 8); |
*((uint32_t *) dst) = rgb & 0xffffff; |
} |
static int byte0888_bgr(void *src) |
{ |
int color = *(uint32_t *)(src); |
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) | |
((color >> 16) & 0xff); |
} |
static void rgb_byte888(void *dst, int rgb) |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
uint8_t *scr = (uint8_t *) dst; |
#if defined(FB_INVERT_ENDIAN) |
scr[0] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[2] = BLUE(rgb, 8); |
#else |
scr[2] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[0] = BLUE(rgb, 8); |
#endif |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
} |
static int byte888_rgb(void *src) |
{ |
uint8_t *scr = (uint8_t *) src; |
#if defined(FB_INVERT_ENDIAN) |
return scr[0] << 16 | scr[1] << 8 | scr[2]; |
#else |
return scr[2] << 16 | scr[1] << 8 | scr[0]; |
#endif |
} |
/** 16-bit depth (5:5:5) */ |
static void rgb_byte555(void *dst, int rgb) |
/** RGB 8:8:8 conversion |
* |
*/ |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
/* 5-bit, 5-bits, 5-bits */ |
*((uint16_t *) dst) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 | |
BLUE(rgb, 5); |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
/** 16-bit depth (5:5:5) */ |
static int byte555_rgb(void *src) |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 10) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3); |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
/** 16-bit depth (5:6:5) */ |
static void rgb_byte565(void *dst, int rgb) |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
{ |
/* 5-bit, 6-bits, 5-bits */ |
*((uint16_t *) dst) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | |
BLUE(rgb, 5); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
/** 16-bit depth (5:6:5) */ |
static int byte565_rgb(void *src) |
/** RGB 5:6:5 conversion |
* |
*/ |
static void rgb_565(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 11) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
/** Put pixel - 8-bit depth (color palette/3:2:3) |
/** RGB 3:2:3 |
* |
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer |
* will most likely use a color palette. The color appearance |
184,246 → 166,162 |
* will be pretty random and depend on the default installed |
* palette. This could be fixed by supporting custom palette |
* and setting it to simulate the 8-bit truecolor. |
* |
* Currently we set the palette on the ia32, amd64 and sparc64 port. |
* |
* Note that the byte is being inverted by this function. The reason is |
* that we would like to use a color palette where the white color code |
* is 0 and the black color code is 255, as some machines (Sun Blade 1500) |
* use these codes for black and white and prevent to set codes |
* 0 and 255 to other colors. |
* |
*/ |
static void rgb_byte8(void *dst, int rgb) |
static void rgb_323(void *dst, uint32_t rgb) |
{ |
*((uint8_t *) dst) = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | |
BLUE(rgb, 3); |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
/** Return pixel color - 8-bit depth (color palette/3:2:3) |
/** Hide logo and refresh screen |
* |
* See the comment for rgb_byte(). |
*/ |
static int byte8_rgb(void *src) |
static void logo_hide(bool silent) |
{ |
int color = *(uint8_t *)src; |
return (((color >> 5) & 0x7) << (16 + 5)) | |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5); |
ylogo = 0; |
ytrim = yres; |
rowtrim = rows; |
if (!silent) |
fb_redraw(); |
} |
static void putpixel(unsigned int x, unsigned int y, int color) |
{ |
(*rgb2scr)(&fbaddress[POINTPOS(x, y)], COLOR(color)); |
if (dbbuffer) { |
int dline = (y + dboffset) % yres; |
(*rgb2scr)(&dbbuffer[POINTPOS(x, dline)], COLOR(color)); |
} |
} |
/** Get pixel from viewport */ |
static int getpixel(unsigned int x, unsigned int y) |
/** Draw character at given position |
* |
*/ |
static void glyph_draw(uint8_t glyph, unsigned int col, unsigned int row, bool silent) |
{ |
if (dbbuffer) { |
int dline = (y + dboffset) % yres; |
return COLOR((*scr2rgb)(&dbbuffer[POINTPOS(x, dline)])); |
unsigned int x = COL2X(col); |
unsigned int y = ROW2Y(row); |
unsigned int yd; |
if (y >= ytrim) |
logo_hide(silent); |
backbuf[BB_POS(col, row)] = glyph; |
if (!silent) { |
for (yd = 0; yd < FONT_SCANLINES; yd++) |
memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)], |
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline); |
} |
return COLOR((*scr2rgb)(&fbaddress[POINTPOS(x, y)])); |
} |
/** Fill screen with background color */ |
static void clear_screen(void) |
/** Scroll screen down by one row |
* |
* |
*/ |
static void screen_scroll(bool silent) |
{ |
unsigned int y; |
for (y = 0; y < yres; y++) { |
memcpy(&fbaddress[scanline * y], blankline, xres * pixelbytes); |
if (dbbuffer) |
memcpy(&dbbuffer[scanline * y], blankline, |
xres * pixelbytes); |
if (ylogo > 0) { |
logo_hide(silent); |
return; |
} |
} |
/** Scroll screen one row up */ |
static void scroll_screen(void) |
{ |
if (dbbuffer) { |
count_t first; |
if (!silent) { |
unsigned int row; |
/* Clear the last row */ |
memcpy(&dbbuffer[dboffset * scanline], blankline, ROW_BYTES); |
dboffset = (dboffset + FONT_SCANLINES) % yres; |
first = yres - dboffset; |
/* Move all rows one row up */ |
if (xres * pixelbytes == scanline) { |
memcpy(fbaddress, &dbbuffer[dboffset * scanline], |
first * scanline); |
memcpy(&fbaddress[first * scanline], dbbuffer, |
dboffset * scanline); |
} else { |
/* |
* When the scanline is bigger than number of bytes |
* in the X-resolution, chances are that the |
* frame buffer memory past the X-resolution is special |
* in some way. For example, the SUNW,ffb framebuffer |
* wraps this area around the beginning of the same |
* line. To avoid troubles, copy only memory as |
* specified by the resolution. |
*/ |
unsigned int i; |
for (i = 0; i < first; i++) |
memcpy(&fbaddress[i * scanline], |
&dbbuffer[(dboffset + i) * scanline], |
xres * pixelbytes); |
for (i = 0; i < dboffset; i++) |
memcpy(&fbaddress[(first + i) * scanline], |
&dbbuffer[i * scanline], xres * pixelbytes); |
for (row = 0; row < rows; row++) { |
unsigned int y = ROW2Y(row); |
unsigned int yd; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
unsigned int x; |
unsigned int col; |
for (col = 0, x = 0; col < cols; col++, |
x += FONT_WIDTH) { |
uint8_t glyph; |
if (row < rows - 1) { |
if (backbuf[BB_POS(col, row)] == |
backbuf[BB_POS(col, row + 1)]) |
continue; |
glyph = backbuf[BB_POS(col, row + 1)]; |
} else |
glyph = 0; |
memcpy(&fb_addr[FB_POS(x, y + yd)], |
&glyphs[GLYPH_POS(glyph, yd)], |
glyphscanline); |
} |
} |
} |
} else { |
uint8_t *lastline = &fbaddress[(rows - 1) * ROW_BYTES]; |
if (xres * pixelbytes == scanline) { |
/* Move all rows one row up */ |
memcpy((void *) fbaddress, |
(void *) &fbaddress[ROW_BYTES], |
scanline * yres - ROW_BYTES); |
/* Clear the last row */ |
memcpy((void *) lastline, (void *) blankline, |
ROW_BYTES); |
} else { |
/* |
* See the comment in the dbbuffer case. |
*/ |
unsigned int i; |
/* Move all rows one row up */ |
for (i = 0; i < yres - FONT_SCANLINES; i++) |
memcpy(&fbaddress[i * scanline], |
&fbaddress[(i + FONT_SCANLINES) * scanline], |
xres * pixelbytes); |
/* Clear the last row */ |
for (i = 0; i < FONT_SCANLINES; i++) |
memcpy(&lastline[i * scanline], |
&blankline[i * scanline], |
xres * pixelbytes); |
} |
} |
memmove(backbuf, backbuf + cols, cols * (rows - 1)); |
memsetb(&backbuf[BB_POS(0, rows - 1)], cols, 0); |
} |
static void invert_pixel(unsigned int x, unsigned int y) |
static void cursor_put(bool silent) |
{ |
putpixel(x, y, ~getpixel(x, y)); |
glyph_draw(CURSOR, position % cols, position / cols, silent); |
} |
/** Draw one line of glyph at a given position */ |
static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y) |
static void cursor_remove(bool silent) |
{ |
unsigned int i; |
for (i = 0; i < 8; i++) |
if (glline & (1 << (7 - i))) { |
putpixel(x + i, y, FGCOLOR); |
} else |
putpixel(x + i, y, BGCOLOR); |
glyph_draw(0, position % cols, position / cols, silent); |
} |
/***************************************************************/ |
/* Character-console functions */ |
/** Draw character at given position */ |
static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row) |
{ |
unsigned int y; |
for (y = 0; y < FONT_SCANLINES; y++) |
draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], |
col * COL_WIDTH, row * FONT_SCANLINES + y); |
} |
/** Invert character at given position */ |
static void invert_char(unsigned int col, unsigned int row) |
{ |
unsigned int x; |
unsigned int y; |
for (x = 0; x < COL_WIDTH; x++) |
for (y = 0; y < FONT_SCANLINES; y++) |
invert_pixel(col * COL_WIDTH + x, |
row * FONT_SCANLINES + y); |
} |
/** Draw character at default position */ |
static void draw_char(char chr) |
{ |
draw_glyph(chr, position % columns, position / columns); |
} |
static void draw_logo(unsigned int startx, unsigned int starty) |
{ |
unsigned int x; |
unsigned int y; |
unsigned int byte; |
unsigned int rowbytes; |
rowbytes = (helenos_width - 1) / 8 + 1; |
for (y = 0; y < helenos_height; y++) |
for (x = 0; x < helenos_width; x++) { |
byte = helenos_bits[rowbytes * y + x / 8]; |
byte >>= x % 8; |
if (byte & 1) |
putpixel(startx + x, starty + y, |
COLOR(LOGOCOLOR)); |
} |
} |
/***************************************************************/ |
/* Stdout specific functions */ |
static void invert_cursor(void) |
{ |
invert_char(position % columns, position / columns); |
} |
/** Print character to screen |
* |
* Emulate basic terminal commands |
* Emulate basic terminal commands. |
* |
*/ |
static void fb_putchar(chardev_t *dev, char ch) |
static void fb_putchar(chardev_t *dev, char ch, bool silent) |
{ |
spinlock_lock(&fb_lock); |
switch (ch) { |
case '\n': |
invert_cursor(); |
position += columns; |
position -= position % columns; |
cursor_remove(silent); |
position += cols; |
position -= position % cols; |
break; |
case '\r': |
invert_cursor(); |
position -= position % columns; |
cursor_remove(silent); |
position -= position % cols; |
break; |
case '\b': |
invert_cursor(); |
if (position % columns) |
cursor_remove(silent); |
if (position % cols) |
position--; |
break; |
case '\t': |
invert_cursor(); |
cursor_remove(silent); |
do { |
draw_char(' '); |
glyph_draw((uint8_t) ' ', position % cols, |
position / cols, silent); |
position++; |
} while ((position % 8) && position < columns * rows); |
} while ((position % 8) && (position < cols * rows)); |
break; |
default: |
draw_char(ch); |
glyph_draw((uint8_t) ch, position % cols, |
position / cols, silent); |
position++; |
} |
if (position >= columns * rows) { |
position -= columns; |
scroll_screen(); |
if (position >= cols * rows) { |
position -= cols; |
screen_scroll(silent); |
} |
invert_cursor(); |
cursor_put(silent); |
spinlock_unlock(&fb_lock); |
} |
434,6 → 332,97 |
}; |
/** Render glyphs |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
*/ |
static void glyphs_render(void) |
{ |
/* Prerender glyphs */ |
unsigned int glyph; |
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) { |
unsigned int y; |
for (y = 0; y < FONT_SCANLINES; y++) { |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) { |
void *dst = &glyphs[GLYPH_POS(glyph, y) + |
x * pixelbytes]; |
uint32_t rgb = (fb_font[ROW2Y(glyph) + y] & |
(1 << (7 - x))) ? FG_COLOR : BG_COLOR; |
rgb_conv(dst, rgb); |
} |
} |
} |
/* Prerender background scanline */ |
unsigned int x; |
for (x = 0; x < xres; x++) |
rgb_conv(&bgscan[x * pixelbytes], BG_COLOR); |
} |
/** Refresh the screen |
* |
*/ |
void fb_redraw(void) |
{ |
if (ylogo > 0) { |
unsigned int y; |
for (y = 0; y < LOGO_HEIGHT; y++) { |
unsigned int x; |
for (x = 0; x < xres; x++) |
rgb_conv(&fb_addr[FB_POS(x, y)], |
(x < LOGO_WIDTH) ? |
fb_logo[y * LOGO_WIDTH + x] : |
LOGO_COLOR); |
} |
} |
unsigned int row; |
for (row = 0; row < rowtrim; row++) { |
unsigned int y = ylogo + ROW2Y(row); |
unsigned int yd; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
unsigned int x; |
unsigned int col; |
for (col = 0, x = 0; col < cols; |
col++, x += FONT_WIDTH) { |
void *d = &fb_addr[FB_POS(x, y + yd)]; |
void *s = &glyphs[GLYPH_POS(backbuf[BB_POS(col, |
row)], yd)]; |
memcpy(d, s, glyphscanline); |
} |
} |
} |
if (COL2X(cols) < xres) { |
unsigned int y; |
unsigned int size = (xres - COL2X(cols)) * pixelbytes; |
for (y = ylogo; y < yres; y++) |
memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size); |
} |
if (ROW2Y(rowtrim) + ylogo < yres) { |
unsigned int y; |
for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++) |
memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes); |
} |
} |
/** Initialize framebuffer as a chardev output device |
* |
* @param addr Physical address of the framebuffer |
443,99 → 432,100 |
* @param visual Color model |
* |
*/ |
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan, |
unsigned int visual) |
void fb_init(fb_properties_t *props) |
{ |
switch (visual) { |
switch (props->visual) { |
case VISUAL_INDIRECT_8: |
rgb2scr = rgb_byte8; |
scr2rgb = byte8_rgb; |
rgb_conv = rgb_323; |
pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
rgb2scr = rgb_byte555; |
scr2rgb = byte555_rgb; |
rgb_conv = rgb_555; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
rgb2scr = rgb_byte565; |
scr2rgb = byte565_rgb; |
rgb_conv = rgb_565; |
pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
rgb2scr = rgb_byte888; |
scr2rgb = byte888_rgb; |
rgb_conv = rgb_888; |
pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
rgb_conv = bgr_888; |
pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
rgb2scr = rgb_byte888; |
scr2rgb = byte888_rgb; |
rgb_conv = rgb_888; |
pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
rgb2scr = rgb_byte0888; |
scr2rgb = byte0888_rgb; |
rgb_conv = rgb_0888; |
pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
rgb2scr = bgr_byte0888; |
scr2rgb = byte0888_bgr; |
rgb_conv = bgr_0888; |
pixelbytes = 4; |
break; |
default: |
panic("Unsupported visual.\n"); |
panic("Unsupported visual."); |
} |
unsigned int fbsize = scan * y; |
xres = props->x; |
yres = props->y; |
scanline = props->scan; |
/* Map the framebuffer */ |
fbaddress = (uint8_t *) hw_map((uintptr_t) addr, fbsize); |
cols = X2COL(xres); |
rows = Y2ROW(yres); |
xres = x; |
yres = y; |
scanline = scan; |
if (yres > ylogo) { |
ylogo = LOGO_HEIGHT; |
rowtrim = rows - Y2ROW(ylogo); |
if (ylogo % FONT_SCANLINES > 0) |
rowtrim--; |
ytrim = ROW2Y(rowtrim); |
} else { |
ylogo = 0; |
ytrim = yres; |
rowtrim = rows; |
} |
rows = y / FONT_SCANLINES; |
columns = x / COL_WIDTH; |
fb_parea.pbase = (uintptr_t) addr; |
fb_parea.vbase = (uintptr_t) fbaddress; |
fb_parea.frames = SIZE2FRAMES(fbsize); |
fb_parea.cacheable = false; |
ddi_parea_register(&fb_parea); |
glyphscanline = FONT_WIDTH * pixelbytes; |
glyphbytes = ROW2Y(glyphscanline); |
bgscanbytes = xres * pixelbytes; |
unsigned int fbsize = scanline * yres; |
unsigned int bbsize = cols * rows; |
unsigned int glyphsize = FONT_GLYPHS * glyphbytes; |
backbuf = (uint8_t *) malloc(bbsize, 0); |
if (!backbuf) |
panic("Unable to allocate backbuffer."); |
glyphs = (uint8_t *) malloc(glyphsize, 0); |
if (!glyphs) |
panic("Unable to allocate glyphs."); |
bgscan = malloc(bgscanbytes, 0); |
if (!bgscan) |
panic("Unable to allocate background pixel."); |
memsetb(backbuf, bbsize, 0); |
glyphs_render(); |
fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize); |
sysinfo_set_item_val("fb", NULL, true); |
sysinfo_set_item_val("fb.kind", NULL, 1); |
sysinfo_set_item_val("fb.width", NULL, xres); |
sysinfo_set_item_val("fb.height", NULL, yres); |
sysinfo_set_item_val("fb.scanline", NULL, scan); |
sysinfo_set_item_val("fb.visual", NULL, visual); |
sysinfo_set_item_val("fb.address.physical", NULL, addr); |
sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors); |
/* Allocate double buffer */ |
unsigned int order = fnzb(SIZE2FRAMES(fbsize) - 1) + 1; |
dbbuffer = (uint8_t *) frame_alloc(order, FRAME_ATOMIC | FRAME_KA); |
if (!dbbuffer) |
printf("Failed to allocate scroll buffer.\n"); |
dboffset = 0; |
/* Initialized blank line */ |
blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC); |
if (!blankline) |
panic("Failed to allocate blank line for framebuffer."); |
for (y = 0; y < FONT_SCANLINES; y++) |
for (x = 0; x < xres; x++) |
(*rgb2scr)(&blankline[POINTPOS(x, y)], COLOR(BGCOLOR)); |
sysinfo_set_item_val("fb.scanline", NULL, scanline); |
sysinfo_set_item_val("fb.visual", NULL, props->visual); |
sysinfo_set_item_val("fb.address.physical", NULL, props->addr); |
clear_screen(); |
/* Update size of screen to match text area */ |
yres = rows * FONT_SCANLINES; |
draw_logo(xres - helenos_width, 0); |
invert_cursor(); |
fb_redraw(); |
chardev_initialize("fb", &framebuffer, &fb_ops); |
stdout = &framebuffer; |
} |
/branches/dd/kernel/genarch/src/fb/font-8x16.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
34,7 → 34,7 |
#include <genarch/fb/font-8x16.h> |
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = { |
uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES] = { |
/* 0 0x00 '^@' */ |
0x00, /* 00000000 */ |
/branches/dd/kernel/genarch/src/mm/as_ht.c |
---|
72,7 → 72,7 |
{ |
if (flags & FLAG_AS_KERNEL) { |
hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations); |
mutex_initialize(&page_ht_lock); |
mutex_initialize(&page_ht_lock, MUTEX_PASSIVE); |
} |
return NULL; |
} |
/branches/dd/kernel/genarch/src/mm/page_pt.c |
---|
76,7 → 76,7 |
if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL1_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0); |
SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt)); |
SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
85,7 → 85,7 |
if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL2_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0); |
SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt)); |
SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
94,7 → 94,7 |
if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) { |
newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA); |
memsetb((uintptr_t)newpt, FRAME_SIZE << PTL3_SIZE, 0); |
memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0); |
SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt)); |
SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE); |
} |
146,7 → 146,7 |
ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page))); |
/* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ |
memsetb((uintptr_t) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); |
/* |
* Second, free all empty tables along the way from PTL3 down to PTL0. |
166,11 → 166,11 |
*/ |
frame_free(KA2PA((uintptr_t) ptl3)); |
if (PTL2_ENTRIES) |
memsetb((uintptr_t) &ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); |
else if (PTL1_ENTRIES) |
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} else { |
/* |
* PTL3 is not empty. |
195,9 → 195,9 |
*/ |
frame_free(KA2PA((uintptr_t) ptl2)); |
if (PTL1_ENTRIES) |
memsetb((uintptr_t) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
else { |
/* |
223,7 → 223,7 |
* Release the frame and remove PTL1 pointer from preceding table. |
*/ |
frame_free(KA2PA((uintptr_t) ptl1)); |
memsetb((uintptr_t) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
} |
/branches/dd/kernel/genarch/src/mm/asid.c |
---|
32,7 → 32,7 |
/** |
* @file |
* @brief ASID management. |
* @brief ASID management. |
* |
* Modern processor architectures optimize TLB utilization |
* by using ASIDs (a.k.a. memory contexts on sparc64 and |
/branches/dd/kernel/genarch/src/mm/as_pt.c |
---|
52,31 → 52,6 |
static void pt_lock(as_t *as, bool lock); |
static void pt_unlock(as_t *as, bool unlock); |
#ifdef __OBJC__ |
@implementation as_t |
+ (pte_t *) page_table_create: (int) flags |
{ |
return ptl0_create(flags); |
} |
+ (void) page_table_destroy: (pte_t *) page_table |
{ |
ptl0_destroy(page_table); |
} |
- (void) page_table_lock: (bool) _lock |
{ |
pt_lock(self, _lock); |
} |
- (void) page_table_unlock: (bool) unlock |
{ |
pt_unlock(self, unlock); |
} |
@end |
#else |
as_operations_t as_pt_operations = { |
.page_table_create = ptl0_create, |
.page_table_destroy = ptl0_destroy, |
83,7 → 58,6 |
.page_table_lock = pt_lock, |
.page_table_unlock = pt_unlock |
}; |
#endif |
/** Create PTL0. |
* |
103,7 → 77,7 |
table_size = FRAME_SIZE << PTL0_SIZE; |
if (flags & FLAG_AS_KERNEL) { |
memsetb((uintptr_t) dst_ptl0, table_size, 0); |
memsetb(dst_ptl0, table_size, 0); |
} else { |
uintptr_t src, dst; |
118,7 → 92,7 |
src = (uintptr_t) &src_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)]; |
dst = (uintptr_t) &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)]; |
memsetb((uintptr_t) dst_ptl0, table_size, 0); |
memsetb(dst_ptl0, table_size, 0); |
memcpy((void *) dst, (void *) src, table_size - (src - (uintptr_t) src_ptl0)); |
mutex_unlock(&AS_KERNEL->lock); |
interrupts_restore(ipl); |
/branches/dd/kernel/genarch/src/ofw/ebus.c |
---|
38,13 → 38,14 |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/memstr.h> |
#include <arch/trap/interrupt.h> |
#include <func.h> |
#include <string.h> |
#include <panic.h> |
#include <debug.h> |
#include <macros.h> |
/** Apply EBUS ranges to EBUS register. */ |
bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa) |
bool |
ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa) |
{ |
ofw_tree_property_t *prop; |
ofw_ebus_range_t *range; |
62,11 → 63,13 |
for (i = 0; i < ranges; i++) { |
if (reg->space != range[i].child_space) |
continue; |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
if (overlaps(reg->addr, reg->size, range[i].child_base, |
range[i].size)) { |
ofw_pci_reg_t pci_reg; |
pci_reg.space = range[i].parent_space; |
pci_reg.addr = range[i].parent_base + (reg->addr - range[i].child_base); |
pci_reg.addr = range[i].parent_base + |
(reg->addr - range[i].child_base); |
pci_reg.size = reg->size; |
return ofw_pci_apply_ranges(node->parent, &pci_reg, pa); |
76,7 → 79,9 |
return false; |
} |
bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr) |
bool |
ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, |
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg) |
{ |
ofw_tree_property_t *prop; |
ofw_tree_node_t *controller; |
104,8 → 109,8 |
unsigned int i; |
for (i = 0; i < count; i++) { |
if ((intr_map[i].space == space) && (intr_map[i].addr == addr) |
&& (intr_map[i].intr == intr)) |
if ((intr_map[i].space == space) && |
(intr_map[i].addr == addr) && (intr_map[i].intr == intr)) |
goto found; |
} |
return false; |
113,10 → 118,12 |
found: |
/* |
* We found the device that functions as an interrupt controller |
* for the interrupt. We also found partial mapping from interrupt to INO. |
* for the interrupt. We also found partial mapping from interrupt to |
* INO. |
*/ |
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle); |
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), |
intr_map[i].controller_handle); |
if (!controller) |
return false; |
130,7 → 137,8 |
/* |
* Let the PCI do the next step in mapping the interrupt. |
*/ |
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, inr)) |
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, |
inr, cir, cir_arg)) |
return false; |
return true; |
/branches/dd/kernel/genarch/src/ofw/fhc.c |
---|
38,7 → 38,7 |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/drivers/fhc.h> |
#include <arch/memstr.h> |
#include <func.h> |
#include <string.h> |
#include <panic.h> |
#include <macros.h> |
67,7 → 67,7 |
return true; |
} |
if (strcmp(ofw_tree_node_name(node->parent), "central") != 0) |
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent)); |
panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent)); |
ofw_central_reg_t central_reg; |
84,7 → 84,7 |
bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa) |
{ |
if (node->parent->parent) |
panic("Unexpected parent node: %s.\n", ofw_tree_node_name(node->parent)); |
panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent)); |
ofw_tree_property_t *prop; |
ofw_central_range_t *range; |
109,7 → 109,9 |
return false; |
} |
bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr) |
bool |
ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, |
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg) |
{ |
fhc_t *fhc = NULL; |
if (!node->device) { |
126,6 → 128,8 |
fhc_enable_interrupt(fhc, interrupt); |
*inr = interrupt; |
*cir = fhc_clear_interrupt; |
*cir_arg = fhc; |
return true; |
} |
/branches/dd/kernel/genarch/src/ofw/ofw_tree.c |
---|
38,7 → 38,7 |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/memstr.h> |
#include <mm/slab.h> |
#include <func.h> |
#include <string.h> |
#include <print.h> |
#include <panic.h> |
54,12 → 54,14 |
/** Get OpenFirmware node property. |
* |
* @param node Node in which to lookup the property. |
* @param name Name of the property. |
* @param node Node in which to lookup the property. |
* @param name Name of the property. |
* |
* @return Pointer to the property structure or NULL if no such property. |
* @return Pointer to the property structure or NULL if no such |
* property. |
*/ |
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name) |
ofw_tree_property_t * |
ofw_tree_getprop(const ofw_tree_node_t *node, const char *name) |
{ |
unsigned int i; |
73,9 → 75,9 |
/** Return value of the 'name' property. |
* |
* @param node Node of interest. |
* @param node Node of interest. |
* |
* @return Value of the 'name' property belonging to the node. |
* @return Value of the 'name' property belonging to the node. |
*/ |
const char *ofw_tree_node_name(const ofw_tree_node_t *node) |
{ |
83,10 → 85,10 |
prop = ofw_tree_getprop(node, "name"); |
if (!prop) |
panic("Node without name property.\n"); |
panic("Node without name property."); |
if (prop->size < 2) |
panic("Invalid name property.\n"); |
panic("Invalid name property."); |
return prop->value; |
} |
93,10 → 95,11 |
/** Lookup child of given name. |
* |
* @param node Node whose child is being looked up. |
* @param name Name of the child being looked up. |
* @param node Node whose child is being looked up. |
* @param name Name of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
* @return NULL if there is no such child or pointer to the |
* matching child node. |
*/ |
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name) |
{ |
127,12 → 130,14 |
/** Lookup first child of given device type. |
* |
* @param node Node whose child is being looked up. |
* @param name Device type of the child being looked up. |
* @param node Node whose child is being looked up. |
* @param name Device type of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
* @return NULL if there is no such child or pointer to the |
* matching child node. |
*/ |
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name) |
ofw_tree_node_t * |
ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
ofw_tree_property_t *prop; |
153,12 → 158,14 |
* Child nodes are looked up recursively contrary to peer nodes that |
* are looked up iteratively to avoid stack overflow. |
* |
* @param root Root of the searched subtree. |
* @param handle OpenFirmware handle. |
* @param root Root of the searched subtree. |
* @param handle OpenFirmware handle. |
* |
* @return NULL if there is no such node or pointer to the matching node. |
* @return NULL if there is no such node or pointer to the matching |
* node. |
*/ |
ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle) |
ofw_tree_node_t * |
ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle) |
{ |
ofw_tree_node_t *cur; |
180,12 → 187,14 |
/** Lookup first peer of given device type. |
* |
* @param node Node whose peer is being looked up. |
* @param name Device type of the child being looked up. |
* @param node Node whose peer is being looked up. |
* @param name Device type of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
* @return NULL if there is no such child or pointer to the |
* matching child node. |
*/ |
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name) |
ofw_tree_node_t * |
ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
ofw_tree_property_t *prop; |
202,15 → 211,41 |
} |
/** Lookup first peer of given name. |
* |
* @param node Node whose peer is being looked up. |
* @param name Name of the child being looked up. |
* |
* @return NULL if there is no such peer or pointer to the matching |
* peer node. |
*/ |
ofw_tree_node_t * |
ofw_tree_find_peer_by_name(ofw_tree_node_t *node, const char *name) |
{ |
ofw_tree_node_t *cur; |
ofw_tree_property_t *prop; |
for (cur = node->peer; cur; cur = cur->peer) { |
prop = ofw_tree_getprop(cur, "name"); |
if (!prop || !prop->value) |
continue; |
if (strcmp(prop->value, name) == 0) |
return cur; |
} |
return NULL; |
} |
/** Lookup OpenFirmware node by its path. |
* |
* @param path Path to the node. |
* @param path Path to the node. |
* |
* @return NULL if there is no such node or pointer to the leaf node. |
* @return NULL if there is no such node or pointer to the leaf |
* node. |
*/ |
ofw_tree_node_t *ofw_tree_lookup(const char *path) |
{ |
char buf[NAME_BUF_LEN+1]; |
char buf[NAME_BUF_LEN + 1]; |
ofw_tree_node_t *node = ofw_root; |
index_t i, j; |
236,8 → 271,8 |
* Child nodes are processed recursively and peer nodes are processed |
* iteratively in order to avoid stack overflow. |
* |
* @param node Root of the subtree. |
* @param path Current path, NULL for the very root of the entire tree. |
* @param node Root of the subtree. |
* @param path Current path, NULL for the very root of the entire tree. |
*/ |
static void ofw_tree_node_print(const ofw_tree_node_t *node, const char *path) |
{ |
/branches/dd/kernel/genarch/src/ofw/pci.c |
---|
39,7 → 39,7 |
#include <arch/drivers/pci.h> |
#include <arch/trap/interrupt.h> |
#include <arch/memstr.h> |
#include <func.h> |
#include <string.h> |
#include <panic.h> |
#include <macros.h> |
49,7 → 49,8 |
#define PCI_IGN 0x1f |
bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa) |
bool |
ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa) |
{ |
ofw_tree_property_t *prop; |
ofw_pci_range_t *range; |
68,10 → 69,13 |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK)) |
if ((reg->space & PCI_SPACE_MASK) != |
(range[i].space & PCI_SPACE_MASK)) |
continue; |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
*pa = range[i].parent_base + (reg->addr - range[i].child_base); |
if (overlaps(reg->addr, reg->size, range[i].child_base, |
range[i].size)) { |
*pa = range[i].parent_base + |
(reg->addr - range[i].child_base); |
return true; |
} |
} |
79,7 → 83,9 |
return false; |
} |
bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out) |
bool |
ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, |
ofw_pci_reg_t *out) |
{ |
if (reg->space & PCI_ABS_MASK) { |
/* already absolute */ |
95,7 → 101,7 |
prop = ofw_tree_getprop(node, "assigned-addresses"); |
if (!prop) |
panic("Can't find \"assigned-addresses\" property.\n"); |
panic("Cannot find 'assigned-addresses' property."); |
assigned_addresses = prop->size / sizeof(ofw_pci_reg_t); |
assigned_address = prop->value; |
103,7 → 109,8 |
unsigned int i; |
for (i = 0; i < assigned_addresses; i++) { |
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) { |
if ((assigned_address[i].space & PCI_REG_MASK) == |
(reg->space & PCI_REG_MASK)) { |
out->space = assigned_address[i].space; |
out->addr = reg->addr + assigned_address[i].addr; |
out->size = reg->size; |
119,7 → 126,9 |
* So far, we only know how to map interrupts of non-PCI devices connected |
* to a PCI bridge. |
*/ |
bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr) |
bool |
ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, |
int *inr, cir_t *cir, void **cir_arg) |
{ |
pci_t *pci = node->device; |
if (!pci) { |
132,6 → 141,8 |
pci_enable_interrupt(pci, ino); |
*inr = (PCI_IGN << IGN_SHIFT) | ino; |
*cir = pci_clear_interrupt; |
*cir_arg = pci; |
return true; |
} |
/branches/dd/kernel/genarch/src/acpi/madt.c |
---|
126,7 → 126,7 |
int madt_irq_to_pin(unsigned int irq) |
{ |
ASSERT(irq < sizeof(isa_irq_map)/sizeof(int)); |
ASSERT(irq < sizeof(isa_irq_map) / sizeof(int)); |
return isa_irq_map[irq]; |
} |
184,15 → 184,15 |
case MADT_IO_SAPIC: |
case MADT_L_SAPIC: |
case MADT_PLATFORM_INTR_SRC: |
printf("MADT: skipping %s entry (type=%zd)\n", entry[h->type], h->type); |
printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type); |
break; |
default: |
if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) { |
printf("MADT: skipping reserved entry (type=%zd)\n", h->type); |
printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type); |
} |
if (h->type >= MADT_RESERVED_OEM_BEGIN) { |
printf("MADT: skipping OEM entry (type=%zd)\n", h->type); |
printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type); |
} |
break; |
} |
233,8 → 233,8 |
void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index) |
{ |
ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int)); |
printf("MADT: ignoring %s entry: bus=%zd, source=%zd, global_int=%zd, flags=%#hx\n", |
ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int)); |
printf("MADT: ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8 ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n", |
entry[override->header.type], override->bus, override->source, |
override->global_int, override->flags); |
} |
/branches/dd/kernel/genarch/src/acpi/acpi.c |
---|
49,8 → 49,12 |
struct acpi_rsdt *acpi_rsdt = NULL; |
struct acpi_xsdt *acpi_xsdt = NULL; |
struct acpi_signature_map signature_map[] = { |
{ (uint8_t *)"APIC", (void *) &acpi_madt, "Multiple APIC Description Table" } |
struct acpi_signature_map signature_map[] = { |
{ |
(uint8_t *) "APIC", |
(void *) &acpi_madt, |
"Multiple APIC Description Table" |
} |
}; |
static int rsdp_check(uint8_t *rsdp) { |
105,7 → 109,7 |
if (!acpi_sdt_check((uint8_t *) h)) |
goto next; |
*signature_map[j].sdt_ptr = h; |
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
} |
} |
next: |
126,7 → 130,7 |
if (!acpi_sdt_check((uint8_t *) h)) |
goto next; |
*signature_map[j].sdt_ptr = h; |
printf("%#zp: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description); |
} |
} |
next: |
160,7 → 164,7 |
return; |
rsdp_found: |
printf("%#zp: ACPI Root System Description Pointer\n", acpi_rsdp); |
LOG("%p: ACPI Root System Description Pointer\n", acpi_rsdp); |
acpi_rsdt = (struct acpi_rsdt *) (unative_t) acpi_rsdp->rsdt_address; |
if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address); |
169,11 → 173,11 |
if (acpi_xsdt) map_sdt((struct acpi_sdt_header *) acpi_xsdt); |
if (acpi_rsdt && !acpi_sdt_check((uint8_t *) acpi_rsdt)) { |
printf("RSDT: %s\n", "bad checksum"); |
printf("RSDT: bad checksum\n"); |
return; |
} |
if (acpi_xsdt && !acpi_sdt_check((uint8_t *) acpi_xsdt)) { |
printf("XSDT: %s\n", "bad checksum"); |
printf("XSDT: bad checksum\n"); |
return; |
} |
/branches/dd/kernel/genarch/src/drivers/ns16550/ns16550.c |
---|
0,0 → 1,116 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief NS 16550 serial controller driver. |
*/ |
#include <genarch/drivers/ns16550/ns16550.h> |
#include <ddi/irq.h> |
#include <arch/asm.h> |
#include <console/chardev.h> |
#include <mm/slab.h> |
#define LSR_DATA_READY 0x01 |
/** Initialize ns16550. |
* |
* @param dev Addrress of the beginning of the device in I/O space. |
* @param devno Device number. |
* @param inr Interrupt number. |
* @param cir Clear interrupt function. |
* @param cir_arg First argument to cir. |
* @param devout Output character device. |
* |
* @return True on success, false on failure. |
*/ |
bool |
ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg, |
chardev_t *devout) |
{ |
ns16550_instance_t *instance; |
instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
instance->devno = devno; |
instance->ns16550 = dev; |
instance->devout = devout; |
irq_initialize(&instance->irq); |
instance->irq.devno = devno; |
instance->irq.inr = inr; |
instance->irq.claim = ns16550_claim; |
instance->irq.handler = ns16550_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
irq_register(&instance->irq); |
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
(void) pio_read_8(&dev->rbr); |
/* Enable interrupts */ |
pio_write_8(&dev->ier, IER_ERBFI); |
pio_write_8(&dev->mcr, MCR_OUT2); |
return true; |
} |
irq_ownership_t ns16550_claim(irq_t *irq) |
{ |
ns16550_instance_t *instance = irq->instance; |
ns16550_t *dev = instance->ns16550; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) |
return IRQ_ACCEPT; |
else |
return IRQ_DECLINE; |
} |
void ns16550_irq_handler(irq_t *irq) |
{ |
ns16550_instance_t *instance = irq->instance; |
ns16550_t *dev = instance->ns16550; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
uint8_t x; |
x = pio_read_8(&dev->rbr); |
if (instance->devout) |
chardev_push_character(instance->devout, x); |
} |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/drivers/i8042/i8042.c |
---|
0,0 → 1,109 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief i8042 processor driver |
* |
* It takes care of the i8042 serial communication. |
*/ |
#include <genarch/drivers/i8042/i8042.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <arch/asm.h> |
#include <console/chardev.h> |
#include <mm/slab.h> |
#define i8042_SET_COMMAND 0x60 |
#define i8042_COMMAND 0x69 |
#define i8042_BUFFER_FULL_MASK 0x01 |
#define i8042_WAIT_MASK 0x02 |
static irq_ownership_t i8042_claim(irq_t *irq) |
{ |
i8042_instance_t *i8042_instance = irq->instance; |
i8042_t *dev = i8042_instance->i8042; |
if (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
return IRQ_ACCEPT; |
else |
return IRQ_DECLINE; |
} |
static void i8042_irq_handler(irq_t *irq) |
{ |
i8042_instance_t *instance = irq->instance; |
i8042_t *dev = instance->i8042; |
uint8_t data; |
uint8_t status; |
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) { |
data = pio_read_8(&dev->data); |
if (instance->devout) |
chardev_push_character(instance->devout, data); |
} |
} |
/** Initialize i8042. */ |
bool |
i8042_init(i8042_t *dev, devno_t devno, inr_t inr, chardev_t *devout) |
{ |
i8042_instance_t *instance; |
instance = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
instance->devno = devno; |
instance->i8042 = dev; |
instance->devout = devout; |
irq_initialize(&instance->irq); |
instance->irq.devno = devno; |
instance->irq.inr = inr; |
instance->irq.claim = i8042_claim; |
instance->irq.handler = i8042_irq_handler; |
instance->irq.instance = instance; |
irq_register(&instance->irq); |
/* |
* Clear input buffer. |
*/ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
return true; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/drivers/z8530/z8530.c |
---|
0,0 → 1,133 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Zilog 8530 serial controller driver. |
*/ |
#include <genarch/drivers/z8530/z8530.h> |
#include <console/chardev.h> |
#include <ddi/irq.h> |
#include <arch/asm.h> |
#include <mm/slab.h> |
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val) |
{ |
/* |
* Registers 8-15 will automatically issue the Point High |
* command as their bit 3 is 1. |
*/ |
pio_write_8(ctl, reg); /* select register */ |
pio_write_8(ctl, val); /* write value */ |
} |
static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg) |
{ |
/* |
* Registers 8-15 will automatically issue the Point High |
* command as their bit 3 is 1. |
*/ |
pio_write_8(ctl, reg); /* select register */ |
return pio_read_8(ctl); |
} |
/** Initialize z8530. */ |
bool |
z8530_init(z8530_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg, |
chardev_t *devout) |
{ |
z8530_instance_t *instance; |
instance = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
instance->devno = devno; |
instance->z8530 = dev; |
instance->devout = devout; |
irq_initialize(&instance->irq); |
instance->irq.devno = devno; |
instance->irq.inr = inr; |
instance->irq.claim = z8530_claim; |
instance->irq.handler = z8530_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
irq_register(&instance->irq); |
(void) z8530_read(&dev->ctl_a, RR8); |
/* |
* Clear any pending TX interrupts or we never manage |
* to set FHC UART interrupt state to idle. |
*/ |
z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST); |
/* interrupt on all characters */ |
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC); |
/* 8 bits per character and enable receiver */ |
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
/* Master Interrupt Enable. */ |
z8530_write(&dev->ctl_a, WR9, WR9_MIE); |
return true; |
} |
irq_ownership_t z8530_claim(irq_t *irq) |
{ |
z8530_instance_t *instance = irq->instance; |
z8530_t *dev = instance->z8530; |
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) |
return IRQ_ACCEPT; |
else |
return IRQ_DECLINE; |
} |
void z8530_irq_handler(irq_t *irq) |
{ |
z8530_instance_t *instance = irq->instance; |
z8530_t *dev = instance->z8530; |
uint8_t x; |
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) { |
x = z8530_read(&dev->ctl_a, RR8); |
if (instance->devout) |
chardev_push_character(instance->devout, x); |
} |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/drivers/ega/ega.c |
---|
0,0 → 1,201 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch_drivers |
* @{ |
*/ |
/** |
* @file |
* @brief EGA driver. |
*/ |
#include <genarch/drivers/ega/ega.h> |
#include <putchar.h> |
#include <mm/page.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <arch/mm/page.h> |
#include <synch/spinlock.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <memstr.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/ddi.h> |
/* |
* The EGA driver. |
* Simple and short. Function for displaying characters and "scrolling". |
*/ |
SPINLOCK_INITIALIZE(egalock); |
static uint32_t ega_cursor; |
static uint8_t *videoram; |
static uint8_t *backbuf; |
static ioport8_t *ega_base; |
#define EMPTY_CHAR 0x0720 |
chardev_t ega_console; |
/* |
* This function takes care of scrolling. |
*/ |
static void ega_check_cursor(void) |
{ |
if (ega_cursor < EGA_SCREEN) |
return; |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
ega_cursor = ega_cursor - EGA_COLS; |
} |
static void ega_show_cursor(void) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5))); |
} |
static void ega_move_cursor(void) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
} |
static void ega_sync_cursor(void) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG); |
ega_cursor = (hi << 8) | lo; |
if (ega_cursor >= EGA_SCREEN) |
ega_cursor = 0; |
if ((ega_cursor % EGA_COLS) != 0) |
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS; |
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
ega_check_cursor(); |
ega_move_cursor(); |
ega_show_cursor(); |
} |
static void ega_display_char(char ch, bool silent) |
{ |
backbuf[ega_cursor * 2] = ch; |
if (!silent) |
videoram[ega_cursor * 2] = ch; |
} |
static void ega_putchar(chardev_t *dev __attribute__((unused)), const char ch, bool silent) |
{ |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&egalock); |
switch (ch) { |
case '\n': |
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS; |
break; |
case '\t': |
ega_cursor = (ega_cursor + 8) - ega_cursor % 8; |
break; |
case '\b': |
if (ega_cursor % EGA_COLS) |
ega_cursor--; |
break; |
default: |
ega_display_char(ch, silent); |
ega_cursor++; |
break; |
} |
ega_check_cursor(); |
if (!silent) |
ega_move_cursor(); |
spinlock_unlock(&egalock); |
interrupts_restore(ipl); |
} |
static chardev_operations_t ega_ops = { |
.write = ega_putchar |
}; |
void ega_init(ioport8_t *base, uintptr_t videoram_phys) |
{ |
/* Initialize the software structure. */ |
ega_base = base; |
backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0); |
if (!backbuf) |
panic("Unable to allocate backbuffer."); |
videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE); |
/* Synchronize the back buffer and cursor position. */ |
memcpy(backbuf, videoram, EGA_VRAM_SIZE); |
ega_sync_cursor(); |
chardev_initialize("ega_out", &ega_console, &ega_ops); |
stdout = &ega_console; |
sysinfo_set_item_val("fb", NULL, true); |
sysinfo_set_item_val("fb.kind", NULL, 2); |
sysinfo_set_item_val("fb.width", NULL, EGA_COLS); |
sysinfo_set_item_val("fb.height", NULL, EGA_ROWS); |
sysinfo_set_item_val("fb.blinking", NULL, true); |
sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys); |
} |
void ega_redraw(void) |
{ |
memcpy(videoram, backbuf, EGA_VRAM_SIZE); |
ega_move_cursor(); |
ega_show_cursor(); |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/multiboot/multiboot.c |
---|
0,0 → 1,148 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#include <genarch/multiboot/multiboot.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <config.h> |
#include <string.h> |
#include <macros.h> |
/** Extract command name from the multiboot module command line. |
* |
* @param buf Destination buffer (will always null-terminate). |
* @param n Size of destination buffer. |
* @param cmd_line Input string (the command line). |
* |
*/ |
static void extract_command(char *buf, size_t n, const char *cmd_line) |
{ |
const char *start, *end, *cp; |
size_t max_len; |
/* Find the first space. */ |
end = strchr(cmd_line, ' '); |
if (end == NULL) |
end = cmd_line + strlen(cmd_line); |
/* |
* Find last occurence of '/' before 'end'. If found, place start at |
* next character. Otherwise, place start at beginning of buffer. |
*/ |
cp = end; |
start = buf; |
while (cp != start) { |
if (*cp == '/') { |
start = cp + 1; |
break; |
} |
--cp; |
} |
/* Copy the command and null-terminate the string. */ |
max_len = min(n - 1, (size_t) (end - start)); |
strncpy(buf, start, max_len + 1); |
buf[max_len] = '\0'; |
} |
/** Parse multiboot information structure. |
* |
* If @a signature does not contain a valid multiboot signature, |
* assumes no multiboot information is available. |
* |
* @param signature Should contain the multiboot signature. |
* @param mi Pointer to the multiboot information structure. |
*/ |
void multiboot_info_parse(uint32_t signature, const multiboot_info_t *mi) |
{ |
uint32_t flags; |
multiboot_mod_t *mods; |
uint32_t i; |
if (signature == MULTIBOOT_LOADER_MAGIC) |
flags = mi->flags; |
else { |
/* No multiboot info available. */ |
flags = 0; |
} |
/* Copy module information. */ |
if ((flags & MBINFO_FLAGS_MODS) != 0) { |
init.cnt = mi->mods_count; |
mods = (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr); |
for (i = 0; i < init.cnt; i++) { |
init.tasks[i].addr = PA2KA(mods[i].start); |
init.tasks[i].size = mods[i].end - mods[i].start; |
/* Copy command line, if available. */ |
if (mods[i].string) { |
extract_command(init.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN, |
MULTIBOOT_PTR(mods[i].string)); |
} else |
init.tasks[i].name[0] = '\0'; |
} |
} else |
init.cnt = 0; |
/* Copy memory map. */ |
int32_t mmap_length; |
multiboot_mmap_t *mme; |
uint32_t size; |
if ((flags & MBINFO_FLAGS_MMAP) != 0) { |
mmap_length = mi->mmap_length; |
mme = MULTIBOOT_PTR(mi->mmap_addr); |
e820counter = 0; |
i = 0; |
while (mmap_length > 0) { |
e820table[i++] = mme->mm_info; |
/* Compute address of next structure. */ |
size = sizeof(mme->size) + mme->size; |
mme = ((void *) mme) + size; |
mmap_length -= size; |
} |
e820counter = i; |
} else |
e820counter = 0; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/srln/srln.c |
---|
0,0 → 1,89 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Serial line processing. |
*/ |
#include <genarch/srln/srln.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <proc/thread.h> |
#include <arch.h> |
chardev_t srlnin; |
static chardev_t *srlnout; |
static void srlnin_suspend(chardev_t *d) |
{ |
} |
static void srlnin_resume(chardev_t *d) |
{ |
} |
chardev_operations_t srlnin_ops = { |
.suspend = srlnin_suspend, |
.resume = srlnin_resume, |
}; |
static void ksrln(void *arg) |
{ |
chardev_t *in = (chardev_t *) arg; |
uint8_t ch; |
while (1) { |
ch = _getc(in); |
if (ch == '\r') |
continue; |
chardev_push_character(srlnout, ch); |
} |
} |
void srln_init(chardev_t *devout) |
{ |
thread_t *t; |
chardev_initialize("srln", &srlnin, &srlnin_ops); |
srlnout = devout; |
t = thread_create(ksrln, &srlnin, TASK, 0, "ksrln", false); |
ASSERT(t); |
thread_ready(t); |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/include/align.h |
---|
26,13 → 26,13 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @ingroup others |
* @{ |
*/ |
/** |
* @file |
* @brief Macros for making values and addresses aligned. |
* @brief Macros for making values and addresses aligned. |
*/ |
#ifndef KERN_ALIGN_H_ |
43,7 → 43,7 |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1)) |
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1)) |
/** Align to the nearest higher address. |
51,7 → 51,7 |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) |
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) |
#endif |
/branches/dd/kernel/generic/include/func.h |
---|
41,11 → 41,6 |
extern atomic_t haltstate; |
extern void halt(void); |
extern size_t strlen(const char *str); |
extern int strcmp(const char *src, const char *dst); |
extern int strncmp(const char *src, const char *dst, size_t len); |
extern void strncpy(char *dest, const char *src, size_t len); |
extern unative_t atoi(const char *text); |
extern void order(const uint64_t val, uint64_t *rv, char *suffix); |
/branches/dd/kernel/generic/include/fpu_context.h |
---|
37,10 → 37,6 |
#include <arch/fpu_context.h> |
#if defined(CONFIG_FPU_LAZY) && !defined(ARCH_HAS_FPU) |
# error "CONFIG_FPU_LAZY defined, but no ARCH_HAS_FPU" |
#endif |
extern void fpu_context_save(fpu_context_t *); |
extern void fpu_context_restore(fpu_context_t *); |
extern void fpu_init(void); |
/branches/dd/kernel/generic/include/stackarg.h |
---|
52,9 → 52,9 |
(ap).last = (uint8_t *) &(lst) |
#define va_arg(ap, type) \ |
(*((type *)((ap).last + ((ap).pos += sizeof(type) ) - sizeof(type)))) |
(*((type *)((ap).last + ((ap).pos += sizeof(type)) - sizeof(type)))) |
#define va_copy(dst,src) dst=src |
#define va_copy(dst, src) dst = src |
#define va_end(ap) |
/branches/dd/kernel/generic/include/byteorder.h |
---|
51,6 → 51,14 |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
61,6 → 69,14 |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
/branches/dd/kernel/generic/include/config.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
38,15 → 38,16 |
#include <arch/types.h> |
#include <arch/mm/page.h> |
#define STACK_SIZE PAGE_SIZE |
#define STACK_SIZE PAGE_SIZE |
#define CONFIG_MEMORY_SIZE (8 * 1024 * 1024) |
#define CONFIG_INIT_TASKS 32 |
#define CONFIG_INIT_TASKS 32 |
#define CONFIG_TASK_NAME_BUFLEN 32 |
typedef struct { |
uintptr_t addr; |
size_t size; |
char name[CONFIG_TASK_NAME_BUFLEN]; |
} init_task_t; |
typedef struct { |
65,14 → 66,14 |
} ballocs_t; |
typedef struct { |
count_t cpu_count; /**< Number of processors detected. */ |
volatile count_t cpu_active; /**< Number of processors that are up and running. */ |
count_t cpu_count; /**< Number of processors detected. */ |
volatile count_t cpu_active; /**< Number of processors that are up and running. */ |
uintptr_t base; |
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */ |
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */ |
uintptr_t stack_base; /**< Base adddress of initial stack */ |
size_t stack_size; /**< Size of initial stack */ |
uintptr_t stack_base; /**< Base adddress of initial stack */ |
size_t stack_size; /**< Size of initial stack */ |
} config_t; |
extern config_t config; |
/branches/dd/kernel/generic/include/string.h |
---|
0,0 → 1,50 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_STRING_H_ |
#define KERN_STRING_H_ |
#include <arch/types.h> |
extern size_t strlen(const char *str); |
extern int strcmp(const char *src, const char *dst); |
extern int strncmp(const char *src, const char *dst, size_t len); |
extern void strncpy(char *dest, const char *src, size_t len); |
extern char *strchr(const char *s, int i); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/proc/task.h |
---|
52,7 → 52,11 |
#include <arch/cpu.h> |
#include <mm/tlb.h> |
#include <proc/scheduler.h> |
#include <udebug/udebug.h> |
#include <ipc/kbox.h> |
#define TASK_NAME_BUFLEN 20 |
struct thread; |
/** Task structure. */ |
66,8 → 70,8 |
* threads. |
*/ |
SPINLOCK_DECLARE(lock); |
char *name; |
char name[TASK_NAME_BUFLEN]; |
/** List of threads contained in this task. */ |
link_t th_head; |
/** Address space. */ |
93,7 → 97,15 |
* certain extent. |
*/ |
atomic_t active_calls; |
#ifdef CONFIG_UDEBUG |
/** Debugging stuff. */ |
udebug_task_t udebug; |
/** Kernel answerbox. */ |
kbox_t kb; |
#endif |
/** Architecture specific task data. */ |
task_arch_t arch; |
116,7 → 128,6 |
extern void task_done(void); |
extern task_t *task_create(as_t *as, char *name); |
extern void task_destroy(task_t *t); |
extern task_t *task_run_program(void *program_addr, char *name); |
extern task_t *task_find_by_id(task_id_t id); |
extern int task_kill(task_id_t id); |
extern uint64_t task_get_accounting(task_t *t); |
133,6 → 144,7 |
#endif |
extern unative_t sys_task_get_id(task_id_t *uspace_task_id); |
extern unative_t sys_task_set_name(const char *uspace_name, size_t name_len); |
#endif |
/branches/dd/kernel/generic/include/proc/thread.h |
---|
46,6 → 46,7 |
#include <arch/cpu.h> |
#include <mm/tlb.h> |
#include <proc/uarg.h> |
#include <udebug/udebug.h> |
#define THREAD_STACK_SIZE STACK_SIZE |
#define THREAD_NAME_BUFLEN 20 |
203,6 → 204,12 |
/** Thread's kernel stack. */ |
uint8_t *kstack; |
#ifdef CONFIG_UDEBUG |
/** Debugging stuff */ |
udebug_thread_t udebug; |
#endif |
} thread_t; |
/** Thread list lock. |
252,7 → 259,8 |
extern slab_cache_t *fpu_context_slab; |
/* Thread syscall prototypes. */ |
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, thread_id_t *uspace_thread_id); |
extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg, |
char *uspace_name, size_t name_len, thread_id_t *uspace_thread_id); |
extern unative_t sys_thread_exit(int uspace_status); |
extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id); |
/branches/dd/kernel/generic/include/proc/program.h |
---|
0,0 → 1,67 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericproc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_PROGRAM_H_ |
#define KERN_PROGRAM_H_ |
#include <arch/types.h> |
struct task; |
struct thread; |
/** Program info structure. |
* |
* A program is an abstraction of a freshly created (not yet running) |
* userspace task containing a main thread along with its userspace stack. |
*/ |
typedef struct program { |
struct task *task; /**< Program task */ |
struct thread *main_thread; /**< Program main thread */ |
} program_t; |
extern void *program_loader; |
extern void program_create(as_t *as, uintptr_t entry_addr, char *name, |
program_t *p); |
extern int program_create_from_image(void *image_addr, char *name, |
program_t *p); |
extern int program_create_loader(program_t *p, char *name); |
extern void program_ready(program_t *p); |
extern unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/lib/objc_ext.h |
---|
File deleted |
/branches/dd/kernel/generic/include/lib/objc.h |
---|
File deleted |
/branches/dd/kernel/generic/include/lib/rd.h |
---|
66,16 → 66,18 |
#define RE_UNSUPPORTED 2 /* Non-supported image (e.g. wrong version) */ |
/** RAM disk header */ |
typedef struct { |
struct rd_header { |
uint8_t magic[RD_MAGIC_SIZE]; |
uint8_t version; |
uint8_t data_type; |
uint32_t header_size; |
uint64_t data_size; |
} rd_header; |
} __attribute__ ((packed)); |
extern int init_rd(rd_header * addr, size_t size); |
typedef struct rd_header rd_header_t; |
extern int init_rd(rd_header_t *addr, size_t size); |
#endif |
/** @} |
/branches/dd/kernel/generic/include/lib/elf.h |
---|
114,7 → 114,8 |
#define EE_MEMORY 2 /* Cannot allocate address space */ |
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ |
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ |
#define EE_IRRECOVERABLE 5 |
#define EE_LOADER 5 /* The image is actually a program loader */ |
#define EE_IRRECOVERABLE 6 |
/** |
* ELF section types |
338,6 → 339,10 |
extern char *elf_error(unsigned int rc); |
/* Interpreter string used to recognize the program loader */ |
#define ELF_INTERP_ZSTR "kernel" |
#define ELF_INTERP_ZLEN sizeof(ELF_INTERP_ZSTR) |
#endif |
/** @} |
/branches/dd/kernel/generic/include/udebug/udebug.h |
---|
0,0 → 1,210 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_H_ |
#define KERN_UDEBUG_H_ |
#include <ipc/ipc.h> |
typedef enum { /* udebug_method_t */ |
/** Start debugging the recipient. |
* Causes all threads in the receiving task to stop. When they |
* are all stoped, an answer with retval 0 is generated. |
*/ |
UDEBUG_M_BEGIN = 1, |
/** Finish debugging the recipient. |
* Answers all pending GO and GUARD messages. |
*/ |
UDEBUG_M_END, |
/** Set which events should be captured. |
*/ |
UDEBUG_M_SET_EVMASK, |
/** Make sure the debugged task is still there. |
* This message is answered when the debugged task dies |
* or the debugging session ends. |
*/ |
UDEBUG_M_GUARD, |
/** Run a thread until a debugging event occurs. |
* This message is answered when the thread stops |
* in a debugging event. |
* |
* - ARG2 - id of the thread to run |
*/ |
UDEBUG_M_GO, |
/** Stop a thread being debugged. |
* Creates a special STOP event in the thread, causing |
* it to answer a pending GO message (if any). |
*/ |
UDEBUG_M_STOP, |
/** Read arguments of a syscall. |
* |
* - ARG2 - thread identification |
* - ARG3 - destination address in the caller's address space |
* |
*/ |
UDEBUG_M_ARGS_READ, |
/** Read the list of the debugged tasks's threads. |
* |
* - ARG2 - destination address in the caller's address space |
* - ARG3 - size of receiving buffer in bytes |
* |
* The kernel fills the buffer with a series of sysarg_t values |
* (thread ids). On answer, the kernel will set: |
* |
* - ARG2 - number of bytes that were actually copied |
* - ARG3 - number of bytes of the complete data |
* |
*/ |
UDEBUG_M_THREAD_READ, |
/** Read the debugged tasks's memory. |
* |
* - ARG2 - destination address in the caller's address space |
* - ARG3 - source address in the recipient's address space |
* - ARG4 - size of receiving buffer in bytes |
* |
*/ |
UDEBUG_M_MEM_READ, |
} udebug_method_t; |
typedef enum { |
UDEBUG_EVENT_FINISHED = 1, /**< Debuging session has finished */ |
UDEBUG_EVENT_STOP, /**< Stopped on DEBUG_STOP request */ |
UDEBUG_EVENT_SYSCALL_B, /**< Before beginning syscall execution */ |
UDEBUG_EVENT_SYSCALL_E, /**< After finishing syscall execution */ |
UDEBUG_EVENT_THREAD_B, /**< The task created a new thread */ |
UDEBUG_EVENT_THREAD_E /**< A thread exited */ |
} udebug_event_t; |
#define UDEBUG_EVMASK(event) (1 << ((event) - 1)) |
typedef enum { |
UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED), |
UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP), |
UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B), |
UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E), |
UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B), |
UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E), |
UDEBUG_EM_ALL = |
UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) | |
UDEBUG_EVMASK(UDEBUG_EVENT_STOP) | |
UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) | |
UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) | |
UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) | |
UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E) |
} udebug_evmask_t; |
#ifdef KERNEL |
#include <synch/mutex.h> |
#include <arch/interrupt.h> |
#include <atomic.h> |
typedef enum { |
/** Task is not being debugged */ |
UDEBUG_TS_INACTIVE, |
/** BEGIN operation in progress (waiting for threads to stop) */ |
UDEBUG_TS_BEGINNING, |
/** Debugger fully connected */ |
UDEBUG_TS_ACTIVE |
} udebug_task_state_t; |
/** Debugging part of task_t structure. |
*/ |
typedef struct { |
/** Synchronize debug ops on this task / access to this structure */ |
mutex_t lock; |
char *lock_owner; |
udebug_task_state_t dt_state; |
call_t *begin_call; |
int not_stoppable_count; |
struct task *debugger; |
udebug_evmask_t evmask; |
} udebug_task_t; |
/** Debugging part of thread_t structure. |
*/ |
typedef struct { |
/** Synchronize debug ops on this thread / access to this structure. */ |
mutex_t lock; |
waitq_t go_wq; |
call_t *go_call; |
unative_t syscall_args[6]; |
istate_t *uspace_state; |
/** What type of event are we stopped in or 0 if none. */ |
udebug_event_t cur_event; |
bool go; /**< thread is GO */ |
bool stoppable; /**< thread is stoppable */ |
bool active; /**< thread is in a debugging session */ |
} udebug_thread_t; |
struct task; |
struct thread; |
void udebug_task_init(udebug_task_t *ut); |
void udebug_thread_initialize(udebug_thread_t *ut); |
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc, |
bool end_variant); |
void udebug_thread_b_event_attach(struct thread *t, struct task *ta); |
void udebug_thread_e_event(void); |
void udebug_stoppable_begin(void); |
void udebug_stoppable_end(void); |
void udebug_before_thread_runs(void); |
int udebug_task_cleanup(struct task *ta); |
#endif |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/udebug/udebug_ops.h |
---|
0,0 → 1,55 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_OPS_H_ |
#define KERN_UDEBUG_OPS_H_ |
#include <ipc/ipc.h> |
int udebug_begin(call_t *call); |
int udebug_end(void); |
int udebug_set_evmask(udebug_evmask_t mask); |
int udebug_go(thread_t *t, call_t *call); |
int udebug_stop(thread_t *t, call_t *call); |
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n); |
int udebug_args_read(thread_t *t, void **buffer); |
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/udebug/udebug_ipc.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_IPC_H_ |
#define KERN_UDEBUG_IPC_H_ |
#include <ipc/ipc.h> |
int udebug_request_preprocess(call_t *call, phone_t *phone); |
void udebug_call_receive(call_t *call); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/debug.h |
---|
38,11 → 38,11 |
#include <panic.h> |
#include <arch/debug.h> |
#define CALLER ((uintptr_t)__builtin_return_address(0)) |
#define CALLER ((uintptr_t) __builtin_return_address(0)) |
#ifndef HERE |
/** Current Instruction Pointer address */ |
# define HERE ((uintptr_t *) 0) |
# define HERE ((uintptr_t *) 0) |
#endif |
/** Debugging ASSERT macro |
55,12 → 55,51 |
* |
*/ |
#ifdef CONFIG_DEBUG |
# define ASSERT(expr) if (!(expr)) { panic("assertion failed (%s), caller=%.*p\n", #expr, sizeof(uintptr_t) * 2, CALLER); } |
# define ASSERT(expr) \ |
if (!(expr)) { \ |
panic("Assertion failed (%s), caller=%p.", #expr, CALLER); \ |
} |
#else |
# define ASSERT(expr) |
#endif |
/** Extensive logging output macro |
* |
* If CONFIG_LOG is set, the LOG() macro |
* will print whatever message is indicated plus |
* an information about the location. |
* |
*/ |
#ifdef CONFIG_LOG |
# define LOG(format, ...) \ |
printf("%s() at %s:%u: " format "\n", __func__, __FILE__, \ |
__LINE__, ##__VA_ARGS__); |
#else |
# define LOG(format, ...) |
#endif |
/** Extensive logging execute macro |
* |
* If CONFIG_LOG is set, the LOG_EXEC() macro |
* will print an information about calling a given |
* function and call it. |
* |
*/ |
#ifdef CONFIG_LOG |
# define LOG_EXEC(fnc) \ |
{ \ |
printf("%s() at %s:%u: " #fnc "\n", __func__, __FILE__, \ |
__LINE__); \ |
fnc; \ |
} |
#else |
# define LOG_EXEC(fnc) fnc |
#endif |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/panic.h |
---|
36,15 → 36,15 |
#define KERN_PANIC_H_ |
#ifdef CONFIG_DEBUG |
#define panic(format, ...) \ |
panic_printf("Kernel panic in %s() at %s on line %d: " format, __func__, \ |
__FILE__, __LINE__, ##__VA_ARGS__); |
# define panic(format, ...) \ |
panic_printf("Kernel panic in %s() at %s:%u: " format "\n", \ |
__func__, __FILE__, __LINE__, ##__VA_ARGS__); |
#else |
#define panic(format, ...) \ |
panic_printf("Kernel panic: " format, ##__VA_ARGS__); |
# define panic(format, ...) \ |
panic_printf("Kernel panic: " format "\n", ##__VA_ARGS__); |
#endif |
extern void panic_printf(char *fmt, ...) __attribute__((noreturn)) ; |
extern void panic_printf(char *fmt, ...) __attribute__((noreturn)); |
#endif |
/branches/dd/kernel/generic/include/interrupt.h |
---|
40,17 → 40,16 |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <console/klog.h> |
#include <ddi/irq.h> |
typedef void (* iroutine)(int n, istate_t *istate); |
#define fault_if_from_uspace(istate, cmd, ...) \ |
#define fault_if_from_uspace(istate, fmt, ...) \ |
{ \ |
if (istate_from_uspace(istate)) { \ |
task_t *task = TASK; \ |
klog_printf("Task %llu killed due to an exception at %p.", task->taskid, istate_get_pc(istate)); \ |
klog_printf(" " cmd, ##__VA_ARGS__); \ |
printf("Task %s (%" PRIu64 ") killed due to an exception at %p: ", task->name, task->taskid, istate_get_pc(istate)); \ |
printf(fmt "\n", ##__VA_ARGS__); \ |
task_kill(task->taskid); \ |
thread_exit(); \ |
} \ |
/branches/dd/kernel/generic/include/main/main.h |
---|
35,8 → 35,13 |
#ifndef KERN_MAIN_H_ |
#define KERN_MAIN_H_ |
#include <arch/types.h> |
extern uintptr_t stack_safe; |
extern void main_bsp(void); |
extern void main_ap(void); |
#endif |
/** @} |
/branches/dd/kernel/generic/include/synch/mutex.h |
---|
39,20 → 39,26 |
#include <synch/semaphore.h> |
#include <synch/synch.h> |
typedef enum { |
MUTEX_PASSIVE, |
MUTEX_ACTIVE |
} mutex_type_t; |
typedef struct { |
mutex_type_t type; |
semaphore_t sem; |
} mutex_t; |
#define mutex_lock(mtx) \ |
#define mutex_lock(mtx) \ |
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE) |
#define mutex_trylock(mtx) \ |
#define mutex_trylock(mtx) \ |
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING) |
#define mutex_lock_timeout(mtx, usec) \ |
#define mutex_lock_timeout(mtx, usec) \ |
_mutex_lock_timeout((mtx), (usec), SYNCH_FLAGS_NON_BLOCKING) |
extern void mutex_initialize(mutex_t *mtx); |
extern int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags); |
extern void mutex_unlock(mutex_t *mtx); |
extern void mutex_initialize(mutex_t *, mutex_type_t); |
extern int _mutex_lock_timeout(mutex_t *, uint32_t, int); |
extern void mutex_unlock(mutex_t *); |
#endif |
/branches/dd/kernel/generic/include/synch/spinlock.h |
---|
36,6 → 36,7 |
#define KERN_SPINLOCK_H_ |
#include <arch/types.h> |
#include <arch/barrier.h> |
#include <preemption.h> |
#include <atomic.h> |
#include <debug.h> |
110,8 → 111,8 |
#define DEADLOCK_PROBE(pname, value) \ |
if ((pname)++ > (value)) { \ |
(pname) = 0; \ |
printf("Deadlock probe %s: exceeded threshold %d\n", \ |
"cpu%d: function=%s, line=%d\n", \ |
printf("Deadlock probe %s: exceeded threshold %u\n", \ |
"cpu%u: function=%s, line=%u\n", \ |
#pname, (value), CPU->id, __func__, __LINE__); \ |
} |
#else |
/branches/dd/kernel/generic/include/synch/smc.h |
---|
0,0 → 1,43 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sync |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_SMC_H_ |
#define KERN_SMC_H_ |
extern unative_t sys_smc_coherence(uintptr_t va, size_t size); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/memstr.h |
---|
42,9 → 42,9 |
* Architecture independent variants. |
*/ |
extern void *_memcpy(void *dst, const void *src, size_t cnt); |
extern void _memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void _memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern char *strcpy(char *dest, const char *src); |
extern void _memsetb(void *dst, size_t cnt, uint8_t x); |
extern void _memsetw(void *dst, size_t cnt, uint16_t x); |
extern void *memmove(void *dst, const void *src, size_t cnt); |
#endif |
/branches/dd/kernel/generic/include/ddi/irq.h |
---|
36,18 → 36,16 |
#define KERN_IRQ_H_ |
typedef enum { |
CMD_MEM_READ_1 = 0, |
CMD_MEM_READ_2, |
CMD_MEM_READ_4, |
CMD_MEM_READ_8, |
CMD_MEM_WRITE_1, |
CMD_MEM_WRITE_2, |
CMD_MEM_WRITE_4, |
CMD_MEM_WRITE_8, |
CMD_PORT_READ_1, |
CMD_PORT_WRITE_1, |
CMD_IA64_GETCHAR, |
CMD_PPC32_GETCHAR, |
CMD_PIO_READ_8 = 1, |
CMD_PIO_READ_16, |
CMD_PIO_READ_32, |
CMD_PIO_WRITE_8, |
CMD_PIO_WRITE_16, |
CMD_PIO_WRITE_32, |
CMD_BTEST, |
CMD_PREDICATE, |
CMD_ACCEPT, |
CMD_DECLINE, |
CMD_LAST |
} irq_cmd_type; |
54,8 → 52,9 |
typedef struct { |
irq_cmd_type cmd; |
void *addr; |
unsigned long long value; |
int dstarg; |
unsigned long long value; |
unsigned int srcarg; |
unsigned int dstarg; |
} irq_cmd_t; |
typedef struct { |
67,8 → 66,10 |
#include <arch/types.h> |
#include <adt/list.h> |
#include <adt/hash_table.h> |
#include <synch/spinlock.h> |
#include <proc/task.h> |
#include <ipc/ipc.h> |
typedef enum { |
IRQ_DECLINE, /**< Decline to service. */ |
81,8 → 82,11 |
} irq_trigger_t; |
struct irq; |
typedef void (* irq_handler_t)(struct irq *irq, void *arg, ...); |
typedef void (* irq_handler_t)(struct irq *); |
/** Type for function used to clear the interrupt. */ |
typedef void (* cir_t)(void *, inr_t); |
/** IPC notification config structure. |
* |
* Primarily, this structure is encapsulated in the irq_t structure. |
95,6 → 99,8 |
answerbox_t *answerbox; |
/** Method to be used for the notification. */ |
unative_t method; |
/** Arguments that will be sent if the IRQ is claimed. */ |
unative_t scratch[IPC_CALL_LEN]; |
/** Top-half pseudocode. */ |
irq_code_t *code; |
/** Counter. */ |
138,22 → 144,29 |
/** Trigger level of the IRQ. */ |
irq_trigger_t trigger; |
/** Claim ownership of the IRQ. */ |
irq_ownership_t (* claim)(void); |
irq_ownership_t (* claim)(struct irq *); |
/** Handler for this IRQ and device. */ |
irq_handler_t handler; |
/** Argument for the handler. */ |
void *arg; |
/** Instance argument for the handler and the claim function. */ |
void *instance; |
/** Clear interrupt routine. */ |
cir_t cir; |
/** First argument to the clear interrupt routine. */ |
void *cir_arg; |
/** Notification configuration structure. */ |
ipc_notif_cfg_t notif_cfg; |
} irq_t; |
extern void irq_init(count_t inrs, count_t chains); |
extern void irq_initialize(irq_t *irq); |
extern void irq_register(irq_t *irq); |
extern irq_t *irq_dispatch_and_lock(inr_t inr); |
extern irq_t *irq_find_and_lock(inr_t inr, devno_t devno); |
SPINLOCK_EXTERN(irq_uspace_hash_table_lock); |
extern hash_table_t irq_uspace_hash_table; |
extern void irq_init(count_t, count_t); |
extern void irq_initialize(irq_t *); |
extern void irq_register(irq_t *); |
extern irq_t *irq_dispatch_and_lock(inr_t); |
#endif |
#endif |
/branches/dd/kernel/generic/include/ddi/device.h |
---|
35,6 → 35,9 |
#ifndef KERN_DEVICE_H_ |
#define KERN_DEVICE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
extern devno_t device_assign_devno(void); |
#endif |
/branches/dd/kernel/generic/include/ddi/ddi.h |
---|
38,13 → 38,14 |
#include <ddi/ddi_arg.h> |
#include <arch/types.h> |
#include <proc/task.h> |
#include <adt/list.h> |
/** Structure representing contiguous physical memory area. */ |
typedef struct { |
uintptr_t pbase; /**< Physical base of the area. */ |
uintptr_t vbase; /**< Virtual base of the area. */ |
count_t frames; /**< Number of frames in the area. */ |
bool cacheable; /**< Cacheability. */ |
uintptr_t pbase; /**< Physical base of the area. */ |
pfn_t frames; /**< Number of frames in the area. */ |
link_t link; /**< Linked list link */ |
} parea_t; |
extern void ddi_init(void); |
/branches/dd/kernel/generic/include/console/klog.h |
---|
File deleted |
/branches/dd/kernel/generic/include/console/chardev.h |
---|
50,7 → 50,7 |
/** Resume pushing characters. */ |
void (* resume)(struct chardev *); |
/** Write character to stream. */ |
void (* write)(struct chardev *, char c); |
void (* write)(struct chardev *, char c, bool silent); |
/** Read character directly from device, assume interrupts disabled. */ |
char (* read)(struct chardev *); |
} chardev_operations_t; |
/branches/dd/kernel/generic/include/console/kconsole.h |
---|
37,6 → 37,7 |
#include <adt/list.h> |
#include <synch/spinlock.h> |
#include <ipc/irq.h> |
#define MAX_CMDLINE 256 |
#define KCONSOLE_HISTORY 10 |
83,11 → 84,16 |
void (* help)(void); |
} cmd_info_t; |
extern bool kconsole_notify; |
extern irq_t kconsole_irq; |
SPINLOCK_EXTERN(cmd_lock); |
extern link_t cmd_head; |
extern void kconsole_init(void); |
extern void kconsole(void *prompt); |
extern void kconsole_notify_init(void); |
extern void kconsole(char *prompt, char *msg, bool kcon); |
extern void kconsole_thread(void *data); |
extern int cmd_register(cmd_info_t *cmd); |
/branches/dd/kernel/generic/include/console/console.h |
---|
41,11 → 41,21 |
extern chardev_t *stdin; |
extern chardev_t *stdout; |
extern bool silent; |
extern void console_init(void); |
extern void klog_init(void); |
extern void klog_update(void); |
extern uint8_t getc(chardev_t *chardev); |
uint8_t _getc(chardev_t *chardev); |
extern uint8_t _getc(chardev_t *chardev); |
extern count_t gets(chardev_t *chardev, char *buf, size_t buflen); |
extern void putchar(char c); |
extern void grab_console(void); |
extern void release_console(void); |
extern void arch_grab_console(void); |
extern void arch_release_console(void); |
/branches/dd/kernel/generic/include/arch.h |
---|
63,12 → 63,11 |
as_t *as; /**< Current address space. */ |
} the_t; |
#define THE ((the_t *)(get_stack_base())) |
#define THE ((the_t * )(get_stack_base())) |
extern void the_initialize(the_t *the); |
extern void the_copy(the_t *src, the_t *dst); |
extern void arch_pre_main(void); |
extern void arch_pre_mm_init(void); |
extern void arch_post_mm_init(void); |
extern void arch_post_cpu_init(void); |
79,6 → 78,7 |
extern void reboot(void); |
extern void arch_reboot(void); |
extern void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller); |
#endif |
/branches/dd/kernel/generic/include/adt/list.h |
---|
36,6 → 36,7 |
#define KERN_LIST_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
/** Doubly linked list head and link type. */ |
typedef struct link { |
/branches/dd/kernel/generic/include/adt/bitmap.h |
---|
49,6 → 49,14 |
extern void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits); |
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits); |
static inline int bitmap_get(bitmap_t *bitmap,index_t bit) |
{ |
if(bit >= bitmap->bits) |
return 0; |
return !! ((bitmap->map)[bit/8] & (1 << (bit & 7))); |
} |
#endif |
/** @} |
/branches/dd/kernel/generic/include/adt/avl.h |
---|
36,6 → 36,7 |
#define KERN_AVLTREE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
/** |
* Macro for getting a pointer to the structure which contains the avltree |
/branches/dd/kernel/generic/include/mm/frame.h |
---|
38,35 → 38,82 |
#include <arch/types.h> |
#include <adt/list.h> |
#include <mm/buddy.h> |
#include <synch/spinlock.h> |
#include <mm/buddy.h> |
#include <arch/mm/page.h> |
#include <arch/mm/frame.h> |
#define ONE_FRAME 0 |
#define TWO_FRAMES 1 |
#define FOUR_FRAMES 2 |
#define ONE_FRAME 0 |
#define TWO_FRAMES 1 |
#define FOUR_FRAMES 2 |
#ifdef ARCH_STACK_FRAMES |
#define STACK_FRAMES ARCH_STACK_FRAMES |
#define STACK_FRAMES ARCH_STACK_FRAMES |
#else |
#define STACK_FRAMES ONE_FRAME |
#define STACK_FRAMES ONE_FRAME |
#endif |
/** Maximum number of zones in system. */ |
#define ZONES_MAX 16 |
/** Maximum number of zones in the system. */ |
#define ZONES_MAX 32 |
/** If possible, merge with neighbouring zones. */ |
#define ZONE_JOIN 0x1 |
typedef uint8_t frame_flags_t; |
/** Convert the frame address to kernel va. */ |
#define FRAME_KA 0x1 |
/** Convert the frame address to kernel VA. */ |
#define FRAME_KA 0x01 |
/** Do not panic and do not sleep on failure. */ |
#define FRAME_ATOMIC 0x2 |
#define FRAME_ATOMIC 0x02 |
/** Do not start reclaiming when no free memory. */ |
#define FRAME_NO_RECLAIM 0x4 |
#define FRAME_NO_RECLAIM 0x04 |
typedef uint8_t zone_flags_t; |
/** Available zone (free for allocation) */ |
#define ZONE_AVAILABLE 0x00 |
/** Zone is reserved (not available for allocation) */ |
#define ZONE_RESERVED 0x08 |
/** Zone is used by firmware (not available for allocation) */ |
#define ZONE_FIRMWARE 0x10 |
/** Currently there is no equivalent zone flags |
for frame flags */ |
#define FRAME_TO_ZONE_FLAGS(frame_flags) 0 |
typedef struct { |
count_t refcount; /**< Tracking of shared frames */ |
uint8_t buddy_order; /**< Buddy system block order */ |
link_t buddy_link; /**< Link to the next free block inside |
one order */ |
void *parent; /**< If allocated by slab, this points there */ |
} frame_t; |
typedef struct { |
pfn_t base; /**< Frame_no of the first frame |
in the frames array */ |
count_t count; /**< Size of zone */ |
count_t free_count; /**< Number of free frame_t |
structures */ |
count_t busy_count; /**< Number of busy frame_t |
structures */ |
zone_flags_t flags; /**< Type of the zone */ |
frame_t *frames; /**< Array of frame_t structures |
in this zone */ |
buddy_system_t *buddy_system; /**< Buddy system for the zone */ |
} zone_t; |
/* |
* The zoneinfo.lock must be locked when accessing zoneinfo structure. |
* Some of the attributes in zone_t structures are 'read-only' |
*/ |
typedef struct { |
SPINLOCK_DECLARE(lock); |
count_t count; |
zone_t info[ZONES_MAX]; |
} zones_t; |
extern zones_t zones; |
static inline uintptr_t PFN2ADDR(pfn_t frame) |
{ |
return (uintptr_t) (frame << FRAME_WIDTH); |
89,31 → 136,37 |
return (size_t) (frames << FRAME_WIDTH); |
} |
#define IS_BUDDY_ORDER_OK(index, order) \ |
((~(((unative_t) -1) << (order)) & (index)) == 0) |
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
static inline bool zone_flags_available(zone_flags_t flags) |
{ |
return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0); |
} |
#define frame_alloc(order, flags) \ |
frame_alloc_generic(order, flags, NULL) |
#define IS_BUDDY_ORDER_OK(index, order) \ |
((~(((unative_t) -1) << (order)) & (index)) == 0) |
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0) |
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1) |
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0) |
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1) |
#define frame_alloc(order, flags) \ |
frame_alloc_generic(order, flags, NULL) |
extern void frame_init(void); |
extern void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone); |
extern void frame_free(uintptr_t frame); |
extern void frame_reference_add(pfn_t pfn); |
extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *); |
extern void frame_free(uintptr_t); |
extern void frame_reference_add(pfn_t); |
extern int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags); |
extern void *frame_get_parent(pfn_t frame, unsigned int hint); |
extern void frame_set_parent(pfn_t frame, void *data, unsigned int hint); |
extern void frame_mark_unavailable(pfn_t start, count_t count); |
extern uintptr_t zone_conf_size(count_t count); |
extern void zone_merge(unsigned int z1, unsigned int z2); |
extern count_t find_zone(pfn_t frame, count_t count, count_t hint); |
extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t); |
extern void *frame_get_parent(pfn_t, count_t); |
extern void frame_set_parent(pfn_t, void *, count_t); |
extern void frame_mark_unavailable(pfn_t, count_t); |
extern uintptr_t zone_conf_size(count_t); |
extern bool zone_merge(count_t, count_t); |
extern void zone_merge_all(void); |
extern uint64_t zone_total_size(void); |
121,7 → 174,7 |
* Console functions |
*/ |
extern void zone_print_list(void); |
extern void zone_print_one(unsigned int znum); |
extern void zone_print_one(count_t); |
#endif |
/branches/dd/kernel/generic/include/mm/page.h |
---|
39,15 → 39,10 |
#include <mm/as.h> |
#include <memstr.h> |
/** |
* Macro for computing page color. |
*/ |
#define PAGE_COLOR(va) (((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1)) |
/** Operations to manipulate page mappings. */ |
typedef struct { |
void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame, |
int flags); |
int flags); |
void (* mapping_remove)(as_t *as, uintptr_t page); |
pte_t *(* mapping_find)(as_t *as, uintptr_t page); |
} page_mapping_operations_t; |
64,6 → 59,7 |
extern pte_t *page_table_create(int flags); |
extern void page_table_destroy(pte_t *page_table); |
extern void map_structure(uintptr_t s, size_t size); |
extern uintptr_t hw_map(uintptr_t physaddr, size_t size); |
#endif |
/branches/dd/kernel/generic/include/mm/slab.h |
---|
53,12 → 53,13 |
#define SLAB_INSIDE_SIZE (PAGE_SIZE >> 3) |
/** Maximum wasted space we allow for cache */ |
#define SLAB_MAX_BADNESS(cache) (((unsigned int) PAGE_SIZE << (cache)->order) >> 2) |
#define SLAB_MAX_BADNESS(cache) \ |
(((unsigned int) PAGE_SIZE << (cache)->order) >> 2) |
/* slab_reclaim constants */ |
/** Reclaim all possible memory, because we are in memory stress */ |
#define SLAB_RECLAIM_ALL 0x1 |
#define SLAB_RECLAIM_ALL 0x01 |
/* cache_create flags */ |
99,7 → 100,7 |
int flags; |
/* Computed values */ |
uint8_t order; /**< Order of frames to be allocated */ |
uint8_t order; /**< Order of frames to be allocated */ |
unsigned int objects; /**< Number of objects that fit in */ |
/* Statistics */ |
121,14 → 122,13 |
slab_mag_cache_t *mag_cache; |
} slab_cache_t; |
extern slab_cache_t * slab_cache_create(char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags); |
extern void slab_cache_destroy(slab_cache_t *cache); |
extern slab_cache_t *slab_cache_create(char *, size_t, size_t, |
int (*)(void *, int), int (*)(void *), int); |
extern void slab_cache_destroy(slab_cache_t *); |
extern void * slab_alloc(slab_cache_t *cache, int flags); |
extern void slab_free(slab_cache_t *cache, void *obj); |
extern count_t slab_reclaim(int flags); |
extern void * slab_alloc(slab_cache_t *, int); |
extern void slab_free(slab_cache_t *, void *); |
extern count_t slab_reclaim(int); |
/* slab subsytem initialization */ |
extern void slab_cache_init(void); |
138,9 → 138,9 |
extern void slab_print_list(void); |
/* malloc support */ |
extern void * malloc(unsigned int size, int flags); |
extern void * realloc(void *ptr, unsigned int size, int flags); |
extern void free(void *ptr); |
extern void *malloc(unsigned int, int); |
extern void *realloc(void *, unsigned int, int); |
extern void free(void *); |
#endif |
/** @} |
/branches/dd/kernel/generic/include/mm/as.h |
---|
53,10 → 53,6 |
#include <adt/btree.h> |
#include <lib/elf.h> |
#ifdef __OBJC__ |
#include <lib/objc.h> |
#endif |
/** |
* Defined to be true if user address space and kernel address space shadow each |
* other. |
84,47 → 80,6 |
/** The page fault was caused by memcpy_from_uspace() or memcpy_to_uspace(). */ |
#define AS_PF_DEFER 2 |
#ifdef __OBJC__ |
@interface as_t : base_t { |
@public |
/** Protected by asidlock. */ |
link_t inactive_as_with_asid_link; |
/** |
* Number of processors on wich is this address space active. |
* Protected by asidlock. |
*/ |
count_t cpu_refcount; |
/** |
* Address space identifier. |
* Constant on architectures that do not support ASIDs. |
* Protected by asidlock. |
*/ |
asid_t asid; |
/** Number of references (i.e tasks that reference this as). */ |
atomic_t refcount; |
mutex_t lock; |
/** B+tree of address space areas. */ |
btree_t as_area_btree; |
/** Non-generic content. */ |
as_genarch_t genarch; |
/** Architecture specific content. */ |
as_arch_t arch; |
} |
+ (pte_t *) page_table_create: (int) flags; |
+ (void) page_table_destroy: (pte_t *) page_table; |
- (void) page_table_lock: (bool) _lock; |
- (void) page_table_unlock: (bool) unlock; |
@end |
#else |
/** Address space structure. |
* |
* as_t contains the list of as_areas of userspace accessible |
168,7 → 123,6 |
void (* page_table_lock)(as_t *as, bool lock); |
void (* page_table_unlock)(as_t *as, bool unlock); |
} as_operations_t; |
#endif |
/** |
* This structure contains information associated with the shared address space |
249,10 → 203,7 |
extern as_t *AS_KERNEL; |
#ifndef __OBJC__ |
extern as_operations_t *as_operations; |
#endif |
extern link_t inactive_as_with_asid_head; |
extern void as_init(void); |
269,6 → 220,7 |
extern int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags); |
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask); |
extern int as_area_change_flags(as_t *as, int flags, uintptr_t address); |
extern int as_area_get_flags(as_area_t *area); |
extern bool as_area_check_access(as_area_t *area, pf_access_t access); |
299,11 → 251,19 |
extern mem_backend_t elf_backend; |
extern mem_backend_t phys_backend; |
extern unsigned int elf_load(elf_header_t *header, as_t *as); |
/** |
* This flags is passed when running the loader, otherwise elf_load() |
* would return with a EE_LOADER error code. |
*/ |
#define ELD_F_NONE 0 |
#define ELD_F_LOADER 1 |
extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags); |
/* Address space area related syscalls. */ |
extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags); |
extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags); |
extern unative_t sys_as_area_change_flags(uintptr_t address, int flags); |
extern unative_t sys_as_area_destroy(uintptr_t address); |
/* Introspection functions. */ |
/branches/dd/kernel/generic/include/mm/buddy.h |
---|
66,7 → 66,6 |
void (*mark_available)(struct buddy_system *, link_t *); |
/** Find parent of block that has given order */ |
link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t); |
void (* print_id)(struct buddy_system *, link_t *); |
} buddy_system_operations_t; |
typedef struct buddy_system { |
78,14 → 77,13 |
void *data; |
} buddy_system_t; |
extern void buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data); |
extern link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i); |
extern bool buddy_system_can_alloc(buddy_system_t *b, uint8_t order); |
extern void buddy_system_free(buddy_system_t *b, link_t *block); |
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size); |
extern size_t buddy_conf_size(int max_order); |
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block); |
extern void buddy_system_create(buddy_system_t *, uint8_t, |
buddy_system_operations_t *, void *); |
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t); |
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t); |
extern void buddy_system_free(buddy_system_t *, link_t *); |
extern size_t buddy_conf_size(size_t); |
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *); |
#endif |
/branches/dd/kernel/generic/include/typedefs.h |
---|
35,8 → 35,26 |
#ifndef KERN_TYPEDEFS_H_ |
#define KERN_TYPEDEFS_H_ |
#include <arch/types.h> |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef void (* function)(); |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
#endif |
/** @} |
/branches/dd/kernel/generic/include/macros.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
37,22 → 37,25 |
#include <arch/types.h> |
#define isdigit(d) (((d) >= '0') && ((d) <= '9')) |
#define islower(c) (((c) >= 'a') && ((c) <= 'z')) |
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z')) |
#define isalpha(c) (is_lower(c) || is_upper(c)) |
#define isalphanum(c) (is_alpha(c) || is_digit(c)) |
#define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \ |
((c) == '\r')) |
#define isdigit(d) (((d) >= '0') && ((d) <= '9')) |
#define islower(c) (((c) >= 'a') && ((c) <= 'z')) |
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z')) |
#define isalpha(c) (is_lower((c)) || is_upper((c))) |
#define isalphanum(c) (is_alpha((c)) || is_digit((c))) |
#define isspace(c) \ |
(((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r')) |
#define min(a,b) ((a) < (b) ? (a) : (b)) |
#define max(a,b) ((a) > (b) ? (a) : (b)) |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
/** Return true if the interlvals overlap. |
#define min3(a, b, c) ((a) < (b) ? (min(a, c)) : (min(b, c))) |
#define max3(a, b, c) ((a) > (b) ? (max(a, c)) : (max(b, c))) |
/** Return true if the intervals overlap. |
* |
* @param s1 Start address of the first interval. |
* @param s1 Start address of the first interval. |
* @param sz1 Size of the first interval. |
* @param s2 Start address of the second interval. |
* @param s2 Start address of the second interval. |
* @param sz2 Size of the second interval. |
*/ |
static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2) |
59,19 → 62,35 |
{ |
uintptr_t e1 = s1 + sz1; |
uintptr_t e2 = s2 + sz2; |
return (s1 < e2) && (s2 < e1); |
return ((s1 < e2) && (s2 < e1)); |
} |
/* Compute overlapping of physical addresses */ |
#define PA_overlaps(x, szx, y, szy) overlaps(KA2PA(x), szx, KA2PA(y), szy) |
#define PA_overlaps(x, szx, y, szy) \ |
overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy)) |
#define SIZE2KB(size) (size >> 10) |
#define SIZE2MB(size) (size >> 20) |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
#define KB2SIZE(kb) ((kb) << 10) |
#define MB2SIZE(mb) ((mb) << 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
/** Pseudorandom generator |
* |
* A pretty standard linear congruential pseudorandom |
* number generator (m = 2^32 or 2^64 depending on architecture). |
* |
*/ |
#define RANDI(seed) \ |
({ \ |
(seed) = 1103515245 * (seed) + 12345; \ |
(seed); \ |
}) |
#endif |
/** @} |
/branches/dd/kernel/generic/include/stdarg.h |
---|
45,7 → 45,7 |
#define va_start(ap, last) __builtin_va_start(ap, last) |
#define va_arg(ap, type) __builtin_va_arg(ap, type) |
#define va_end(ap) __builtin_va_end(ap) |
#define va_copy(dst,src) __builtin_va_copy(dst,src) |
#define va_copy(dst, src) __builtin_va_copy(dst, src) |
#endif |
/branches/dd/kernel/generic/include/syscall/syscall.h |
---|
36,17 → 36,26 |
#define KERN_SYSCALL_H_ |
typedef enum { |
SYS_IO = 0, |
SYS_KLOG = 0, |
SYS_TLS_SET = 1, /* Hardcoded in AMD64, IA32 uspace - fibril.S */ |
SYS_THREAD_CREATE, |
SYS_THREAD_EXIT, |
SYS_THREAD_GET_ID, |
SYS_TASK_GET_ID, |
SYS_TASK_SET_NAME, |
SYS_PROGRAM_SPAWN_LOADER, |
SYS_FUTEX_SLEEP, |
SYS_FUTEX_WAKEUP, |
SYS_SMC_COHERENCE, |
SYS_AS_AREA_CREATE, |
SYS_AS_AREA_RESIZE, |
SYS_AS_AREA_CHANGE_FLAGS, |
SYS_AS_AREA_DESTROY, |
SYS_IPC_CALL_SYNC_FAST, |
SYS_IPC_CALL_SYNC_SLOW, |
SYS_IPC_CALL_ASYNC_FAST, |
54,18 → 63,25 |
SYS_IPC_ANSWER_FAST, |
SYS_IPC_ANSWER_SLOW, |
SYS_IPC_FORWARD_FAST, |
SYS_IPC_FORWARD_SLOW, |
SYS_IPC_WAIT, |
SYS_IPC_HANGUP, |
SYS_IPC_REGISTER_IRQ, |
SYS_IPC_UNREGISTER_IRQ, |
SYS_CAP_GRANT, |
SYS_CAP_REVOKE, |
SYS_PHYSMEM_MAP, |
SYS_IOSPACE_ENABLE, |
SYS_PREEMPT_CONTROL, |
SYS_SYSINFO_VALID, |
SYS_SYSINFO_VALUE, |
SYS_DEBUG_ENABLE_CONSOLE, |
SYS_DEBUG_DISABLE_CONSOLE, |
SYS_IPC_CONNECT_KBOX, |
SYSCALL_END |
} syscall_t; |
/branches/dd/kernel/generic/include/ipc/sysipc.h |
---|
53,10 → 53,13 |
int nonblocking); |
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
unative_t method, unative_t arg1, unative_t arg2, int mode); |
unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid, |
ipc_data_t *data, int mode); |
unative_t sys_ipc_hangup(int phoneid); |
unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, |
irq_code_t *ucode); |
unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno); |
unative_t sys_ipc_connect_kbox(sysarg64_t *task_id); |
#endif |
/branches/dd/kernel/generic/include/ipc/ipc.h |
---|
195,6 → 195,12 |
*/ |
#define IPC_M_DATA_READ 7 |
/** Debug the recipient. |
* - ARG1 - specifies the debug method (from udebug_method_t) |
* - other arguments are specific to the debug method |
*/ |
#define IPC_M_DEBUG_ALL 8 |
/* Well-known methods */ |
#define IPC_M_LAST_SYSTEM 511 |
#define IPC_M_PING 512 |
281,6 → 287,13 |
/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */ |
uint8_t *buffer; |
/* |
* The forward operation can masquerade the caller phone. For those |
* cases, we must keep it aside so that the answer is processed |
* correctly. |
*/ |
phone_t *caller_phone; |
} call_t; |
extern void ipc_init(void); |
287,7 → 300,7 |
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int); |
extern void ipc_answer(answerbox_t *, call_t *); |
extern int ipc_call(phone_t *, call_t *); |
extern void ipc_call_sync(phone_t *, call_t *); |
extern int ipc_call_sync(phone_t *, call_t *); |
extern void ipc_phone_init(phone_t *); |
extern void ipc_phone_connect(phone_t *, answerbox_t *); |
extern void ipc_call_free(call_t *); |
300,6 → 313,8 |
extern int ipc_phone_hangup(phone_t *); |
extern void ipc_backsend_err(phone_t *, call_t *, unative_t); |
extern void ipc_print_task(task_id_t); |
extern void ipc_answerbox_slam_phones(answerbox_t *, bool); |
extern void ipc_cleanup_call_list(link_t *); |
extern answerbox_t *ipc_phone_0; |
/branches/dd/kernel/generic/include/ipc/irq.h |
---|
36,7 → 36,7 |
#define KERN_IPC_IRQ_H_ |
/** Maximum length of IPC IRQ program */ |
#define IRQ_MAX_PROG_SIZE 10 |
#define IRQ_MAX_PROG_SIZE 20 |
#include <ipc/ipc.h> |
#include <ddi/irq.h> |
43,16 → 43,21 |
#include <arch/types.h> |
#include <adt/list.h> |
extern int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, |
unative_t method, irq_code_t *ucode); |
extern void ipc_irq_send_notif(irq_t *irq); |
extern void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno); |
extern void ipc_irq_cleanup(answerbox_t *box); |
extern int ipc_irq_register(answerbox_t *, inr_t, devno_t, unative_t, |
irq_code_t *); |
extern irq_ownership_t ipc_irq_top_half_claim(irq_t *); |
extern void ipc_irq_top_half_handler(irq_t *); |
extern int ipc_irq_unregister(answerbox_t *, inr_t, devno_t); |
extern void ipc_irq_cleanup(answerbox_t *); |
/* |
* User friendly wrappers for ipc_irq_send_msg(). They are in the form |
* ipc_irq_send_msg_m(), where m is the number of payload arguments. |
*/ |
#define ipc_irq_send_msg_0(irq) \ |
ipc_irq_send_msg((irq), 0, 0, 0, 0, 0) |
#define ipc_irq_send_msg_1(irq, a1) \ |
ipc_irq_send_msg((irq), (a1), 0, 0, 0, 0) |
#define ipc_irq_send_msg_2(irq, a1, a2) \ |
64,8 → 69,8 |
#define ipc_irq_send_msg_5(irq, a1, a2, a3, a4, a5) \ |
ipc_irq_send_msg((irq), (a1), (a2), (a3), (a4), (a5)) |
extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, |
unative_t a3, unative_t a4, unative_t a5); |
extern void ipc_irq_send_msg(irq_t *, unative_t, unative_t, unative_t, unative_t, |
unative_t); |
#endif |
/branches/dd/kernel/generic/include/ipc/kbox.h |
---|
0,0 → 1,58 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_IPC_KBOX_H_ |
#define KERN_IPC_KBOX_H_ |
#include <typedefs.h> |
/** Kernel answerbox structure. */ |
typedef struct kbox { |
/** The answerbox itself. */ |
answerbox_t box; |
/** Thread used to service the answerbox. */ |
struct thread *thread; |
/** Kbox thread creation vs. begin of cleanup mutual exclusion. */ |
mutex_t cleanup_lock; |
/** True if cleanup of kbox has already started. */ |
bool finished; |
} kbox_t; |
extern int ipc_connect_kbox(task_id_t); |
extern void ipc_kbox_cleanup(void); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/generic/include/errno.h |
---|
48,14 → 48,18 |
* sys_ipc_hangup() to close the connection. |
* Used by answerbox to close the connection. |
*/ |
#define EEXISTS -8 /* Entry already exists */ |
#define EBADMEM -9 /* Bad memory pointer */ |
#define ENOTSUP -10 /* Not supported */ |
#define EADDRNOTAVAIL -11 /* Address not available. */ |
#define ETIMEOUT -12 /* Timeout expired */ |
#define EINVAL -13 /* Invalid value */ |
#define EBUSY -14 /* Resource is busy */ |
#define EOVERFLOW -15 /* The result does not fit its size. */ |
#define EPARTY -8 /* The other party encountered an error when |
* receiving the call. |
*/ |
#define EEXISTS -9 /* Entry already exists */ |
#define EBADMEM -10 /* Bad memory pointer */ |
#define ENOTSUP -11 /* Not supported */ |
#define EADDRNOTAVAIL -12 /* Address not available. */ |
#define ETIMEOUT -13 /* Timeout expired */ |
#define EINVAL -14 /* Invalid value */ |
#define EBUSY -15 /* Resource is busy */ |
#define EOVERFLOW -16 /* The result does not fit its size. */ |
#define EINTR -17 /* Operation was interrupted. */ |
#endif |
/branches/dd/kernel/generic/src/synch/rwlock.c |
---|
82,7 → 82,7 |
*/ |
void rwlock_initialize(rwlock_t *rwl) { |
spinlock_initialize(&rwl->lock, "rwlock_t"); |
mutex_initialize(&rwl->exclusive); |
mutex_initialize(&rwl->exclusive, MUTEX_PASSIVE); |
rwl->readers_in = 0; |
} |
231,10 → 231,10 |
interrupts_restore(ipl); |
break; |
case ESYNCH_OK_ATOMIC: |
panic("_mutex_lock_timeout()==ESYNCH_OK_ATOMIC\n"); |
panic("_mutex_lock_timeout() == ESYNCH_OK_ATOMIC."); |
break; |
default: |
panic("invalid ESYNCH\n"); |
panic("Invalid ESYNCH."); |
break; |
} |
return rc; |
/branches/dd/kernel/generic/src/synch/mutex.c |
---|
38,42 → 38,54 |
#include <synch/mutex.h> |
#include <synch/semaphore.h> |
#include <synch/synch.h> |
#include <debug.h> |
/** Initialize mutex |
/** Initialize mutex. |
* |
* Initialize mutex. |
* |
* @param mtx Mutex. |
* @param mtx Mutex. |
* @param type Type of the mutex. |
*/ |
void mutex_initialize(mutex_t *mtx) |
void mutex_initialize(mutex_t *mtx, mutex_type_t type) |
{ |
mtx->type = type; |
semaphore_initialize(&mtx->sem, 1); |
} |
/** Acquire mutex |
/** Acquire mutex. |
* |
* Acquire mutex. |
* Timeout mode and non-blocking mode can be requested. |
* |
* @param mtx Mutex. |
* @param usec Timeout in microseconds. |
* @param flags Specify mode of operation. |
* @param mtx Mutex. |
* @param usec Timeout in microseconds. |
* @param flags Specify mode of operation. |
* |
* For exact description of possible combinations of |
* usec and flags, see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags) |
{ |
return _semaphore_down_timeout(&mtx->sem, usec, flags); |
int rc; |
if (mtx->type == MUTEX_PASSIVE) { |
rc = _semaphore_down_timeout(&mtx->sem, usec, flags); |
} else { |
ASSERT(mtx->type == MUTEX_ACTIVE); |
ASSERT(usec == SYNCH_NO_TIMEOUT); |
ASSERT(!(flags & SYNCH_FLAGS_INTERRUPTIBLE)); |
do { |
rc = semaphore_trydown(&mtx->sem); |
} while (SYNCH_FAILED(rc) && |
!(flags & SYNCH_FLAGS_NON_BLOCKING)); |
} |
return rc; |
} |
/** Release mutex |
/** Release mutex. |
* |
* Release mutex. |
* |
* @param mtx Mutex. |
* @param mtx Mutex. |
*/ |
void mutex_unlock(mutex_t *mtx) |
{ |
/branches/dd/kernel/generic/src/synch/spinlock.c |
---|
106,9 → 106,8 |
continue; |
#endif |
if (i++ > DEADLOCK_THRESHOLD) { |
printf("cpu%d: looping on spinlock %.*p:%s, " |
"caller=%.*p", CPU->id, sizeof(uintptr_t) * 2, sl, |
sl->name, sizeof(uintptr_t) * 2, CALLER); |
printf("cpu%u: looping on spinlock %" PRIp ":%s, caller=%" PRIp, |
CPU->id, sl, sl->name, CALLER); |
symbol = get_symtab_entry(CALLER); |
if (symbol) |
printf("(%s)", symbol); |
119,7 → 118,7 |
} |
if (deadlock_reported) |
printf("cpu%d: not deadlocked\n", CPU->id); |
printf("cpu%u: not deadlocked\n", CPU->id); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/dd/kernel/generic/src/synch/smc.c |
---|
0,0 → 1,60 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sync |
* @{ |
*/ |
/** |
* @file |
* @brief Self-modifying code barriers. |
*/ |
#include <arch.h> |
#include <macros.h> |
#include <errno.h> |
#include <arch/barrier.h> |
#include <synch/smc.h> |
unative_t sys_smc_coherence(uintptr_t va, size_t size) |
{ |
if (overlaps(va, size, NULL, PAGE_SIZE)) |
return EINVAL; |
if (!KERNEL_ADDRESS_SPACE_SHADOWED) { |
if (overlaps(va, size, KERNEL_ADDRESS_SPACE_START, |
KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START)) |
return EINVAL; |
} |
smc_coherence_block((void *) va, size); |
return 0; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/synch/futex.c |
---|
115,6 → 115,7 |
uintptr_t paddr; |
pte_t *t; |
ipl_t ipl; |
int rc; |
ipl = interrupts_disable(); |
134,9 → 135,17 |
interrupts_restore(ipl); |
futex = futex_find(paddr); |
return (unative_t) waitq_sleep_timeout(&futex->wq, usec, flags | |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_begin(); |
#endif |
rc = waitq_sleep_timeout(&futex->wq, usec, flags | |
SYNCH_FLAGS_INTERRUPTIBLE); |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_end(); |
#endif |
return (unative_t) rc; |
} |
/** Wakeup one thread waiting in futex wait queue. |
/branches/dd/kernel/generic/src/synch/condvar.c |
---|
43,7 → 43,7 |
/** Initialize condition variable. |
* |
* @param cv Condition variable. |
* @param cv Condition variable. |
*/ |
void condvar_initialize(condvar_t *cv) |
{ |
50,11 → 50,10 |
waitq_initialize(&cv->wq); |
} |
/** |
* Signal the condition has become true |
* to the first waiting thread by waking it up. |
/** Signal the condition has become true to the first waiting thread by waking |
* it up. |
* |
* @param cv Condition variable. |
* @param cv Condition variable. |
*/ |
void condvar_signal(condvar_t *cv) |
{ |
61,11 → 60,10 |
waitq_wakeup(&cv->wq, WAKEUP_FIRST); |
} |
/** |
* Signal the condition has become true |
* to all waiting threads by waking them up. |
/** Signal the condition has become true to all waiting threads by waking |
* them up. |
* |
* @param cv Condition variable. |
* @param cv Condition variable. |
*/ |
void condvar_broadcast(condvar_t *cv) |
{ |
74,17 → 72,17 |
/** Wait for the condition becoming true. |
* |
* @param cv Condition variable. |
* @param mtx Mutex. |
* @param usec Timeout value in microseconds. |
* @param flags Select mode of operation. |
* @param cv Condition variable. |
* @param mtx Mutex. |
* @param usec Timeout value in microseconds. |
* @param flags Select mode of operation. |
* |
* For exact description of meaning of possible combinations |
* of usec and flags, see comment for waitq_sleep_timeout(). |
* Note that when SYNCH_FLAGS_NON_BLOCKING is specified here, |
* ESYNCH_WOULD_BLOCK is always returned. |
* For exact description of meaning of possible combinations of usec and flags, |
* see comment for waitq_sleep_timeout(). Note that when |
* SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always |
* returned. |
* |
* @return See comment for waitq_sleep_timeout(). |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, uint32_t usec, int flags) |
{ |
/branches/dd/kernel/generic/src/main/kinit.c |
---|
32,7 → 32,7 |
/** |
* @file |
* @brief Kernel initialization thread. |
* @brief Kernel initialization thread. |
* |
* This file contains kinit kernel thread which carries out |
* high level system initialization. |
47,6 → 47,7 |
#include <proc/scheduler.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <proc/program.h> |
#include <panic.h> |
#include <func.h> |
#include <cpu.h> |
63,6 → 64,8 |
#include <security/cap.h> |
#include <lib/rd.h> |
#include <ipc/ipc.h> |
#include <debug.h> |
#include <string.h> |
#ifdef CONFIG_SMP |
#include <smp/smp.h> |
71,6 → 74,15 |
#include <synch/waitq.h> |
#include <synch/spinlock.h> |
#define ALIVE_CHARS 4 |
#ifdef CONFIG_KCONSOLE |
static char alive[ALIVE_CHARS] = "-\\|/"; |
#endif |
#define INIT_PREFIX "init:" |
#define INIT_PREFIX_LEN 5 |
/** Kernel initialization thread. |
* |
* kinit takes care of higher level kernel |
81,16 → 93,19 |
*/ |
void kinit(void *arg) |
{ |
thread_t *t; |
#if defined(CONFIG_SMP) || defined(CONFIG_KCONSOLE) |
thread_t *thread; |
#endif |
/* |
* Detach kinit as nobody will call thread_join_timeout() on it. |
*/ |
thread_detach(THREAD); |
interrupts_disable(); |
#ifdef CONFIG_SMP |
#ifdef CONFIG_SMP |
if (config.cpu_count > 1) { |
waitq_initialize(&ap_completion_wq); |
/* |
99,24 → 114,18 |
* not mess together with kcpulb threads. |
* Just a beautification. |
*/ |
if ((t = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED, |
"kmp", true))) { |
spinlock_lock(&t->lock); |
t->cpu = &cpus[0]; |
spinlock_unlock(&t->lock); |
thread_ready(t); |
thread = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED, "kmp", true); |
if (thread != NULL) { |
spinlock_lock(&thread->lock); |
thread->cpu = &cpus[0]; |
spinlock_unlock(&thread->lock); |
thread_ready(thread); |
} else |
panic("thread_create/kmp\n"); |
thread_join(t); |
thread_detach(t); |
panic("Unable to create kmp thread."); |
thread_join(thread); |
thread_detach(thread); |
} |
#endif /* CONFIG_SMP */ |
/* |
* Now that all CPUs are up, we can report what we've found. |
*/ |
cpu_list(); |
#ifdef CONFIG_SMP |
if (config.cpu_count > 1) { |
count_t i; |
124,75 → 133,119 |
* For each CPU, create its load balancing thread. |
*/ |
for (i = 0; i < config.cpu_count; i++) { |
if ((t = thread_create(kcpulb, NULL, TASK, |
THREAD_FLAG_WIRED, "kcpulb", true))) { |
spinlock_lock(&t->lock); |
t->cpu = &cpus[i]; |
spinlock_unlock(&t->lock); |
thread_ready(t); |
thread = thread_create(kcpulb, NULL, TASK, THREAD_FLAG_WIRED, "kcpulb", true); |
if (thread != NULL) { |
spinlock_lock(&thread->lock); |
thread->cpu = &cpus[i]; |
spinlock_unlock(&thread->lock); |
thread_ready(thread); |
} else |
panic("thread_create/kcpulb\n"); |
printf("Unable to create kcpulb thread for cpu" PRIc "\n", i); |
} |
} |
#endif /* CONFIG_SMP */ |
/* |
* At this point SMP, if present, is configured. |
*/ |
arch_post_smp_init(); |
#ifdef CONFIG_KCONSOLE |
if (stdin) { |
/* |
* Create kernel console. |
*/ |
thread = thread_create(kconsole_thread, NULL, TASK, 0, "kconsole", false); |
if (thread != NULL) |
thread_ready(thread); |
else |
printf("Unable to create kconsole thread\n"); |
} |
#endif /* CONFIG_KCONSOLE */ |
interrupts_enable(); |
/* |
* Create kernel console. |
* Create user tasks, load RAM disk images. |
*/ |
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole", false); |
if (t) |
thread_ready(t); |
else |
panic("thread_create/kconsole\n"); |
interrupts_enable(); |
count_t i; |
program_t programs[CONFIG_INIT_TASKS]; |
for (i = 0; i < init.cnt; i++) { |
/* |
* Run user tasks, load RAM disk images. |
*/ |
if (init.tasks[i].addr % FRAME_SIZE) { |
printf("init[%d].addr is not frame aligned", i); |
printf("init[%" PRIc "].addr is not frame aligned\n", i); |
continue; |
} |
task_t *utask = task_run_program((void *) init.tasks[i].addr, |
"uspace"); |
if (utask) { |
/* |
* Construct task name from the 'init:' prefix and the |
* name stored in the init structure (if any). |
*/ |
char namebuf[TASK_NAME_BUFLEN]; |
char *name; |
name = init.tasks[i].name; |
if (name[0] == '\0') |
name = "<unknown>"; |
ASSERT(TASK_NAME_BUFLEN >= INIT_PREFIX_LEN); |
strncpy(namebuf, INIT_PREFIX, TASK_NAME_BUFLEN); |
strncpy(namebuf + INIT_PREFIX_LEN, name, |
TASK_NAME_BUFLEN - INIT_PREFIX_LEN); |
int rc = program_create_from_image((void *) init.tasks[i].addr, |
namebuf, &programs[i]); |
if ((rc == 0) && (programs[i].task != NULL)) { |
/* |
* Set capabilities to init userspace tasks. |
*/ |
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER | |
cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER | |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG); |
if (!ipc_phone_0) |
ipc_phone_0 = &utask->answerbox; |
if (!ipc_phone_0) |
ipc_phone_0 = &programs[i].task->answerbox; |
} else if (rc == 0) { |
/* It was the program loader and was registered */ |
} else { |
int rd = init_rd((rd_header *) init.tasks[i].addr, |
init.tasks[i].size); |
/* RAM disk image */ |
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size); |
if (rd != RE_OK) |
printf("Init binary %zd not used, error code %d.\n", i, rd); |
printf("Init binary %" PRIc " not used (error %d)\n", i, rd); |
} |
} |
/* |
* Run user tasks with small delays |
* to avoid intermixed klog output. |
* |
* TODO: This certainly does not guarantee |
* anything, it just works in most of the |
* cases. Some better way how to achieve |
* nice klog output should be found. |
*/ |
for (i = 0; i < init.cnt; i++) { |
if (programs[i].task != NULL) { |
program_ready(&programs[i]); |
thread_usleep(10000); |
} |
} |
#ifdef CONFIG_KCONSOLE |
if (!stdin) { |
while (1) { |
thread_sleep(10); |
printf("kinit: No stdin\nKernel alive: ."); |
unsigned int i = 0; |
while (true) { |
printf("\b%c", alive[i % ALIVE_CHARS]); |
thread_sleep(1); |
printf("kinit... "); |
i++; |
} |
} |
#endif /* CONFIG_KCONSOLE */ |
} |
/** @} |
/branches/dd/kernel/generic/src/main/main.c |
---|
61,6 → 61,7 |
#include <main/kinit.h> |
#include <main/version.h> |
#include <console/kconsole.h> |
#include <console/console.h> |
#include <cpu.h> |
#include <align.h> |
#include <interrupt.h> |
78,9 → 79,9 |
#include <ipc/ipc.h> |
#include <macros.h> |
#include <adt/btree.h> |
#include <console/klog.h> |
#include <smp/smp.h> |
#include <ddi/ddi.h> |
#include <main/main.h> |
/** Global configuration structure. */ |
config_t config; |
104,18 → 105,15 |
* appropriate sizes and addresses. |
*/ |
/**< Virtual address of where the kernel is loaded. */ |
/** Virtual address of where the kernel is loaded. */ |
uintptr_t hardcoded_load_address = 0; |
/**< Size of the kernel code in bytes. */ |
/** Size of the kernel code in bytes. */ |
size_t hardcoded_ktext_size = 0; |
/**< Size of the kernel data in bytes. */ |
/** Size of the kernel data in bytes. */ |
size_t hardcoded_kdata_size = 0; |
/**< Lowest safe stack virtual address. */ |
/** Lowest safe stack virtual address. */ |
uintptr_t stack_safe = 0; |
void main_bsp(void); |
void main_ap(void); |
/* |
* These two functions prevent stack from underflowing during the |
* kernel boot phase when SP is set to the very top of the reserved |
131,9 → 129,11 |
/** Main kernel routine for bootstrap CPU. |
* |
* Initializes the kernel by bootstrap CPU. |
* This function passes control directly to |
* main_bsp_separated_stack(). |
* The code here still runs on the boot stack, which knows nothing about |
* preemption counts. Because of that, this function cannot directly call |
* functions that disable or enable preemption (e.g. spinlock_lock()). The |
* primary task of this function is to calculate address of a new stack and |
* switch to it. |
* |
* Assuming interrupts_disable(). |
* |
186,90 → 186,97 |
*/ |
void main_bsp_separated_stack(void) |
{ |
task_t *k; |
thread_t *t; |
count_t i; |
/* Keep this the first thing. */ |
the_initialize(THE); |
the_initialize(THE); |
version_print(); |
LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs |
"\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs, |
config.base, config.kernel_size, config.stack_base, |
config.stack_size); |
#ifdef CONFIG_KCONSOLE |
/* |
* kconsole data structures must be initialized very early |
* because other subsystems will register their respective |
* commands. |
*/ |
kconsole_init(); |
LOG_EXEC(kconsole_init()); |
#endif |
/* |
* Exception handler initialization, before architecture |
* starts adding its own handlers |
*/ |
exc_init(); |
LOG_EXEC(exc_init()); |
/* |
* Memory management subsystems initialization. |
*/ |
arch_pre_mm_init(); |
frame_init(); |
*/ |
LOG_EXEC(arch_pre_mm_init()); |
LOG_EXEC(frame_init()); |
/* Initialize at least 1 memory segment big enough for slab to work. */ |
slab_cache_init(); |
btree_init(); |
as_init(); |
page_init(); |
tlb_init(); |
ddi_init(); |
tasklet_init(); |
arch_post_mm_init(); |
LOG_EXEC(slab_cache_init()); |
LOG_EXEC(btree_init()); |
LOG_EXEC(as_init()); |
LOG_EXEC(page_init()); |
LOG_EXEC(tlb_init()); |
LOG_EXEC(ddi_init()); |
LOG_EXEC(tasklet_init()); |
LOG_EXEC(arch_post_mm_init()); |
LOG_EXEC(arch_pre_smp_init()); |
LOG_EXEC(smp_init()); |
version_print(); |
printf("kernel: %.*p hardcoded_ktext_size=%zd KB, " |
"hardcoded_kdata_size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.base, SIZE2KB(hardcoded_ktext_size), |
SIZE2KB(hardcoded_kdata_size)); |
printf("stack: %.*p size=%zd KB\n", sizeof(uintptr_t) * 2, |
config.stack_base, SIZE2KB(config.stack_size)); |
arch_pre_smp_init(); |
smp_init(); |
/* Slab must be initialized after we know the number of processors. */ |
slab_enable_cpucache(); |
LOG_EXEC(slab_enable_cpucache()); |
printf("Detected %zu CPU(s), %llu MB free memory\n", |
config.cpu_count, SIZE2MB(zone_total_size())); |
cpu_init(); |
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n", |
config.cpu_count, SIZE2MB(zone_total_size())); |
calibrate_delay_loop(); |
clock_counter_init(); |
timeout_init(); |
scheduler_init(); |
task_init(); |
thread_init(); |
futex_init(); |
klog_init(); |
LOG_EXEC(cpu_init()); |
LOG_EXEC(calibrate_delay_loop()); |
LOG_EXEC(clock_counter_init()); |
LOG_EXEC(timeout_init()); |
LOG_EXEC(scheduler_init()); |
LOG_EXEC(task_init()); |
LOG_EXEC(thread_init()); |
LOG_EXEC(futex_init()); |
if (init.cnt > 0) { |
count_t i; |
for (i = 0; i < init.cnt; i++) |
printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, |
sizeof(uintptr_t) * 2, init.tasks[i].addr, i, |
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc |
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i, |
init.tasks[i].size); |
} else |
printf("No init binaries found\n"); |
ipc_init(); |
LOG_EXEC(ipc_init()); |
LOG_EXEC(klog_init()); |
LOG_EXEC(console_init()); |
#ifdef CONFIG_KCONSOLE |
LOG_EXEC(kconsole_notify_init()); |
#endif |
/* |
* Create kernel task. |
*/ |
k = task_create(AS_KERNEL, "kernel"); |
if (!k) |
panic("can't create kernel task\n"); |
task_t *kernel = task_create(AS_KERNEL, "kernel"); |
if (!kernel) |
panic("Cannot create kernel task."); |
/* |
* Create the first thread. |
*/ |
t = thread_create(kinit, NULL, k, 0, "kinit", true); |
if (!t) |
panic("can't create kinit thread\n"); |
thread_ready(t); |
thread_t *kinit_thread |
= thread_create(kinit, NULL, kernel, 0, "kinit", true); |
if (!kinit_thread) |
panic("Cannot create kinit thread."); |
LOG_EXEC(thread_ready(kinit_thread)); |
/* |
* This call to scheduler() will return to kinit, |
322,6 → 329,7 |
* collide with another CPU coming up. To prevent this, we |
* switch to this cpu's private stack prior to waking kmp up. |
*/ |
context_save(&CPU->saved_context); |
context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), |
(uintptr_t) CPU->stack, CPU_STACK_SIZE); |
context_restore(&CPU->saved_context); |
/branches/dd/kernel/generic/src/main/version.c |
---|
34,21 → 34,22 |
#include <main/version.h> |
#include <print.h> |
#include <macros.h> |
char *project = "SPARTAN kernel"; |
char *copyright = "Copyright (c) 2001-2008 HelenOS project"; |
char *release = RELEASE; |
char *name = NAME; |
char *arch = ARCH; |
char *copyright = "Copyright (c) 2001-2009 HelenOS project"; |
char *release = STRING(RELEASE); |
char *name = STRING(NAME); |
char *arch = STRING(KARCH); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = " on " TIMESTAMP; |
char *timestamp = " on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
/branches/dd/kernel/generic/src/main/uinit.c |
---|
46,7 → 46,9 |
#include <userspace.h> |
#include <mm/slab.h> |
#include <arch.h> |
#include <udebug/udebug.h> |
/** Thread used to bring up userspace thread. |
* |
* @param arg Pointer to structure containing userspace entry and stack |
65,6 → 67,10 |
* deployed for the event of forceful task termination. |
*/ |
thread_detach(THREAD); |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_end(); |
#endif |
uarg.uspace_entry = ((uspace_arg_t *) arg)->uspace_entry; |
uarg.uspace_stack = ((uspace_arg_t *) arg)->uspace_stack; |
/branches/dd/kernel/generic/src/debug/symtab.c |
---|
37,8 → 37,10 |
#include <symtab.h> |
#include <byteorder.h> |
#include <func.h> |
#include <string.h> |
#include <print.h> |
#include <arch/types.h> |
#include <typedefs.h> |
/** Return entry that seems most likely to correspond to argument. |
* |
139,7 → 141,7 |
while (symtab_search_one(name, &i)) { |
addr = uint64_t_le2host(symbol_table[i].address_le); |
realname = symbol_table[i].symbol_name; |
printf("%.*p: %s\n", sizeof(uintptr_t) * 2, addr, realname); |
printf("%p: %s\n", addr, realname); |
i++; |
} |
} |
/branches/dd/kernel/generic/src/cpu/cpu.c |
---|
64,10 → 64,10 |
cpus = (cpu_t *) malloc(sizeof(cpu_t) * config.cpu_count, |
FRAME_ATOMIC); |
if (!cpus) |
panic("malloc/cpus"); |
panic("Cannot allocate CPU structures."); |
/* initialize everything */ |
memsetb((uintptr_t) cpus, sizeof(cpu_t) * config.cpu_count, 0); |
memsetb(cpus, sizeof(cpu_t) * config.cpu_count, 0); |
for (i = 0; i < config.cpu_count; i++) { |
cpus[i].stack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | FRAME_ATOMIC); |
86,7 → 86,7 |
} |
#endif /* CONFIG_SMP */ |
CPU = &cpus[config.cpu_active-1]; |
CPU = &cpus[config.cpu_active - 1]; |
CPU->active = 1; |
CPU->tlb_active = 1; |
104,7 → 104,7 |
if (cpus[i].active) |
cpu_print_report(&cpus[i]); |
else |
printf("cpu%d: not active\n", i); |
printf("cpu%u: not active\n", i); |
} |
} |
/branches/dd/kernel/generic/src/sysinfo/sysinfo.c |
---|
163,7 → 163,8 |
i = 0; |
} |
} |
panic("Not reached\n"); |
panic("Not reached."); |
return NULL; |
} |
177,7 → 178,7 |
sysinfo_item_t *item = sysinfo_create_path(name, root); |
if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ |
item->val.val=val; |
item->val.val = val; |
item->val_type = SYSINFO_VAL_VAL; |
} |
} |
192,7 → 193,7 |
sysinfo_item_t *item = sysinfo_create_path(name, root); |
if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ |
item->val.fn=fn; |
item->val.fn = fn; |
item->val_type = SYSINFO_VAL_FUNCTION; |
} |
} |
244,7 → 245,7 |
break; |
} |
printf("%s %s val:%d(%x) sub:%s\n", root->name, vtype, val, |
printf("%s %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val, |
val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? |
"NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? |
"TAB" : "FUN")); |
281,10 → 282,15 |
return ret; |
} |
#define SYSINFO_MAX_LEN 1024 |
unative_t sys_sysinfo_valid(unative_t ptr, unative_t len) |
{ |
char *str; |
sysinfo_rettype_t ret = {0, 0}; |
if (len > SYSINFO_MAX_LEN) |
return ret.valid; |
str = malloc(len + 1, 0); |
ASSERT(str); |
299,6 → 305,9 |
{ |
char *str; |
sysinfo_rettype_t ret = {0, 0}; |
if (len > SYSINFO_MAX_LEN) |
return ret.val; |
str = malloc(len + 1, 0); |
ASSERT(str); |
/branches/dd/kernel/generic/src/interrupt/interrupt.c |
---|
86,8 → 86,17 |
void exc_dispatch(int n, istate_t *istate) |
{ |
ASSERT(n < IVT_ITEMS); |
#ifdef CONFIG_UDEBUG |
if (THREAD) THREAD->udebug.uspace_state = istate; |
#endif |
exc_table[n].f(n + IVT_FIRST, istate); |
#ifdef CONFIG_UDEBUG |
if (THREAD) THREAD->udebug.uspace_state = NULL; |
#endif |
/* This is a safe place to exit exiting thread */ |
if (THREAD && THREAD->interrupted && istate_from_uspace(istate)) |
thread_exit(); |
100,8 → 109,10 |
panic("Unhandled exception %d.", n); |
} |
#ifdef CONFIG_KCONSOLE |
/** kconsole cmd - print all exceptions */ |
static int exc_print_cmd(cmd_arg_t *argv) |
static int cmd_exc_print(cmd_arg_t *argv) |
{ |
#if (IVT_ITEMS > 0) |
unsigned int i; |
108,27 → 119,32 |
char *symbol; |
spinlock_lock(&exctbl_lock); |
#ifdef __32_BITS__ |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ---------- --------\n"); |
#endif |
#ifdef __64_BITS__ |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ------------------ --------\n"); |
#endif |
if (sizeof(void *) == 4) { |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ---------- --------\n"); |
} else { |
printf("Exc Description Handler Symbol\n"); |
printf("--- -------------------- ------------------ --------\n"); |
} |
for (i = 0; i < IVT_ITEMS; i++) { |
symbol = get_symtab_entry((unative_t) exc_table[i].f); |
if (!symbol) |
symbol = "not found"; |
#ifdef __32_BITS__ |
printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
#endif |
#ifdef __64_BITS__ |
printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
#endif |
if (sizeof(void *) == 4) |
printf("%-3u %-20s %#10zx %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
else |
printf("%-3u %-20s %#18zx %s\n", i + IVT_FIRST, exc_table[i].name, |
exc_table[i].f, symbol); |
if (((i + 1) % 20) == 0) { |
printf(" -- Press any key to continue -- "); |
spinlock_unlock(&exctbl_lock); |
144,26 → 160,31 |
return 1; |
} |
static cmd_info_t exc_info = { |
.name = "exc", |
.description = "Print exception table.", |
.func = exc_print_cmd, |
.func = cmd_exc_print, |
.help = NULL, |
.argc = 0, |
.argv = NULL |
}; |
#endif |
/** Initialize generic exception handling support */ |
void exc_init(void) |
{ |
int i; |
for (i=0;i < IVT_ITEMS; i++) |
for (i = 0; i < IVT_ITEMS; i++) |
exc_register(i, "undef", (iroutine) exc_undef); |
#ifdef CONFIG_KCONSOLE |
cmd_initialize(&exc_info); |
if (!cmd_register(&exc_info)) |
panic("could not register command %s\n", exc_info.name); |
printf("Cannot register command %s\n", exc_info.name); |
#endif |
} |
/** @} |
/branches/dd/kernel/generic/src/time/timeout.c |
---|
113,7 → 113,7 |
spinlock_lock(&t->lock); |
if (t->cpu) |
panic("t->cpu != 0"); |
panic("Unexpected: t->cpu != 0."); |
t->cpu = CPU; |
t->ticks = us2ticks(time); |
/branches/dd/kernel/generic/src/time/clock.c |
---|
79,7 → 79,7 |
faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC); |
if (!faddr) |
panic("Cannot allocate page for clock"); |
panic("Cannot allocate page for clock."); |
uptime = (uptime_t *) PA2KA(faddr); |
88,9 → 88,7 |
uptime->useconds = 0; |
clock_parea.pbase = (uintptr_t) faddr; |
clock_parea.vbase = (uintptr_t) uptime; |
clock_parea.frames = 1; |
clock_parea.cacheable = true; |
ddi_parea_register(&clock_parea); |
/* |
189,7 → 187,19 |
spinlock_unlock(&THREAD->lock); |
if (!ticks && !PREEMPTION_DISABLED) { |
#ifdef CONFIG_UDEBUG |
istate_t *istate; |
#endif |
scheduler(); |
#ifdef CONFIG_UDEBUG |
/* |
* Give udebug chance to stop the thread |
* before it begins executing userspace code. |
*/ |
istate = THREAD->udebug.uspace_state; |
if (istate && istate_from_uspace(istate)) |
udebug_before_thread_runs(); |
#endif |
} |
} |
/branches/dd/kernel/generic/src/ddi/ddi.c |
---|
29,10 → 29,10 |
/** @addtogroup genericddi |
* @{ |
*/ |
/** |
* @file |
* @brief Device Driver Interface functions. |
* @brief Device Driver Interface functions. |
* |
* This file contains functions that comprise the Device Driver Interface. |
* These are the functions for mapping physical memory and enabling I/O |
68,82 → 68,100 |
* |
* @param parea Pointer to physical area structure. |
* |
* @todo This function doesn't check for overlaps. It depends on the kernel to |
* create disjunct physical memory areas. |
*/ |
void ddi_parea_register(parea_t *parea) |
{ |
ipl_t ipl; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&parea_lock); |
/* |
* TODO: we should really check for overlaps here. |
* However, we should be safe because the kernel is pretty sane and |
* memory of different devices doesn't overlap. |
* We don't check for overlaps here as the kernel is pretty sane. |
*/ |
btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL); |
spinlock_unlock(&parea_lock); |
interrupts_restore(ipl); |
interrupts_restore(ipl); |
} |
/** Map piece of physical memory into virtual address space of current task. |
* |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the starting page. |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the starting page. |
* @param pages Number of pages to map. |
* @param flags Address space area flags for the mapping. |
* |
* @return 0 on success, EPERM if the caller lacks capabilities to use this |
* syscall, ENOENT if there is no task matching the specified ID or the |
* physical address space is not enabled for mapping and ENOMEM if there |
* was a problem in creating address space area. |
* syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there |
* is no task matching the specified ID or the physical address space |
* is not enabled for mapping and ENOMEM if there was a problem in |
* creating address space area. |
* |
*/ |
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags) |
{ |
ipl_t ipl; |
cap_t caps; |
mem_backend_data_t backend_data; |
backend_data.base = pf; |
backend_data.frames = pages; |
ASSERT(TASK); |
ASSERT((pf % FRAME_SIZE) == 0); |
ASSERT((vp % PAGE_SIZE) == 0); |
/* |
* Make sure the caller is authorised to make this syscall. |
*/ |
caps = cap_get(TASK); |
cap_t caps = cap_get(TASK); |
if (!(caps & CAP_MEM_MANAGER)) |
return EPERM; |
ipl = interrupts_disable(); |
/* |
* Check if the physical memory area is enabled for mapping. |
* If the architecture supports virtually indexed caches, intercept |
* attempts to create an illegal address alias. |
*/ |
spinlock_lock(&parea_lock); |
parea_t *parea; |
btree_node_t *nodep; |
parea = (parea_t *) btree_search(&parea_btree, (btree_key_t) pf, &nodep); |
if (!parea || parea->frames < pages || ((flags & AS_AREA_CACHEABLE) && |
!parea->cacheable) || (!(flags & AS_AREA_CACHEABLE) && |
parea->cacheable)) { |
/* |
* This physical memory area cannot be mapped. |
mem_backend_data_t backend_data; |
backend_data.base = pf; |
backend_data.frames = pages; |
ipl_t ipl = interrupts_disable(); |
/* Find the zone of the physical memory */ |
spinlock_lock(&zones.lock); |
count_t znum = find_zone(ADDR2PFN(pf), pages, 0); |
if (znum == (count_t) -1) { |
/* Frames not found in any zones |
* -> assume it is hardware device and allow mapping |
*/ |
spinlock_unlock(&zones.lock); |
goto map; |
} |
if (zones.info[znum].flags & ZONE_FIRMWARE) { |
/* Frames are part of firmware */ |
spinlock_unlock(&zones.lock); |
goto map; |
} |
if (zone_flags_available(zones.info[znum].flags)) { |
/* Frames are part of physical memory, check if the memory |
* region is enabled for mapping. |
*/ |
spinlock_unlock(&zones.lock); |
spinlock_lock(&parea_lock); |
btree_node_t *nodep; |
parea_t *parea = (parea_t *) btree_search(&parea_btree, |
(btree_key_t) pf, &nodep); |
if ((!parea) || (parea->frames < pages)) |
goto err; |
spinlock_unlock(&parea_lock); |
interrupts_restore(ipl); |
return ENOENT; |
goto map; |
} |
spinlock_unlock(&parea_lock); |
err: |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return ENOENT; |
map: |
spinlock_lock(&TASK->lock); |
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE, |
&phys_backend, &backend_data)) { |
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, |
AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) { |
/* |
* The address space area could not have been created. |
* We report it using ENOMEM. |
169,28 → 187,24 |
* @param size Size of the enabled I/O space.. |
* |
* @return 0 on success, EPERM if the caller lacks capabilities to use this |
* syscall, ENOENT if there is no task matching the specified ID. |
* syscall, ENOENT if there is no task matching the specified ID. |
* |
*/ |
static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size) |
{ |
ipl_t ipl; |
cap_t caps; |
task_t *t; |
int rc; |
/* |
* Make sure the caller is authorised to make this syscall. |
*/ |
caps = cap_get(TASK); |
cap_t caps = cap_get(TASK); |
if (!(caps & CAP_IO_MANAGER)) |
return EPERM; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
t = task_find_by_id(id); |
task_t *task = task_find_by_id(id); |
if ((!t) || (!context_check(CONTEXT, t->context))) { |
if ((!task) || (!context_check(CONTEXT, task->context))) { |
/* |
* There is no task with the specified ID |
* or the task belongs to a different security |
200,15 → 214,16 |
interrupts_restore(ipl); |
return ENOENT; |
} |
/* Lock the task and release the lock protecting tasks_btree. */ |
spinlock_lock(&t->lock); |
spinlock_lock(&task->lock); |
spinlock_unlock(&tasks_lock); |
rc = ddi_iospace_enable_arch(t, ioaddr, size); |
spinlock_unlock(&t->lock); |
int rc = ddi_iospace_enable_arch(task, ioaddr, size); |
spinlock_unlock(&task->lock); |
interrupts_restore(ipl); |
return rc; |
} |
220,7 → 235,8 |
* @param flags Flags of newly mapped pages |
* |
* @return 0 on success, otherwise it returns error code found in errno.h |
*/ |
* |
*/ |
unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, |
unative_t pages, unative_t flags) |
{ |
234,16 → 250,15 |
* @param uspace_io_arg User space address of DDI argument structure. |
* |
* @return 0 on success, otherwise it returns error code found in errno.h |
*/ |
* |
*/ |
unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg) |
{ |
ddi_ioarg_t arg; |
int rc; |
rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t)); |
int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t)); |
if (rc != 0) |
return (unative_t) rc; |
return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id, |
(uintptr_t) arg.ioaddr, (size_t) arg.size); |
} |
251,20 → 266,24 |
/** Disable or enable preemption. |
* |
* @param enable If non-zero, the preemption counter will be decremented, |
* leading to potential enabling of preemption. Otherwise the preemption |
* counter will be incremented, preventing preemption from occurring. |
* leading to potential enabling of preemption. Otherwise |
* the preemption counter will be incremented, preventing |
* preemption from occurring. |
* |
* @return Zero on success or EPERM if callers capabilities are not sufficient. |
*/ |
* |
*/ |
unative_t sys_preempt_control(int enable) |
{ |
if (!cap_get(TASK) & CAP_PREEMPT_CONTROL) |
return EPERM; |
if (enable) |
preemption_enable(); |
else |
preemption_disable(); |
return 0; |
if (!cap_get(TASK) & CAP_PREEMPT_CONTROL) |
return EPERM; |
if (enable) |
preemption_enable(); |
else |
preemption_disable(); |
return 0; |
} |
/** @} |
/branches/dd/kernel/generic/src/ddi/irq.c |
---|
39,7 → 39,8 |
* |
* This code is designed to support: |
* - multiple devices sharing single IRQ |
* - multiple IRQs per signle device |
* - multiple IRQs per single device |
* - multiple instances of the same device |
* |
* |
* Note about architectures. |
68,8 → 69,11 |
#include <ddi/irq.h> |
#include <adt/hash_table.h> |
#include <mm/slab.h> |
#include <arch/types.h> |
#include <synch/spinlock.h> |
#include <console/console.h> |
#include <memstr.h> |
#include <arch.h> |
#define KEY_INR 0 |
76,13 → 80,22 |
#define KEY_DEVNO 1 |
/** |
* Spinlock protecting the hash table. |
* Spinlock protecting the kernel IRQ hash table. |
* This lock must be taken only when interrupts are disabled. |
*/ |
SPINLOCK_INITIALIZE(irq_hash_table_lock); |
static hash_table_t irq_hash_table; |
SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock); |
/** The kernel IRQ hash table. */ |
static hash_table_t irq_kernel_hash_table; |
/** |
* Spinlock protecting the uspace IRQ hash table. |
* This lock must be taken only when interrupts are disabled. |
*/ |
SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock); |
/** The uspace IRQ hash table. */ |
hash_table_t irq_uspace_hash_table; |
/** |
* Hash table operations for cases when we know that |
* there will be collisions between different keys. |
*/ |
110,6 → 123,9 |
.remove_callback = NULL /* not used */ |
}; |
/** Number of buckets in either of the hash tables. */ |
static count_t buckets; |
/** Initialize IRQ subsystem. |
* |
* @param inrs Numbers of unique IRQ numbers or INRs. |
117,6 → 133,7 |
*/ |
void irq_init(count_t inrs, count_t chains) |
{ |
buckets = chains; |
/* |
* Be smart about the choice of the hash table operations. |
* In cases in which inrs equals the requested number of |
123,10 → 140,17 |
* chains (i.e. where there is no collision between |
* different keys), we can use optimized set of operations. |
*/ |
if (inrs == chains) |
hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops); |
else |
hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops); |
if (inrs == chains) { |
hash_table_create(&irq_uspace_hash_table, chains, 2, |
&irq_lin_ops); |
hash_table_create(&irq_kernel_hash_table, chains, 2, |
&irq_lin_ops); |
} else { |
hash_table_create(&irq_uspace_hash_table, chains, 2, |
&irq_ht_ops); |
hash_table_create(&irq_kernel_hash_table, chains, 2, |
&irq_ht_ops); |
} |
} |
/** Initialize one IRQ structure. |
136,21 → 160,12 |
*/ |
void irq_initialize(irq_t *irq) |
{ |
memsetb(irq, sizeof(irq_t), 0); |
link_initialize(&irq->link); |
spinlock_initialize(&irq->lock, "irq.lock"); |
irq->preack = false; |
link_initialize(&irq->notif_cfg.link); |
irq->inr = -1; |
irq->devno = -1; |
irq->trigger = (irq_trigger_t) 0; |
irq->claim = NULL; |
irq->handler = NULL; |
irq->arg = NULL; |
irq->notif_cfg.notify = false; |
irq->notif_cfg.answerbox = NULL; |
irq->notif_cfg.code = NULL; |
irq->notif_cfg.method = 0; |
irq->notif_cfg.counter = 0; |
link_initialize(&irq->notif_cfg.link); |
} |
/** Register IRQ for device. |
157,9 → 172,10 |
* |
* The irq structure must be filled with information |
* about the interrupt source and with the claim() |
* function pointer and irq_handler() function pointer. |
* function pointer and handler() function pointer. |
* |
* @param irq IRQ structure belonging to a device. |
* @param irq IRQ structure belonging to a device. |
* @return True on success, false on failure. |
*/ |
void irq_register(irq_t *irq) |
{ |
170,88 → 186,101 |
}; |
ipl = interrupts_disable(); |
spinlock_lock(&irq_hash_table_lock); |
hash_table_insert(&irq_hash_table, key, &irq->link); |
spinlock_unlock(&irq_hash_table_lock); |
spinlock_lock(&irq_kernel_hash_table_lock); |
spinlock_lock(&irq->lock); |
hash_table_insert(&irq_kernel_hash_table, key, &irq->link); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_kernel_hash_table_lock); |
interrupts_restore(ipl); |
} |
/** Dispatch the IRQ. |
/** Search and lock the uspace IRQ hash table. |
* |
* We assume this function is only called from interrupt |
* context (i.e. that interrupts are disabled prior to |
* this call). |
* |
* This function attempts to lookup a fitting IRQ |
* structure. In case of success, return with interrupts |
* disabled and holding the respective structure. |
* |
* @param inr Interrupt number (aka inr or irq). |
* |
* @return IRQ structure of the respective device or NULL. |
*/ |
irq_t *irq_dispatch_and_lock(inr_t inr) |
static irq_t *irq_dispatch_and_lock_uspace(inr_t inr) |
{ |
link_t *lnk; |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) -1 /* search will use claim() instead of devno */ |
(unative_t) -1 /* search will use claim() instead of devno */ |
}; |
spinlock_lock(&irq_hash_table_lock); |
lnk = hash_table_find(&irq_hash_table, key); |
spinlock_lock(&irq_uspace_hash_table_lock); |
lnk = hash_table_find(&irq_uspace_hash_table, key); |
if (lnk) { |
irq_t *irq; |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq_hash_table_lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
return irq; |
} |
spinlock_unlock(&irq_uspace_hash_table_lock); |
spinlock_unlock(&irq_hash_table_lock); |
return NULL; |
return NULL; |
} |
/** Find the IRQ structure corresponding to inr and devno. |
/** Search and lock the kernel IRQ hash table. |
* |
* This functions attempts to lookup the IRQ structure |
* corresponding to its arguments. On success, this |
* function returns with interrups disabled, holding |
* the lock of the respective IRQ structure. |
* |
* This function assumes interrupts are already disabled. |
* |
* @param inr INR being looked up. |
* @param devno Devno being looked up. |
* |
* @return Locked IRQ structure on success or NULL on failure. |
*/ |
irq_t *irq_find_and_lock(inr_t inr, devno_t devno) |
static irq_t *irq_dispatch_and_lock_kernel(inr_t inr) |
{ |
link_t *lnk; |
unative_t keys[] = { |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) devno |
(unative_t) -1 /* search will use claim() instead of devno */ |
}; |
spinlock_lock(&irq_hash_table_lock); |
lnk = hash_table_find(&irq_hash_table, keys); |
spinlock_lock(&irq_kernel_hash_table_lock); |
lnk = hash_table_find(&irq_kernel_hash_table, key); |
if (lnk) { |
irq_t *irq; |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq_hash_table_lock); |
spinlock_unlock(&irq_kernel_hash_table_lock); |
return irq; |
} |
spinlock_unlock(&irq_kernel_hash_table_lock); |
spinlock_unlock(&irq_hash_table_lock); |
return NULL; |
} |
return NULL; |
/** Dispatch the IRQ. |
* |
* We assume this function is only called from interrupt |
* context (i.e. that interrupts are disabled prior to |
* this call). |
* |
* This function attempts to lookup a fitting IRQ |
* structure. In case of success, return with interrupts |
* disabled and holding the respective structure. |
* |
* @param inr Interrupt number (aka inr or irq). |
* |
* @return IRQ structure of the respective device or NULL. |
*/ |
irq_t *irq_dispatch_and_lock(inr_t inr) |
{ |
irq_t *irq; |
/* |
* If the kernel console is silenced, |
* then try first the uspace handlers, |
* eventually fall back to kernel handlers. |
* |
* If the kernel console is active, |
* then do it the other way around. |
*/ |
if (silent) { |
irq = irq_dispatch_and_lock_uspace(inr); |
if (irq) |
return irq; |
return irq_dispatch_and_lock_kernel(inr); |
} |
irq = irq_dispatch_and_lock_kernel(inr); |
if (irq) |
return irq; |
return irq_dispatch_and_lock_uspace(inr); |
} |
/** Compute hash index for the key. |
270,7 → 299,7 |
index_t irq_ht_hash(unative_t key[]) |
{ |
inr_t inr = (inr_t) key[KEY_INR]; |
return inr % irq_hash_table.entries; |
return inr % buckets; |
} |
/** Compare hash table element with a key. |
304,7 → 333,8 |
spinlock_lock(&irq->lock); |
if (devno == -1) { |
/* Invoked by irq_dispatch_and_lock(). */ |
rv = ((irq->inr == inr) && (irq->claim() == IRQ_ACCEPT)); |
rv = ((irq->inr == inr) && |
(irq->claim(irq) == IRQ_ACCEPT)); |
} else { |
/* Invoked by irq_find_and_lock(). */ |
rv = ((irq->inr == inr) && (irq->devno == devno)); |
363,7 → 393,7 |
spinlock_lock(&irq->lock); |
if (devno == -1) { |
/* Invoked by irq_dispatch_and_lock() */ |
rv = (irq->claim() == IRQ_ACCEPT); |
rv = (irq->claim(irq) == IRQ_ACCEPT); |
} else { |
/* Invoked by irq_find_and_lock() */ |
rv = (irq->devno == devno); |
/branches/dd/kernel/generic/src/printf/vprintf.c |
---|
37,6 → 37,8 |
#include <putchar.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/types.h> |
#include <typedefs.h> |
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */ |
60,13 → 62,13 |
{ |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vprintf_write, NULL}; |
int irqpri = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&printf_lock); |
int ret = printf_core(fmt, &ps, ap); |
spinlock_unlock(&printf_lock); |
interrupts_restore(irqpri); |
interrupts_restore(ipl); |
return ret; |
} |
/branches/dd/kernel/generic/src/printf/printf_core.c |
---|
40,7 → 40,7 |
#include <print.h> |
#include <arch/arg.h> |
#include <macros.h> |
#include <func.h> |
#include <string.h> |
#include <arch.h> |
/** show prefixes 0x or 0 */ |
75,7 → 75,6 |
PrintfQualifierInt, |
PrintfQualifierLong, |
PrintfQualifierLongLong, |
PrintfQualifierNative, |
PrintfQualifierPointer |
} qualifier_t; |
432,7 → 431,6 |
* - "" Signed or unsigned int (default value).@n |
* - "l" Signed or unsigned long int.@n |
* - "ll" Signed or unsigned long long int.@n |
* - "z" unative_t (non-standard extension).@n |
* |
* |
* CONVERSION:@n |
486,7 → 484,7 |
while ((c = fmt[i])) { |
/* control character */ |
if (c == '%' ) { |
if (c == '%') { |
/* print common characters if any processed */ |
if (i > j) { |
if ((retval = printf_putnchars(&fmt[j], |
536,7 → 534,7 |
} else if (fmt[i] == '*') { |
/* get width value from argument list */ |
i++; |
width = (int)va_arg(ap, int); |
width = (int) va_arg(ap, int); |
if (width < 0) { |
/* negative width sets '-' flag */ |
width *= -1; |
559,7 → 557,7 |
* list. |
*/ |
i++; |
precision = (int)va_arg(ap, int); |
precision = (int) va_arg(ap, int); |
if (precision < 0) { |
/* ignore negative precision */ |
precision = 0; |
585,9 → 583,6 |
qualifier = PrintfQualifierLongLong; |
} |
break; |
case 'z': /* unative_t */ |
qualifier = PrintfQualifierNative; |
break; |
default: |
/* default type */ |
qualifier = PrintfQualifierInt; |
627,7 → 622,7 |
* Integer values |
*/ |
case 'P': /* pointer */ |
flags |= __PRINTF_FLAG_BIGCHARS; |
flags |= __PRINTF_FLAG_BIGCHARS; |
case 'p': |
flags |= __PRINTF_FLAG_PREFIX; |
base = 16; |
670,34 → 665,28 |
switch (qualifier) { |
case PrintfQualifierByte: |
size = sizeof(unsigned char); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierShort: |
size = sizeof(unsigned short); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierInt: |
size = sizeof(unsigned int); |
number = (uint64_t)va_arg(ap, unsigned int); |
number = (uint64_t) va_arg(ap, unsigned int); |
break; |
case PrintfQualifierLong: |
size = sizeof(unsigned long); |
number = (uint64_t)va_arg(ap, unsigned long); |
number = (uint64_t) va_arg(ap, unsigned long); |
break; |
case PrintfQualifierLongLong: |
size = sizeof(unsigned long long); |
number = (uint64_t)va_arg(ap, |
unsigned long long); |
number = (uint64_t) va_arg(ap, unsigned long long); |
break; |
case PrintfQualifierPointer: |
size = sizeof(void *); |
number = (uint64_t)(unsigned long)va_arg(ap, |
void *); |
number = (uint64_t) (unsigned long) va_arg(ap, void *); |
break; |
case PrintfQualifierNative: |
size = sizeof(unative_t); |
number = (uint64_t)va_arg(ap, unative_t); |
break; |
default: /* Unknown qualifier */ |
counter = -counter; |
goto out; |
708,7 → 697,7 |
flags |= __PRINTF_FLAG_NEGATIVE; |
if (size == sizeof(uint64_t)) { |
number = -((int64_t)number); |
number = -((int64_t) number); |
} else { |
number = ~number; |
number &= |
734,7 → 723,7 |
} |
if (i > j) { |
if ((retval = printf_putnchars(&fmt[j], (unative_t)(i - j), |
if ((retval = printf_putnchars(&fmt[j], (unative_t) (i - j), |
ps)) < 0) { /* error */ |
counter = -counter; |
goto out; |
744,7 → 733,6 |
} |
out: |
return counter; |
} |
/branches/dd/kernel/generic/src/console/klog.c |
---|
File deleted |
/branches/dd/kernel/generic/src/console/console.c |
---|
35,30 → 35,59 |
#include <console/console.h> |
#include <console/chardev.h> |
#include <sysinfo/sysinfo.h> |
#include <synch/waitq.h> |
#include <synch/spinlock.h> |
#include <arch/types.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <ddi/ddi.h> |
#include <ipc/irq.h> |
#include <arch.h> |
#include <func.h> |
#include <print.h> |
#include <atomic.h> |
#define BUFLEN 2048 |
static char debug_buffer[BUFLEN]; |
static size_t offset = 0; |
/** Initialize stdout to something that does not print, but does not fail |
* |
* Save data in some buffer so that it could be retrieved in the debugger |
#define KLOG_SIZE PAGE_SIZE |
#define KLOG_LATENCY 8 |
/** Kernel log cyclic buffer */ |
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE))); |
/** Kernel log initialized */ |
static bool klog_inited = false; |
/** First kernel log characters */ |
static index_t klog_start = 0; |
/** Number of valid kernel log characters */ |
static size_t klog_len = 0; |
/** Number of stored (not printed) kernel log characters */ |
static size_t klog_stored = 0; |
/** Number of stored kernel log characters for uspace */ |
static size_t klog_uspace = 0; |
/** Silence output */ |
bool silent = false; |
/** Kernel log spinlock */ |
SPINLOCK_INITIALIZE(klog_lock); |
/** Physical memory area used for klog buffer */ |
static parea_t klog_parea; |
/* |
* For now, we use 0 as INR. |
* However, it is therefore desirable to have architecture specific |
* definition of KLOG_VIRT_INR in the future. |
*/ |
static void null_putchar(chardev_t *d, const char ch) |
{ |
if (offset >= BUFLEN) |
offset = 0; |
debug_buffer[offset++] = ch; |
} |
#define KLOG_VIRT_INR 0 |
static irq_t klog_irq; |
static chardev_operations_t null_stdout_ops = { |
.write = null_putchar |
.suspend = NULL, |
.resume = NULL, |
.write = NULL, |
.read = NULL |
}; |
chardev_t null_stdout = { |
66,10 → 95,88 |
.op = &null_stdout_ops |
}; |
/** Standard input character device. */ |
/** Allways refuse IRQ ownership. |
* |
* This is not a real IRQ, so we always decline. |
* |
* @return Always returns IRQ_DECLINE. |
*/ |
static irq_ownership_t klog_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
static void stdin_suspend(chardev_t *d) |
{ |
} |
static void stdin_resume(chardev_t *d) |
{ |
} |
static chardev_operations_t stdin_ops = { |
.suspend = stdin_suspend, |
.resume = stdin_resume, |
}; |
/** Standard input character device */ |
static chardev_t _stdin; |
chardev_t *stdin = NULL; |
chardev_t *stdout = &null_stdout; |
void console_init(void) |
{ |
chardev_initialize("stdin", &_stdin, &stdin_ops); |
stdin = &_stdin; |
} |
/** Initialize kernel logging facility |
* |
* The shared area contains kernel cyclic buffer. Userspace application may |
* be notified on new data with indication of position and size |
* of the data within the circular buffer. |
*/ |
void klog_init(void) |
{ |
void *faddr = (void *) KA2PA(klog); |
ASSERT((uintptr_t) faddr % FRAME_SIZE == 0); |
ASSERT(KLOG_SIZE % FRAME_SIZE == 0); |
devno_t devno = device_assign_devno(); |
klog_parea.pbase = (uintptr_t) faddr; |
klog_parea.frames = SIZE2FRAMES(KLOG_SIZE); |
ddi_parea_register(&klog_parea); |
sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr); |
sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE)); |
sysinfo_set_item_val("klog.devno", NULL, devno); |
sysinfo_set_item_val("klog.inr", NULL, KLOG_VIRT_INR); |
irq_initialize(&klog_irq); |
klog_irq.devno = devno; |
klog_irq.inr = KLOG_VIRT_INR; |
klog_irq.claim = klog_claim; |
irq_register(&klog_irq); |
spinlock_lock(&klog_lock); |
klog_inited = true; |
spinlock_unlock(&klog_lock); |
} |
void grab_console(void) |
{ |
silent = false; |
arch_grab_console(); |
} |
void release_console(void) |
{ |
silent = true; |
arch_release_console(); |
} |
/** Get character from character device. Do not echo character. |
* |
* @param chardev Character device. |
90,10 → 197,10 |
return chardev->op->read(chardev); |
/* no other way of interacting with user, halt */ |
if (CPU) |
printf("cpu%d: ", CPU->id); |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted - no kconsole\n"); |
printf("halted (no kconsole)\n"); |
cpu_halt(); |
} |
125,7 → 232,7 |
{ |
index_t index = 0; |
char ch; |
while (index < buflen) { |
ch = _getc(chardev); |
if (ch == '\b') { |
139,7 → 246,7 |
continue; |
} |
putchar(ch); |
if (ch == '\n') { /* end of string => write 0, return */ |
buf[index] = '\0'; |
return (count_t) index; |
159,10 → 266,60 |
return ch; |
} |
void klog_update(void) |
{ |
spinlock_lock(&klog_lock); |
if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) { |
ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace); |
klog_uspace = 0; |
} |
spinlock_unlock(&klog_lock); |
} |
void putchar(char c) |
{ |
spinlock_lock(&klog_lock); |
if ((klog_stored > 0) && (stdout->op->write)) { |
/* Print charaters stored in kernel log */ |
index_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent); |
klog_stored = 0; |
} |
/* Store character in the cyclic kernel log */ |
klog[(klog_start + klog_len) % KLOG_SIZE] = c; |
if (klog_len < KLOG_SIZE) |
klog_len++; |
else |
klog_start = (klog_start + 1) % KLOG_SIZE; |
if (stdout->op->write) |
stdout->op->write(stdout, c); |
stdout->op->write(stdout, c, silent); |
else { |
/* The character is just in the kernel log */ |
if (klog_stored < klog_len) |
klog_stored++; |
} |
/* The character is stored for uspace */ |
if (klog_uspace < klog_len) |
klog_uspace++; |
/* Check notify uspace to update */ |
bool update; |
if ((klog_uspace > KLOG_LATENCY) || (c == '\n')) |
update = true; |
else |
update = false; |
spinlock_unlock(&klog_lock); |
if (update) |
klog_update(); |
} |
/** @} |
/branches/dd/kernel/generic/src/console/cmd.c |
---|
50,6 → 50,7 |
#include <arch.h> |
#include <config.h> |
#include <func.h> |
#include <string.h> |
#include <macros.h> |
#include <debug.h> |
#include <symtab.h> |
398,17 → 399,17 |
.argc = 0 |
}; |
/* Data and methods for 'ipc_task' command */ |
static int cmd_ipc_task(cmd_arg_t *argv); |
static cmd_arg_t ipc_task_argv = { |
/* Data and methods for 'ipc' command */ |
static int cmd_ipc(cmd_arg_t *argv); |
static cmd_arg_t ipc_argv = { |
.type = ARG_TYPE_INT, |
}; |
static cmd_info_t ipc_task_info = { |
.name = "ipc_task", |
.description = "ipc_task <taskid> Show IPC information of given task.", |
.func = cmd_ipc_task, |
static cmd_info_t ipc_info = { |
.name = "ipc", |
.description = "ipc <taskid> Show IPC information of given task.", |
.func = cmd_ipc, |
.argc = 1, |
.argv = &ipc_task_argv |
.argv = &ipc_argv |
}; |
/* Data and methods for 'zone' command */ |
461,7 → 462,7 |
&uptime_info, |
&halt_info, |
&help_info, |
&ipc_task_info, |
&ipc_info, |
&set4_info, |
&slabs_info, |
&symaddr_info, |
501,7 → 502,7 |
for (i = 0; basic_commands[i]; i++) { |
cmd_initialize(basic_commands[i]); |
if (!cmd_register(basic_commands[i])) |
panic("could not register command %s\n", basic_commands[i]->name); |
printf("Cannot register command %s\n", basic_commands[i]->name); |
} |
} |
514,23 → 515,31 |
*/ |
int cmd_help(cmd_arg_t *argv) |
{ |
link_t *cur; |
spinlock_lock(&cmd_lock); |
link_t *cur; |
size_t len = 0; |
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) { |
cmd_info_t *hlp; |
hlp = list_get_instance(cur, cmd_info_t, link); |
spinlock_lock(&hlp->lock); |
if (strlen(hlp->name) > len) |
len = strlen(hlp->name); |
spinlock_unlock(&hlp->lock); |
} |
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) { |
cmd_info_t *hlp; |
hlp = list_get_instance(cur, cmd_info_t, link); |
spinlock_lock(&hlp->lock); |
printf("%s - %s\n", hlp->name, hlp->description); |
printf("%-*s %s\n", len, hlp->name, hlp->description); |
spinlock_unlock(&hlp->lock); |
} |
spinlock_unlock(&cmd_lock); |
spinlock_unlock(&cmd_lock); |
return 1; |
} |
563,7 → 572,7 |
/* This doesn't have to be very accurate */ |
unative_t sec = uptime->seconds1; |
printf("Up %u days, %u hours, %u minutes, %u seconds\n", |
printf("Up %" PRIun " days, %" PRIun " hours, %" PRIun " minutes, %" PRIun " seconds\n", |
sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60); |
return 1; |
616,14 → 625,9 |
{ |
uintptr_t symaddr; |
char *symbol; |
unative_t (*f)(void); |
#ifdef ia64 |
struct { |
unative_t f; |
unative_t gp; |
} fptr; |
#endif |
unative_t (*fnc)(void); |
fncptr_t fptr; |
symaddr = get_symbol_addr((char *) argv->buffer); |
if (!symaddr) |
printf("Symbol %s not found.\n", argv->buffer); |
632,15 → 636,9 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling %s() (%.*p)\n", symbol, sizeof(uintptr_t) * 2, symaddr); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
f = (unative_t (*)(void)) &fptr; |
#else |
f = (unative_t (*)(void)) symaddr; |
#endif |
printf("Result: %#zx\n", f()); |
fnc = (unative_t (*)(void)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call0); |
printf("Calling %s() (%p)\n", symbol, symaddr); |
printf("Result: %#" PRIxn "\n", fnc()); |
} |
return 1; |
680,15 → 678,10 |
{ |
uintptr_t symaddr; |
char *symbol; |
unative_t (*f)(unative_t,...); |
unative_t (*fnc)(unative_t, ...); |
unative_t arg1 = argv[1].intval; |
#ifdef ia64 |
struct { |
unative_t f; |
unative_t gp; |
}fptr; |
#endif |
fncptr_t fptr; |
symaddr = get_symbol_addr((char *) argv->buffer); |
if (!symaddr) |
printf("Symbol %s not found.\n", argv->buffer); |
697,16 → 690,9 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
f = (unative_t (*)(unative_t,...)) &fptr; |
#else |
f = (unative_t (*)(unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1)); |
fnc = (unative_t (*)(unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call1); |
printf("Calling f(%#" PRIxn "): %p: %s\n", arg1, symaddr, symbol); |
printf("Result: %#" PRIxn "\n", fnc(arg1)); |
} |
return 1; |
717,16 → 703,11 |
{ |
uintptr_t symaddr; |
char *symbol; |
unative_t (*f)(unative_t,unative_t,...); |
unative_t (*fnc)(unative_t, unative_t, ...); |
unative_t arg1 = argv[1].intval; |
unative_t arg2 = argv[2].intval; |
#ifdef ia64 |
struct { |
unative_t f; |
unative_t gp; |
}fptr; |
#endif |
fncptr_t fptr; |
symaddr = get_symbol_addr((char *) argv->buffer); |
if (!symaddr) |
printf("Symbol %s not found.\n", argv->buffer); |
735,16 → 716,10 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(0x%zx,0x%zx): %.*p: %s\n", |
arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
f = (unative_t (*)(unative_t,unative_t,...)) &fptr; |
#else |
f = (unative_t (*)(unative_t,unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1, arg2)); |
fnc = (unative_t (*)(unative_t, unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call2); |
printf("Calling f(%#" PRIxn ", %#" PRIxn "): %p: %s\n", |
arg1, arg2, symaddr, symbol); |
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2)); |
} |
return 1; |
755,17 → 730,12 |
{ |
uintptr_t symaddr; |
char *symbol; |
unative_t (*f)(unative_t,unative_t,unative_t,...); |
unative_t (*fnc)(unative_t, unative_t, unative_t, ...); |
unative_t arg1 = argv[1].intval; |
unative_t arg2 = argv[2].intval; |
unative_t arg3 = argv[3].intval; |
#ifdef ia64 |
struct { |
unative_t f; |
unative_t gp; |
}fptr; |
#endif |
fncptr_t fptr; |
symaddr = get_symbol_addr((char *) argv->buffer); |
if (!symaddr) |
printf("Symbol %s not found.\n", argv->buffer); |
774,16 → 744,10 |
printf("Duplicate symbol, be more specific.\n"); |
} else { |
symbol = get_symtab_entry(symaddr); |
printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n", |
arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol); |
#ifdef ia64 |
fptr.f = symaddr; |
fptr.gp = ((unative_t *)cmd_call2)[1]; |
f = (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr; |
#else |
f = (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr; |
#endif |
printf("Result: %#zx\n", f(arg1, arg2, arg3)); |
fnc = (unative_t (*)(unative_t, unative_t, unative_t, ...)) arch_construct_function(&fptr, (void *) symaddr, (void *) cmd_call3); |
printf("Calling f(%#" PRIxn ",%#" PRIxn ", %#" PRIxn "): %p: %s\n", |
arg1, arg2, arg3, symaddr, symbol); |
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3)); |
} |
return 1; |
856,7 → 820,7 |
} else { |
if (pointer) |
addr = (uint32_t *)(*(unative_t *)addr); |
printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr); |
printf("Writing %#" PRIx64 " -> %p\n", arg1, addr); |
*addr = arg1; |
} |
937,7 → 901,7 |
* |
* return Always 1 |
*/ |
int cmd_ipc_task(cmd_arg_t * argv) { |
int cmd_ipc(cmd_arg_t * argv) { |
ipc_print_task(argv[0].intval); |
return 1; |
} |
976,8 → 940,11 |
int cmd_continue(cmd_arg_t *argv) |
{ |
printf("The kernel will now relinquish the console.\n"); |
printf("Use userspace controls to redraw the screen.\n"); |
arch_release_console(); |
release_console(); |
if ((kconsole_notify) && (kconsole_irq.notif_cfg.notify)) |
ipc_irq_send_msg_0(&kconsole_irq); |
return 1; |
} |
990,18 → 957,23 |
*/ |
int cmd_tests(cmd_arg_t *argv) |
{ |
size_t len = 0; |
test_t *test; |
for (test = tests; test->name != NULL; test++) { |
if (strlen(test->name) > len) |
len = strlen(test->name); |
} |
for (test = tests; test->name != NULL; test++) |
printf("%s\t\t%s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("*\t\tRun all safe tests\n"); |
printf("%-*s Run all safe tests\n", len, "*"); |
return 1; |
} |
static bool run_test(const test_t *test) |
{ |
printf("%s\t\t%s\n", test->name, test->desc); |
printf("%s (%s)\n", test->name, test->desc); |
/* Update and read thread accounting |
for benchmarking */ |
1025,7 → 997,7 |
char suffix; |
order(dt, &cycles, &suffix); |
printf("Time: %llu%c cycles\n", cycles, suffix); |
printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix); |
if (ret == NULL) { |
printf("Test passed\n"); |
1053,7 → 1025,7 |
} |
for (i = 0; i < cnt; i++) { |
printf("%s (%d/%d) ... ", test->name, i + 1, cnt); |
printf("%s (%u/%u) ... ", test->name, i + 1, cnt); |
/* Update and read thread accounting |
for benchmarking */ |
1081,7 → 1053,7 |
data[i] = dt; |
order(dt, &cycles, &suffix); |
printf("OK (%llu%c cycles)\n", cycles, suffix); |
printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix); |
} |
if (ret) { |
1094,7 → 1066,7 |
} |
order(sum / (uint64_t) cnt, &cycles, &suffix); |
printf("Average\t\t%llu%c\n", cycles, suffix); |
printf("Average\t\t%" PRIu64 "%c\n", cycles, suffix); |
} |
free(data); |
/branches/dd/kernel/generic/src/console/chardev.c |
---|
42,7 → 42,7 |
* @param chardev Character device. |
* @param op Implementation of character device operations. |
*/ |
void chardev_initialize(char *name,chardev_t *chardev, |
void chardev_initialize(char *name, chardev_t *chardev, |
chardev_operations_t *op) |
{ |
chardev->name = name; |
/branches/dd/kernel/generic/src/console/kconsole.c |
---|
49,8 → 49,11 |
#include <macros.h> |
#include <debug.h> |
#include <func.h> |
#include <string.h> |
#include <symtab.h> |
#include <macros.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/device.h> |
/** Simple kernel console. |
* |
83,10 → 86,39 |
index_t *end); |
static char history[KCONSOLE_HISTORY][MAX_CMDLINE] = {}; |
/** Initialize kconsole data structures. */ |
/* |
* For now, we use 0 as INR. |
* However, it is therefore desirable to have architecture specific |
* definition of KCONSOLE_VIRT_INR in the future. |
*/ |
#define KCONSOLE_VIRT_INR 0 |
bool kconsole_notify = false; |
irq_t kconsole_irq; |
/** Allways refuse IRQ ownership. |
* |
* This is not a real IRQ, so we always decline. |
* |
* @return Always returns IRQ_DECLINE. |
* |
*/ |
static irq_ownership_t kconsole_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
/** Initialize kconsole data structures |
* |
* This is the most basic initialization, almost no |
* other kernel subsystem is ready yet. |
* |
*/ |
void kconsole_init(void) |
{ |
int i; |
unsigned int i; |
cmd_init(); |
for (i = 0; i < KCONSOLE_HISTORY; i++) |
94,6 → 126,29 |
} |
/** Initialize kconsole notification mechanism |
* |
* Initialize the virtual IRQ notification mechanism. |
* |
*/ |
void kconsole_notify_init(void) |
{ |
devno_t devno = device_assign_devno(); |
sysinfo_set_item_val("kconsole.present", NULL, true); |
sysinfo_set_item_val("kconsole.devno", NULL, devno); |
sysinfo_set_item_val("kconsole.inr", NULL, KCONSOLE_VIRT_INR); |
irq_initialize(&kconsole_irq); |
kconsole_irq.devno = devno; |
kconsole_irq.inr = KCONSOLE_VIRT_INR; |
kconsole_irq.claim = kconsole_claim; |
irq_register(&kconsole_irq); |
kconsole_notify = true; |
} |
/** Register kconsole command. |
* |
* @param cmd Structure describing the command. |
169,7 → 224,7 |
} |
/** Try to find a command beginning with prefix */ |
static const char * cmdtab_search_one(const char *name,link_t **startpos) |
static const char *cmdtab_search_one(const char *name,link_t **startpos) |
{ |
size_t namelen = strlen(name); |
const char *curname; |
203,7 → 258,7 |
*/ |
static int cmdtab_compl(char *name) |
{ |
static char output[MAX_SYMBOL_NAME+1]; |
static char output[MAX_SYMBOL_NAME + 1]; |
link_t *startpos = NULL; |
const char *foundtxt; |
int found = 0; |
213,7 → 268,7 |
while ((foundtxt = cmdtab_search_one(name, &startpos))) { |
startpos = startpos->next; |
if (!found) |
strncpy(output, foundtxt, strlen(foundtxt)+1); |
strncpy(output, foundtxt, strlen(foundtxt) + 1); |
else { |
for (i = 0; output[i] && foundtxt[i] && |
output[i] == foundtxt[i]; i++) |
240,11 → 295,11 |
} |
static char * clever_readline(const char *prompt, chardev_t *input) |
static char *clever_readline(const char *prompt, chardev_t *input) |
{ |
static int histposition = 0; |
static char tmp[MAX_CMDLINE+1]; |
static char tmp[MAX_CMDLINE + 1]; |
int curlen = 0, position = 0; |
char *current = history[histposition]; |
int i; |
257,7 → 312,8 |
if (c == '\n') { |
putchar(c); |
break; |
} if (c == '\b') { /* Backspace */ |
} |
if (c == '\b') { /* Backspace */ |
if (position == 0) |
continue; |
for (i = position; i < curlen; i++) |
400,11 → 456,15 |
return current; |
} |
/** Kernel console managing thread. |
/** Kernel console prompt. |
* |
* @param prompt Kernel console prompt (e.g kconsole/panic). |
* @param msg Message to display in the beginning. |
* @param kcon Wait for keypress to show the prompt |
* and never exit. |
* |
*/ |
void kconsole(void *prompt) |
void kconsole(char *prompt, char *msg, bool kcon) |
{ |
cmd_info_t *cmd_info; |
count_t len; |
411,25 → 471,42 |
char *cmdline; |
if (!stdin) { |
printf("%s: no stdin\n", __func__); |
LOG("No stdin for kernel console"); |
return; |
} |
if (msg) |
printf("%s", msg); |
if (kcon) |
_getc(stdin); |
while (true) { |
cmdline = clever_readline((char *) prompt, stdin); |
len = strlen(cmdline); |
if (!len) |
continue; |
cmd_info = parse_cmdline(cmdline, len); |
if (!cmd_info) |
continue; |
if (strncmp(cmd_info->name, "exit", |
min(strlen(cmd_info->name), 5)) == 0) |
if ((!kcon) |
&& (strncmp(cmd_info->name, "exit", min(strlen(cmd_info->name), 5)) == 0)) |
break; |
(void) cmd_info->func(cmd_info->argv); |
} |
} |
/** Kernel console managing thread. |
* |
*/ |
void kconsole_thread(void *data) |
{ |
kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true); |
} |
static int parse_int_arg(char *text, size_t len, unative_t *result) |
{ |
static char symname[MAX_SYMBOL_NAME]; |
543,7 → 620,8 |
buf = (char *) cmd->argv[i].buffer; |
strncpy(buf, (const char *) &cmdline[start], |
min((end - start) + 2, cmd->argv[i].len)); |
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0'; |
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = |
'\0'; |
break; |
case ARG_TYPE_INT: |
if (parse_int_arg(cmdline + start, end - start + 1, |
560,8 → 638,8 |
'\0'; |
cmd->argv[i].intval = (unative_t) buf; |
cmd->argv[i].vartype = ARG_TYPE_STRING; |
} else if (!parse_int_arg(cmdline + start, end - start + 1, |
&cmd->argv[i].intval)) { |
} else if (!parse_int_arg(cmdline + start, |
end - start + 1, &cmd->argv[i].intval)) { |
cmd->argv[i].vartype = ARG_TYPE_INT; |
} else { |
printf("Unrecognized variable argument.\n"); |
/branches/dd/kernel/generic/src/proc/scheduler.c |
---|
451,8 → 451,8 |
/* |
* Entering state is unexpected. |
*/ |
panic("tid%llu: unexpected state %s\n", THREAD->tid, |
thread_states[THREAD->state]); |
panic("tid%" PRIu64 ": unexpected state %s.", |
THREAD->tid, thread_states[THREAD->state]); |
break; |
} |
504,9 → 504,9 |
THREAD->state = Running; |
#ifdef SCHEDULER_VERBOSE |
printf("cpu%d: tid %llu (priority=%d, ticks=%llu, nrdy=%ld)\n", |
CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, |
atomic_get(&CPU->nrdy)); |
printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64 |
", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority, |
THREAD->ticks, atomic_get(&CPU->nrdy)); |
#endif |
/* |
640,9 → 640,9 |
*/ |
spinlock_lock(&t->lock); |
#ifdef KCPULB_VERBOSE |
printf("kcpulb%d: TID %llu -> cpu%d, nrdy=%ld, " |
"avg=%nd\n", CPU->id, t->tid, CPU->id, |
atomic_get(&CPU->nrdy), |
printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, " |
"nrdy=%ld, avg=%ld\n", CPU->id, t->tid, |
CPU->id, atomic_get(&CPU->nrdy), |
atomic_get(&nrdy) / config.cpu_active); |
#endif |
t->flags |= THREAD_FLAG_STOLEN; |
708,7 → 708,7 |
continue; |
spinlock_lock(&cpus[cpu].lock); |
printf("cpu%d: address=%p, nrdy=%ld, needs_relink=%ld\n", |
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIc "\n", |
cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy), |
cpus[cpu].needs_relink); |
719,11 → 719,11 |
spinlock_unlock(&r->lock); |
continue; |
} |
printf("\trq[%d]: ", i); |
printf("\trq[%u]: ", i); |
for (cur = r->rq_head.next; cur != &r->rq_head; |
cur = cur->next) { |
t = list_get_instance(cur, thread_t, rq_link); |
printf("%llu(%s) ", t->tid, |
printf("%" PRIu64 "(%s) ", t->tid, |
thread_states[t->state]); |
} |
printf("\n"); |
/branches/dd/kernel/generic/src/proc/task.c |
---|
35,10 → 35,8 |
* @brief Task management. |
*/ |
#include <main/uinit.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/uarg.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <atomic.h> |
45,23 → 43,18 |
#include <synch/spinlock.h> |
#include <synch/waitq.h> |
#include <arch.h> |
#include <panic.h> |
#include <arch/barrier.h> |
#include <adt/avl.h> |
#include <adt/btree.h> |
#include <adt/list.h> |
#include <ipc/ipc.h> |
#include <security/cap.h> |
#include <memstr.h> |
#include <ipc/ipcrsc.h> |
#include <print.h> |
#include <lib/elf.h> |
#include <errno.h> |
#include <func.h> |
#include <string.h> |
#include <syscall/copy.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** Spinlock protecting the tasks_tree AVL tree. */ |
SPINLOCK_INITIALIZE(tasks_lock); |
79,11 → 72,7 |
static task_id_t task_counter = 0; |
/** Initialize tasks |
* |
* Initialize kernel tasks support. |
* |
*/ |
/** Initialize kernel tasks support. */ |
void task_init(void) |
{ |
TASK = NULL; |
91,7 → 80,8 |
} |
/* |
* The idea behind this walker is to remember a single task different from TASK. |
* The idea behind this walker is to remember a single task different from |
* TASK. |
*/ |
static bool task_done_walker(avltree_node_t *node, void *arg) |
{ |
106,9 → 96,7 |
return true; /* continue the walk */ |
} |
/** Kill all tasks except the current task. |
* |
*/ |
/** Kill all tasks except the current task. */ |
void task_done(void) |
{ |
task_t *t; |
128,7 → 116,7 |
interrupts_restore(ipl); |
#ifdef CONFIG_DEBUG |
printf("Killing task %llu\n", id); |
printf("Killing task %" PRIu64 "\n", id); |
#endif |
task_kill(id); |
thread_usleep(10000); |
140,15 → 128,13 |
} while (t != NULL); |
} |
/** Create new task |
/** Create new task with no threads. |
* |
* Create new task with no threads. |
* @param as Task's address space. |
* @param name Symbolic name (a copy is made). |
* |
* @param as Task's address space. |
* @param name Symbolic name. |
* @return New task's structure. |
* |
* @return New task's structure |
* |
*/ |
task_t *task_create(as_t *as, char *name) |
{ |
163,7 → 149,10 |
spinlock_initialize(&ta->lock, "task_ta_lock"); |
list_initialize(&ta->th_head); |
ta->as = as; |
ta->name = name; |
memcpy(ta->name, name, TASK_NAME_BUFLEN); |
ta->name[TASK_NAME_BUFLEN - 1] = '\0'; |
atomic_set(&ta->refcount, 0); |
atomic_set(&ta->lifecount, 0); |
ta->context = CONTEXT; |
170,7 → 159,18 |
ta->capabilities = 0; |
ta->cycles = 0; |
#ifdef CONFIG_UDEBUG |
/* Init debugging stuff */ |
udebug_task_init(&ta->udebug); |
/* Init kbox stuff */ |
ipc_answerbox_init(&ta->kb.box, ta); |
ta->kb.thread = NULL; |
mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE); |
ta->kb.finished = false; |
#endif |
ipc_answerbox_init(&ta->answerbox, ta); |
for (i = 0; i < IPC_MAX_PHONES; i++) |
ipc_phone_init(&ta->phones[i]); |
179,7 → 179,7 |
ipc_phone_connect(&ta->phones[0], ipc_phone_0); |
atomic_set(&ta->active_calls, 0); |
mutex_initialize(&ta->futexes_lock); |
mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE); |
btree_create(&ta->futexes); |
ipl = interrupts_disable(); |
202,7 → 202,7 |
/** Destroy task. |
* |
* @param t Task to be destroyed. |
* @param t Task to be destroyed. |
*/ |
void task_destroy(task_t *t) |
{ |
233,90 → 233,63 |
TASK = NULL; |
} |
/** Create new task with 1 thread and run it |
/** Syscall for reading task ID from userspace. |
* |
* @param program_addr Address of program executable image. |
* @param name Program name. |
* @param uspace_task_id userspace address of 8-byte buffer |
* where to store current task ID. |
* |
* @return Task of the running program or NULL on error. |
* @return Zero on success or an error code from @ref errno.h. |
*/ |
task_t *task_run_program(void *program_addr, char *name) |
unative_t sys_task_get_id(task_id_t *uspace_task_id) |
{ |
as_t *as; |
as_area_t *a; |
unsigned int rc; |
thread_t *t; |
task_t *task; |
uspace_arg_t *kernel_uarg; |
as = as_create(0); |
ASSERT(as); |
rc = elf_load((elf_header_t *) program_addr, as); |
if (rc != EE_OK) { |
as_destroy(as); |
return NULL; |
} |
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
kernel_uarg->uspace_entry = |
(void *) ((elf_header_t *) program_addr)->e_entry; |
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
kernel_uarg->uspace_thread_function = NULL; |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
task = task_create(as, name); |
ASSERT(task); |
/* |
* Create the data as_area. |
* No need to acquire lock on TASK because taskid remains constant for |
* the lifespan of the task. |
*/ |
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
AS_AREA_ATTR_NONE, &anon_backend, NULL); |
/* |
* Create the main thread. |
*/ |
t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
"uinit", false); |
ASSERT(t); |
thread_ready(t); |
return task; |
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
sizeof(TASK->taskid)); |
} |
/** Syscall for reading task ID from userspace. |
/** Syscall for setting the task name. |
* |
* @param uspace_task_id Userspace address of 8-byte buffer where to store |
* current task ID. |
* The name simplifies identifying the task in the task list. |
* |
* @param name The new name for the task. (typically the same |
* as the command used to execute it). |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_task_get_id(task_id_t *uspace_task_id) |
unative_t sys_task_set_name(const char *uspace_name, size_t name_len) |
{ |
/* |
* No need to acquire lock on TASK because taskid |
* remains constant for the lifespan of the task. |
*/ |
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
sizeof(TASK->taskid)); |
int rc; |
char namebuf[TASK_NAME_BUFLEN]; |
/* Cap length of name and copy it from userspace. */ |
if (name_len > TASK_NAME_BUFLEN - 1) |
name_len = TASK_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
strncpy(TASK->name, namebuf, TASK_NAME_BUFLEN); |
return EOK; |
} |
/** Find task structure corresponding to task ID. |
* |
* The tasks_lock must be already held by the caller of this function |
* and interrupts must be disabled. |
* The tasks_lock must be already held by the caller of this function and |
* interrupts must be disabled. |
* |
* @param id Task ID. |
* @param id Task ID. |
* |
* @return Task structure address or NULL if there is no such task ID. |
* @return Task structure address or NULL if there is no such task |
* ID. |
*/ |
task_t *task_find_by_id(task_id_t id) |
{ |
avltree_node_t *node; |
task_t *task_find_by_id(task_id_t id) { avltree_node_t *node; |
node = avltree_search(&tasks_tree, (avltree_key_t) id); |
327,11 → 300,13 |
/** Get accounting data of given task. |
* |
* Note that task lock of 't' must be already held and |
* interrupts must be already disabled. |
* Note that task lock of 't' must be already held and interrupts must be |
* already disabled. |
* |
* @param t Pointer to thread. |
* @param t Pointer to thread. |
* |
* @return Number of cycles used by the task and all its threads |
* so far. |
*/ |
uint64_t task_get_accounting(task_t *t) |
{ |
363,9 → 338,9 |
* This function is idempotent. |
* It signals all the task's threads to bail it out. |
* |
* @param id ID of the task to be killed. |
* @param id ID of the task to be killed. |
* |
* @return 0 on success or an error code from errno.h |
* @return Zero on success or an error code from errno.h. |
*/ |
int task_kill(task_id_t id) |
{ |
386,7 → 361,7 |
spinlock_unlock(&tasks_lock); |
/* |
* Interrupt all threads except ktaskclnp. |
* Interrupt all threads. |
*/ |
spinlock_lock(&ta->lock); |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
394,7 → 369,7 |
bool sleeping = false; |
thr = list_get_instance(cur, thread_t, th_link); |
spinlock_lock(&thr->lock); |
thr->interrupted = true; |
if (thr->state == Sleeping) |
420,18 → 395,22 |
uint64_t cycles; |
char suffix; |
order(task_get_accounting(t), &cycles, &suffix); |
if (sizeof(void *) == 4) |
printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd", |
t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
t->refcount, atomic_get(&t->active_calls)); |
else |
printf("%-6llu %-10s %-3ld %#18zx %#18zx %9llu%c %7zd %6zd", |
t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
t->refcount, atomic_get(&t->active_calls)); |
#ifdef __32_BITS__ |
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
#ifdef __64_BITS__ |
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
for (j = 0; j < IPC_MAX_PHONES; j++) { |
if (t->phones[j].callee) |
printf(" %zd:%#zx", j, t->phones[j].callee); |
printf(" %d:%p", j, t->phones[j].callee); |
} |
printf("\n"); |
447,19 → 426,21 |
/* Messing with task structures, avoid deadlock */ |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
if (sizeof(void *) == 4) { |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ---------- ---------- " |
"---------- ------- ------ ------>\n"); |
} else { |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ------------------ ------------------ " |
"---------- ------- ------ ------>\n"); |
} |
#ifdef __32_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ------------ --- ---------- ---------- " |
"---------- ------- ------ ------>\n"); |
#endif |
#ifdef __64_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ------------ --- ------------------ ------------------ " |
"---------- ------- ------ ------>\n"); |
#endif |
avltree_walk(&tasks_tree, task_print_walker, NULL); |
spinlock_unlock(&tasks_lock); |
/branches/dd/kernel/generic/src/proc/tasklet.c |
---|
51,7 → 51,7 |
tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0); |
if (!tasklet_list) |
panic("Error initializing tasklets"); |
panic("Error initializing tasklets."); |
for (i = 0; i < config.cpu_count; i++) |
tasklet_list[i] = NULL; |
/branches/dd/kernel/generic/src/proc/thread.c |
---|
67,9 → 67,13 |
#include <main/uinit.h> |
#include <syscall/copy.h> |
#include <errno.h> |
#include <console/klog.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** Thread states */ |
char *thread_states[] = { |
"Invalid", |
98,7 → 102,7 |
thread_id_t last_tid = 0; |
static slab_cache_t *thread_slab; |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
slab_cache_t *fpu_context_slab; |
#endif |
157,7 → 161,7 |
/* call the architecture-specific part of the constructor */ |
thr_constructor_arch(t); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
#ifdef CONFIG_FPU_LAZY |
t->saved_fpu_context = NULL; |
#else |
165,11 → 169,11 |
if (!t->saved_fpu_context) |
return -1; |
#endif |
#endif |
#endif |
t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags); |
if (!t->kstack) { |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
176,6 → 180,10 |
return -1; |
} |
#ifdef CONFIG_UDEBUG |
mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE); |
#endif |
return 0; |
} |
188,7 → 196,7 |
thr_destructor_arch(t); |
frame_free(KA2PA(t->kstack)); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
203,11 → 211,11 |
void thread_init(void) |
{ |
THREAD = NULL; |
atomic_set(&nrdy,0); |
atomic_set(&nrdy, 0); |
thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0, |
thr_constructor, thr_destructor, 0); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t), |
FPU_CONTEXT_ALIGN, NULL, NULL, 0); |
#endif |
271,7 → 279,7 |
* guarantee that the task won't cease to exist during the |
* call. The task's lock may not be held. |
* @param flags Thread flags. |
* @param name Symbolic name. |
* @param name Symbolic name (a copy is made). |
* @param uncounted Thread's accounting doesn't affect accumulated task |
* accounting. |
* |
289,8 → 297,7 |
return NULL; |
/* Not needed, but good for debugging */ |
memsetb((uintptr_t) t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, |
0); |
memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0); |
ipl = interrupts_disable(); |
spinlock_lock(&tidlock); |
309,6 → 316,7 |
interrupts_restore(ipl); |
memcpy(t->name, name, THREAD_NAME_BUFLEN); |
t->name[THREAD_NAME_BUFLEN - 1] = '\0'; |
t->thread_code = func; |
t->thread_arg = arg; |
344,6 → 352,11 |
avltree_node_initialize(&t->threads_tree_node); |
t->threads_tree_node.key = (uintptr_t) t; |
#ifdef CONFIG_UDEBUG |
/* Init debugging stuff */ |
udebug_thread_initialize(&t->udebug); |
#endif |
/* might depend on previous initialization */ |
thread_create_arch(t); |
406,12 → 419,17 |
ipl_t ipl; |
/* |
* Attach to the current task. |
* Attach to the specified task. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&task->lock); |
atomic_inc(&task->refcount); |
atomic_inc(&task->lifecount); |
/* Must not count kbox thread into lifecount */ |
if (t->flags & THREAD_FLAG_USPACE) |
atomic_inc(&task->lifecount); |
list_append(&t->th_link, &task->th_head); |
spinlock_unlock(&task->lock); |
434,18 → 452,22 |
{ |
ipl_t ipl; |
if (atomic_predec(&TASK->lifecount) == 0) { |
/* |
* We are the last thread in the task that still has not exited. |
* With the exception of the moment the task was created, new |
* threads can only be created by threads of the same task. |
* We are safe to perform cleanup. |
*/ |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
#ifdef CONFIG_UDEBUG |
/* Generate udebug THREAD_E event */ |
udebug_thread_e_event(); |
#endif |
if (atomic_predec(&TASK->lifecount) == 0) { |
/* |
* We are the last userspace thread in the task that |
* still has not exited. With the exception of the |
* moment the task was created, new userspace threads |
* can only be created by threads of the same task. |
* We are safe to perform cleanup. |
*/ |
ipc_cleanup(); |
futex_cleanup(); |
klog_printf("Cleanup of task %llu completed.", |
TASK->taskid); |
futex_cleanup(); |
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid); |
} |
} |
581,33 → 603,37 |
static bool thread_walker(avltree_node_t *node, void *arg) |
{ |
thread_t *t; |
t = avltree_get_instance(node, thread_t, threads_tree_node); |
thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node); |
uint64_t cycles; |
char suffix; |
order(t->cycles, &cycles, &suffix); |
if (sizeof(void *) == 4) |
printf("%-6llu %-10s %#10zx %-8s %#10zx %-3ld %#10zx %#10zx %9llu%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
else |
printf("%-6llu %-10s %#18zx %-8s %#18zx %-3ld %#18zx %#18zx %9llu%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
#ifdef __32_BITS__ |
printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
#endif |
#ifdef __64_BITS__ |
printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ", |
t->tid, t->name, t, thread_states[t->state], t->task, |
t->task->context, t->thread_code, t->kstack, cycles, suffix); |
#endif |
if (t->cpu) |
printf("%-4zd", t->cpu->id); |
printf("%-4u", t->cpu->id); |
else |
printf("none"); |
if (t->state == Sleeping) { |
if (sizeof(uintptr_t) == 4) |
printf(" %#10zx", t->sleep_queue); |
else |
printf(" %#18zx", t->sleep_queue); |
#ifdef __32_BITS__ |
printf(" %10p", t->sleep_queue); |
#endif |
#ifdef __64_BITS__ |
printf(" %18p", t->sleep_queue); |
#endif |
} |
printf("\n"); |
623,23 → 649,25 |
/* Messing with thread structures, avoid deadlock */ |
ipl = interrupts_disable(); |
spinlock_lock(&threads_lock); |
if (sizeof(uintptr_t) == 4) { |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
printf("------ ---------- ---------- -------- ---------- " |
"--- ---------- ---------- ---------- ---- " |
"----------\n"); |
} else { |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
printf("------ ---------- ------------------ -------- ------------------ " |
"--- ------------------ ------------------ ---------- ---- " |
"------------------\n"); |
} |
#ifdef __32_BITS__ |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
printf("------ ---------- ---------- -------- ---------- " |
"--- ---------- ---------- ---------- ---- " |
"----------\n"); |
#endif |
#ifdef __64_BITS__ |
printf("tid name address state task " |
"ctx code stack cycles cpu " |
"waitqueue\n"); |
printf("------ ---------- ------------------ -------- ------------------ " |
"--- ------------------ ------------------ ---------- ---- " |
"------------------\n"); |
#endif |
avltree_walk(&threads_tree, thread_walker, NULL); |
spinlock_unlock(&threads_lock); |
664,7 → 692,6 |
return node != NULL; |
} |
/** Update accounting of current thread. |
* |
* Note that thread_lock on THREAD must be already held and |
682,7 → 709,7 |
* |
*/ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, |
thread_id_t *uspace_thread_id) |
size_t name_len, thread_id_t *uspace_thread_id) |
{ |
thread_t *t; |
char namebuf[THREAD_NAME_BUFLEN]; |
689,10 → 716,15 |
uspace_arg_t *kernel_uarg; |
int rc; |
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
/* |
* In case of failure, kernel_uarg will be deallocated in this function. |
* In case of success, kernel_uarg will be freed in uinit(). |
731,7 → 763,18 |
return (unative_t) rc; |
} |
} |
#ifdef CONFIG_UDEBUG |
/* |
* Generate udebug THREAD_B event and attach the thread. |
* This must be done atomically (with the debug locks held), |
* otherwise we would either miss some thread or receive |
* THREAD_B events for threads that already existed |
* and could be detected with THREAD_READ before. |
*/ |
udebug_thread_b_event_attach(t, TASK); |
#else |
thread_attach(t, TASK); |
#endif |
thread_ready(t); |
return 0; |
/branches/dd/kernel/generic/src/proc/program.c |
---|
0,0 → 1,233 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericproc |
* @{ |
*/ |
/** |
* @file |
* @brief Running userspace programs. |
*/ |
#include <main/uinit.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/uarg.h> |
#include <mm/as.h> |
#include <mm/slab.h> |
#include <arch.h> |
#include <adt/list.h> |
#include <ipc/ipc.h> |
#include <ipc/ipcrsc.h> |
#include <security/cap.h> |
#include <lib/elf.h> |
#include <errno.h> |
#include <print.h> |
#include <syscall/copy.h> |
#include <proc/program.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
/** |
* Points to the binary image used as the program loader. All non-initial |
* tasks are created from this executable image. |
*/ |
void *program_loader = NULL; |
/** Create a program using an existing address space. |
* |
* @param as Address space containing a binary program image. |
* @param entry_addr Program entry-point address in program address space. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program information. |
*/ |
void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p) |
{ |
as_area_t *a; |
uspace_arg_t *kernel_uarg; |
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
kernel_uarg->uspace_entry = (void *) entry_addr; |
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
kernel_uarg->uspace_thread_function = NULL; |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
p->task = task_create(as, name); |
ASSERT(p->task); |
/* |
* Create the data as_area. |
*/ |
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
AS_AREA_ATTR_NONE, &anon_backend, NULL); |
/* |
* Create the main thread. |
*/ |
p->main_thread = thread_create(uinit, kernel_uarg, p->task, |
THREAD_FLAG_USPACE, "uinit", false); |
ASSERT(p->main_thread); |
} |
/** Parse an executable image in the kernel memory. |
* |
* If the image belongs to a program loader, it is registered as such, |
* (and *task is set to NULL). Otherwise a task is created from the |
* executable image. The task is returned in *task. |
* |
* @param image_addr Address of an executable program image. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program info. If image_addr |
* points to a loader image, p->task will be set to |
* NULL and EOK will be returned. |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_from_image(void *image_addr, char *name, program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
as = as_create(0); |
ASSERT(as); |
rc = elf_load((elf_header_t *) image_addr, as, 0); |
if (rc != EE_OK) { |
as_destroy(as); |
p->task = NULL; |
p->main_thread = NULL; |
if (rc != EE_LOADER) |
return ENOTSUP; |
/* Register image as the program loader */ |
ASSERT(program_loader == NULL); |
program_loader = image_addr; |
printf("Registered program loader at 0x%" PRIp "\n", |
image_addr); |
return EOK; |
} |
program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p); |
return EOK; |
} |
/** Create a task from the program loader image. |
* |
* @param p Buffer for storing program info. |
* @param name Name to set for the program's task. |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_loader(program_t *p, char *name) |
{ |
as_t *as; |
unsigned int rc; |
void *loader; |
as = as_create(0); |
ASSERT(as); |
loader = program_loader; |
if (!loader) { |
printf("Cannot spawn loader as none was registered\n"); |
return ENOENT; |
} |
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER); |
if (rc != EE_OK) { |
as_destroy(as); |
return ENOENT; |
} |
program_create(as, ((elf_header_t *) program_loader)->e_entry, |
name, p); |
return EOK; |
} |
/** Make program ready. |
* |
* Switch program's main thread to the ready state. |
* |
* @param p Program to make ready. |
*/ |
void program_ready(program_t *p) |
{ |
thread_ready(p->main_thread); |
} |
/** Syscall for creating a new loader instance from userspace. |
* |
* Creates a new task from the program loader image and sets |
* the task name. |
* |
* @param name Name to set on the new task (typically the same |
* as the command used to execute it). |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len) |
{ |
program_t p; |
int rc; |
char namebuf[TASK_NAME_BUFLEN]; |
/* Cap length of name and copy it from userspace. */ |
if (name_len > TASK_NAME_BUFLEN - 1) |
name_len = TASK_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
/* Spawn the new task. */ |
rc = program_create_loader(&p, namebuf); |
if (rc != 0) |
return rc; |
// FIXME: control the capabilities |
cap_set(p.task, cap_get(TASK)); |
program_ready(&p); |
return EOK; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/lib/objc_ext.c |
---|
File deleted |
/branches/dd/kernel/generic/src/lib/objc.c |
---|
File deleted |
/branches/dd/kernel/generic/src/lib/rd.c |
---|
42,7 → 42,6 |
#include <mm/frame.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/ddi.h> |
#include <print.h> |
#include <align.h> |
static parea_t rd_parea; /**< Physical memory area for rd. */ |
49,14 → 48,14 |
/** |
* RAM disk initialization routine. At this point, the RAM disk memory is shared |
* and information about the share is provided as sysinfo values to the userspace |
* tasks. |
* and information about the share is provided as sysinfo values to the |
* userspace tasks. |
*/ |
int init_rd(rd_header * header, size_t size) |
int init_rd(rd_header_t *header, size_t size) |
{ |
/* Identify RAM disk */ |
if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) || |
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3)) |
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3)) |
return RE_INVALID; |
/* Identify version */ |
80,10 → 79,7 |
if ((hsize % FRAME_SIZE) || (dsize % FRAME_SIZE)) |
return RE_UNSUPPORTED; |
if (dsize % FRAME_SIZE) |
return RE_UNSUPPORTED; |
if (hsize > size) |
return RE_INVALID; |
90,17 → 86,16 |
if ((uint64_t) hsize + dsize > size) |
dsize = size - hsize; |
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), FRAME_SIZE); |
rd_parea.vbase = (uintptr_t) ((void *) header + hsize); |
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), |
FRAME_SIZE); |
rd_parea.frames = SIZE2FRAMES(dsize); |
rd_parea.cacheable = true; |
ddi_parea_register(&rd_parea); |
sysinfo_set_item_val("rd", NULL, true); |
sysinfo_set_item_val("rd.header_size", NULL, hsize); |
sysinfo_set_item_val("rd.size", NULL, dsize); |
sysinfo_set_item_val("rd.address.physical", NULL, (unative_t) |
KA2PA((void *) header + hsize)); |
sysinfo_set_item_val("rd.address.physical", NULL, |
(unative_t) KA2PA((void *) header + hsize)); |
return RE_OK; |
} |
/branches/dd/kernel/generic/src/lib/elf.c |
---|
57,7 → 57,7 |
}; |
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, |
as_t *as); |
as_t *as, int flags); |
static int section_header(elf_section_header_t *entry, elf_header_t *elf, |
as_t *as); |
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, |
67,9 → 67,10 |
* |
* @param header Pointer to ELF header in memory |
* @param as Created and properly mapped address space |
* @param flags A combination of ELD_F_* |
* @return EE_OK on success |
*/ |
unsigned int elf_load(elf_header_t *header, as_t * as) |
unsigned int elf_load(elf_header_t *header, as_t * as, int flags) |
{ |
int i, rc; |
110,7 → 111,7 |
seghdr = &((elf_segment_header_t *)(((uint8_t *) header) + |
header->e_phoff))[i]; |
rc = segment_header(seghdr, header, as); |
rc = segment_header(seghdr, header, as, flags); |
if (rc != EE_OK) |
return rc; |
} |
151,8 → 152,10 |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, |
as_t *as) |
as_t *as, int flags) |
{ |
char *interp; |
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
162,6 → 165,16 |
break; |
case PT_DYNAMIC: |
case PT_INTERP: |
interp = (char *)elf + entry->p_offset; |
/* FIXME */ |
/*if (memcmp((uintptr_t)interp, (uintptr_t)ELF_INTERP_ZSTR, |
ELF_INTERP_ZLEN) != 0) { |
return EE_UNSUPPORTED; |
}*/ |
if ((flags & ELD_F_LOADER) == 0) { |
return EE_LOADER; |
} |
break; |
case PT_SHLIB: |
case PT_NOTE: |
case PT_LOPROC: |
/branches/dd/kernel/generic/src/lib/string.c |
---|
0,0 → 1,170 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Miscellaneous functions. |
*/ |
#include <string.h> |
#include <print.h> |
#include <cpu.h> |
#include <arch/asm.h> |
#include <arch.h> |
#include <console/kconsole.h> |
/** Return number of characters in a string. |
* |
* @param str NULL terminated string. |
* |
* @return Number of characters in str. |
* |
*/ |
size_t strlen(const char *str) |
{ |
int i; |
for (i = 0; str[i]; i++); |
return i; |
} |
/** Compare two NULL terminated strings |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* |
*/ |
int strcmp(const char *src, const char *dst) |
{ |
for (; *src && *dst; src++, dst++) { |
if (*src < *dst) |
return -1; |
if (*src > *dst) |
return 1; |
} |
if (*src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
} |
/** Compare two NULL terminated strings |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths and specified maximal |
* length. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param len Maximal length for comparison. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* |
*/ |
int strncmp(const char *src, const char *dst, size_t len) |
{ |
unsigned int i; |
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) { |
if (*src < *dst) |
return -1; |
if (*src > *dst) |
return 1; |
} |
if (i == len || *src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
} |
/** Copy NULL terminated string. |
* |
* Copy at most 'len' characters from string 'src' to 'dest'. |
* If 'src' is shorter than 'len', '\0' is inserted behind the |
* last copied character. |
* |
* @param src Source string. |
* @param dest Destination buffer. |
* @param len Size of destination buffer. |
* |
*/ |
void strncpy(char *dest, const char *src, size_t len) |
{ |
unsigned int i; |
for (i = 0; i < len; i++) { |
if (!(dest[i] = src[i])) |
return; |
} |
dest[i - 1] = '\0'; |
} |
/** Find first occurence of character in string. |
* |
* @param s String to search. |
* @param i Character to look for. |
* |
* @return Pointer to character in @a s or NULL if not found. |
*/ |
extern char *strchr(const char *s, int i) |
{ |
while (*s != '\0') { |
if (*s == i) |
return (char *) s; |
++s; |
} |
return NULL; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/lib/memstr.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
34,12 → 35,10 |
* @file |
* @brief Memory string operations. |
* |
* This file provides architecture independent functions |
* to manipulate blocks of memory. These functions |
* are optimized as much as generic functions of |
* this type can be. However, architectures are |
* free to provide even more optimized versions of these |
* functions. |
* This file provides architecture independent functions to manipulate blocks of |
* memory. These functions are optimized as much as generic functions of this |
* type can be. However, architectures are free to provide even more optimized |
* versions of these functions. |
*/ |
#include <memstr.h> |
46,93 → 45,119 |
#include <arch/types.h> |
#include <align.h> |
/** Copy block of memory |
/** Copy block of memory. |
* |
* Copy cnt bytes from src address to dst address. |
* The copying is done word-by-word and then byte-by-byte. |
* The source and destination memory areas cannot overlap. |
* Copy cnt bytes from src address to dst address. The copying is done |
* word-by-word and then byte-by-byte. The source and destination memory areas |
* cannot overlap. |
* |
* @param src Origin address to copy from. |
* @param dst Origin address to copy to. |
* @param cnt Number of bytes to copy. |
* @param src Source address to copy from. |
* @param dst Destination address to copy to. |
* @param cnt Number of bytes to copy. |
* |
* @return Destination address. |
*/ |
void *_memcpy(void * dst, const void *src, size_t cnt) |
void *_memcpy(void *dst, const void *src, size_t cnt) |
{ |
unsigned int i, j; |
if (ALIGN_UP((uintptr_t) src, sizeof(unative_t)) != (uintptr_t) src || |
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) { |
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) { |
for (i = 0; i < cnt; i++) |
((uint8_t *) dst)[i] = ((uint8_t *) src)[i]; |
} else { |
for (i = 0; i < cnt/sizeof(unative_t); i++) |
for (i = 0; i < cnt / sizeof(unative_t); i++) |
((unative_t *) dst)[i] = ((unative_t *) src)[i]; |
for (j = 0; j < cnt%sizeof(unative_t); j++) |
((uint8_t *)(((unative_t *) dst) + i))[j] = ((uint8_t *)(((unative_t *) src) + i))[j]; |
for (j = 0; j < cnt % sizeof(unative_t); j++) |
((uint8_t *)(((unative_t *) dst) + i))[j] = |
((uint8_t *)(((unative_t *) src) + i))[j]; |
} |
return (char *) src; |
return (char *) dst; |
} |
/** Fill block of memory |
/** Move memory block with possible overlapping. |
* |
* Fill cnt bytes at dst address with the value x. |
* The filling is done byte-by-byte. |
* Copy cnt bytes from src address to dst address. The source and destination |
* memory areas may overlap. |
* |
* @param dst Origin address to fill. |
* @param cnt Number of bytes to fill. |
* @param x Value to fill. |
* @param src Source address to copy from. |
* @param dst Destination address to copy to. |
* @param cnt Number of bytes to copy. |
* |
* @return Destination address. |
*/ |
void _memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
void *memmove(void *dst, const void *src, size_t n) |
{ |
unsigned int i; |
uint8_t *p = (uint8_t *) dst; |
for (i = 0; i < cnt; i++) |
p[i] = x; |
const uint8_t *sp; |
uint8_t *dp; |
/* Nothing to do? */ |
if (src == dst) |
return dst; |
/* Non-overlapping? */ |
if (dst >= src + n || src >= dst + n) { |
return memcpy(dst, src, n); |
} |
/* Which direction? */ |
if (src > dst) { |
/* Forwards. */ |
sp = src; |
dp = dst; |
while (n-- != 0) |
*dp++ = *sp++; |
} else { |
/* Backwards. */ |
sp = src + (n - 1); |
dp = dst + (n - 1); |
while (n-- != 0) |
*dp-- = *sp--; |
} |
return dst; |
} |
/** Fill block of memory |
* |
* Fill cnt words at dst address with the value x. |
* The filling is done word-by-word. |
* Fill cnt bytes at dst address with the value x. The filling is done |
* byte-by-byte. |
* |
* @param dst Origin address to fill. |
* @param cnt Number of words to fill. |
* @param x Value to fill. |
* @param dst Destination address to fill. |
* @param cnt Number of bytes to fill. |
* @param x Value to fill. |
* |
*/ |
void _memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
void _memsetb(void *dst, size_t cnt, uint8_t x) |
{ |
unsigned int i; |
uint16_t *p = (uint16_t *) dst; |
uint8_t *p = (uint8_t *) dst; |
for (i = 0; i < cnt; i++) |
p[i] = x; |
p[i] = x; |
} |
/** Copy string |
/** Fill block of memory. |
* |
* Copy string from src address to dst address. |
* The copying is done char-by-char until the null |
* character. The source and destination memory areas |
* cannot overlap. |
* Fill cnt words at dst address with the value x. The filling is done |
* word-by-word. |
* |
* @param src Origin string to copy from. |
* @param dst Origin string to copy to. |
* @param dst Destination address to fill. |
* @param cnt Number of words to fill. |
* @param x Value to fill. |
* |
*/ |
char *strcpy(char *dest, const char *src) |
void _memsetw(void *dst, size_t cnt, uint16_t x) |
{ |
char *orig = dest; |
unsigned int i; |
uint16_t *p = (uint16_t *) dst; |
while ((*(dest++) = *(src++))) |
; |
return orig; |
for (i = 0; i < cnt; i++) |
p[i] = x; |
} |
/** @} |
/branches/dd/kernel/generic/src/lib/func.c |
---|
55,8 → 55,6 |
#ifdef CONFIG_DEBUG |
bool rundebugger = false; |
// TODO test_and_set not defined on all arches |
// if (!test_and_set(&haltstate)) |
if (!atomic_get(&haltstate)) { |
atomic_set(&haltstate, 1); |
rundebugger = true; |
66,116 → 64,19 |
#endif |
interrupts_disable(); |
#ifdef CONFIG_DEBUG |
if (rundebugger) { |
printf("\n"); |
kconsole("panic"); /* Run kconsole as a last resort to user */ |
} |
#endif |
#if (defined(CONFIG_DEBUG)) && (defined(CONFIG_KCONSOLE)) |
if (rundebugger) |
kconsole("panic", "\nLast resort kernel console ready\n", false); |
#endif |
if (CPU) |
printf("cpu%d: halted\n", CPU->id); |
printf("cpu%u: halted\n", CPU->id); |
else |
printf("cpu: halted\n"); |
cpu_halt(); |
} |
/** Return number of characters in a string. |
* |
* @param str NULL terminated string. |
* |
* @return Number of characters in str. |
*/ |
size_t strlen(const char *str) |
{ |
int i; |
for (i = 0; str[i]; i++) |
; |
return i; |
} |
/** Compare two NULL terminated strings |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* |
*/ |
int strcmp(const char *src, const char *dst) |
{ |
for (; *src && *dst; src++, dst++) { |
if (*src < *dst) |
return -1; |
if (*src > *dst) |
return 1; |
} |
if (*src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
} |
/** Compare two NULL terminated strings |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths and specified maximal |
* length. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param len Maximal length for comparison. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* |
*/ |
int strncmp(const char *src, const char *dst, size_t len) |
{ |
unsigned int i; |
for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) { |
if (*src < *dst) |
return -1; |
if (*src > *dst) |
return 1; |
} |
if (i == len || *src == *dst) |
return 0; |
if (!*src) |
return -1; |
return 1; |
} |
/** Copy NULL terminated string. |
* |
* Copy at most 'len' characters from string 'src' to 'dest'. |
* If 'src' is shorter than 'len', '\0' is inserted behind the |
* last copied character. |
* |
* @param src Source string. |
* @param dest Destination buffer. |
* @param len Size of destination buffer. |
*/ |
void strncpy(char *dest, const char *src, size_t len) |
{ |
unsigned int i; |
for (i = 0; i < len; i++) { |
if (!(dest[i] = src[i])) |
return; |
} |
dest[i-1] = '\0'; |
} |
/** Convert ascii representation to unative_t |
* |
* Supports 0x for hexa & 0 for octal notation. |
/branches/dd/kernel/generic/src/adt/btree.c |
---|
124,7 → 124,7 |
lnode = leaf_node; |
if (!lnode) { |
if (btree_search(t, key, &lnode)) { |
panic("B-tree %p already contains key %d\n", t, key); |
panic("B-tree %p already contains key %" PRIu64 ".", t, key); |
} |
} |
224,7 → 224,7 |
lnode = leaf_node; |
if (!lnode) { |
if (!btree_search(t, key, &lnode)) { |
panic("B-tree %p does not contain key %d\n", t, key); |
panic("B-tree %p does not contain key %" PRIu64 ".", t, key); |
} |
} |
524,7 → 524,7 |
return; |
} |
} |
panic("node %p does not contain key %d\n", node, key); |
panic("Node %p does not contain key %" PRIu64 ".", node, key); |
} |
/** Remove key and its right subtree pointer from B-tree node. |
551,7 → 551,7 |
return; |
} |
} |
panic("node %p does not contain key %d\n", node, key); |
panic("Node %p does not contain key %" PRIu64 ".", node, key); |
} |
/** Split full B-tree node and insert new key-value-right-subtree triplet. |
693,7 → 693,7 |
if (subtree == node->subtree[i]) |
return i - (int) (right != false); |
} |
panic("node %p does not contain subtree %p\n", node, subtree); |
panic("Node %p does not contain subtree %p.", node, subtree); |
} |
/** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling. |
970,7 → 970,7 |
printf("("); |
for (i = 0; i < node->keys; i++) { |
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); |
if (node->depth && node->subtree[i]) { |
list_append(&node->subtree[i]->bfs_link, &head); |
} |
992,7 → 992,7 |
printf("("); |
for (i = 0; i < node->keys; i++) |
printf("%llu%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); |
printf(")"); |
} |
printf("\n"); |
/branches/dd/kernel/generic/src/adt/avl.c |
---|
43,7 → 43,7 |
* |
* Every node has a pointer to its parent which allows insertion of multiple |
* identical keys into the tree. |
* |
* |
* Be careful when using this tree because of the base atribute which is added |
* to every inserted node key. There is no rule in which order nodes with the |
* same key are visited. |
/branches/dd/kernel/generic/src/adt/hash_table.c |
---|
61,9 → 61,9 |
h->entry = (link_t *) malloc(m * sizeof(link_t), 0); |
if (!h->entry) { |
panic("cannot allocate memory for hash table\n"); |
panic("Cannot allocate memory for hash table."); |
} |
memsetb((uintptr_t) h->entry, m * sizeof(link_t), 0); |
memsetb(h->entry, m * sizeof(link_t), 0); |
for (i = 0; i < m; i++) |
list_initialize(&h->entry[i]); |
/branches/dd/kernel/generic/src/mm/slab.c |
---|
167,19 → 167,19 |
* Allocate frames for slab space and initialize |
* |
*/ |
static slab_t * slab_space_alloc(slab_cache_t *cache, int flags) |
static slab_t *slab_space_alloc(slab_cache_t *cache, int flags) |
{ |
void *data; |
slab_t *slab; |
size_t fsize; |
unsigned int i; |
unsigned int zone = 0; |
count_t zone = 0; |
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone); |
if (!data) { |
return NULL; |
} |
if (! (cache->flags & SLAB_CACHE_SLINSIDE)) { |
if (!(cache->flags & SLAB_CACHE_SLINSIDE)) { |
slab = slab_alloc(slab_extern_cache, flags); |
if (!slab) { |
frame_free(KA2PA(data)); |
200,7 → 200,7 |
slab->cache = cache; |
for (i = 0; i < cache->objects; i++) |
*((int *) (slab->start + i*cache->size)) = i+1; |
*((int *) (slab->start + i*cache->size)) = i + 1; |
atomic_inc(&cache->allocated_slabs); |
return slab; |
239,8 → 239,7 |
* |
* @return Number of freed pages |
*/ |
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, |
slab_t *slab) |
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab) |
{ |
int freed = 0; |
256,7 → 255,7 |
ASSERT(slab->available < cache->objects); |
*((int *)obj) = slab->nextavail; |
slab->nextavail = (obj - slab->start)/cache->size; |
slab->nextavail = (obj - slab->start) / cache->size; |
slab->available++; |
/* Move it to correct list */ |
281,7 → 280,7 |
* |
* @return Object address or null |
*/ |
static void * slab_obj_create(slab_cache_t *cache, int flags) |
static void *slab_obj_create(slab_cache_t *cache, int flags) |
{ |
slab_t *slab; |
void *obj; |
301,7 → 300,8 |
return NULL; |
spinlock_lock(&cache->slablock); |
} else { |
slab = list_get_instance(cache->partial_slabs.next, slab_t, link); |
slab = list_get_instance(cache->partial_slabs.next, slab_t, |
link); |
list_remove(&slab->link); |
} |
obj = slab->start + slab->nextavail * cache->size; |
332,8 → 332,7 |
* |
* @param first If true, return first, else last mag |
*/ |
static slab_magazine_t * get_mag_from_cache(slab_cache_t *cache, |
int first) |
static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, int first) |
{ |
slab_magazine_t *mag = NULL; |
link_t *cur; |
368,8 → 367,7 |
* |
* @return Number of freed pages |
*/ |
static count_t magazine_destroy(slab_cache_t *cache, |
slab_magazine_t *mag) |
static count_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag) |
{ |
unsigned int i; |
count_t frames = 0; |
389,7 → 387,7 |
* |
* Assume cpu_magazine lock is held |
*/ |
static slab_magazine_t * get_full_current_mag(slab_cache_t *cache) |
static slab_magazine_t *get_full_current_mag(slab_cache_t *cache) |
{ |
slab_magazine_t *cmag, *lastmag, *newmag; |
423,7 → 421,7 |
* |
* @return Pointer to object or NULL if not available |
*/ |
static void * magazine_obj_get(slab_cache_t *cache) |
static void *magazine_obj_get(slab_cache_t *cache) |
{ |
slab_magazine_t *mag; |
void *obj; |
458,7 → 456,7 |
* allocate new, exchange last & current |
* |
*/ |
static slab_magazine_t * make_empty_current_mag(slab_cache_t *cache) |
static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache) |
{ |
slab_magazine_t *cmag,*lastmag,*newmag; |
530,7 → 528,8 |
static unsigned int comp_objects(slab_cache_t *cache) |
{ |
if (cache->flags & SLAB_CACHE_SLINSIDE) |
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) / cache->size; |
return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) / |
cache->size; |
else |
return (PAGE_SIZE << cache->order) / cache->size; |
} |
557,28 → 556,25 |
ASSERT(_slab_initialized >= 2); |
cache->mag_cache = malloc(sizeof(slab_mag_cache_t)*config.cpu_count,0); |
cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count, |
0); |
for (i = 0; i < config.cpu_count; i++) { |
memsetb((uintptr_t)&cache->mag_cache[i], |
sizeof(cache->mag_cache[i]), 0); |
spinlock_initialize(&cache->mag_cache[i].lock, "slab_maglock_cpu"); |
memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0); |
spinlock_initialize(&cache->mag_cache[i].lock, |
"slab_maglock_cpu"); |
} |
} |
/** Initialize allocated memory as a slab cache */ |
static void |
_slab_cache_create(slab_cache_t *cache, |
char *name, |
size_t size, |
size_t align, |
int (*constructor)(void *obj, int kmflag), |
int (*destructor)(void *obj), |
int flags) |
_slab_cache_create(slab_cache_t *cache, char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags) |
{ |
int pages; |
ipl_t ipl; |
memsetb((uintptr_t)cache, sizeof(*cache), 0); |
memsetb(cache, sizeof(*cache), 0); |
cache->name = name; |
if (align < sizeof(unative_t)) |
596,7 → 592,7 |
list_initialize(&cache->magazines); |
spinlock_initialize(&cache->slablock, "slab_lock"); |
spinlock_initialize(&cache->maglock, "slab_maglock"); |
if (! (cache->flags & SLAB_CACHE_NOMAGAZINE)) |
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) |
make_magcache(cache); |
/* Compute slab sizes, object counts in slabs etc. */ |
609,7 → 605,7 |
if (pages == 1) |
cache->order = 0; |
else |
cache->order = fnzb(pages-1)+1; |
cache->order = fnzb(pages - 1) + 1; |
while (badness(cache) > SLAB_MAX_BADNESS(cache)) { |
cache->order += 1; |
630,18 → 626,16 |
} |
/** Create slab cache */ |
slab_cache_t * slab_cache_create(char *name, |
size_t size, |
size_t align, |
int (*constructor)(void *obj, int kmflag), |
int (*destructor)(void *obj), |
int flags) |
slab_cache_t * |
slab_cache_create(char *name, size_t size, size_t align, |
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj), |
int flags) |
{ |
slab_cache_t *cache; |
cache = slab_alloc(&slab_cache_cache, 0); |
_slab_cache_create(cache, name, size, align, constructor, destructor, |
flags); |
flags); |
return cache; |
} |
665,7 → 659,7 |
* endless loop |
*/ |
magcount = atomic_get(&cache->magazine_counter); |
while (magcount-- && (mag=get_mag_from_cache(cache,0))) { |
while (magcount-- && (mag=get_mag_from_cache(cache, 0))) { |
frames += magazine_destroy(cache,mag); |
if (!(flags & SLAB_RECLAIM_ALL) && frames) |
break; |
718,8 → 712,8 |
_slab_reclaim(cache, SLAB_RECLAIM_ALL); |
/* All slabs must be empty */ |
if (!list_empty(&cache->full_slabs) \ |
|| !list_empty(&cache->partial_slabs)) |
if (!list_empty(&cache->full_slabs) || |
!list_empty(&cache->partial_slabs)) |
panic("Destroying cache that is not empty."); |
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) |
727,9 → 721,8 |
slab_free(&slab_cache_cache, cache); |
} |
/** Allocate new object from cache - if no flags given, always returns |
memory */ |
void * slab_alloc(slab_cache_t *cache, int flags) |
/** Allocate new object from cache - if no flags given, always returns memory */ |
void *slab_alloc(slab_cache_t *cache, int flags) |
{ |
ipl_t ipl; |
void *result = NULL; |
758,9 → 751,8 |
ipl = interrupts_disable(); |
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) \ |
|| magazine_obj_put(cache, obj)) { |
if ((cache->flags & SLAB_CACHE_NOMAGAZINE) || |
magazine_obj_put(cache, obj)) { |
slab_obj_destroy(cache, obj, slab); |
} |
787,7 → 779,8 |
* memory allocation from interrupts can deadlock. |
*/ |
for (cur = slab_cache_list.next;cur!=&slab_cache_list; cur=cur->next) { |
for (cur = slab_cache_list.next; cur != &slab_cache_list; |
cur = cur->next) { |
cache = list_get_instance(cur, slab_cache_t, link); |
frames += _slab_reclaim(cache, flags); |
} |
801,22 → 794,77 |
/* Print list of slabs */ |
void slab_print_list(void) |
{ |
slab_cache_t *cache; |
link_t *cur; |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&slab_cache_lock); |
printf("slab name size pages obj/pg slabs cached allocated ctl\n"); |
printf("---------------- -------- ------ ------ ------ ------ --------- ---\n"); |
for (cur = slab_cache_list.next; cur != &slab_cache_list; cur = cur->next) { |
int skip = 0; |
printf("slab name size pages obj/pg slabs cached allocated" |
" ctl\n"); |
printf("---------------- -------- ------ ------ ------ ------ ---------" |
" ---\n"); |
while (true) { |
slab_cache_t *cache; |
link_t *cur; |
ipl_t ipl; |
int i; |
/* |
* We must not hold the slab_cache_lock spinlock when printing |
* the statistics. Otherwise we can easily deadlock if the print |
* needs to allocate memory. |
* |
* Therefore, we walk through the slab cache list, skipping some |
* amount of already processed caches during each iteration and |
* gathering statistics about the first unprocessed cache. For |
* the sake of printing the statistics, we realese the |
* slab_cache_lock and reacquire it afterwards. Then the walk |
* starts again. |
* |
* This limits both the efficiency and also accuracy of the |
* obtained statistics. The efficiency is decreased because the |
* time complexity of the algorithm is quadratic instead of |
* linear. The accuracy is impacted because we drop the lock |
* after processing one cache. If there is someone else |
* manipulating the cache list, we might omit an arbitrary |
* number of caches or process one cache multiple times. |
* However, we don't bleed for this algorithm for it is only |
* statistics. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&slab_cache_lock); |
for (i = 0, cur = slab_cache_list.next; |
i < skip && cur != &slab_cache_list; |
i++, cur = cur->next) |
; |
if (cur == &slab_cache_list) { |
spinlock_unlock(&slab_cache_lock); |
interrupts_restore(ipl); |
break; |
} |
skip++; |
cache = list_get_instance(cur, slab_cache_t, link); |
char *name = cache->name; |
uint8_t order = cache->order; |
size_t size = cache->size; |
unsigned int objects = cache->objects; |
long allocated_slabs = atomic_get(&cache->allocated_slabs); |
long cached_objs = atomic_get(&cache->cached_objs); |
long allocated_objs = atomic_get(&cache->allocated_objs); |
int flags = cache->flags; |
printf("%-16s %8zd %6zd %6zd %6zd %6zd %9zd %-3s\n", cache->name, cache->size, (1 << cache->order), cache->objects, atomic_get(&cache->allocated_slabs), atomic_get(&cache->cached_objs), atomic_get(&cache->allocated_objs), cache->flags & SLAB_CACHE_SLINSIDE ? "in" : "out"); |
spinlock_unlock(&slab_cache_lock); |
interrupts_restore(ipl); |
printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n", |
name, size, (1 << order), objects, allocated_slabs, |
cached_objs, allocated_objs, |
flags & SLAB_CACHE_SLINSIDE ? "in" : "out"); |
} |
spinlock_unlock(&slab_cache_lock); |
interrupts_restore(ipl); |
} |
void slab_cache_init(void) |
824,32 → 872,24 |
int i, size; |
/* Initialize magazine cache */ |
_slab_cache_create(&mag_cache, |
"slab_magazine", |
sizeof(slab_magazine_t)+SLAB_MAG_SIZE*sizeof(void*), |
sizeof(uintptr_t), |
NULL, NULL, |
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE); |
_slab_cache_create(&mag_cache, "slab_magazine", |
sizeof(slab_magazine_t) + SLAB_MAG_SIZE * sizeof(void*), |
sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE | |
SLAB_CACHE_SLINSIDE); |
/* Initialize slab_cache cache */ |
_slab_cache_create(&slab_cache_cache, |
"slab_cache", |
sizeof(slab_cache_cache), |
sizeof(uintptr_t), |
NULL, NULL, |
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE); |
_slab_cache_create(&slab_cache_cache, "slab_cache", |
sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL, |
SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE); |
/* Initialize external slab cache */ |
slab_extern_cache = slab_cache_create("slab_extern", |
sizeof(slab_t), |
0, NULL, NULL, |
SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED); |
slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0, |
NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED); |
/* Initialize structures for malloc */ |
for (i=0, size=(1<<SLAB_MIN_MALLOC_W); |
i < (SLAB_MAX_MALLOC_W-SLAB_MIN_MALLOC_W+1); |
i++, size <<= 1) { |
malloc_caches[i] = slab_cache_create(malloc_names[i], |
size, 0, |
NULL,NULL, SLAB_CACHE_MAGDEFERRED); |
for (i = 0, size = (1 << SLAB_MIN_MALLOC_W); |
i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1); |
i++, size <<= 1) { |
malloc_caches[i] = slab_cache_create(malloc_names[i], size, 0, |
NULL, NULL, SLAB_CACHE_MAGDEFERRED); |
} |
#ifdef CONFIG_DEBUG |
_slab_initialized = 1; |
874,9 → 914,11 |
spinlock_lock(&slab_cache_lock); |
for (cur=slab_cache_list.next; cur != &slab_cache_list;cur=cur->next){ |
for (cur = slab_cache_list.next; cur != &slab_cache_list; |
cur = cur->next){ |
s = list_get_instance(cur, slab_cache_t, link); |
if ((s->flags & SLAB_CACHE_MAGDEFERRED) != SLAB_CACHE_MAGDEFERRED) |
if ((s->flags & SLAB_CACHE_MAGDEFERRED) != |
SLAB_CACHE_MAGDEFERRED) |
continue; |
make_magcache(s); |
s->flags &= ~SLAB_CACHE_MAGDEFERRED; |
887,7 → 929,7 |
/**************************************/ |
/* kalloc/kfree functions */ |
void * malloc(unsigned int size, int flags) |
void *malloc(unsigned int size, int flags) |
{ |
ASSERT(_slab_initialized); |
ASSERT(size && size <= (1 << SLAB_MAX_MALLOC_W)); |
900,7 → 942,7 |
return slab_alloc(malloc_caches[idx], flags); |
} |
void * realloc(void *ptr, unsigned int size, int flags) |
void *realloc(void *ptr, unsigned int size, int flags) |
{ |
ASSERT(_slab_initialized); |
ASSERT(size <= (1 << SLAB_MAX_MALLOC_W)); |
/branches/dd/kernel/generic/src/mm/tlb.c |
---|
173,7 → 173,7 |
tlb_invalidate_pages(asid, page, count); |
break; |
default: |
panic("unknown type (%d)\n", type); |
panic("Unknown type (%d).", type); |
break; |
} |
if (type == TLB_INVL_ALL) |
/branches/dd/kernel/generic/src/mm/backend_anon.c |
---|
78,7 → 78,6 |
int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
{ |
uintptr_t frame; |
bool dirty = false; |
if (!as_area_check_access(area, access)) |
return AS_PF_FAULT; |
106,7 → 105,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == |
ALIGN_DOWN(addr, PAGE_SIZE)) { |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base) { |
allocate = false; |
break; |
} |
113,8 → 112,7 |
} |
if (allocate) { |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
/* |
* Insert the address of the newly allocated |
144,8 → 142,7 |
* the different causes |
*/ |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
} |
/* |
155,7 → 152,7 |
*/ |
page_mapping_insert(AS, addr, frame, as_area_get_flags(area)); |
if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1)) |
panic("Could not insert used space.\n"); |
panic("Cannot insert used space."); |
return AS_PF_OK; |
} |
/branches/dd/kernel/generic/src/mm/as.c |
---|
82,7 → 82,6 |
#include <arch/mm/cache.h> |
#endif /* CONFIG_VIRT_IDX_DCACHE */ |
#ifndef __OBJC__ |
/** |
* Each architecture decides what functions will be used to carry out |
* address space operations such as creating or locking page tables. |
93,7 → 92,6 |
* Slab for as_t objects. |
*/ |
static slab_cache_t *as_slab; |
#endif |
/** |
* This lock serializes access to the ASID subsystem. |
113,13 → 111,11 |
/** Kernel address space. */ |
as_t *AS_KERNEL = NULL; |
static int area_flags_to_page_flags(int aflags); |
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va); |
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area); |
static void sh_info_remove_reference(share_info_t *sh_info); |
static int area_flags_to_page_flags(int); |
static as_area_t *find_area_and_lock(as_t *, uintptr_t); |
static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *); |
static void sh_info_remove_reference(share_info_t *); |
#ifndef __OBJC__ |
static int as_constructor(void *obj, int flags) |
{ |
as_t *as = (as_t *) obj; |
126,7 → 122,7 |
int rc; |
link_initialize(&as->inactive_as_with_asid_link); |
mutex_initialize(&as->lock); |
mutex_initialize(&as->lock, MUTEX_PASSIVE); |
rc = as_constructor_arch(as, flags); |
139,7 → 135,6 |
return as_destructor_arch(as); |
} |
#endif |
/** Initialize address space subsystem. */ |
void as_init(void) |
146,33 → 141,29 |
{ |
as_arch_init(); |
#ifndef __OBJC__ |
as_slab = slab_cache_create("as_slab", sizeof(as_t), 0, |
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED); |
#endif |
AS_KERNEL = as_create(FLAG_AS_KERNEL); |
if (!AS_KERNEL) |
panic("can't create kernel address space\n"); |
panic("Cannot create kernel address space."); |
/* Make sure the kernel address space |
* reference count never drops to zero. |
*/ |
atomic_set(&AS_KERNEL->refcount, 1); |
} |
/** Create address space. |
* |
* @param flags Flags that influence way in wich the address space is created. |
* @param flags Flags that influence the way in wich the address space |
* is created. |
*/ |
as_t *as_create(int flags) |
{ |
as_t *as; |
#ifdef __OBJC__ |
as = [as_t new]; |
link_initialize(&as->inactive_as_with_asid_link); |
mutex_initialize(&as->lock); |
(void) as_constructor_arch(as, flags); |
#else |
as = (as_t *) slab_alloc(as_slab, 0); |
#endif |
(void) as_create_arch(as, 0); |
btree_create(&as->as_area_btree); |
189,7 → 180,7 |
#else |
page_table_create(flags); |
#endif |
return as; |
} |
199,6 → 190,8 |
* zero), the address space can be destroyed. |
* |
* We know that we don't hold any spinlock. |
* |
* @param as Address space to be destroyed. |
*/ |
void as_destroy(as_t *as) |
{ |
263,11 → 256,7 |
interrupts_restore(ipl); |
#ifdef __OBJC__ |
[as free]; |
#else |
slab_free(as_slab, as); |
#endif |
} |
/** Create address space area of common attributes. |
274,19 → 263,19 |
* |
* The created address space area is added to the target address space. |
* |
* @param as Target address space. |
* @param flags Flags of the area memory. |
* @param size Size of area. |
* @param base Base address of area. |
* @param attrs Attributes of the area. |
* @param backend Address space area backend. NULL if no backend is used. |
* @param backend_data NULL or a pointer to an array holding two void *. |
* @param as Target address space. |
* @param flags Flags of the area memory. |
* @param size Size of area. |
* @param base Base address of area. |
* @param attrs Attributes of the area. |
* @param backend Address space area backend. NULL if no backend is used. |
* @param backend_data NULL or a pointer to an array holding two void *. |
* |
* @return Address space area on success or NULL on failure. |
* @return Address space area on success or NULL on failure. |
*/ |
as_area_t * |
as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs, |
mem_backend_t *backend, mem_backend_data_t *backend_data) |
mem_backend_t *backend, mem_backend_data_t *backend_data) |
{ |
ipl_t ipl; |
as_area_t *a; |
312,7 → 301,7 |
a = (as_area_t *) malloc(sizeof(as_area_t), 0); |
mutex_initialize(&a->lock); |
mutex_initialize(&a->lock, MUTEX_PASSIVE); |
a->as = as; |
a->flags = flags; |
324,8 → 313,7 |
if (backend_data) |
a->backend_data = *backend_data; |
else |
memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), |
0); |
memsetb(&a->backend_data, sizeof(a->backend_data), 0); |
btree_create(&a->used_space); |
339,13 → 327,14 |
/** Find address space area and change it. |
* |
* @param as Address space. |
* @param address Virtual address belonging to the area to be changed. Must be |
* page-aligned. |
* @param size New size of the virtual memory block starting at address. |
* @param flags Flags influencing the remap operation. Currently unused. |
* @param as Address space. |
* @param address Virtual address belonging to the area to be changed. |
* Must be page-aligned. |
* @param size New size of the virtual memory block starting at |
* address. |
* @param flags Flags influencing the remap operation. Currently unused. |
* |
* @return Zero on success or a value from @ref errno.h otherwise. |
* @return Zero on success or a value from @ref errno.h otherwise. |
*/ |
int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags) |
{ |
400,7 → 389,7 |
if (pages < area->pages) { |
bool cond; |
uintptr_t start_free = area->base + pages*PAGE_SIZE; |
uintptr_t start_free = area->base + pages * PAGE_SIZE; |
/* |
* Shrinking the area. |
410,7 → 399,7 |
/* |
* Start TLB shootdown sequence. |
*/ |
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + |
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base + |
pages * PAGE_SIZE, area->pages - pages); |
/* |
455,8 → 444,8 |
i = (start_free - b) >> PAGE_WIDTH; |
if (!used_space_remove(area, start_free, |
c - i)) |
panic("Could not remove used " |
"space.\n"); |
panic("Cannot remove used " |
"space."); |
} else { |
/* |
* The interval of used space can be |
463,8 → 452,8 |
* completely removed. |
*/ |
if (!used_space_remove(area, b, c)) |
panic("Could not remove used " |
"space.\n"); |
panic("Cannot remove used " |
"space."); |
} |
for (; i < c; i++) { |
526,10 → 515,10 |
/** Destroy address space area. |
* |
* @param as Address space. |
* @param address Address withing the area to be deleted. |
* @param as Address space. |
* @param address Address within the area to be deleted. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int as_area_destroy(as_t *as, uintptr_t address) |
{ |
626,18 → 615,19 |
* sh_info of the source area. The process of duplicating the |
* mapping is done through the backend share function. |
* |
* @param src_as Pointer to source address space. |
* @param src_base Base address of the source address space area. |
* @param acc_size Expected size of the source area. |
* @param dst_as Pointer to destination address space. |
* @param dst_base Target base address. |
* @param src_as Pointer to source address space. |
* @param src_base Base address of the source address space area. |
* @param acc_size Expected size of the source area. |
* @param dst_as Pointer to destination address space. |
* @param dst_base Target base address. |
* @param dst_flags_mask Destination address space area flags mask. |
* |
* @return Zero on success or ENOENT if there is no such task or if there is no |
* such address space area, EPERM if there was a problem in accepting the area |
* or ENOMEM if there was a problem in allocating destination address space |
* area. ENOTSUP is returned if the address space area backend does not support |
* sharing. |
* @return Zero on success or ENOENT if there is no such task or if |
* there is no such address space area, EPERM if there was |
* a problem in accepting the area or ENOMEM if there was a |
* problem in allocating destination address space area. |
* ENOTSUP is returned if the address space area backend |
* does not support sharing. |
*/ |
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
698,7 → 688,7 |
sh_info = src_area->sh_info; |
if (!sh_info) { |
sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0); |
mutex_initialize(&sh_info->lock); |
mutex_initialize(&sh_info->lock, MUTEX_PASSIVE); |
sh_info->refcount = 2; |
btree_create(&sh_info->pagemap); |
src_area->sh_info = sh_info; |
756,10 → 746,11 |
* |
* The address space area must be locked prior to this call. |
* |
* @param area Address space area. |
* @param access Access mode. |
* @param area Address space area. |
* @param access Access mode. |
* |
* @return False if access violates area's permissions, true otherwise. |
* @return False if access violates area's permissions, true |
* otherwise. |
*/ |
bool as_area_check_access(as_area_t *area, pf_access_t access) |
{ |
775,21 → 766,183 |
return true; |
} |
/** Change adress space area flags. |
* |
* The idea is to have the same data, but with a different access mode. |
* This is needed e.g. for writing code into memory and then executing it. |
* In order for this to work properly, this may copy the data |
* into private anonymous memory (unless it's already there). |
* |
* @param as Address space. |
* @param flags Flags of the area memory. |
* @param address Address within the area to be changed. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
* |
*/ |
int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
{ |
as_area_t *area; |
uintptr_t base; |
link_t *cur; |
ipl_t ipl; |
int page_flags; |
uintptr_t *old_frame; |
index_t frame_idx; |
count_t used_pages; |
/* Flags for the new memory mapping */ |
page_flags = area_flags_to_page_flags(flags); |
ipl = interrupts_disable(); |
mutex_lock(&as->lock); |
area = find_area_and_lock(as, address); |
if (!area) { |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
if ((area->sh_info) || (area->backend != &anon_backend)) { |
/* Copying shared areas not supported yet */ |
/* Copying non-anonymous memory not supported yet */ |
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOTSUP; |
} |
base = area->base; |
/* |
* Compute total number of used pages in the used_space B+tree |
*/ |
used_pages = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
used_pages += (count_t) node->value[i]; |
} |
} |
/* An array for storing frame numbers */ |
old_frame = malloc(used_pages * sizeof(uintptr_t), 0); |
/* |
* Start TLB shootdown sequence. |
*/ |
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
/* |
* Remove used pages from page tables and remember their frame |
* numbers. |
*/ |
frame_idx = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t b = node->key[i]; |
count_t j; |
pte_t *pte; |
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
pte = page_mapping_find(as, b + j * PAGE_SIZE); |
ASSERT(pte && PTE_VALID(pte) && |
PTE_PRESENT(pte)); |
old_frame[frame_idx++] = PTE_GET_FRAME(pte); |
/* Remove old mapping */ |
page_mapping_remove(as, b + j * PAGE_SIZE); |
page_table_unlock(as, false); |
} |
} |
} |
/* |
* Finish TLB shootdown sequence. |
*/ |
tlb_invalidate_pages(as->asid, area->base, area->pages); |
/* |
* Invalidate potential software translation caches (e.g. TSB on |
* sparc64). |
*/ |
as_invalidate_translation_cache(as, area->base, area->pages); |
tlb_shootdown_finalize(); |
/* |
* Set the new flags. |
*/ |
area->flags = flags; |
/* |
* Map pages back in with new flags. This step is kept separate |
* so that the memory area could not be accesed with both the old and |
* the new flags at once. |
*/ |
frame_idx = 0; |
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t b = node->key[i]; |
count_t j; |
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
/* Insert the new mapping */ |
page_mapping_insert(as, b + j * PAGE_SIZE, |
old_frame[frame_idx++], page_flags); |
page_table_unlock(as, false); |
} |
} |
} |
free(old_frame); |
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return 0; |
} |
/** Handle page fault within the current address space. |
* |
* This is the high-level page fault handler. It decides |
* whether the page fault can be resolved by any backend |
* and if so, it invokes the backend to resolve the page |
* fault. |
* This is the high-level page fault handler. It decides whether the page fault |
* can be resolved by any backend and if so, it invokes the backend to resolve |
* the page fault. |
* |
* Interrupts are assumed disabled. |
* |
* @param page Faulting page. |
* @param access Access mode that caused the fault (i.e. read/write/exec). |
* @param istate Pointer to interrupted state. |
* @param page Faulting page. |
* @param access Access mode that caused the page fault (i.e. |
* read/write/exec). |
* @param istate Pointer to the interrupted state. |
* |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
* fault was caused by copy_to_uspace() or copy_from_uspace(). |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or |
* AS_PF_DEFER if the fault was caused by copy_to_uspace() |
* or copy_from_uspace(). |
*/ |
int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) |
{ |
835,9 → 988,8 |
page_table_lock(AS, false); |
/* |
* To avoid race condition between two page faults |
* on the same address, we need to make sure |
* the mapping has not been already inserted. |
* To avoid race condition between two page faults on the same address, |
* we need to make sure the mapping has not been already inserted. |
*/ |
if ((pte = page_mapping_find(AS, page))) { |
if (PTE_PRESENT(pte)) { |
891,8 → 1043,8 |
* |
* When this function is enetered, no spinlocks may be held. |
* |
* @param old Old address space or NULL. |
* @param new New address space. |
* @param old Old address space or NULL. |
* @param new New address space. |
*/ |
void as_switch(as_t *old_as, as_t *new_as) |
{ |
963,9 → 1115,9 |
/** Convert address space area flags to page flags. |
* |
* @param aflags Flags of some address space area. |
* @param aflags Flags of some address space area. |
* |
* @return Flags to be passed to page_mapping_insert(). |
* @return Flags to be passed to page_mapping_insert(). |
*/ |
int area_flags_to_page_flags(int aflags) |
{ |
993,9 → 1145,9 |
* The address space area must be locked. |
* Interrupts must be disabled. |
* |
* @param a Address space area. |
* @param a Address space area. |
* |
* @return Flags to be used in page_mapping_insert(). |
* @return Flags to be used in page_mapping_insert(). |
*/ |
int as_area_get_flags(as_area_t *a) |
{ |
1004,23 → 1156,20 |
/** Create page table. |
* |
* Depending on architecture, create either address space |
* private or global page table. |
* Depending on architecture, create either address space private or global page |
* table. |
* |
* @param flags Flags saying whether the page table is for kernel address space. |
* @param flags Flags saying whether the page table is for the kernel |
* address space. |
* |
* @return First entry of the page table. |
* @return First entry of the page table. |
*/ |
pte_t *page_table_create(int flags) |
{ |
#ifdef __OBJC__ |
return [as_t page_table_create: flags]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_create); |
return as_operations->page_table_create(flags); |
#endif |
} |
/** Destroy page table. |
1027,18 → 1176,14 |
* |
* Destroy page table in architecture specific way. |
* |
* @param page_table Physical address of PTL0. |
* @param page_table Physical address of PTL0. |
*/ |
void page_table_destroy(pte_t *page_table) |
{ |
#ifdef __OBJC__ |
return [as_t page_table_destroy: page_table]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_destroy); |
as_operations->page_table_destroy(page_table); |
#endif |
} |
/** Lock page table. |
1050,36 → 1195,28 |
* prior to this call. Address space can be locked prior to this |
* call in which case the lock argument is false. |
* |
* @param as Address space. |
* @param lock If false, do not attempt to lock as->lock. |
* @param as Address space. |
* @param lock If false, do not attempt to lock as->lock. |
*/ |
void page_table_lock(as_t *as, bool lock) |
{ |
#ifdef __OBJC__ |
[as page_table_lock: lock]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_lock); |
as_operations->page_table_lock(as, lock); |
#endif |
} |
/** Unlock page table. |
* |
* @param as Address space. |
* @param unlock If false, do not attempt to unlock as->lock. |
* @param as Address space. |
* @param unlock If false, do not attempt to unlock as->lock. |
*/ |
void page_table_unlock(as_t *as, bool unlock) |
{ |
#ifdef __OBJC__ |
[as page_table_unlock: unlock]; |
#else |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_unlock); |
as_operations->page_table_unlock(as, unlock); |
#endif |
} |
1087,11 → 1224,11 |
* |
* The address space must be locked and interrupts must be disabled. |
* |
* @param as Address space. |
* @param va Virtual address. |
* @param as Address space. |
* @param va Virtual address. |
* |
* @return Locked address space area containing va on success or NULL on |
* failure. |
* @return Locked address space area containing va on success or |
* NULL on failure. |
*/ |
as_area_t *find_area_and_lock(as_t *as, uintptr_t va) |
{ |
1143,15 → 1280,15 |
* |
* The address space must be locked and interrupts must be disabled. |
* |
* @param as Address space. |
* @param va Starting virtual address of the area being tested. |
* @param size Size of the area being tested. |
* @param avoid_area Do not touch this area. |
* @param as Address space. |
* @param va Starting virtual address of the area being tested. |
* @param size Size of the area being tested. |
* @param avoid_area Do not touch this area. |
* |
* @return True if there is no conflict, false otherwise. |
* @return True if there is no conflict, false otherwise. |
*/ |
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area) |
bool |
check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area) |
{ |
as_area_t *a; |
btree_node_t *leaf, *node; |
1240,7 → 1377,7 |
ipl = interrupts_disable(); |
src_area = find_area_and_lock(AS, base); |
if (src_area){ |
if (src_area) { |
size = src_area->pages * PAGE_SIZE; |
mutex_unlock(&src_area->lock); |
} else { |
1254,11 → 1391,11 |
* |
* The address space area must be already locked. |
* |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return 0 on failure and 1 on success. |
* @return Zero on failure and non-zero on success. |
*/ |
int used_space_insert(as_area_t *a, uintptr_t page, count_t count) |
{ |
1528,8 → 1665,8 |
} |
} |
panic("Inconsistency detected while adding %d pages of used space at " |
"%p.\n", count, page); |
panic("Inconsistency detected while adding %" PRIc " pages of used " |
"space at %p.", count, page); |
} |
/** Mark portion of address space area as unused. |
1536,11 → 1673,11 |
* |
* The address space area must be already locked. |
* |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return 0 on failure and 1 on success. |
* @return Zero on failure and non-zero on success. |
*/ |
int used_space_remove(as_area_t *a, uintptr_t page, count_t count) |
{ |
1707,8 → 1844,8 |
} |
error: |
panic("Inconsistency detected while removing %d pages of used space " |
"from %p.\n", count, page); |
panic("Inconsistency detected while removing %" PRIc " pages of used " |
"space from %p.", count, page); |
} |
/** Remove reference to address space area share info. |
1715,7 → 1852,7 |
* |
* If the reference count drops to 0, the sh_info is deallocated. |
* |
* @param sh_info Pointer to address space area share info. |
* @param sh_info Pointer to address space area share info. |
*/ |
void sh_info_remove_reference(share_info_t *sh_info) |
{ |
1770,6 → 1907,12 |
return (unative_t) as_area_resize(AS, address, size, 0); |
} |
/** Wrapper for as_area_change_flags(). */ |
unative_t sys_as_area_change_flags(uintptr_t address, int flags) |
{ |
return (unative_t) as_area_change_flags(AS, flags, address); |
} |
/** Wrapper for as_area_destroy(). */ |
unative_t sys_as_area_destroy(uintptr_t address) |
{ |
1778,7 → 1921,7 |
/** Print out information about address space. |
* |
* @param as Address space. |
* @param as Address space. |
*/ |
void as_print(as_t *as) |
{ |
1800,9 → 1943,9 |
as_area_t *area = node->value[i]; |
mutex_lock(&area->lock); |
printf("as_area: %p, base=%p, pages=%d (%p - %p)\n", |
area, area->base, area->pages, area->base, |
area->base + area->pages*PAGE_SIZE); |
printf("as_area: %p, base=%p, pages=%" PRIc |
" (%p - %p)\n", area, area->base, area->pages, |
area->base, area->base + FRAMES2SIZE(area->pages)); |
mutex_unlock(&area->lock); |
} |
} |
/branches/dd/kernel/generic/src/mm/buddy.c |
---|
35,8 → 35,7 |
* @brief Buddy allocator framework. |
* |
* This file contains buddy system allocator framework. |
* Specialized functions are needed for this abstract framework |
* to be useful. |
* Specialized functions are needed for this abstract framework to be useful. |
*/ |
#include <mm/buddy.h> |
44,29 → 43,29 |
#include <arch/types.h> |
#include <debug.h> |
#include <print.h> |
#include <macros.h> |
/** Return size needed for the buddy configuration data */ |
size_t buddy_conf_size(int max_order) |
/** Return size needed for the buddy configuration data. */ |
size_t buddy_conf_size(size_t max_order) |
{ |
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t); |
} |
/** Create buddy system |
/** Create buddy system. |
* |
* Allocate memory for and initialize new buddy system. |
* |
* @param b Preallocated buddy system control data. |
* @param max_order The biggest allocable size will be 2^max_order. |
* @param op Operations for new buddy system. |
* @param data Pointer to be used by implementation. |
* @param b Preallocated buddy system control data. |
* @param max_order The biggest allocable size will be 2^max_order. |
* @param op Operations for new buddy system. |
* @param data Pointer to be used by implementation. |
* |
* @return New buddy system. |
* @return New buddy system. |
*/ |
void buddy_system_create(buddy_system_t *b, |
uint8_t max_order, |
buddy_system_operations_t *op, |
void *data) |
void |
buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data) |
{ |
int i; |
80,7 → 79,7 |
ASSERT(op->mark_busy); |
/* |
* Use memory after our own structure |
* Use memory after our own structure. |
*/ |
b->order = (link_t *) (&b[1]); |
92,14 → 91,15 |
b->data = data; |
} |
/** Check if buddy system can allocate block |
/** Check if buddy system can allocate block. |
* |
* @param b Buddy system pointer |
* @param i Size of the block (2^i) |
* @param b Buddy system pointer. |
* @param i Size of the block (2^i). |
* |
* @return True if block can be allocated |
* @return True if block can be allocated. |
*/ |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) { |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) |
{ |
uint8_t k; |
/* |
106,12 → 106,13 |
* If requested block is greater then maximal block |
* we know immediatly that we cannot satisfy the request. |
*/ |
if (i > b->max_order) return false; |
if (i > b->max_order) |
return false; |
/* |
* Check if any bigger or equal order has free elements |
*/ |
for (k=i; k <= b->max_order; k++) { |
for (k = i; k <= b->max_order; k++) { |
if (!list_empty(&b->order[k])) { |
return true; |
} |
118,12 → 119,11 |
} |
return false; |
} |
/** Allocate PARTICULAR block from buddy system |
/** Allocate PARTICULAR block from buddy system. |
* |
* @ return Block of data or NULL if no such block was found |
* @return Block of data or NULL if no such block was found. |
*/ |
link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block) |
{ |
134,7 → 134,7 |
ASSERT(left); |
list_remove(left); |
while (1) { |
if (! b->op->get_order(b,left)) { |
if (!b->op->get_order(b, left)) { |
b->op->mark_busy(b, left); |
return left; |
} |
142,8 → 142,8 |
order = b->op->get_order(b, left); |
right = b->op->bisect(b, left); |
b->op->set_order(b, left, order-1); |
b->op->set_order(b, right, order-1); |
b->op->set_order(b, left, order - 1); |
b->op->set_order(b, right, order - 1); |
tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK); |
160,10 → 160,10 |
/** Allocate block from buddy system. |
* |
* @param b Buddy system pointer. |
* @param i Returned block will be 2^i big. |
* @param b Buddy system pointer. |
* @param i Returned block will be 2^i big. |
* |
* @return Block of data represented by link_t. |
* @return Block of data represented by link_t. |
*/ |
link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i) |
{ |
217,13 → 217,12 |
buddy_system_free(b, hlp); |
return res; |
} |
/** Return block to buddy system. |
* |
* @param b Buddy system pointer. |
* @param block Block to return. |
* @param b Buddy system pointer. |
* @param block Block to return. |
*/ |
void buddy_system_free(buddy_system_t *b, link_t *block) |
{ |
267,7 → 266,8 |
b->op->set_order(b, hlp, i + 1); |
/* |
* Recursively add the coalesced block to the list of order i + 1. |
* Recursively add the coalesced block to the list of |
* order i + 1. |
*/ |
buddy_system_free(b, hlp); |
return; |
278,46 → 278,7 |
* Insert block into the list of order i. |
*/ |
list_append(block, &b->order[i]); |
} |
/** Prints out structure of buddy system |
* |
* @param b Pointer to buddy system |
* @param elem_size Element size |
*/ |
void buddy_system_structure_print(buddy_system_t *b, size_t elem_size) { |
index_t i; |
count_t cnt, elem_count = 0, block_count = 0; |
link_t * cur; |
printf("Order\tBlocks\tSize \tBlock size\tElems per block\n"); |
printf("-----\t------\t--------\t----------\t---------------\n"); |
for (i=0;i <= b->max_order; i++) { |
cnt = 0; |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) |
cnt++; |
} |
printf("#%zd\t%5zd\t%7zdK\t%8zdK\t%6zd\t", i, cnt, (cnt * (1 << i) * elem_size) >> 10, ((1 << i) * elem_size) >> 10, 1 << i); |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) { |
b->op->print_id(b, cur); |
printf(" "); |
} |
} |
printf("\n"); |
block_count += cnt; |
elem_count += (1 << i) * cnt; |
} |
printf("-----\t------\t--------\t----------\t---------------\n"); |
printf("Buddy system contains %zd free elements (%zd blocks)\n" , elem_count, block_count); |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/mm/backend_phys.c |
---|
77,7 → 77,7 |
page_mapping_insert(AS, addr, base + (addr - area->base), |
as_area_get_flags(area)); |
if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1)) |
panic("Could not insert used space.\n"); |
panic("Cannot insert used space."); |
return AS_PF_OK; |
} |
/branches/dd/kernel/generic/src/mm/frame.c |
---|
1,6 → 1,7 |
/* |
* Copyright (c) 2001-2005 Jakub Jermar |
* Copyright (c) 2005 Sergey Bondari |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
33,7 → 34,7 |
/** |
* @file |
* @brief Physical frame allocator. |
* @brief Physical frame allocator. |
* |
* This file contains the physical frame allocator and memory zone management. |
* The frame allocator is built on top of the buddy allocator. |
41,16 → 42,6 |
* @see buddy.c |
*/ |
/* |
* Locking order |
* |
* In order to access particular zone, the process must first lock |
* the zones.lock, then lock the zone and then unlock the zones.lock. |
* This insures, that we can fiddle with the zones in runtime without |
* affecting the processes. |
* |
*/ |
#include <arch/types.h> |
#include <mm/frame.h> |
#include <mm/as.h> |
57,7 → 48,8 |
#include <panic.h> |
#include <debug.h> |
#include <adt/list.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <synch/condvar.h> |
#include <arch/asm.h> |
#include <arch.h> |
#include <print.h> |
67,43 → 59,17 |
#include <macros.h> |
#include <config.h> |
typedef struct { |
count_t refcount; /**< tracking of shared frames */ |
uint8_t buddy_order; /**< buddy system block order */ |
link_t buddy_link; /**< link to the next free block inside one |
order */ |
void *parent; /**< If allocated by slab, this points there */ |
} frame_t; |
zones_t zones; |
typedef struct { |
SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ |
pfn_t base; /**< frame_no of the first frame in the frames |
array */ |
count_t count; /**< Size of zone */ |
frame_t *frames; /**< array of frame_t structures in this |
zone */ |
count_t free_count; /**< number of free frame_t structures */ |
count_t busy_count; /**< number of busy frame_t structures */ |
buddy_system_t *buddy_system; /**< buddy system for the zone */ |
int flags; |
} zone_t; |
/* |
* The zoneinfo.lock must be locked when accessing zoneinfo structure. |
* Some of the attributes in zone_t structures are 'read-only' |
* Synchronization primitives used to sleep when there is no memory |
* available. |
*/ |
mutex_t mem_avail_mtx; |
condvar_t mem_avail_cv; |
count_t mem_avail_req = 0; /**< Number of frames requested. */ |
count_t mem_avail_gen = 0; /**< Generation counter. */ |
typedef struct { |
SPINLOCK_DECLARE(lock); |
unsigned int count; |
zone_t *info[ZONES_MAX]; |
} zones_t; |
static zones_t zones; |
/********************/ |
/* Helper functions */ |
/********************/ |
118,22 → 84,20 |
return (index_t) (frame - zone->frames) + zone->base; |
} |
static inline int frame_index_valid(zone_t *zone, index_t index) |
static inline bool frame_index_valid(zone_t *zone, index_t index) |
{ |
return (index < zone->count); |
} |
/** Compute pfn_t from frame_t pointer & zone pointer */ |
static index_t make_frame_index(zone_t *zone, frame_t *frame) |
static inline index_t make_frame_index(zone_t *zone, frame_t *frame) |
{ |
return (frame - zone->frames); |
} |
/** Initialize frame structure |
/** Initialize frame structure. |
* |
* Initialize frame structure. |
* @param frame Frame structure to be initialized. |
* |
* @param frame Frame structure to be initialized. |
*/ |
static void frame_initialize(frame_t *frame) |
{ |
141,142 → 105,145 |
frame->buddy_order = 0; |
} |
/**********************/ |
/* Zoneinfo functions */ |
/**********************/ |
/*******************/ |
/* Zones functions */ |
/*******************/ |
/** |
* Insert-sort zone into zones list |
/** Insert-sort zone into zones list. |
* |
* @param newzone New zone to be inserted into zone list |
* @return zone number on success, -1 on error |
* Assume interrupts are disabled and zones lock is |
* locked. |
* |
* @param base Base frame of the newly inserted zone. |
* @param count Number of frames of the newly inserted zone. |
* |
* @return Zone number on success, -1 on error. |
* |
*/ |
static int zones_add_zone(zone_t *newzone) |
static count_t zones_insert_zone(pfn_t base, count_t count) |
{ |
unsigned int i, j; |
ipl_t ipl; |
zone_t *z; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
/* Try to merge */ |
if (zones.count + 1 == ZONES_MAX) { |
printf("Maximum zone count %u exceeded!\n", ZONES_MAX); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return -1; |
return (count_t) -1; |
} |
count_t i; |
for (i = 0; i < zones.count; i++) { |
/* Check for overflow */ |
z = zones.info[i]; |
if (overlaps(newzone->base, newzone->count, z->base, z->count)) { |
/* Check for overlap */ |
if (overlaps(base, count, |
zones.info[i].base, zones.info[i].count)) { |
printf("Zones overlap!\n"); |
return -1; |
return (count_t) -1; |
} |
if (newzone->base < z->base) |
if (base < zones.info[i].base) |
break; |
} |
/* Move other zones up */ |
for (j = i; j < zones.count; j++) |
zones.info[j + 1] = zones.info[j]; |
count_t j; |
for (j = zones.count; j > i; j--) { |
zones.info[j] = zones.info[j - 1]; |
zones.info[j].buddy_system->data = |
(void *) &zones.info[j - 1]; |
} |
zones.info[i] = newzone; |
zones.count++; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return i; |
} |
/** |
* Try to find a zone where can we find the frame |
/** Get total available frames. |
* |
* Assume interrupts are disabled. |
* Assume interrupts are disabled and zones lock is |
* locked. |
* |
* @param frame Frame number contained in zone |
* @param pzone If not null, it is used as zone hint. Zone index |
* is filled into the variable on success. |
* @return Pointer to locked zone containing frame |
* @return Total number of available frames. |
* |
*/ |
static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone) |
#ifdef CONFIG_DEBUG |
static count_t total_frames_free(void) |
{ |
unsigned int i; |
unsigned int hint = pzone ? *pzone : 0; |
zone_t *z; |
count_t total = 0; |
count_t i; |
for (i = 0; i < zones.count; i++) |
total += zones.info[i].free_count; |
spinlock_lock(&zones.lock); |
return total; |
} |
#endif |
/** Find a zone with a given frames. |
* |
* Assume interrupts are disabled and zones lock is |
* locked. |
* |
* @param frame Frame number contained in zone. |
* @param count Number of frames to look for. |
* @param hint Used as zone hint. |
* |
* @return Zone index or -1 if not found. |
* |
*/ |
count_t find_zone(pfn_t frame, count_t count, count_t hint) |
{ |
if (hint >= zones.count) |
hint = 0; |
i = hint; |
count_t i = hint; |
do { |
z = zones.info[i]; |
spinlock_lock(&z->lock); |
if (z->base <= frame && z->base + z->count > frame) { |
/* Unlock the global lock */ |
spinlock_unlock(&zones.lock); |
if (pzone) |
*pzone = i; |
return z; |
} |
spinlock_unlock(&z->lock); |
if ((zones.info[i].base <= frame) |
&& (zones.info[i].base + zones.info[i].count >= frame + count)) |
return i; |
i++; |
if (i >= zones.count) |
i = 0; |
} while(i != hint); |
spinlock_unlock(&zones.lock); |
return NULL; |
} while (i != hint); |
return (count_t) -1; |
} |
/** @return True if zone can allocate specified order */ |
static int zone_can_alloc(zone_t *z, uint8_t order) |
static bool zone_can_alloc(zone_t *zone, uint8_t order) |
{ |
return buddy_system_can_alloc(z->buddy_system, order); |
return (zone_flags_available(zone->flags) |
&& buddy_system_can_alloc(zone->buddy_system, order)); |
} |
/** Find and lock zone that can allocate order frames. |
/** Find a zone that can allocate order frames. |
* |
* Assume interrupts are disabled. |
* Assume interrupts are disabled and zones lock is |
* locked. |
* |
* @param order Size (2^order) of free space we are trying to find |
* @param pzone Pointer to preferred zone or NULL, on return contains zone |
* number |
* @param order Size (2^order) of free space we are trying to find. |
* @param flags Required flags of the target zone. |
* @param hind Preferred zone. |
* |
*/ |
static zone_t * find_free_zone_and_lock(uint8_t order, unsigned int *pzone) |
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint) |
{ |
unsigned int i; |
zone_t *z; |
unsigned int hint = pzone ? *pzone : 0; |
spinlock_lock(&zones.lock); |
if (hint >= zones.count) |
hint = 0; |
i = hint; |
count_t i = hint; |
do { |
z = zones.info[i]; |
/* |
* Check whether the zone meets the search criteria. |
*/ |
if ((zones.info[i].flags & flags) == flags) { |
/* |
* Check if the zone has 2^order frames area available. |
*/ |
if (zone_can_alloc(&zones.info[i], order)) |
return i; |
} |
spinlock_lock(&z->lock); |
/* Check if the zone has 2^order frames area available */ |
if (zone_can_alloc(z, order)) { |
spinlock_unlock(&zones.lock); |
if (pzone) |
*pzone = i; |
return z; |
} |
spinlock_unlock(&z->lock); |
if (++i >= zones.count) |
i++; |
if (i >= zones.count) |
i = 0; |
} while(i != hint); |
spinlock_unlock(&zones.lock); |
return NULL; |
} while (i != hint); |
return (count_t) -1; |
} |
/**************************/ |
283,167 → 250,146 |
/* Buddy system functions */ |
/**************************/ |
/** Buddy system find_block implementation |
/** Buddy system find_block implementation. |
* |
* Find block that is parent of current list. |
* That means go to lower addresses, until such block is found |
* |
* @param order - Order of parent must be different then this parameter!! |
* @param order Order of parent must be different then this |
* parameter!! |
* |
*/ |
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, |
static link_t *zone_buddy_find_block(buddy_system_t *buddy, link_t *child, |
uint8_t order) |
{ |
frame_t *frame; |
zone_t *zone; |
index_t index; |
frame_t *frame = list_get_instance(child, frame_t, buddy_link); |
zone_t *zone = (zone_t *) buddy->data; |
frame = list_get_instance(child, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
index = frame_index(zone, frame); |
index_t index = frame_index(zone, frame); |
do { |
if (zone->frames[index].buddy_order != order) { |
if (zone->frames[index].buddy_order != order) |
return &zone->frames[index].buddy_link; |
} |
} while(index-- > 0); |
} while (index-- > 0); |
return NULL; |
} |
static void zone_buddy_print_id(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame; |
zone_t *zone; |
index_t index; |
frame = list_get_instance(block, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
index = frame_index(zone, frame); |
printf("%zd", index); |
} |
/** Buddy system find_buddy implementation |
/** Buddy system find_buddy implementation. |
* |
* @param b Buddy system. |
* @param block Block for which buddy should be found |
* @param buddy Buddy system. |
* @param block Block for which buddy should be found. |
* |
* @return Buddy for given block if found |
* @return Buddy for given block if found. |
* |
*/ |
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block) |
static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, link_t *block) |
{ |
frame_t *frame; |
zone_t *zone; |
index_t index; |
bool is_left, is_right; |
frame = list_get_instance(block, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
frame_t *frame = list_get_instance(block, frame_t, buddy_link); |
zone_t *zone = (zone_t *) buddy->data; |
ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), |
frame->buddy_order)); |
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); |
ASSERT(is_left ^ is_right); |
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
index_t index; |
if (is_left) { |
index = (frame_index(zone, frame)) + (1 << frame->buddy_order); |
} else { /* if (is_right) */ |
index = (frame_index(zone, frame)) - (1 << frame->buddy_order); |
index = (frame_index(zone, frame)) + |
(1 << frame->buddy_order); |
} else { /* is_right */ |
index = (frame_index(zone, frame)) - |
(1 << frame->buddy_order); |
} |
if (frame_index_valid(zone, index)) { |
if (zone->frames[index].buddy_order == frame->buddy_order && |
zone->frames[index].refcount == 0) { |
if ((zone->frames[index].buddy_order == frame->buddy_order) && |
(zone->frames[index].refcount == 0)) { |
return &zone->frames[index].buddy_link; |
} |
} |
return NULL; |
return NULL; |
} |
/** Buddy system bisect implementation |
/** Buddy system bisect implementation. |
* |
* @param b Buddy system. |
* @param block Block to bisect |
* @param buddy Buddy system. |
* @param block Block to bisect. |
* |
* @return right block |
* @return Right block. |
* |
*/ |
static link_t * zone_buddy_bisect(buddy_system_t *b, link_t *block) { |
frame_t *frame_l, *frame_r; |
frame_l = list_get_instance(block, frame_t, buddy_link); |
frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block) |
{ |
frame_t *frame_l = list_get_instance(block, frame_t, buddy_link); |
frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
return &frame_r->buddy_link; |
} |
/** Buddy system coalesce implementation |
/** Buddy system coalesce implementation. |
* |
* @param b Buddy system. |
* @param block_1 First block |
* @param block_2 First block's buddy |
* @param buddy Buddy system. |
* @param block_1 First block. |
* @param block_2 First block's buddy. |
* |
* @return Coalesced block (actually block that represents lower address) |
* @return Coalesced block (actually block that represents lower |
* address). |
* |
*/ |
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1, |
link_t *block_2) |
static link_t *zone_buddy_coalesce(buddy_system_t *buddy, link_t *block_1, |
link_t *block_2) |
{ |
frame_t *frame1, *frame2; |
frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link); |
frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link); |
frame1 = list_get_instance(block_1, frame_t, buddy_link); |
frame2 = list_get_instance(block_2, frame_t, buddy_link); |
return frame1 < frame2 ? block_1 : block_2; |
return ((frame1 < frame2) ? block_1 : block_2); |
} |
/** Buddy system set_order implementation |
/** Buddy system set_order implementation. |
* |
* @param b Buddy system. |
* @param block Buddy system block |
* @param order Order to set |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* @param order Order to set. |
* |
*/ |
static void zone_buddy_set_order(buddy_system_t *b, link_t *block, |
uint8_t order) { |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->buddy_order = order; |
static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block, |
uint8_t order) |
{ |
list_get_instance(block, frame_t, buddy_link)->buddy_order = order; |
} |
/** Buddy system get_order implementation |
/** Buddy system get_order implementation. |
* |
* @param b Buddy system. |
* @param block Buddy system block |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* |
* @return Order of block |
* @return Order of block. |
* |
*/ |
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) { |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
return frame->buddy_order; |
static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block) |
{ |
return list_get_instance(block, frame_t, buddy_link)->buddy_order; |
} |
/** Buddy system mark_busy implementation |
/** Buddy system mark_busy implementation. |
* |
* @param b Buddy system |
* @param block Buddy system block |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* |
*/ |
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { |
frame_t * frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->refcount = 1; |
static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block) |
{ |
list_get_instance(block, frame_t, buddy_link)->refcount = 1; |
} |
/** Buddy system mark_available implementation |
/** Buddy system mark_available implementation. |
* |
* @param b Buddy system |
* @param block Buddy system block |
* |
* @param buddy Buddy system. |
* @param block Buddy system block. |
*/ |
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) { |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->refcount = 0; |
static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block) |
{ |
list_get_instance(block, frame_t, buddy_link)->refcount = 0; |
} |
static buddy_system_operations_t zone_buddy_system_operations = { |
454,8 → 400,7 |
.get_order = zone_buddy_get_order, |
.mark_busy = zone_buddy_mark_busy, |
.mark_available = zone_buddy_mark_available, |
.find_block = zone_buddy_find_block, |
.print_id = zone_buddy_print_id |
.find_block = zone_buddy_find_block |
}; |
/******************/ |
462,62 → 407,59 |
/* Zone functions */ |
/******************/ |
/** Allocate frame in particular zone |
/** Allocate frame in particular zone. |
* |
* Assume zone is locked |
* Assume zone is locked and is available for allocation. |
* Panics if allocation is impossible. |
* |
* @param zone Zone to allocate from. |
* @param order Allocate exactly 2^order frames. |
* |
* @return Frame index in zone |
* @return Frame index in zone. |
* |
*/ |
static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order) |
{ |
pfn_t v; |
link_t *tmp; |
frame_t *frame; |
ASSERT(zone_flags_available(zone->flags)); |
/* Allocate frames from zone buddy system */ |
tmp = buddy_system_alloc(zone->buddy_system, order); |
link_t *link = buddy_system_alloc(zone->buddy_system, order); |
ASSERT(tmp); |
ASSERT(link); |
/* Update zone information. */ |
zone->free_count -= (1 << order); |
zone->busy_count += (1 << order); |
/* Frame will be actually a first frame of the block. */ |
frame = list_get_instance(tmp, frame_t, buddy_link); |
frame_t *frame = list_get_instance(link, frame_t, buddy_link); |
/* get frame address */ |
v = make_frame_index(zone, frame); |
return v; |
/* Get frame address */ |
return make_frame_index(zone, frame); |
} |
/** Free frame from zone |
/** Free frame from zone. |
* |
* Assume zone is locked |
* Assume zone is locked and is available for deallocation. |
* |
* @param zone Pointer to zone from which the frame is to be freed |
* @param frame_idx Frame index relative to zone |
* @param zone Pointer to zone from which the frame is to be freed. |
* @param frame_idx Frame index relative to zone. |
* |
*/ |
static void zone_frame_free(zone_t *zone, index_t frame_idx) |
{ |
frame_t *frame; |
uint8_t order; |
frame = &zone->frames[frame_idx]; |
ASSERT(zone_flags_available(zone->flags)); |
/* remember frame order */ |
order = frame->buddy_order; |
frame_t *frame = &zone->frames[frame_idx]; |
/* Remember frame order */ |
uint8_t order = frame->buddy_order; |
ASSERT(frame->refcount); |
if (!--frame->refcount) { |
buddy_system_free(zone->buddy_system, &frame->buddy_link); |
/* Update zone information. */ |
zone->free_count += (1 << order); |
zone->busy_count -= (1 << order); |
524,521 → 466,643 |
} |
} |
/** Return frame from zone */ |
static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx) |
/** Return frame from zone. */ |
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx) |
{ |
ASSERT(frame_idx < zone->count); |
return &zone->frames[frame_idx]; |
} |
/** Mark frame in zone unavailable to allocation */ |
/** Mark frame in zone unavailable to allocation. */ |
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx) |
{ |
frame_t *frame; |
link_t *link; |
frame = zone_get_frame(zone, frame_idx); |
ASSERT(zone_flags_available(zone->flags)); |
frame_t *frame = zone_get_frame(zone, frame_idx); |
if (frame->refcount) |
return; |
link_t *link __attribute__ ((unused)); |
link = buddy_system_alloc_block(zone->buddy_system, |
&frame->buddy_link); |
ASSERT(link); |
zone->free_count--; |
} |
/** |
* Join 2 zones |
/** Merge two zones. |
* |
* Expect zone_t *z to point to space at least zone_conf_size large |
* Expect buddy to point to space at least zone_conf_size large. |
* Assume z1 & z2 are locked and compatible and zones lock is |
* locked. |
* |
* Assume z1 & z2 are locked |
* @param z1 First zone to merge. |
* @param z2 Second zone to merge. |
* @param old_z1 Original date of the first zone. |
* @param buddy Merged zone buddy. |
* |
* @param z Target zone structure pointer |
* @param z1 Zone to merge |
* @param z2 Zone to merge |
*/ |
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy) |
{ |
uint8_t max_order; |
unsigned int i; |
int z2idx; |
pfn_t frame_idx; |
frame_t *frame; |
ASSERT(!overlaps(z1->base, z1->count, z2->base, z2->count)); |
ASSERT(z1->base < z2->base); |
spinlock_initialize(&z->lock, "zone_lock"); |
z->base = z1->base; |
z->count = z2->base + z2->count - z1->base; |
z->flags = z1->flags & z2->flags; |
z->free_count = z1->free_count + z2->free_count; |
z->busy_count = z1->busy_count + z2->busy_count; |
ASSERT(zone_flags_available(zones.info[z1].flags)); |
ASSERT(zone_flags_available(zones.info[z2].flags)); |
ASSERT(zones.info[z1].flags == zones.info[z2].flags); |
ASSERT(zones.info[z1].base < zones.info[z2].base); |
ASSERT(!overlaps(zones.info[z1].base, zones.info[z1].count, |
zones.info[z2].base, zones.info[z2].count)); |
max_order = fnzb(z->count); |
z->buddy_system = (buddy_system_t *) &z[1]; |
buddy_system_create(z->buddy_system, max_order, |
&zone_buddy_system_operations, (void *) z); |
z->frames = (frame_t *)((uint8_t *) z->buddy_system + |
buddy_conf_size(max_order)); |
for (i = 0; i < z->count; i++) { |
/* This marks all frames busy */ |
frame_initialize(&z->frames[i]); |
} |
/* Difference between zone bases */ |
pfn_t base_diff = zones.info[z2].base - zones.info[z1].base; |
zones.info[z1].count = base_diff + zones.info[z2].count; |
zones.info[z1].free_count += zones.info[z2].free_count; |
zones.info[z1].busy_count += zones.info[z2].busy_count; |
zones.info[z1].buddy_system = buddy; |
uint8_t order = fnzb(zones.info[z1].count); |
buddy_system_create(zones.info[z1].buddy_system, order, |
&zone_buddy_system_operations, (void *) &zones.info[z1]); |
zones.info[z1].frames = |
(frame_t *) ((uint8_t *) zones.info[z1].buddy_system |
+ buddy_conf_size(order)); |
/* This marks all frames busy */ |
count_t i; |
for (i = 0; i < zones.info[z1].count; i++) |
frame_initialize(&zones.info[z1].frames[i]); |
/* Copy frames from both zones to preserve full frame orders, |
* parents etc. Set all free frames with refcount=0 to 1, because |
* we add all free frames to buddy allocator later again, clear |
* order to 0. Don't set busy frames with refcount=0, as they |
* parents etc. Set all free frames with refcount = 0 to 1, because |
* we add all free frames to buddy allocator later again, clearing |
* order to 0. Don't set busy frames with refcount = 0, as they |
* will not be reallocated during merge and it would make later |
* problems with allocation/free. |
*/ |
for (i = 0; i < z1->count; i++) |
z->frames[i] = z1->frames[i]; |
for (i = 0; i < z2->count; i++) { |
z2idx = i + (z2->base - z1->base); |
z->frames[z2idx] = z2->frames[i]; |
} |
for (i = 0; i < old_z1->count; i++) |
zones.info[z1].frames[i] = old_z1->frames[i]; |
for (i = 0; i < zones.info[z2].count; i++) |
zones.info[z1].frames[base_diff + i] |
= zones.info[z2].frames[i]; |
i = 0; |
while (i < z->count) { |
if (z->frames[i].refcount) { |
/* skip busy frames */ |
i += 1 << z->frames[i].buddy_order; |
} else { /* Free frames, set refcount=1 */ |
/* All free frames have refcount=0, we need not |
* to check the order */ |
z->frames[i].refcount = 1; |
z->frames[i].buddy_order = 0; |
while (i < zones.info[z1].count) { |
if (zones.info[z1].frames[i].refcount) { |
/* Skip busy frames */ |
i += 1 << zones.info[z1].frames[i].buddy_order; |
} else { |
/* Free frames, set refcount = 1 |
* (all free frames have refcount == 0, we need not |
* to check the order) |
*/ |
zones.info[z1].frames[i].refcount = 1; |
zones.info[z1].frames[i].buddy_order = 0; |
i++; |
} |
} |
/* Add free blocks from the 2 original zones */ |
while (zone_can_alloc(z1, 0)) { |
frame_idx = zone_frame_alloc(z1, 0); |
frame = &z->frames[frame_idx]; |
/* Add free blocks from the original zone z1 */ |
while (zone_can_alloc(old_z1, 0)) { |
/* Allocate from the original zone */ |
pfn_t frame_idx = zone_frame_alloc(old_z1, 0); |
/* Free the frame from the merged zone */ |
frame_t *frame = &zones.info[z1].frames[frame_idx]; |
frame->refcount = 0; |
buddy_system_free(z->buddy_system, &frame->buddy_link); |
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); |
} |
while (zone_can_alloc(z2, 0)) { |
frame_idx = zone_frame_alloc(z2, 0); |
frame = &z->frames[frame_idx + (z2->base - z1->base)]; |
/* Add free blocks from the original zone z2 */ |
while (zone_can_alloc(&zones.info[z2], 0)) { |
/* Allocate from the original zone */ |
pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0); |
/* Free the frame from the merged zone */ |
frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx]; |
frame->refcount = 0; |
buddy_system_free(z->buddy_system, &frame->buddy_link); |
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); |
} |
} |
/** Return old configuration frames into the zone |
/** Return old configuration frames into the zone. |
* |
* We have several cases |
* - the conf. data is outside of zone -> exit, shall we call frame_free?? |
* - the conf. data was created by zone_create or |
* updated with reduce_region -> free every frame |
* We have two cases: |
* - The configuration data is outside the zone |
* -> do nothing (perhaps call frame_free?) |
* - The configuration data was created by zone_create |
* or updated by reduce_region -> free every frame |
* |
* @param newzone The actual zone where freeing should occur |
* @param oldzone Pointer to old zone configuration data that should |
* be freed from new zone |
* @param znum The actual zone where freeing should occur. |
* @param pfn Old zone configuration frame. |
* @param count Old zone frame count. |
* |
*/ |
static void return_config_frames(zone_t *newzone, zone_t *oldzone) |
static void return_config_frames(count_t znum, pfn_t pfn, count_t count) |
{ |
pfn_t pfn; |
frame_t *frame; |
count_t cframes; |
unsigned int i; |
pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone)); |
cframes = SIZE2FRAMES(zone_conf_size(oldzone->count)); |
ASSERT(zone_flags_available(zones.info[znum].flags)); |
if (pfn < newzone->base || pfn >= newzone->base + newzone->count) |
count_t cframes = SIZE2FRAMES(zone_conf_size(count)); |
if ((pfn < zones.info[znum].base) |
|| (pfn >= zones.info[znum].base + zones.info[znum].count)) |
return; |
frame_t *frame __attribute__ ((unused)); |
frame = &newzone->frames[pfn - newzone->base]; |
frame = &zones.info[znum].frames[pfn - zones.info[znum].base]; |
ASSERT(!frame->buddy_order); |
count_t i; |
for (i = 0; i < cframes; i++) { |
newzone->busy_count++; |
zone_frame_free(newzone, pfn+i-newzone->base); |
zones.info[znum].busy_count++; |
zone_frame_free(&zones.info[znum], |
pfn - zones.info[znum].base + i); |
} |
} |
/** Reduce allocated block to count of order 0 frames |
/** Reduce allocated block to count of order 0 frames. |
* |
* The allocated block need 2^order frames of space. Reduce all frames |
* in block to order 0 and free the unneeded frames. This means, that |
* when freeing the previously allocated block starting with frame_idx, |
* The allocated block needs 2^order frames. Reduce all frames |
* in the block to order 0 and free the unneeded frames. This means that |
* when freeing the previously allocated block starting with frame_idx, |
* you have to free every frame. |
* |
* @param zone |
* @param frame_idx Index to block |
* @param count Allocated space in block |
* @param znum Zone. |
* @param frame_idx Index the first frame of the block. |
* @param count Allocated frames in block. |
* |
*/ |
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count) |
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count) |
{ |
count_t i; |
uint8_t order; |
frame_t *frame; |
ASSERT(zone_flags_available(zones.info[znum].flags)); |
ASSERT(frame_idx + count < zones.info[znum].count); |
ASSERT(frame_idx + count < zone->count); |
order = zone->frames[frame_idx].buddy_order; |
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order; |
ASSERT((count_t) (1 << order) >= count); |
/* Reduce all blocks to order 0 */ |
count_t i; |
for (i = 0; i < (count_t) (1 << order); i++) { |
frame = &zone->frames[i + frame_idx]; |
frame_t *frame = &zones.info[znum].frames[i + frame_idx]; |
frame->buddy_order = 0; |
if (!frame->refcount) |
frame->refcount = 1; |
ASSERT(frame->refcount == 1); |
} |
/* Free unneeded frames */ |
for (i = count; i < (count_t) (1 << order); i++) { |
zone_frame_free(zone, i + frame_idx); |
} |
for (i = count; i < (count_t) (1 << order); i++) |
zone_frame_free(&zones.info[znum], i + frame_idx); |
} |
/** Merge zones z1 and z2 |
/** Merge zones z1 and z2. |
* |
* - the zones must be 2 zones with no zone existing in between, |
* which means that z2 = z1+1 |
* The merged zones must be 2 zones with no zone existing in between |
* (which means that z2 = z1 + 1). Both zones must be available zones |
* with the same flags. |
* |
* - When you create a new zone, the frame allocator configuration does |
* not to be 2^order size. Once the allocator is running it is no longer |
* possible, merged configuration data occupies more space :-/ |
* When you create a new zone, the frame allocator configuration does |
* not to be 2^order size. Once the allocator is running it is no longer |
* possible, merged configuration data occupies more space :-/ |
* |
* The function uses |
* |
*/ |
void zone_merge(unsigned int z1, unsigned int z2) |
bool zone_merge(count_t z1, count_t z2) |
{ |
ipl_t ipl; |
zone_t *zone1, *zone2, *newzone; |
unsigned int cframes; |
uint8_t order; |
unsigned int i; |
pfn_t pfn; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if ((z1 >= zones.count) || (z2 >= zones.count)) |
bool ret = true; |
/* We can join only 2 zones with none existing inbetween, |
* the zones have to be available and with the same |
* set of flags |
*/ |
if ((z1 >= zones.count) || (z2 >= zones.count) |
|| (z2 - z1 != 1) |
|| (!zone_flags_available(zones.info[z1].flags)) |
|| (!zone_flags_available(zones.info[z2].flags)) |
|| (zones.info[z1].flags != zones.info[z2].flags)) { |
ret = false; |
goto errout; |
/* We can join only 2 zones with none existing inbetween */ |
if (z2-z1 != 1) |
goto errout; |
zone1 = zones.info[z1]; |
zone2 = zones.info[z2]; |
spinlock_lock(&zone1->lock); |
spinlock_lock(&zone2->lock); |
cframes = SIZE2FRAMES(zone_conf_size(zone2->base + zone2->count - |
zone1->base)); |
} |
pfn_t cframes = SIZE2FRAMES(zone_conf_size( |
zones.info[z2].base - zones.info[z1].base |
+ zones.info[z2].count)); |
uint8_t order; |
if (cframes == 1) |
order = 0; |
else |
else |
order = fnzb(cframes - 1) + 1; |
/* Allocate zonedata inside one of the zones */ |
if (zone_can_alloc(zone1, order)) |
pfn = zone1->base + zone_frame_alloc(zone1, order); |
else if (zone_can_alloc(zone2, order)) |
pfn = zone2->base + zone_frame_alloc(zone2, order); |
else |
goto errout2; |
newzone = (zone_t *) PA2KA(PFN2ADDR(pfn)); |
_zone_merge(newzone, zone1, zone2); |
/* Allocate merged zone data inside one of the zones */ |
pfn_t pfn; |
if (zone_can_alloc(&zones.info[z1], order)) { |
pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order); |
} else if (zone_can_alloc(&zones.info[z2], order)) { |
pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order); |
} else { |
ret = false; |
goto errout; |
} |
/* Preserve original data from z1 */ |
zone_t old_z1 = zones.info[z1]; |
old_z1.buddy_system->data = (void *) &old_z1; |
/* Do zone merging */ |
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn)); |
zone_merge_internal(z1, z2, &old_z1, buddy); |
/* Free unneeded config frames */ |
zone_reduce_region(newzone, pfn - newzone->base, cframes); |
zone_reduce_region(z1, pfn - zones.info[z1].base, cframes); |
/* Subtract zone information from busy frames */ |
newzone->busy_count -= cframes; |
/* Replace existing zones in zoneinfo list */ |
zones.info[z1] = newzone; |
for (i = z2 + 1; i < zones.count; i++) |
zones.info[z1].busy_count -= cframes; |
/* Free old zone information */ |
return_config_frames(z1, |
ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count); |
return_config_frames(z1, |
ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)), |
zones.info[z2].count); |
/* Move zones down */ |
count_t i; |
for (i = z2 + 1; i < zones.count; i++) { |
zones.info[i - 1] = zones.info[i]; |
zones.info[i - 1].buddy_system->data = |
(void *) &zones.info[i - 1]; |
} |
zones.count--; |
/* Free old zone information */ |
return_config_frames(newzone, zone1); |
return_config_frames(newzone, zone2); |
errout2: |
/* Nobody is allowed to enter to zone, so we are safe |
* to touch the spinlocks last time */ |
spinlock_unlock(&zone1->lock); |
spinlock_unlock(&zone2->lock); |
errout: |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return ret; |
} |
/** |
* Merge all zones into one big zone |
/** Merge all mergeable zones into one big zone. |
* |
* It is reasonable to do this on systems whose bios reports parts in chunks, |
* so that we could have 1 zone (it's faster). |
* It is reasonable to do this on systems where |
* BIOS reports parts in chunks, so that we could |
* have 1 zone (it's faster). |
* |
*/ |
void zone_merge_all(void) |
{ |
int count = zones.count; |
while (zones.count > 1 && --count) { |
zone_merge(0,1); |
break; |
count_t i = 0; |
while (i < zones.count) { |
if (!zone_merge(i, i + 1)) |
i++; |
} |
} |
/** Create frame zone |
/** Create new frame zone. |
* |
* Create new frame zone. |
* |
* @param zone Zone to construct. |
* @param buddy Address of buddy system configuration information. |
* @param start Physical address of the first frame within the zone. |
* @param count Count of frames in zone |
* @param z Address of configuration information of zone |
* @param count Count of frames in zone. |
* @param flags Zone flags. |
* |
* @return Initialized zone. |
* |
*/ |
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) |
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags) |
{ |
unsigned int i; |
uint8_t max_order; |
spinlock_initialize(&z->lock, "zone_lock"); |
z->base = start; |
z->count = count; |
z->flags = flags; |
z->free_count = count; |
z->busy_count = 0; |
/* |
* Compute order for buddy system, initialize |
*/ |
max_order = fnzb(count); |
z->buddy_system = (buddy_system_t *)&z[1]; |
zone->base = start; |
zone->count = count; |
zone->flags = flags; |
zone->free_count = count; |
zone->busy_count = 0; |
zone->buddy_system = buddy; |
buddy_system_create(z->buddy_system, max_order, |
&zone_buddy_system_operations, |
(void *) z); |
/* Allocate frames _after_ the conframe */ |
/* Check sizes */ |
z->frames = (frame_t *)((uint8_t *) z->buddy_system + |
buddy_conf_size(max_order)); |
for (i = 0; i < count; i++) { |
frame_initialize(&z->frames[i]); |
} |
/* Stuffing frames */ |
for (i = 0; i < count; i++) { |
z->frames[i].refcount = 0; |
buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); |
} |
if (zone_flags_available(flags)) { |
/* |
* Compute order for buddy system and initialize |
*/ |
uint8_t order = fnzb(count); |
buddy_system_create(zone->buddy_system, order, |
&zone_buddy_system_operations, (void *) zone); |
/* Allocate frames _after_ the confframe */ |
/* Check sizes */ |
zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system + |
buddy_conf_size(order)); |
count_t i; |
for (i = 0; i < count; i++) |
frame_initialize(&zone->frames[i]); |
/* Stuffing frames */ |
for (i = 0; i < count; i++) { |
zone->frames[i].refcount = 0; |
buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link); |
} |
} else |
zone->frames = NULL; |
} |
/** Compute configuration data size for zone |
/** Compute configuration data size for zone. |
* |
* @param count Size of zone in frames |
* @return Size of zone configuration info (in bytes) |
* @param count Size of zone in frames. |
* |
* @return Size of zone configuration info (in bytes). |
* |
*/ |
uintptr_t zone_conf_size(count_t count) |
{ |
int size = sizeof(zone_t) + count*sizeof(frame_t); |
int max_order; |
max_order = fnzb(count); |
size += buddy_conf_size(max_order); |
return size; |
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count))); |
} |
/** Create and add zone to system |
/** Create and add zone to system. |
* |
* @param start First frame number (absolute) |
* @param count Size of zone in frames |
* @param start First frame number (absolute). |
* @param count Size of zone in frames. |
* @param confframe Where configuration frames are supposed to be. |
* Automatically checks, that we will not disturb the |
* kernel and possibly init. |
* If confframe is given _outside_ this zone, it is expected, |
* that the area is already marked BUSY and big enough |
* to contain zone_conf_size() amount of data. |
* If the confframe is inside the area, the zone free frame |
* information is modified not to include it. |
* Automatically checks, that we will not disturb the |
* kernel and possibly init. If confframe is given |
* _outside_ this zone, it is expected, that the area is |
* already marked BUSY and big enough to contain |
* zone_conf_size() amount of data. If the confframe is |
* inside the area, the zone free frame information is |
* modified not to include it. |
* |
* @return Zone number or -1 on error |
* @return Zone number or -1 on error. |
* |
*/ |
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags) |
{ |
zone_t *z; |
uintptr_t addr; |
count_t confcount; |
unsigned int i; |
int znum; |
/* Theoretically we could have here 0, practically make sure |
* nobody tries to do that. If some platform requires, remove |
* the assert |
*/ |
ASSERT(confframe); |
/* If conframe is supposed to be inside our zone, then make sure |
* it does not span kernel & init |
*/ |
confcount = SIZE2FRAMES(zone_conf_size(count)); |
if (confframe >= start && confframe < start+count) { |
for (;confframe < start + count; confframe++) { |
addr = PFN2ADDR(confframe); |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(config.base), config.kernel_size)) |
continue; |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(config.stack_base), config.stack_size)) |
continue; |
bool overlap = false; |
count_t i; |
for (i = 0; i < init.cnt; i++) |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (zone_flags_available(flags)) { /* Create available zone */ |
/* Theoretically we could have NULL here, practically make sure |
* nobody tries to do that. If some platform requires, remove |
* the assert |
*/ |
ASSERT(confframe != NULL); |
/* If confframe is supposed to be inside our zone, then make sure |
* it does not span kernel & init |
*/ |
count_t confcount = SIZE2FRAMES(zone_conf_size(count)); |
if ((confframe >= start) && (confframe < start + count)) { |
for (; confframe < start + count; confframe++) { |
uintptr_t addr = PFN2ADDR(confframe); |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(init.tasks[i].addr), |
init.tasks[i].size)) { |
overlap = true; |
break; |
} |
if (overlap) |
continue; |
KA2PA(config.base), config.kernel_size)) |
continue; |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(config.stack_base), config.stack_size)) |
continue; |
bool overlap = false; |
count_t i; |
for (i = 0; i < init.cnt; i++) |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(init.tasks[i].addr), |
init.tasks[i].size)) { |
overlap = true; |
break; |
} |
if (overlap) |
continue; |
break; |
} |
break; |
if (confframe >= start + count) |
panic("Cannot find configuration data for zone."); |
} |
if (confframe >= start + count) |
panic("Cannot find configuration data for zone."); |
count_t znum = zones_insert_zone(start, count); |
if (znum == (count_t) -1) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return (count_t) -1; |
} |
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe)); |
zone_construct(&zones.info[znum], buddy, start, count, flags); |
/* If confdata in zone, mark as unavailable */ |
if ((confframe >= start) && (confframe < start + count)) { |
count_t i; |
for (i = confframe; i < confframe + confcount; i++) |
zone_mark_unavailable(&zones.info[znum], |
i - zones.info[znum].base); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return znum; |
} |
z = (zone_t *) PA2KA(PFN2ADDR(confframe)); |
zone_construct(start, count, z, flags); |
znum = zones_add_zone(z); |
if (znum == -1) |
return -1; |
/* If confdata in zone, mark as unavailable */ |
if (confframe >= start && confframe < start + count) |
for (i = confframe; i < confframe + confcount; i++) { |
zone_mark_unavailable(z, i - z->base); |
} |
/* Non-available zone */ |
count_t znum = zones_insert_zone(start, count); |
if (znum == (count_t) -1) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return (count_t) -1; |
} |
zone_construct(&zones.info[znum], NULL, start, count, flags); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return znum; |
} |
/***************************************/ |
/*******************/ |
/* Frame functions */ |
/*******************/ |
/** Set parent of frame */ |
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint) |
/** Set parent of frame. */ |
void frame_set_parent(pfn_t pfn, void *data, count_t hint) |
{ |
zone_t *zone = find_zone_and_lock(pfn, &hint); |
ASSERT(zone); |
zone_get_frame(zone, pfn-zone->base)->parent = data; |
spinlock_unlock(&zone->lock); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
count_t znum = find_zone(pfn, 1, hint); |
ASSERT(znum != (count_t) -1); |
zone_get_frame(&zones.info[znum], |
pfn - zones.info[znum].base)->parent = data; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
void *frame_get_parent(pfn_t pfn, unsigned int hint) |
void *frame_get_parent(pfn_t pfn, count_t hint) |
{ |
zone_t *zone = find_zone_and_lock(pfn, &hint); |
void *res; |
ASSERT(zone); |
res = zone_get_frame(zone, pfn - zone->base)->parent; |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
spinlock_unlock(&zone->lock); |
count_t znum = find_zone(pfn, 1, hint); |
ASSERT(znum != (count_t) -1); |
void *res = zone_get_frame(&zones.info[znum], |
pfn - zones.info[znum].base)->parent; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return res; |
} |
/** Allocate power-of-two frames of physical memory. |
* |
* @param order Allocate exactly 2^order frames. |
* @param flags Flags for host zone selection and address processing. |
* @param pzone Preferred zone |
* @param order Allocate exactly 2^order frames. |
* @param flags Flags for host zone selection and address processing. |
* @param pzone Preferred zone. |
* |
* @return Physical address of the allocated frame. |
* |
*/ |
void * frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone) |
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone) |
{ |
count_t size = ((count_t) 1) << order; |
ipl_t ipl; |
int freed; |
pfn_t v; |
zone_t *zone; |
count_t hint = pzone ? (*pzone) : 0; |
loop: |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
/* |
* First, find suitable frame zone. |
*/ |
zone = find_free_zone_and_lock(order, pzone); |
count_t znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
freed = slab_reclaim(0); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
if (!zone) { |
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { |
count_t freed = slab_reclaim(0); |
if (freed > 0) |
znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
if (znum == (count_t) -1) { |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
if (freed > 0) |
znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
} |
} |
if (!zone) { |
if (znum == (count_t) -1) { |
if (flags & FRAME_ATOMIC) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return NULL; |
} |
#ifdef CONFIG_DEBUG |
count_t avail = total_frames_free(); |
#endif |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
/* |
* TODO: Sleep until frames are available again. |
* Sleep until some frames are available again. |
*/ |
interrupts_restore(ipl); |
if (flags & FRAME_ATOMIC) |
return 0; |
panic("Sleep not implemented.\n"); |
#ifdef CONFIG_DEBUG |
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, " |
"%" PRIc " available.\n", THREAD->tid, size, avail); |
#endif |
mutex_lock(&mem_avail_mtx); |
if (mem_avail_req > 0) |
mem_avail_req = min(mem_avail_req, size); |
else |
mem_avail_req = size; |
count_t gen = mem_avail_gen; |
while (gen == mem_avail_gen) |
condvar_wait(&mem_avail_cv, &mem_avail_mtx); |
mutex_unlock(&mem_avail_mtx); |
#ifdef CONFIG_DEBUG |
printf("Thread %" PRIu64 " woken up.\n", THREAD->tid); |
#endif |
goto loop; |
} |
v = zone_frame_alloc(zone, order); |
v += zone->base; |
spinlock_unlock(&zone->lock); |
pfn_t pfn = zone_frame_alloc(&zones.info[znum], order) |
+ zones.info[znum].base; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
if (pzone) |
*pzone = znum; |
if (flags & FRAME_KA) |
return (void *)PA2KA(PFN2ADDR(v)); |
return (void *)PFN2ADDR(v); |
return (void *) PA2KA(PFN2ADDR(pfn)); |
return (void *) PFN2ADDR(pfn); |
} |
/** Free a frame. |
* |
* Find respective frame structure for supplied physical frame address. |
* Decrement frame reference count. |
* If it drops to zero, move the frame structure to free list. |
* Decrement frame reference count. If it drops to zero, move the frame |
* structure to free list. |
* |
* @param Frame Physical Address of of the frame to be freed. |
* @param frame Physical Address of of the frame to be freed. |
* |
*/ |
void frame_free(uintptr_t frame) |
{ |
ipl_t ipl; |
zone_t *zone; |
pfn_t pfn = ADDR2PFN(frame); |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
/* |
* First, find host frame zone for addr. |
*/ |
zone = find_zone_and_lock(pfn,NULL); |
ASSERT(zone); |
pfn_t pfn = ADDR2PFN(frame); |
count_t znum = find_zone(pfn, 1, NULL); |
zone_frame_free(zone, pfn-zone->base); |
ASSERT(znum != (count_t) -1); |
spinlock_unlock(&zone->lock); |
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
/* |
* Signal that some memory has been freed. |
*/ |
mutex_lock(&mem_avail_mtx); |
if (mem_avail_req > 0) |
mem_avail_req--; |
if (mem_avail_req == 0) { |
mem_avail_gen++; |
condvar_broadcast(&mem_avail_cv); |
} |
mutex_unlock(&mem_avail_mtx); |
} |
/** Add reference to frame. |
1047,55 → 1111,56 |
* increment frame reference count. |
* |
* @param pfn Frame number of the frame to be freed. |
* |
*/ |
void frame_reference_add(pfn_t pfn) |
{ |
ipl_t ipl; |
zone_t *zone; |
frame_t *frame; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
/* |
* First, find host frame zone for addr. |
*/ |
zone = find_zone_and_lock(pfn,NULL); |
ASSERT(zone); |
count_t znum = find_zone(pfn, 1, NULL); |
frame = &zone->frames[pfn-zone->base]; |
frame->refcount++; |
ASSERT(znum != (count_t) -1); |
spinlock_unlock(&zone->lock); |
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
/** Mark given range unavailable in frame zones */ |
/** Mark given range unavailable in frame zones. */ |
void frame_mark_unavailable(pfn_t start, count_t count) |
{ |
unsigned int i; |
zone_t *zone; |
unsigned int prefzone = 0; |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
count_t i; |
for (i = 0; i < count; i++) { |
zone = find_zone_and_lock(start + i, &prefzone); |
if (!zone) /* PFN not found */ |
count_t znum = find_zone(start + i, 1, 0); |
if (znum == (count_t) -1) /* PFN not found */ |
continue; |
zone_mark_unavailable(zone, start + i - zone->base); |
spinlock_unlock(&zone->lock); |
zone_mark_unavailable(&zones.info[znum], |
start + i - zones.info[znum].base); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
/** Initialize physical memory management |
* |
* Initialize physical memory managemnt. |
*/ |
/** Initialize physical memory management. */ |
void frame_init(void) |
{ |
if (config.cpu_active == 1) { |
zones.count = 0; |
spinlock_initialize(&zones.lock, "zones.lock"); |
mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE); |
condvar_initialize(&mem_avail_cv); |
} |
/* Tell the architecture to create some memory */ |
frame_arch_init(); |
if (config.cpu_active == 1) { |
1110,36 → 1175,28 |
frame_mark_unavailable(pfn, |
SIZE2FRAMES(init.tasks[i].size)); |
} |
if (ballocs.size) |
frame_mark_unavailable(ADDR2PFN(KA2PA(ballocs.base)), |
SIZE2FRAMES(ballocs.size)); |
/* Black list first frame, as allocating NULL would |
* fail in some places */ |
* fail in some places |
*/ |
frame_mark_unavailable(0, 1); |
} |
} |
/** Return total size of all zones |
* |
*/ |
uint64_t zone_total_size(void) { |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
uint64_t total = 0; |
ipl = interrupts_disable(); |
/** Return total size of all zones. */ |
uint64_t zone_total_size(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
for (i = 0; i < zones.count; i++) { |
zone = zones.info[i]; |
spinlock_lock(&zone->lock); |
total += (uint64_t) FRAMES2SIZE(zone->count); |
spinlock_unlock(&zone->lock); |
} |
uint64_t total = 0; |
count_t i; |
for (i = 0; i < zones.count; i++) |
total += (uint64_t) FRAMES2SIZE(zones.info[i].count); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
1147,86 → 1204,128 |
return total; |
} |
/** Prints list of zones. */ |
void zone_print_list(void) |
{ |
#ifdef __32_BITS__ |
printf("# base address frames flags free frames busy frames\n"); |
printf("-- ------------ ------------ -------- ------------ ------------\n"); |
#endif |
/** Prints list of zones |
* |
*/ |
void zone_print_list(void) { |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
#ifdef __64_BITS__ |
printf("# base address frames flags free frames busy frames\n"); |
printf("-- -------------------- ------------ -------- ------------ ------------\n"); |
#endif |
if (sizeof(void *) == 4) { |
printf("# base address free frames busy frames\n"); |
printf("-- ------------ ------------ ------------\n"); |
} else { |
printf("# base address free frames busy frames\n"); |
printf("-- -------------------- ------------ ------------\n"); |
} |
/* |
* Because printing may require allocation of memory, we may not hold |
* the frame allocator locks when printing zone statistics. Therefore, |
* we simply gather the statistics under the protection of the locks and |
* print the statistics when the locks have been released. |
* |
* When someone adds/removes zones while we are printing the statistics, |
* we may end up with inaccurate output (e.g. a zone being skipped from |
* the listing). |
*/ |
for (i = 0; i < zones.count; i++) { |
zone = zones.info[i]; |
spinlock_lock(&zone->lock); |
count_t i; |
for (i = 0;; i++) { |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (sizeof(void *) == 4) |
printf("%-2d %#10zx %12zd %12zd\n", i, PFN2ADDR(zone->base), |
zone->free_count, zone->busy_count); |
else |
printf("%-2d %#18zx %12zd %12zd\n", i, PFN2ADDR(zone->base), |
zone->free_count, zone->busy_count); |
if (i >= zones.count) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
break; |
} |
spinlock_unlock(&zone->lock); |
uintptr_t base = PFN2ADDR(zones.info[i].base); |
count_t count = zones.info[i].count; |
zone_flags_t flags = zones.info[i].flags; |
count_t free_count = zones.info[i].free_count; |
count_t busy_count = zones.info[i].busy_count; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
bool available = zone_flags_available(flags); |
printf("%-2" PRIc, i); |
#ifdef __32_BITS__ |
printf(" %10p", base); |
#endif |
#ifdef __64_BITS__ |
printf(" %18p", base); |
#endif |
printf(" %12" PRIc " %c%c%c ", count, |
available ? 'A' : ' ', |
(flags & ZONE_RESERVED) ? 'R' : ' ', |
(flags & ZONE_FIRMWARE) ? 'F' : ' '); |
if (available) |
printf("%12" PRIc " %12" PRIc, |
free_count, busy_count); |
printf("\n"); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
/** Prints zone details. |
* |
* @param num Zone base address or zone number. |
* |
*/ |
void zone_print_one(unsigned int num) { |
zone_t *zone = NULL; |
ipl_t ipl; |
unsigned int i; |
ipl = interrupts_disable(); |
void zone_print_one(count_t num) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
count_t znum = (count_t) -1; |
count_t i; |
for (i = 0; i < zones.count; i++) { |
if ((i == num) || (PFN2ADDR(zones.info[i]->base) == num)) { |
zone = zones.info[i]; |
if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) { |
znum = i; |
break; |
} |
} |
if (!zone) { |
if (znum == (count_t) -1) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone not found.\n"); |
goto out; |
return; |
} |
spinlock_lock(&zone->lock); |
printf("Memory zone information\n"); |
printf("Zone base address: %#.*p\n", sizeof(uintptr_t) * 2, |
PFN2ADDR(zone->base)); |
printf("Zone size: %zd frames (%zd KB)\n", zone->count, |
SIZE2KB(FRAMES2SIZE(zone->count))); |
printf("Allocated space: %zd frames (%zd KB)\n", zone->busy_count, |
SIZE2KB(FRAMES2SIZE(zone->busy_count))); |
printf("Available space: %zd frames (%zd KB)\n", zone->free_count, |
SIZE2KB(FRAMES2SIZE(zone->free_count))); |
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
spinlock_unlock(&zone->lock); |
uintptr_t base = PFN2ADDR(zones.info[i].base); |
zone_flags_t flags = zones.info[i].flags; |
count_t count = zones.info[i].count; |
count_t free_count = zones.info[i].free_count; |
count_t busy_count = zones.info[i].busy_count; |
out: |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
bool available = zone_flags_available(flags); |
printf("Zone number: %" PRIc "\n", znum); |
printf("Zone base address: %p\n", base); |
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count, |
SIZE2KB(FRAMES2SIZE(count))); |
printf("Zone flags: %c%c%c\n", |
available ? 'A' : ' ', |
(flags & ZONE_RESERVED) ? 'R' : ' ', |
(flags & ZONE_FIRMWARE) ? 'F' : ' '); |
if (available) { |
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", |
busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); |
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", |
free_count, SIZE2KB(FRAMES2SIZE(free_count))); |
} |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/mm/page.c |
---|
40,11 → 40,28 |
* They however, define the single interface. |
*/ |
/* |
* Note on memory prefetching and updating memory mappings, also described in: |
* AMD x86-64 Architecture Programmer's Manual, Volume 2, System Programming, |
* 7.2.1 Special Coherency Considerations. |
* |
* The processor which modifies a page table mapping can access prefetched data |
* from the old mapping. In order to prevent this, we place a memory barrier |
* after a mapping is updated. |
* |
* We assume that the other processors are either not using the mapping yet |
* (i.e. during the bootstrap) or are executing the TLB shootdown code. While |
* we don't care much about the former case, the processors in the latter case |
* will do an implicit serialization by virtue of running the TLB shootdown |
* interrupt handler. |
*/ |
#include <mm/page.h> |
#include <arch/mm/page.h> |
#include <arch/mm/asid.h> |
#include <mm/as.h> |
#include <mm/frame.h> |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <memstr.h> |
65,8 → 82,8 |
* considering possible crossings |
* of page boundaries. |
* |
* @param s Address of the structure. |
* @param size Size of the structure. |
* @param s Address of the structure. |
* @param size Size of the structure. |
*/ |
void map_structure(uintptr_t s, size_t size) |
{ |
76,8 → 93,11 |
cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0); |
for (i = 0; i < cnt; i++) |
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE, |
s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Insert mapping of page to frame. |
87,10 → 107,11 |
* |
* The page table must be locked and interrupts must be disabled. |
* |
* @param as Address space to wich page belongs. |
* @param page Virtual address of the page to be mapped. |
* @param frame Physical address of memory frame to which the mapping is done. |
* @param flags Flags to be used for mapping. |
* @param as Address space to wich page belongs. |
* @param page Virtual address of the page to be mapped. |
* @param frame Physical address of memory frame to which the mapping is |
* done. |
* @param flags Flags to be used for mapping. |
*/ |
void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags) |
{ |
98,6 → 119,9 |
ASSERT(page_mapping_operations->mapping_insert); |
page_mapping_operations->mapping_insert(as, page, frame, flags); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Remove mapping of page. |
108,8 → 132,8 |
* |
* The page table must be locked and interrupts must be disabled. |
* |
* @param as Address space to wich page belongs. |
* @param page Virtual address of the page to be demapped. |
* @param as Address space to wich page belongs. |
* @param page Virtual address of the page to be demapped. |
*/ |
void page_mapping_remove(as_t *as, uintptr_t page) |
{ |
117,6 → 141,9 |
ASSERT(page_mapping_operations->mapping_remove); |
page_mapping_operations->mapping_remove(as, page); |
/* Repel prefetched accesses to the old mapping. */ |
memory_barrier(); |
} |
/** Find mapping for virtual page |
125,10 → 152,11 |
* |
* The page table must be locked and interrupts must be disabled. |
* |
* @param as Address space to wich page belongs. |
* @param page Virtual page. |
* @param as Address space to wich page belongs. |
* @param page Virtual page. |
* |
* @return NULL if there is no such mapping; requested mapping otherwise. |
* @return NULL if there is no such mapping; requested mapping |
* otherwise. |
*/ |
pte_t *page_mapping_find(as_t *as, uintptr_t page) |
{ |
/branches/dd/kernel/generic/src/mm/backend_elf.c |
---|
48,6 → 48,7 |
#include <memstr.h> |
#include <macros.h> |
#include <arch.h> |
#include <arch/barrier.h> |
#ifdef CONFIG_VIRT_IDX_DCACHE |
#include <arch/mm/cache.h> |
67,12 → 68,13 |
* |
* The address space area and page tables must be already locked. |
* |
* @param area Pointer to the address space area. |
* @param addr Faulting virtual address. |
* @param access Access mode that caused the fault (i.e. read/write/exec). |
* @param area Pointer to the address space area. |
* @param addr Faulting virtual address. |
* @param access Access mode that caused the fault (i.e. |
* read/write/exec). |
* |
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. |
* serviced). |
* @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK |
* on success (i.e. serviced). |
*/ |
int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
{ |
116,7 → 118,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == page) { |
if (leaf->key[i] == page - area->base) { |
found = true; |
break; |
} |
127,7 → 129,7 |
page_mapping_insert(AS, addr, frame, |
as_area_get_flags(area)); |
if (!used_space_insert(area, page, 1)) |
panic("Could not insert used space.\n"); |
panic("Cannot insert used space."); |
mutex_unlock(&area->sh_info->lock); |
return AS_PF_OK; |
} |
150,6 → 152,10 |
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
memcpy((void *) PA2KA(frame), |
(void *) (base + i * FRAME_SIZE), FRAME_SIZE); |
if (entry->p_flags & PF_X) { |
smc_coherence_block((void *) PA2KA(frame), |
FRAME_SIZE); |
} |
dirty = true; |
} else { |
frame = KA2PA(base + i * FRAME_SIZE); |
162,7 → 168,7 |
* and cleared. |
*/ |
frame = (uintptr_t)frame_alloc(ONE_FRAME, 0); |
memsetb(PA2KA(frame), FRAME_SIZE, 0); |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
} else { |
size_t pad_lo, pad_hi; |
187,8 → 193,13 |
memcpy((void *) (PA2KA(frame) + pad_lo), |
(void *) (base + i * FRAME_SIZE + pad_lo), |
FRAME_SIZE - pad_lo - pad_hi); |
memsetb(PA2KA(frame), pad_lo, 0); |
memsetb(PA2KA(frame) + FRAME_SIZE - pad_hi, pad_hi, 0); |
if (entry->p_flags & PF_X) { |
smc_coherence_block((void *) (PA2KA(frame) + pad_lo), |
FRAME_SIZE - pad_lo - pad_hi); |
} |
memsetb((void *) PA2KA(frame), pad_lo, 0); |
memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi, |
0); |
dirty = true; |
} |
203,7 → 214,7 |
page_mapping_insert(AS, addr, frame, as_area_get_flags(area)); |
if (!used_space_insert(area, page, 1)) |
panic("Could not insert used space.\n"); |
panic("Cannot insert used space."); |
return AS_PF_OK; |
} |
212,9 → 223,10 |
* |
* The address space area and page tables must be already locked. |
* |
* @param area Pointer to the address space area. |
* @param page Page that is mapped to frame. Must be aligned to PAGE_SIZE. |
* @param frame Frame to be released. |
* @param area Pointer to the address space area. |
* @param page Page that is mapped to frame. Must be aligned to |
* PAGE_SIZE. |
* @param frame Frame to be released. |
* |
*/ |
void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame) |
257,7 → 269,7 |
* |
* The address space and address space area must be locked prior to the call. |
* |
* @param area Address space area. |
* @param area Address space area. |
*/ |
void elf_share(as_area_t *area) |
{ |
/branches/dd/kernel/generic/src/syscall/syscall.c |
---|
38,6 → 38,7 |
#include <syscall/syscall.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <proc/program.h> |
#include <mm/as.h> |
#include <print.h> |
#include <putchar.h> |
46,40 → 47,43 |
#include <debug.h> |
#include <ipc/sysipc.h> |
#include <synch/futex.h> |
#include <synch/smc.h> |
#include <ddi/ddi.h> |
#include <security/cap.h> |
#include <syscall/copy.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <console/klog.h> |
#include <udebug/udebug.h> |
/** Print using kernel facility |
* |
* Some simulators can print only through kernel. Userspace can use |
* this syscall to facilitate it. |
* Print to kernel log. |
* |
*/ |
static unative_t sys_io(int fd, const void * buf, size_t count) |
static unative_t sys_klog(int fd, const void * buf, size_t count) |
{ |
size_t i; |
char *data; |
int rc; |
if (count > PAGE_SIZE) |
return ELIMIT; |
data = (char *) malloc(count, 0); |
if (!data) |
return ENOMEM; |
rc = copy_from_uspace(data, buf, count); |
if (rc) { |
if (count > 0) { |
data = (char *) malloc(count + 1, 0); |
if (!data) |
return ENOMEM; |
rc = copy_from_uspace(data, buf, count); |
if (rc) { |
free(data); |
return rc; |
} |
data[count] = 0; |
printf("%s", data); |
free(data); |
return rc; |
} |
for (i = 0; i < count; i++) |
putchar(data[i]); |
free(data); |
} else |
klog_update(); |
return count; |
} |
87,10 → 91,21 |
/** Tell kernel to get keyboard/console access again */ |
static unative_t sys_debug_enable_console(void) |
{ |
arch_grab_console(); |
return 0; |
#ifdef CONFIG_KCONSOLE |
grab_console(); |
return true; |
#else |
return false; |
#endif |
} |
/** Tell kernel to relinquish keyboard/console access */ |
static unative_t sys_debug_disable_console(void) |
{ |
release_console(); |
return true; |
} |
/** Dispatch system call */ |
unative_t syscall_handler(unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5, unative_t a6, unative_t id) |
97,11 → 112,13 |
{ |
unative_t rc; |
if (id < SYSCALL_END) |
#ifdef CONFIG_UDEBUG |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false); |
#endif |
if (id < SYSCALL_END) { |
rc = syscall_table[id](a1, a2, a3, a4, a5, a6); |
else { |
klog_printf("TASK %llu: Unknown syscall id %llx", TASK->taskid, |
id); |
} else { |
printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id); |
task_kill(TASK->taskid); |
thread_exit(); |
} |
108,12 → 125,22 |
if (THREAD->interrupted) |
thread_exit(); |
#ifdef CONFIG_UDEBUG |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true); |
/* |
* Stopping point needed for tasks that only invoke non-blocking |
* system calls. |
*/ |
udebug_stoppable_begin(); |
udebug_stoppable_end(); |
#endif |
return rc; |
} |
syshandler_t syscall_table[SYSCALL_END] = { |
(syshandler_t) sys_io, |
(syshandler_t) sys_klog, |
(syshandler_t) sys_tls_set, |
/* Thread and task related syscalls. */ |
120,15 → 147,20 |
(syshandler_t) sys_thread_create, |
(syshandler_t) sys_thread_exit, |
(syshandler_t) sys_thread_get_id, |
(syshandler_t) sys_task_get_id, |
(syshandler_t) sys_task_set_name, |
(syshandler_t) sys_program_spawn_loader, |
/* Synchronization related syscalls. */ |
(syshandler_t) sys_futex_sleep_timeout, |
(syshandler_t) sys_futex_wakeup, |
(syshandler_t) sys_smc_coherence, |
/* Address space related syscalls. */ |
(syshandler_t) sys_as_area_create, |
(syshandler_t) sys_as_area_resize, |
(syshandler_t) sys_as_area_change_flags, |
(syshandler_t) sys_as_area_destroy, |
/* IPC related syscalls. */ |
139,6 → 171,7 |
(syshandler_t) sys_ipc_answer_fast, |
(syshandler_t) sys_ipc_answer_slow, |
(syshandler_t) sys_ipc_forward_fast, |
(syshandler_t) sys_ipc_forward_slow, |
(syshandler_t) sys_ipc_wait_for_call, |
(syshandler_t) sys_ipc_hangup, |
(syshandler_t) sys_ipc_register_irq, |
158,7 → 191,10 |
(syshandler_t) sys_sysinfo_value, |
/* Debug calls */ |
(syshandler_t) sys_debug_enable_console |
(syshandler_t) sys_debug_enable_console, |
(syshandler_t) sys_debug_disable_console, |
(syshandler_t) sys_ipc_connect_kbox |
}; |
/** @} |
/branches/dd/kernel/generic/src/ipc/ipcrsc.c |
---|
170,7 → 170,6 |
int i; |
spinlock_lock(&TASK->lock); |
for (i = 0; i < IPC_MAX_PHONES; i++) { |
if (TASK->phones[i].state == IPC_PHONE_HUNGUP && |
atomic_get(&TASK->phones[i].active_calls) == 0) |
183,8 → 182,9 |
} |
spinlock_unlock(&TASK->lock); |
if (i >= IPC_MAX_PHONES) |
if (i == IPC_MAX_PHONES) |
return -1; |
return i; |
} |
/branches/dd/kernel/generic/src/ipc/kbox.c |
---|
0,0 → 1,284 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genericipc |
* @{ |
*/ |
/** @file |
*/ |
#include <synch/synch.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <ipc/ipc.h> |
#include <ipc/ipcrsc.h> |
#include <arch.h> |
#include <errno.h> |
#include <debug.h> |
#include <udebug/udebug_ipc.h> |
#include <ipc/kbox.h> |
#include <print.h> |
void ipc_kbox_cleanup(void) |
{ |
ipl_t ipl; |
bool have_kb_thread; |
/* |
* Only hold kb.cleanup_lock while setting kb.finished - |
* this is enough. |
*/ |
mutex_lock(&TASK->kb.cleanup_lock); |
TASK->kb.finished = true; |
mutex_unlock(&TASK->kb.cleanup_lock); |
have_kb_thread = (TASK->kb.thread != NULL); |
/* |
* From now on nobody will try to connect phones or attach |
* kbox threads |
*/ |
/* |
* Disconnect all phones connected to our kbox. Passing true for |
* notify_box causes a HANGUP message to be inserted for each |
* disconnected phone. This ensures the kbox thread is going to |
* wake up and terminate. |
*/ |
ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread); |
/* |
* If the task was being debugged, clean up debugging session. |
* This is necessarry as slamming the phones won't force |
* kbox thread to clean it up since sender != debugger. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
if (have_kb_thread) { |
LOG("join kb.thread..\n"); |
thread_join(TASK->kb.thread); |
thread_detach(TASK->kb.thread); |
LOG("join done\n"); |
TASK->kb.thread = NULL; |
} |
/* Answer all messages in 'calls' and 'dispatched_calls' queues. */ |
spinlock_lock(&TASK->kb.box.lock); |
ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls); |
ipc_cleanup_call_list(&TASK->kb.box.calls); |
spinlock_unlock(&TASK->kb.box.lock); |
} |
/** Handle hangup message in kbox. |
* |
* @param call The IPC_M_PHONE_HUNGUP call structure. |
* @param last Output, the function stores @c true here if |
* this was the last phone, @c false otherwise. |
**/ |
static void kbox_proc_phone_hungup(call_t *call, bool *last) |
{ |
ipl_t ipl; |
LOG("kbox_proc_phone_hungup()\n"); |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->udebug.debugger) { |
/* Terminate debugging session (if any). */ |
LOG("kbox: terminate debug session\n"); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} else { |
LOG("kbox: was not debugger\n"); |
} |
LOG("kbox: continue with hangup message\n"); |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kb.box, call); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
spinlock_lock(&TASK->kb.box.lock); |
if (list_empty(&TASK->kb.box.connected_phones)) { |
/* |
* Last phone has been disconnected. Detach this thread so it |
* gets freed and signal to the caller. |
*/ |
/* Only detach kbox thread unless already terminating. */ |
mutex_lock(&TASK->kb.cleanup_lock); |
if (&TASK->kb.finished == false) { |
/* Detach kbox thread so it gets freed from memory. */ |
thread_detach(TASK->kb.thread); |
TASK->kb.thread = NULL; |
} |
mutex_unlock(&TASK->kb.cleanup_lock); |
LOG("phone list is empty\n"); |
*last = true; |
} else { |
*last = false; |
} |
spinlock_unlock(&TASK->kb.box.lock); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} |
/** Implementing function for the kbox thread. |
* |
* This function listens for debug requests. It terminates |
* when all phones are disconnected from the kbox. |
* |
* @param arg Ignored. |
*/ |
static void kbox_thread_proc(void *arg) |
{ |
call_t *call; |
bool done; |
(void)arg; |
LOG("kbox_thread_proc()\n"); |
done = false; |
while (!done) { |
call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_NONE); |
if (call == NULL) |
continue; /* Try again. */ |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_DEBUG_ALL: |
/* Handle debug call. */ |
udebug_call_receive(call); |
break; |
case IPC_M_PHONE_HUNGUP: |
/* |
* Process the hangup call. If this was the last |
* phone, done will be set to true and the |
* while loop will terminate. |
*/ |
kbox_proc_phone_hungup(call, &done); |
break; |
default: |
/* Ignore */ |
break; |
} |
} |
LOG("kbox: finished\n"); |
} |
/** |
* Connect phone to a task kernel-box specified by id. |
* |
* Note that this is not completely atomic. For optimisation reasons, the task |
* might start cleaning up kbox after the phone has been connected and before |
* a kbox thread has been created. This must be taken into account in the |
* cleanup code. |
* |
* @return Phone id on success, or negative error code. |
*/ |
int ipc_connect_kbox(task_id_t taskid) |
{ |
int newphid; |
task_t *ta; |
thread_t *kb_thread; |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
ta = task_find_by_id(taskid); |
if (ta == NULL) { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
atomic_inc(&ta->refcount); |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
mutex_lock(&ta->kb.cleanup_lock); |
if (atomic_predec(&ta->refcount) == 0) { |
mutex_unlock(&ta->kb.cleanup_lock); |
task_destroy(ta); |
return ENOENT; |
} |
if (ta->kb.finished != false) { |
mutex_unlock(&ta->kb.cleanup_lock); |
return EINVAL; |
} |
newphid = phone_alloc(); |
if (newphid < 0) { |
mutex_unlock(&ta->kb.cleanup_lock); |
return ELIMIT; |
} |
/* Connect the newly allocated phone to the kbox */ |
ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box); |
if (ta->kb.thread != NULL) { |
mutex_unlock(&ta->kb.cleanup_lock); |
return newphid; |
} |
/* Create a kbox thread */ |
kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0, |
"kbox", false); |
if (!kb_thread) { |
mutex_unlock(&ta->kb.cleanup_lock); |
return ENOMEM; |
} |
ta->kb.thread = kb_thread; |
thread_ready(kb_thread); |
mutex_unlock(&ta->kb.cleanup_lock); |
return newphid; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/ipc/sysipc.c |
---|
42,8 → 42,9 |
#include <ipc/sysipc.h> |
#include <ipc/irq.h> |
#include <ipc/ipcrsc.h> |
#include <ipc/kbox.h> |
#include <udebug/udebug_ipc.h> |
#include <arch/interrupt.h> |
#include <print.h> |
#include <syscall/copy.h> |
#include <security/cap.h> |
#include <mm/as.h> |
270,12 → 271,12 |
/* The recipient agreed to receive data. */ |
int rc; |
uintptr_t dst; |
uintptr_t size; |
uintptr_t max_size; |
size_t size; |
size_t max_size; |
dst = IPC_GET_ARG1(answer->data); |
size = IPC_GET_ARG2(answer->data); |
max_size = IPC_GET_ARG2(*olddata); |
dst = (uintptr_t)IPC_GET_ARG1(answer->data); |
size = (size_t)IPC_GET_ARG2(answer->data); |
max_size = (size_t)IPC_GET_ARG2(*olddata); |
if (size <= max_size) { |
rc = copy_to_uspace((void *) dst, |
295,10 → 296,11 |
/** Called before the request is sent. |
* |
* @param call Call structure with the request. |
* @param phone Phone that the call will be sent through. |
* |
* @return Return 0 on success, ELIMIT or EPERM on error. |
*/ |
static int request_preprocess(call_t *call) |
static int request_preprocess(call_t *call, phone_t *phone) |
{ |
int newphid; |
size_t size; |
340,6 → 342,10 |
return rc; |
} |
break; |
#ifdef CONFIG_UDEBUG |
case IPC_M_DEBUG_ALL: |
return udebug_request_preprocess(call, phone); |
#endif |
default: |
break; |
} |
369,6 → 375,7 |
if (call->buffer) { |
/* This must be an affirmative answer to IPC_M_DATA_READ. */ |
/* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */ |
uintptr_t dst = IPC_GET_ARG1(call->data); |
size_t size = IPC_GET_ARG2(call->data); |
int rc = copy_to_uspace((void *) dst, call->buffer, size); |
399,7 → 406,13 |
return -1; |
} |
IPC_SET_ARG5(call->data, phoneid); |
} |
} |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_DEBUG_ALL: |
return -1; |
default: |
break; |
} |
return 0; |
} |
426,7 → 439,7 |
phone_t *phone; |
int res; |
int rc; |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
ipc_call_static_init(&call); |
441,9 → 454,18 |
IPC_SET_ARG4(call.data, 0); |
IPC_SET_ARG5(call.data, 0); |
if (!(res = request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
if (!(res = request_preprocess(&call, phone))) { |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_begin(); |
#endif |
rc = ipc_call_sync(phone, &call); |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_end(); |
#endif |
if (rc != EOK) |
return rc; |
process_answer(&call); |
} else { |
IPC_SET_RETVAL(call.data, res); |
} |
479,8 → 501,16 |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
if (!(res = request_preprocess(&call))) { |
ipc_call_sync(phone, &call); |
if (!(res = request_preprocess(&call, phone))) { |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_begin(); |
#endif |
rc = ipc_call_sync(phone, &call); |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_end(); |
#endif |
if (rc != EOK) |
return rc; |
process_answer(&call); |
} else |
IPC_SET_RETVAL(call.data, res); |
546,7 → 576,7 |
*/ |
IPC_SET_ARG5(call->data, 0); |
if (!(res = request_preprocess(call))) |
if (!(res = request_preprocess(call, phone))) |
ipc_call(phone, call); |
else |
ipc_backsend_err(phone, call, res); |
580,7 → 610,7 |
ipc_call_free(call); |
return (unative_t) rc; |
} |
if (!(res = request_preprocess(call))) |
if (!(res = request_preprocess(call, phone))) |
ipc_call(phone, call); |
else |
ipc_backsend_err(phone, call, res); |
588,7 → 618,8 |
return (unative_t) call; |
} |
/** Forward a received call to another destination. |
/** Forward a received call to another destination - common code for both the |
* fast and the slow version. |
* |
* @param callid Hash of the call to forward. |
* @param phoneid Phone handle to use for forwarding. |
595,23 → 626,21 |
* @param method New method to use for the forwarded call. |
* @param arg1 New value of the first argument for the forwarded call. |
* @param arg2 New value of the second argument for the forwarded call. |
* @param arg3 New value of the third argument for the forwarded call. |
* @param arg4 New value of the fourth argument for the forwarded call. |
* @param arg5 New value of the fifth argument for the forwarded call. |
* @param mode Flags that specify mode of the forward operation. |
* @param slow If true, arg3, arg4 and arg5 are considered. Otherwise |
* the function considers only the fast version arguments: |
* i.e. arg1 and arg2. |
* |
* @return Return 0 on succes, otherwise return an error code. |
* |
* In case the original method is a system method, ARG1, ARG2 and ARG3 are |
* overwritten in the forwarded message with the new method and the new arg1 and |
* arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are rewritten with |
* the new method, arg1 and arg2, respectively. Also note there is a set of |
* immutable methods, for which the new method and argument is not set and |
* these values are ignored. |
* |
* Warning: When implementing support for changing additional payload |
* arguments, make sure that ARG5 is not rewritten for certain |
* system IPC |
* Warning: Make sure that ARG5 is not rewritten for certain system IPC |
*/ |
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
unative_t method, unative_t arg1, unative_t arg2, int mode) |
static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid, |
unative_t method, unative_t arg1, unative_t arg2, unative_t arg3, |
unative_t arg4, unative_t arg5, int mode, bool slow) |
{ |
call_t *call; |
phone_t *phone; |
619,7 → 648,7 |
call = get_call(callid); |
if (!call) |
return ENOENT; |
call->flags |= IPC_CALL_FORWARDED; |
GET_CHECK_PHONE(phone, phoneid, { |
626,7 → 655,7 |
IPC_SET_RETVAL(call->data, EFORWARD); |
ipc_answer(&TASK->answerbox, call); |
return ENOENT; |
}); |
}); |
if (!method_is_forwardable(IPC_GET_METHOD(call->data))) { |
IPC_SET_RETVAL(call->data, EFORWARD); |
636,8 → 665,8 |
/* |
* Userspace is not allowed to change method of system methods on |
* forward, allow changing ARG1, ARG2 and ARG3 by means of method, |
* arg1 and arg2. |
* forward, allow changing ARG1, ARG2, ARG3 and ARG4 by means of method, |
* arg1, arg2 and arg3. |
* If the method is immutable, don't change anything. |
*/ |
if (!method_is_immutable(IPC_GET_METHOD(call->data))) { |
648,10 → 677,22 |
IPC_SET_ARG1(call->data, method); |
IPC_SET_ARG2(call->data, arg1); |
IPC_SET_ARG3(call->data, arg2); |
if (slow) { |
IPC_SET_ARG4(call->data, arg3); |
/* |
* For system methods we deliberately don't |
* overwrite ARG5. |
*/ |
} |
} else { |
IPC_SET_METHOD(call->data, method); |
IPC_SET_ARG1(call->data, arg1); |
IPC_SET_ARG2(call->data, arg2); |
if (slow) { |
IPC_SET_ARG3(call->data, arg3); |
IPC_SET_ARG4(call->data, arg4); |
IPC_SET_ARG5(call->data, arg5); |
} |
} |
} |
658,6 → 699,64 |
return ipc_forward(call, phone, &TASK->answerbox, mode); |
} |
/** Forward a received call to another destination - fast version. |
* |
* @param callid Hash of the call to forward. |
* @param phoneid Phone handle to use for forwarding. |
* @param method New method to use for the forwarded call. |
* @param arg1 New value of the first argument for the forwarded call. |
* @param arg2 New value of the second argument for the forwarded call. |
* @param mode Flags that specify mode of the forward operation. |
* |
* @return Return 0 on succes, otherwise return an error code. |
* |
* In case the original method is a system method, ARG1, ARG2 and ARG3 are |
* overwritten in the forwarded message with the new method and the new |
* arg1 and arg2, respectively. Otherwise the METHOD, ARG1 and ARG2 are |
* rewritten with the new method, arg1 and arg2, respectively. Also note there |
* is a set of immutable methods, for which the new method and arguments are not |
* set and these values are ignored. |
*/ |
unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, |
unative_t method, unative_t arg1, unative_t arg2, int mode) |
{ |
return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0, |
0, mode, false); |
} |
/** Forward a received call to another destination - slow version. |
* |
* @param callid Hash of the call to forward. |
* @param phoneid Phone handle to use for forwarding. |
* @param data Userspace address of the new IPC data. |
* @param mode Flags that specify mode of the forward operation. |
* |
* @return Return 0 on succes, otherwise return an error code. |
* |
* This function is the slow verision of the sys_ipc_forward_fast interface. |
* It can copy all five new arguments and the new method from the userspace. |
* It naturally extends the functionality of the fast version. For system |
* methods, it additionally stores the new value of arg3 to ARG4. For non-system |
* methods, it additionally stores the new value of arg3, arg4 and arg5, |
* respectively, to ARG3, ARG4 and ARG5, respectively. |
*/ |
unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid, |
ipc_data_t *data, int mode) |
{ |
ipc_data_t newdata; |
int rc; |
rc = copy_from_uspace(&newdata.args, &data->args, |
sizeof(newdata.args)); |
if (rc != 0) |
return (unative_t) rc; |
return sys_ipc_forward_common(callid, phoneid, |
IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata), |
IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata), |
IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true); |
} |
/** Answer an IPC call - fast version. |
* |
* This function can handle only two return arguments of payload, but is faster |
781,9 → 880,17 |
{ |
call_t *call; |
restart: |
restart: |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_begin(); |
#endif |
call = ipc_wait_for_call(&TASK->answerbox, usec, |
flags | SYNCH_FLAGS_INTERRUPTIBLE); |
#ifdef CONFIG_UDEBUG |
udebug_stoppable_end(); |
#endif |
if (!call) |
return 0; |
805,11 → 912,16 |
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
atomic_dec(&TASK->active_calls); |
if (call->flags & IPC_CALL_DISCARD_ANSWER) { |
ipc_call_free(call); |
goto restart; |
} else { |
/* |
* Decrement the counter of active calls only if the |
* call is not an answer to IPC_M_PHONE_HUNGUP, |
* which doesn't contribute to the counter. |
*/ |
atomic_dec(&TASK->active_calls); |
} |
STRUCT_TO_USPACE(&calldata->args, &call->data.args); |
824,6 → 936,21 |
/* Include phone address('id') of the caller in the request, |
* copy whole call->data, not only call->data.args */ |
if (STRUCT_TO_USPACE(calldata, &call->data)) { |
/* |
* The callee will not receive this call and no one else has |
* a chance to answer it. Reply with the EPARTY error code. |
*/ |
ipc_data_t saved_data; |
int saveddata = 0; |
if (answer_need_old(call)) { |
memcpy(&saved_data, &call->data, sizeof(call->data)); |
saveddata = 1; |
} |
IPC_SET_RETVAL(call->data, EPARTY); |
(void) answer_preprocess(call, saveddata ? &saved_data : NULL); |
ipc_answer(&TASK->answerbox, call); |
return 0; |
} |
return (unative_t)call; |
864,5 → 991,30 |
return 0; |
} |
#include <console/console.h> |
/** |
* Syscall connect to a task by id. |
* |
* @return Phone id on success, or negative error code. |
*/ |
unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg) |
{ |
#ifdef CONFIG_UDEBUG |
sysarg64_t taskid_arg; |
int rc; |
rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); |
if (rc != 0) |
return (unative_t) rc; |
LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value); |
return ipc_connect_kbox(taskid_arg.value); |
#else |
return (unative_t) ENOTSUP; |
#endif |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/ipc/ipc.c |
---|
43,6 → 43,7 |
#include <synch/waitq.h> |
#include <synch/synch.h> |
#include <ipc/ipc.h> |
#include <ipc/kbox.h> |
#include <errno.h> |
#include <mm/slab.h> |
#include <arch.h> |
51,6 → 52,7 |
#include <debug.h> |
#include <print.h> |
#include <console/console.h> |
#include <proc/thread.h> |
#include <arch/interrupt.h> |
#include <ipc/irq.h> |
66,7 → 68,7 |
*/ |
static void _ipc_call_init(call_t *call) |
{ |
memsetb((uintptr_t) call, sizeof(*call), 0); |
memsetb(call, sizeof(*call), 0); |
call->callerbox = &TASK->answerbox; |
call->sender = TASK; |
call->buffer = NULL; |
87,7 → 89,8 |
call_t *call; |
call = slab_alloc(ipc_call_slab, flags); |
_ipc_call_init(call); |
if (call) |
_ipc_call_init(call); |
return call; |
} |
160,7 → 163,7 |
*/ |
void ipc_phone_init(phone_t *phone) |
{ |
mutex_initialize(&phone->lock); |
mutex_initialize(&phone->lock, MUTEX_PASSIVE); |
phone->callee = NULL; |
phone->state = IPC_PHONE_FREE; |
atomic_set(&phone->active_calls, 0); |
170,8 → 173,10 |
* |
* @param phone Destination kernel phone structure. |
* @param request Call structure with request. |
* |
* @return EOK on success or EINTR if the sleep was interrupted. |
*/ |
void ipc_call_sync(phone_t *phone, call_t *request) |
int ipc_call_sync(phone_t *phone, call_t *request) |
{ |
answerbox_t sync_box; |
181,7 → 186,10 |
request->callerbox = &sync_box; |
ipc_call(phone, request); |
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_INTERRUPTIBLE)) |
return EINTR; |
return EOK; |
} |
/** Answer a message which was not dispatched and is not listed in any queue. |
194,6 → 202,13 |
call->flags |= IPC_CALL_ANSWERED; |
if (call->flags & IPC_CALL_FORWARDED) { |
if (call->caller_phone) { |
/* Demasquerade the caller phone. */ |
call->data.phone = call->caller_phone; |
} |
} |
spinlock_lock(&callerbox->lock); |
list_append(&call->link, &callerbox->answers); |
spinlock_unlock(&callerbox->lock); |
346,8 → 361,11 |
list_remove(&call->link); |
spinlock_unlock(&oldbox->lock); |
if (mode & IPC_FF_ROUTE_FROM_ME) |
if (mode & IPC_FF_ROUTE_FROM_ME) { |
if (!call->caller_phone) |
call->caller_phone = call->data.phone; |
call->data.phone = newphone; |
} |
return ipc_call(newphone, call); |
} |
411,7 → 429,7 |
* |
* @param lst Head of the list to be cleaned up. |
*/ |
static void ipc_cleanup_call_list(link_t *lst) |
void ipc_cleanup_call_list(link_t *lst) |
{ |
call_t *call; |
426,33 → 444,31 |
} |
} |
/** Cleans up all IPC communication of the current task. |
/** Disconnects all phones connected to an answerbox. |
* |
* Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
* have to change it as well if you want to cleanup other tasks than TASK. |
* @param box Answerbox to disconnect phones from. |
* @param notify_box If true, the answerbox will get a hangup message for |
* each disconnected phone. |
*/ |
void ipc_cleanup(void) |
void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) |
{ |
int i; |
call_t *call; |
phone_t *phone; |
DEADLOCK_PROBE_INIT(p_phonelck); |
ipl_t ipl; |
call_t *call; |
/* Disconnect all our phones ('ipc_phone_hangup') */ |
for (i = 0; i < IPC_MAX_PHONES; i++) |
ipc_phone_hangup(&TASK->phones[i]); |
call = notify_box ? ipc_call_alloc(0) : NULL; |
/* Disconnect all connected irqs */ |
ipc_irq_cleanup(&TASK->answerbox); |
/* Disconnect all phones connected to our answerbox */ |
restart_phones: |
spinlock_lock(&TASK->answerbox.lock); |
while (!list_empty(&TASK->answerbox.connected_phones)) { |
phone = list_get_instance(TASK->answerbox.connected_phones.next, |
ipl = interrupts_disable(); |
spinlock_lock(&box->lock); |
while (!list_empty(&box->connected_phones)) { |
phone = list_get_instance(box->connected_phones.next, |
phone_t, link); |
if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&box->lock); |
interrupts_restore(ipl); |
DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); |
goto restart_phones; |
} |
459,13 → 475,70 |
/* Disconnect phone */ |
ASSERT(phone->state == IPC_PHONE_CONNECTED); |
list_remove(&phone->link); |
phone->state = IPC_PHONE_SLAMMED; |
list_remove(&phone->link); |
if (notify_box) { |
mutex_unlock(&phone->lock); |
spinlock_unlock(&box->lock); |
interrupts_restore(ipl); |
/* |
* Send one message to the answerbox for each |
* phone. Used to make sure the kbox thread |
* wakes up after the last phone has been |
* disconnected. |
*/ |
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
call->flags |= IPC_CALL_DISCARD_ANSWER; |
_ipc_call(phone, box, call); |
/* Allocate another call in advance */ |
call = ipc_call_alloc(0); |
/* Must start again */ |
goto restart_phones; |
} |
mutex_unlock(&phone->lock); |
} |
spinlock_unlock(&box->lock); |
interrupts_restore(ipl); |
/* Free unused call */ |
if (call) |
ipc_call_free(call); |
} |
/** Cleans up all IPC communication of the current task. |
* |
* Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
* have to change it as well if you want to cleanup other tasks than TASK. |
*/ |
void ipc_cleanup(void) |
{ |
int i; |
call_t *call; |
/* Disconnect all our phones ('ipc_phone_hangup') */ |
for (i = 0; i < IPC_MAX_PHONES; i++) |
ipc_phone_hangup(&TASK->phones[i]); |
/* Disconnect all connected irqs */ |
ipc_irq_cleanup(&TASK->answerbox); |
/* Disconnect all phones connected to our regular answerbox */ |
ipc_answerbox_slam_phones(&TASK->answerbox, false); |
#ifdef CONFIG_UDEBUG |
/* Clean up kbox thread and communications */ |
ipc_kbox_cleanup(); |
#endif |
/* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
spinlock_lock(&TASK->answerbox.lock); |
ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
ipc_cleanup_call_list(&TASK->answerbox.calls); |
spinlock_unlock(&TASK->answerbox.lock); |
501,7 → 574,13 |
(call->flags & IPC_CALL_NOTIF)); |
ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); |
atomic_dec(&TASK->active_calls); |
/* |
* Record the receipt of this call in the current task's counter |
* of active calls. IPC_M_PHONE_HUNGUP calls do not contribute |
* to this counter so do not record answers to them either. |
*/ |
if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) |
atomic_dec(&TASK->active_calls); |
ipc_call_free(call); |
} |
} |
562,7 → 641,7 |
default: |
break; |
} |
printf("active: %d\n", |
printf("active: %ld\n", |
atomic_get(&task->phones[i].active_calls)); |
} |
mutex_unlock(&task->phones[i].lock); |
575,8 → 654,10 |
for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
584,12 → 665,14 |
} |
/* Print answerbox - calls */ |
printf("ABOX - DISPATCHED CALLS:\n"); |
for (tmp = task->answerbox.dispatched_calls.next; |
tmp != &task->answerbox.dispatched_calls; |
tmp = tmp->next) { |
for (tmp = task->answerbox.dispatched_calls.next; |
tmp != &task->answerbox.dispatched_calls; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%llu M:%d A1:%d A2:%d A3:%d " |
"A4:%d A5:%d Flags:%x\n", call, call->sender->taskid, |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
597,10 → 680,12 |
} |
/* Print answerbox - calls */ |
printf("ABOX - ANSWERS:\n"); |
for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers; |
for (tmp = task->answerbox.answers.next; |
tmp != &task->answerbox.answers; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid:%p M:%d A1:%d A2:%d A3:%d A4:%d A5:%d Flags:%x\n", |
printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun |
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
/branches/dd/kernel/generic/src/ipc/irq.c |
---|
44,8 → 44,28 |
* - ARG1: payload modified by a 'top-half' handler |
* - ARG2: payload modified by a 'top-half' handler |
* - ARG3: payload modified by a 'top-half' handler |
* - ARG4: payload modified by a 'top-half' handler |
* - ARG5: payload modified by a 'top-half' handler |
* - in_phone_hash: interrupt counter (may be needed to assure correct order |
* in multithreaded drivers) |
* |
* Note on synchronization for ipc_irq_register(), ipc_irq_unregister(), |
* ipc_irq_cleanup() and IRQ handlers: |
* |
* By always taking all of the uspace IRQ hash table lock, IRQ structure lock |
* and answerbox lock, we can rule out race conditions between the |
* registration functions and also the cleanup function. Thus the observer can |
* either see the IRQ structure present in both the hash table and the |
* answerbox list or absent in both. Views in which the IRQ structure would be |
* linked in the hash table but not in the answerbox list, or vice versa, are |
* not possible. |
* |
* By always taking the hash table lock and the IRQ structure lock, we can |
* rule out a scenario in which we would free up an IRQ structure, which is |
* still referenced by, for example, an IRQ handler. The locking scheme forces |
* us to lock the IRQ structure only after any progressing IRQs on that |
* structure are finished. Because we hold the hash table lock, we prevent new |
* IRQs from taking new references to the IRQ structure. |
*/ |
#include <arch.h> |
58,78 → 78,8 |
#include <console/console.h> |
#include <print.h> |
/** Execute code associated with IRQ notification. |
/** Free the top-half pseudocode. |
* |
* @param call Notification call. |
* @param code Top-half pseudocode. |
*/ |
static void code_execute(call_t *call, irq_code_t *code) |
{ |
unsigned int i; |
unative_t dstval = 0; |
if (!code) |
return; |
for (i = 0; i < code->cmdcount; i++) { |
switch (code->cmds[i].cmd) { |
case CMD_MEM_READ_1: |
dstval = *((uint8_t *) code->cmds[i].addr); |
break; |
case CMD_MEM_READ_2: |
dstval = *((uint16_t *) code->cmds[i].addr); |
break; |
case CMD_MEM_READ_4: |
dstval = *((uint32_t *) code->cmds[i].addr); |
break; |
case CMD_MEM_READ_8: |
dstval = *((uint64_t *) code->cmds[i].addr); |
break; |
case CMD_MEM_WRITE_1: |
*((uint8_t *) code->cmds[i].addr) = code->cmds[i].value; |
break; |
case CMD_MEM_WRITE_2: |
*((uint16_t *) code->cmds[i].addr) = |
code->cmds[i].value; |
break; |
case CMD_MEM_WRITE_4: |
*((uint32_t *) code->cmds[i].addr) = |
code->cmds[i].value; |
break; |
case CMD_MEM_WRITE_8: |
*((uint64_t *) code->cmds[i].addr) = |
code->cmds[i].value; |
break; |
#if defined(ia32) || defined(amd64) |
case CMD_PORT_READ_1: |
dstval = inb((long) code->cmds[i].addr); |
break; |
case CMD_PORT_WRITE_1: |
outb((long) code->cmds[i].addr, code->cmds[i].value); |
break; |
#endif |
#if defined(ia64) && defined(SKI) |
case CMD_IA64_GETCHAR: |
dstval = _getc(&ski_uconsole); |
break; |
#endif |
#if defined(ppc32) |
case CMD_PPC32_GETCHAR: |
dstval = cuda_get_scancode(); |
break; |
#endif |
default: |
break; |
} |
if (code->cmds[i].dstarg && code->cmds[i].dstarg < |
IPC_CALL_LEN) { |
call->data.args[code->cmds[i].dstarg] = dstval; |
} |
} |
} |
/** Free top-half pseudocode. |
* |
* @param code Pointer to the top-half pseudocode. |
*/ |
static void code_free(irq_code_t *code) |
140,7 → 90,7 |
} |
} |
/** Copy top-half pseudocode from userspace into the kernel. |
/** Copy the top-half pseudocode from userspace into the kernel. |
* |
* @param ucode Userspace address of the top-half pseudocode. |
* |
176,38 → 126,6 |
return code; |
} |
/** Unregister task from IRQ notification. |
* |
* @param box Answerbox associated with the notification. |
* @param inr IRQ number. |
* @param devno Device number. |
*/ |
void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) |
{ |
ipl_t ipl; |
irq_t *irq; |
ipl = interrupts_disable(); |
irq = irq_find_and_lock(inr, devno); |
if (irq) { |
if (irq->notif_cfg.answerbox == box) { |
code_free(irq->notif_cfg.code); |
irq->notif_cfg.notify = false; |
irq->notif_cfg.answerbox = NULL; |
irq->notif_cfg.code = NULL; |
irq->notif_cfg.method = 0; |
irq->notif_cfg.counter = 0; |
spinlock_lock(&box->irq_lock); |
list_remove(&irq->notif_cfg.link); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
} |
} |
interrupts_restore(ipl); |
} |
/** Register an answerbox as a receiving end for IRQ notifications. |
* |
* @param box Receiving answerbox. |
224,6 → 142,10 |
ipl_t ipl; |
irq_code_t *code; |
irq_t *irq; |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) devno |
}; |
if (ucode) { |
code = code_from_uspace(ucode); |
233,21 → 155,15 |
code = NULL; |
} |
ipl = interrupts_disable(); |
irq = irq_find_and_lock(inr, devno); |
if (!irq) { |
interrupts_restore(ipl); |
code_free(code); |
return ENOENT; |
} |
if (irq->notif_cfg.answerbox) { |
spinlock_unlock(&irq->lock); |
interrupts_restore(ipl); |
code_free(code); |
return EEXISTS; |
} |
/* |
* Allocate and populate the IRQ structure. |
*/ |
irq = malloc(sizeof(irq_t), 0); |
irq_initialize(irq); |
irq->devno = devno; |
irq->inr = inr; |
irq->claim = ipc_irq_top_half_claim; |
irq->handler = ipc_irq_top_half_handler; |
irq->notif_cfg.notify = true; |
irq->notif_cfg.answerbox = box; |
irq->notif_cfg.method = method; |
254,14 → 170,140 |
irq->notif_cfg.code = code; |
irq->notif_cfg.counter = 0; |
/* |
* Enlist the IRQ structure in the uspace IRQ hash table and the |
* answerbox's list. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&irq_uspace_hash_table_lock); |
spinlock_lock(&irq->lock); |
spinlock_lock(&box->irq_lock); |
if (hash_table_find(&irq_uspace_hash_table, key)) { |
code_free(code); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
free(irq); |
interrupts_restore(ipl); |
return EEXISTS; |
} |
hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
list_append(&irq->notif_cfg.link, &box->irq_head); |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
interrupts_restore(ipl); |
return EOK; |
} |
/** Unregister task from IRQ notification. |
* |
* @param box Answerbox associated with the notification. |
* @param inr IRQ number. |
* @param devno Device number. |
*/ |
int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) |
{ |
ipl_t ipl; |
unative_t key[] = { |
(unative_t) inr, |
(unative_t) devno |
}; |
link_t *lnk; |
irq_t *irq; |
ipl = interrupts_disable(); |
spinlock_lock(&irq_uspace_hash_table_lock); |
lnk = hash_table_find(&irq_uspace_hash_table, key); |
if (!lnk) { |
spinlock_unlock(&irq_uspace_hash_table_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_lock(&irq->lock); |
spinlock_lock(&box->irq_lock); |
ASSERT(irq->notif_cfg.answerbox == box); |
/* Free up the pseudo code and associated structures. */ |
code_free(irq->notif_cfg.code); |
/* Remove the IRQ from the answerbox's list. */ |
list_remove(&irq->notif_cfg.link); |
/* Remove the IRQ from the uspace IRQ hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&box->irq_lock); |
/* Free up the IRQ structure. */ |
free(irq); |
interrupts_restore(ipl); |
return EOK; |
} |
return 0; |
/** Disconnect all IRQ notifications from an answerbox. |
* |
* This function is effective because the answerbox contains |
* list of all irq_t structures that are registered to |
* send notifications to it. |
* |
* @param box Answerbox for which we want to carry out the cleanup. |
*/ |
void ipc_irq_cleanup(answerbox_t *box) |
{ |
ipl_t ipl; |
loop: |
ipl = interrupts_disable(); |
spinlock_lock(&irq_uspace_hash_table_lock); |
spinlock_lock(&box->irq_lock); |
while (box->irq_head.next != &box->irq_head) { |
link_t *cur = box->irq_head.next; |
irq_t *irq; |
DEADLOCK_PROBE_INIT(p_irqlock); |
unative_t key[2]; |
irq = list_get_instance(cur, irq_t, notif_cfg.link); |
if (!spinlock_trylock(&irq->lock)) { |
/* |
* Avoid deadlock by trying again. |
*/ |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
interrupts_restore(ipl); |
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD); |
goto loop; |
} |
key[0] = irq->inr; |
key[1] = irq->devno; |
ASSERT(irq->notif_cfg.answerbox == box); |
/* Unlist from the answerbox. */ |
list_remove(&irq->notif_cfg.link); |
/* Remove from the hash table. */ |
hash_table_remove(&irq_uspace_hash_table, key, 2); |
/* Free up the pseudo code and associated structures. */ |
code_free(irq->notif_cfg.code); |
spinlock_unlock(&irq->lock); |
free(irq); |
} |
spinlock_unlock(&box->irq_lock); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
interrupts_restore(ipl); |
} |
/** Add a call to the proper answerbox queue. |
280,125 → 322,158 |
waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST); |
} |
/** Send notification message. |
/** Apply the top-half pseudo code to find out whether to accept the IRQ or not. |
* |
* @param irq IRQ structure. |
* @param a1 Driver-specific payload argument. |
* @param a2 Driver-specific payload argument. |
* @param a3 Driver-specific payload argument. |
* @param a4 Driver-specific payload argument. |
* @param a5 Driver-specific payload argument. |
* |
* @return IRQ_ACCEPT if the interrupt is accepted by the |
* pseudocode. IRQ_DECLINE otherwise. |
*/ |
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5) |
irq_ownership_t ipc_irq_top_half_claim(irq_t *irq) |
{ |
call_t *call; |
unsigned int i; |
unative_t dstval; |
irq_code_t *code = irq->notif_cfg.code; |
unative_t *scratch = irq->notif_cfg.scratch; |
spinlock_lock(&irq->lock); |
if (irq->notif_cfg.answerbox) { |
call = ipc_call_alloc(FRAME_ATOMIC); |
if (!call) { |
spinlock_unlock(&irq->lock); |
return; |
if (!irq->notif_cfg.notify) |
return IRQ_DECLINE; |
if (!code) |
return IRQ_DECLINE; |
for (i = 0; i < code->cmdcount; i++) { |
unsigned int srcarg = code->cmds[i].srcarg; |
unsigned int dstarg = code->cmds[i].dstarg; |
if (srcarg >= IPC_CALL_LEN) |
break; |
if (dstarg >= IPC_CALL_LEN) |
break; |
switch (code->cmds[i].cmd) { |
case CMD_PIO_READ_8: |
dstval = pio_read_8((ioport8_t *) code->cmds[i].addr); |
if (dstarg) |
scratch[dstarg] = dstval; |
break; |
case CMD_PIO_READ_16: |
dstval = pio_read_16((ioport16_t *) code->cmds[i].addr); |
if (dstarg) |
scratch[dstarg] = dstval; |
break; |
case CMD_PIO_READ_32: |
dstval = pio_read_32((ioport32_t *) code->cmds[i].addr); |
if (dstarg) |
scratch[dstarg] = dstval; |
break; |
case CMD_PIO_WRITE_8: |
pio_write_8((ioport8_t *) code->cmds[i].addr, |
(uint8_t) code->cmds[i].value); |
break; |
case CMD_PIO_WRITE_16: |
pio_write_16((ioport16_t *) code->cmds[i].addr, |
(uint16_t) code->cmds[i].value); |
break; |
case CMD_PIO_WRITE_32: |
pio_write_32((ioport32_t *) code->cmds[i].addr, |
(uint32_t) code->cmds[i].value); |
break; |
case CMD_BTEST: |
if (srcarg && dstarg) { |
dstval = scratch[srcarg] & code->cmds[i].value; |
scratch[dstarg] = dstval; |
} |
break; |
case CMD_PREDICATE: |
if (srcarg && !scratch[srcarg]) { |
i += code->cmds[i].value; |
continue; |
} |
break; |
case CMD_ACCEPT: |
return IRQ_ACCEPT; |
break; |
case CMD_DECLINE: |
default: |
return IRQ_DECLINE; |
} |
call->flags |= IPC_CALL_NOTIF; |
IPC_SET_METHOD(call->data, irq->notif_cfg.method); |
IPC_SET_ARG1(call->data, a1); |
IPC_SET_ARG2(call->data, a2); |
IPC_SET_ARG3(call->data, a3); |
IPC_SET_ARG4(call->data, a4); |
IPC_SET_ARG5(call->data, a5); |
/* Put a counter to the message */ |
call->priv = ++irq->notif_cfg.counter; |
send_call(irq, call); |
} |
spinlock_unlock(&irq->lock); |
return IRQ_DECLINE; |
} |
/** Notify a task that an IRQ had occurred. |
/* IRQ top-half handler. |
* |
* We expect interrupts to be disabled and the irq->lock already held. |
* |
* @param irq IRQ structure. |
*/ |
void ipc_irq_send_notif(irq_t *irq) |
void ipc_irq_top_half_handler(irq_t *irq) |
{ |
call_t *call; |
ASSERT(irq); |
if (irq->notif_cfg.answerbox) { |
call_t *call; |
call = ipc_call_alloc(FRAME_ATOMIC); |
if (!call) { |
if (!call) |
return; |
} |
call->flags |= IPC_CALL_NOTIF; |
/* Put a counter to the message */ |
call->priv = ++irq->notif_cfg.counter; |
/* Set up args */ |
IPC_SET_METHOD(call->data, irq->notif_cfg.method); |
IPC_SET_ARG1(call->data, irq->notif_cfg.scratch[1]); |
IPC_SET_ARG2(call->data, irq->notif_cfg.scratch[2]); |
IPC_SET_ARG3(call->data, irq->notif_cfg.scratch[3]); |
IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]); |
IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]); |
/* Execute code to handle irq */ |
code_execute(call, irq->notif_cfg.code); |
send_call(irq, call); |
} |
} |
/** Disconnect all IRQ notifications from an answerbox. |
/** Send notification message. |
* |
* This function is effective because the answerbox contains |
* list of all irq_t structures that are registered to |
* send notifications to it. |
* |
* @param box Answerbox for which we want to carry out the cleanup. |
* @param irq IRQ structure. |
* @param a1 Driver-specific payload argument. |
* @param a2 Driver-specific payload argument. |
* @param a3 Driver-specific payload argument. |
* @param a4 Driver-specific payload argument. |
* @param a5 Driver-specific payload argument. |
*/ |
void ipc_irq_cleanup(answerbox_t *box) |
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5) |
{ |
ipl_t ipl; |
loop: |
ipl = interrupts_disable(); |
spinlock_lock(&box->irq_lock); |
while (box->irq_head.next != &box->irq_head) { |
link_t *cur = box->irq_head.next; |
irq_t *irq; |
DEADLOCK_PROBE_INIT(p_irqlock); |
irq = list_get_instance(cur, irq_t, notif_cfg.link); |
if (!spinlock_trylock(&irq->lock)) { |
/* |
* Avoid deadlock by trying again. |
*/ |
spinlock_unlock(&box->irq_lock); |
interrupts_restore(ipl); |
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD); |
goto loop; |
call_t *call; |
spinlock_lock(&irq->lock); |
if (irq->notif_cfg.answerbox) { |
call = ipc_call_alloc(FRAME_ATOMIC); |
if (!call) { |
spinlock_unlock(&irq->lock); |
return; |
} |
call->flags |= IPC_CALL_NOTIF; |
/* Put a counter to the message */ |
call->priv = ++irq->notif_cfg.counter; |
IPC_SET_METHOD(call->data, irq->notif_cfg.method); |
IPC_SET_ARG1(call->data, a1); |
IPC_SET_ARG2(call->data, a2); |
IPC_SET_ARG3(call->data, a3); |
IPC_SET_ARG4(call->data, a4); |
IPC_SET_ARG5(call->data, a5); |
ASSERT(irq->notif_cfg.answerbox == box); |
list_remove(&irq->notif_cfg.link); |
/* |
* Don't forget to free any top-half pseudocode. |
*/ |
code_free(irq->notif_cfg.code); |
irq->notif_cfg.notify = false; |
irq->notif_cfg.answerbox = NULL; |
irq->notif_cfg.code = NULL; |
irq->notif_cfg.method = 0; |
irq->notif_cfg.counter = 0; |
spinlock_unlock(&irq->lock); |
send_call(irq, call); |
} |
spinlock_unlock(&box->irq_lock); |
interrupts_restore(ipl); |
spinlock_unlock(&irq->lock); |
} |
/** @} |
/branches/dd/kernel/generic/src/udebug/udebug.c |
---|
0,0 → 1,504 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Udebug hooks and data structure management. |
* |
* Udebug is an interface that makes userspace debuggers possible. |
*/ |
#include <synch/waitq.h> |
#include <debug.h> |
#include <udebug/udebug.h> |
#include <errno.h> |
#include <print.h> |
#include <arch.h> |
/** Initialize udebug part of task structure. |
* |
* Called as part of task structure initialization. |
* @param ut Pointer to the structure to initialize. |
*/ |
void udebug_task_init(udebug_task_t *ut) |
{ |
mutex_initialize(&ut->lock, MUTEX_PASSIVE); |
ut->dt_state = UDEBUG_TS_INACTIVE; |
ut->begin_call = NULL; |
ut->not_stoppable_count = 0; |
ut->evmask = 0; |
} |
/** Initialize udebug part of thread structure. |
* |
* Called as part of thread structure initialization. |
* @param ut Pointer to the structure to initialize. |
*/ |
void udebug_thread_initialize(udebug_thread_t *ut) |
{ |
mutex_initialize(&ut->lock, MUTEX_PASSIVE); |
waitq_initialize(&ut->go_wq); |
ut->go_call = NULL; |
ut->uspace_state = NULL; |
ut->go = false; |
ut->stoppable = true; |
ut->active = false; |
ut->cur_event = 0; /* none */ |
} |
/** Wait for a GO message. |
* |
* When a debugging event occurs in a thread or the thread is stopped, |
* this function is called to block the thread until a GO message |
* is received. |
* |
* @param wq The wait queue used by the thread to wait for GO messages. |
*/ |
static void udebug_wait_for_go(waitq_t *wq) |
{ |
int rc; |
ipl_t ipl; |
ipl = waitq_sleep_prepare(wq); |
wq->missed_wakeups = 0; /* Enforce blocking. */ |
rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
waitq_sleep_finish(wq, rc, ipl); |
} |
/** Do a preliminary check that a debugging session is in progress. |
* |
* This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock |
* mutex). For an undebugged task, this will never block (while there could be |
* collisions by different threads on the TASK mutex), thus improving SMP |
* perormance for undebugged tasks. |
* |
* @return True if the thread was in a debugging session when the function |
* checked, false otherwise. |
*/ |
static bool udebug_thread_precheck(void) |
{ |
bool res; |
mutex_lock(&THREAD->udebug.lock); |
res = THREAD->udebug.active; |
mutex_unlock(&THREAD->udebug.lock); |
return res; |
} |
/** Start of stoppable section. |
* |
* A stoppable section is a section of code where if the thread can be stoped. In other words, |
* if a STOP operation is issued, the thread is guaranteed not to execute |
* any userspace instructions until the thread is resumed. |
* |
* Having stoppable sections is better than having stopping points, since |
* a thread can be stopped even when it is blocked indefinitely in a system |
* call (whereas it would not reach any stopping point). |
*/ |
void udebug_stoppable_begin(void) |
{ |
int nsc; |
call_t *db_call, *go_call; |
ASSERT(THREAD); |
ASSERT(TASK); |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
mutex_lock(&TASK->udebug.lock); |
nsc = --TASK->udebug.not_stoppable_count; |
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */ |
mutex_lock(&THREAD->udebug.lock); |
ASSERT(THREAD->udebug.stoppable == false); |
THREAD->udebug.stoppable = true; |
if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING && nsc == 0) { |
/* |
* This was the last non-stoppable thread. Reply to |
* DEBUG_BEGIN call. |
*/ |
db_call = TASK->udebug.begin_call; |
ASSERT(db_call); |
TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
TASK->udebug.begin_call = NULL; |
IPC_SET_RETVAL(db_call->data, 0); |
ipc_answer(&TASK->answerbox, db_call); |
} else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
/* |
* Active debugging session |
*/ |
if (THREAD->udebug.active == true && |
THREAD->udebug.go == false) { |
/* |
* Thread was requested to stop - answer go call |
*/ |
/* Make sure nobody takes this call away from us */ |
go_call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
ASSERT(go_call); |
IPC_SET_RETVAL(go_call->data, 0); |
IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP); |
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP; |
ipc_answer(&TASK->answerbox, go_call); |
} |
} |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
} |
/** End of a stoppable section. |
* |
* This is the point where the thread will block if it is stopped. |
* (As, by definition, a stopped thread must not leave its stoppable section). |
*/ |
void udebug_stoppable_end(void) |
{ |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
restart: |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
if (THREAD->udebug.active && THREAD->udebug.go == false) { |
TASK->udebug.begin_call = NULL; |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
udebug_wait_for_go(&THREAD->udebug.go_wq); |
goto restart; |
/* Must try again - have to lose stoppability atomically. */ |
} else { |
++TASK->udebug.not_stoppable_count; |
ASSERT(THREAD->udebug.stoppable == true); |
THREAD->udebug.stoppable = false; |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
} |
} |
/** Upon being scheduled to run, check if the current thread should stop. |
* |
* This function is called from clock(). |
*/ |
void udebug_before_thread_runs(void) |
{ |
/* Check if we're supposed to stop */ |
udebug_stoppable_begin(); |
udebug_stoppable_end(); |
} |
/** Syscall event hook. |
* |
* Must be called before and after servicing a system call. This generates |
* a SYSCALL_B or SYSCALL_E event, depending on the value of @a end_variant. |
*/ |
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc, |
bool end_variant) |
{ |
call_t *call; |
udebug_event_t etype; |
etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
/* Must only generate events when in debugging session and is go. */ |
if (THREAD->udebug.active != true || THREAD->udebug.go == false || |
(TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
} |
//printf("udebug_syscall_event\n"); |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, etype); |
IPC_SET_ARG2(call->data, id); |
IPC_SET_ARG3(call->data, rc); |
//printf("udebug_syscall_event/ipc_answer\n"); |
THREAD->udebug.syscall_args[0] = a1; |
THREAD->udebug.syscall_args[1] = a2; |
THREAD->udebug.syscall_args[2] = a3; |
THREAD->udebug.syscall_args[3] = a4; |
THREAD->udebug.syscall_args[4] = a5; |
THREAD->udebug.syscall_args[5] = a6; |
/* |
* Make sure udebug.go is false when going to sleep |
* in case we get woken up by DEBUG_END. (At which |
* point it must be back to the initial true value). |
*/ |
THREAD->udebug.go = false; |
THREAD->udebug.cur_event = etype; |
ipc_answer(&TASK->answerbox, call); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
udebug_wait_for_go(&THREAD->udebug.go_wq); |
} |
/** Thread-creation event hook combined with attaching the thread. |
* |
* Must be called when a new userspace thread is created in the debugged |
* task. Generates a THREAD_B event. Also attaches the thread @a t |
* to the task @a ta. |
* |
* This is necessary to avoid a race condition where the BEGIN and THREAD_READ |
* requests would be handled inbetween attaching the thread and checking it |
* for being in a debugging session to send the THREAD_B event. We could then |
* either miss threads or get some threads both in the thread list |
* and get a THREAD_B event for them. |
* |
* @param t Structure of the thread being created. Not locked, as the |
* thread is not executing yet. |
* @param ta Task to which the thread should be attached. |
*/ |
void udebug_thread_b_event_attach(struct thread *t, struct task *ta) |
{ |
call_t *call; |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
thread_attach(t, ta); |
LOG("udebug_thread_b_event\n"); |
LOG("- check state\n"); |
/* Must only generate events when in debugging session */ |
if (THREAD->udebug.active != true) { |
LOG("- udebug.active: %s, udebug.go: %s\n", |
THREAD->udebug.active ? "yes(+)" : "no(-)", |
THREAD->udebug.go ? "yes(-)" : "no(+)"); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
} |
LOG("- trigger event\n"); |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B); |
IPC_SET_ARG2(call->data, (unative_t)t); |
/* |
* Make sure udebug.go is false when going to sleep |
* in case we get woken up by DEBUG_END. (At which |
* point it must be back to the initial true value). |
*/ |
THREAD->udebug.go = false; |
THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B; |
ipc_answer(&TASK->answerbox, call); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
LOG("- sleep\n"); |
udebug_wait_for_go(&THREAD->udebug.go_wq); |
} |
/** Thread-termination event hook. |
* |
* Must be called when the current thread is terminating. |
* Generates a THREAD_E event. |
*/ |
void udebug_thread_e_event(void) |
{ |
call_t *call; |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
LOG("udebug_thread_e_event\n"); |
LOG("- check state\n"); |
/* Must only generate events when in debugging session. */ |
if (THREAD->udebug.active != true) { |
/* printf("- udebug.active: %s, udebug.go: %s\n", |
THREAD->udebug.active ? "yes(+)" : "no(-)", |
THREAD->udebug.go ? "yes(-)" : "no(+)");*/ |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
} |
LOG("- trigger event\n"); |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
/* Prevent any further debug activity in thread. */ |
THREAD->udebug.active = false; |
THREAD->udebug.cur_event = 0; /* none */ |
THREAD->udebug.go = false; /* set to initial value */ |
ipc_answer(&TASK->answerbox, call); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
/* |
* This event does not sleep - debugging has finished |
* in this thread. |
*/ |
} |
/** |
* Terminate task debugging session. |
* |
* Gracefully terminates the debugging session for a task. If the debugger |
* is still waiting for events on some threads, it will receive a |
* FINISHED event for each of them. |
* |
* @param ta Task structure. ta->udebug.lock must be already locked. |
* @return Zero on success or negative error code. |
*/ |
int udebug_task_cleanup(struct task *ta) |
{ |
thread_t *t; |
link_t *cur; |
int flags; |
ipl_t ipl; |
LOG("udebug_task_cleanup()\n"); |
LOG("task %" PRIu64 "\n", ta->taskid); |
if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING && |
ta->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
LOG("udebug_task_cleanup(): task not being debugged\n"); |
return EINVAL; |
} |
/* Finish debugging of all userspace threads */ |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
mutex_lock(&t->udebug.lock); |
ipl = interrupts_disable(); |
spinlock_lock(&t->lock); |
flags = t->flags; |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
/* Only process userspace threads. */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Prevent any further debug activity in thread. */ |
t->udebug.active = false; |
t->udebug.cur_event = 0; /* none */ |
/* Is the thread still go? */ |
if (t->udebug.go == true) { |
/* |
* Yes, so clear go. As active == false, |
* this doesn't affect anything. |
*/ |
t->udebug.go = false; |
/* Answer GO call */ |
LOG("answer GO call with EVENT_FINISHED\n"); |
IPC_SET_RETVAL(t->udebug.go_call->data, 0); |
IPC_SET_ARG1(t->udebug.go_call->data, |
UDEBUG_EVENT_FINISHED); |
ipc_answer(&ta->answerbox, t->udebug.go_call); |
t->udebug.go_call = NULL; |
} else { |
/* |
* Debug_stop is already at initial value. |
* Yet this means the thread needs waking up. |
*/ |
/* |
* t's lock must not be held when calling |
* waitq_wakeup. |
*/ |
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST); |
} |
} |
mutex_unlock(&t->udebug.lock); |
} |
ta->udebug.dt_state = UDEBUG_TS_INACTIVE; |
ta->udebug.debugger = NULL; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/udebug/udebug_ops.c |
---|
0,0 → 1,524 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Udebug operations. |
* |
* Udebug operations on tasks and threads are implemented here. The |
* functions defined here are called from the udebug_ipc module |
* when servicing udebug IPC messages. |
*/ |
#include <debug.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <errno.h> |
#include <print.h> |
#include <syscall/copy.h> |
#include <ipc/ipc.h> |
#include <udebug/udebug.h> |
#include <udebug/udebug_ops.h> |
/** |
* Prepare a thread for a debugging operation. |
* |
* Simply put, return thread t with t->udebug.lock held, |
* but only if it verifies all conditions. |
* |
* Specifically, verifies that thread t exists, is a userspace thread, |
* and belongs to the current task (TASK). Verifies, that the thread |
* is (or is not) go according to being_go (typically false). |
* It also locks t->udebug.lock, making sure that t->udebug.active |
* is true - that the thread is in a valid debugging session. |
* |
* With this verified and the t->udebug.lock mutex held, it is ensured |
* that the thread cannot leave the debugging session, let alone cease |
* to exist. |
* |
* In this function, holding the TASK->udebug.lock mutex prevents the |
* thread from leaving the debugging session, while relaxing from |
* the t->lock spinlock to the t->udebug.lock mutex. |
* |
* @param t Pointer, need not at all be valid. |
* @param being_go Required thread state. |
* |
* Returns EOK if all went well, or an error code otherwise. |
*/ |
static int _thread_op_begin(thread_t *t, bool being_go) |
{ |
task_id_t taskid; |
ipl_t ipl; |
taskid = TASK->taskid; |
mutex_lock(&TASK->udebug.lock); |
/* thread_exists() must be called with threads_lock held */ |
ipl = interrupts_disable(); |
spinlock_lock(&threads_lock); |
if (!thread_exists(t)) { |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
mutex_unlock(&TASK->udebug.lock); |
return ENOENT; |
} |
/* t->lock is enough to ensure the thread's existence */ |
spinlock_lock(&t->lock); |
spinlock_unlock(&threads_lock); |
/* Verify that 't' is a userspace thread. */ |
if ((t->flags & THREAD_FLAG_USPACE) == 0) { |
/* It's not, deny its existence */ |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
mutex_unlock(&TASK->udebug.lock); |
return ENOENT; |
} |
/* Verify debugging state. */ |
if (t->udebug.active != true) { |
/* Not in debugging session or undesired GO state */ |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
mutex_unlock(&TASK->udebug.lock); |
return ENOENT; |
} |
/* |
* Since the thread has active == true, TASK->udebug.lock |
* is enough to ensure its existence and that active remains |
* true. |
*/ |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
/* Only mutex TASK->udebug.lock left. */ |
/* Now verify that the thread belongs to the current task. */ |
if (t->task != TASK) { |
/* No such thread belonging this task*/ |
mutex_unlock(&TASK->udebug.lock); |
return ENOENT; |
} |
/* |
* Now we need to grab the thread's debug lock for synchronization |
* of the threads stoppability/stop state. |
*/ |
mutex_lock(&t->udebug.lock); |
/* The big task mutex is no longer needed. */ |
mutex_unlock(&TASK->udebug.lock); |
if (t->udebug.go != being_go) { |
/* Not in debugging session or undesired GO state. */ |
mutex_unlock(&t->udebug.lock); |
return EINVAL; |
} |
/* Only t->udebug.lock left. */ |
return EOK; /* All went well. */ |
} |
/** End debugging operation on a thread. */ |
static void _thread_op_end(thread_t *t) |
{ |
mutex_unlock(&t->udebug.lock); |
} |
/** Begin debugging the current task. |
* |
* Initiates a debugging session for the current task (and its threads). |
* When the debugging session has started a reply will be sent to the |
* UDEBUG_BEGIN call. This may happen immediately in this function if |
* all the threads in this task are stoppable at the moment and in this |
* case the function returns 1. |
* |
* Otherwise the function returns 0 and the reply will be sent as soon as |
* all the threads become stoppable (i.e. they can be considered stopped). |
* |
* @param call The BEGIN call we are servicing. |
* @return 0 (OK, but not done yet), 1 (done) or negative error code. |
*/ |
int udebug_begin(call_t *call) |
{ |
int reply; |
thread_t *t; |
link_t *cur; |
LOG("udebug_begin()\n"); |
mutex_lock(&TASK->udebug.lock); |
LOG("debugging task %llu\n", TASK->taskid); |
if (TASK->udebug.dt_state != UDEBUG_TS_INACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_begin(): busy error\n"); |
return EBUSY; |
} |
TASK->udebug.dt_state = UDEBUG_TS_BEGINNING; |
TASK->udebug.begin_call = call; |
TASK->udebug.debugger = call->sender; |
if (TASK->udebug.not_stoppable_count == 0) { |
TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
TASK->udebug.begin_call = NULL; |
reply = 1; /* immediate reply */ |
} else { |
reply = 0; /* no reply */ |
} |
/* Set udebug.active on all of the task's userspace threads. */ |
for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
mutex_lock(&t->udebug.lock); |
if ((t->flags & THREAD_FLAG_USPACE) != 0) |
t->udebug.active = true; |
mutex_unlock(&t->udebug.lock); |
} |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_begin() done (%s)\n", |
reply ? "reply" : "stoppability wait"); |
return reply; |
} |
/** Finish debugging the current task. |
* |
* Closes the debugging session for the current task. |
* @return Zero on success or negative error code. |
*/ |
int udebug_end(void) |
{ |
int rc; |
LOG("udebug_end()\n"); |
mutex_lock(&TASK->udebug.lock); |
LOG("task %" PRIu64 "\n", TASK->taskid); |
rc = udebug_task_cleanup(TASK); |
mutex_unlock(&TASK->udebug.lock); |
return rc; |
} |
/** Set the event mask. |
* |
* Sets the event mask that determines which events are enabled. |
* |
* @param mask Or combination of events that should be enabled. |
* @return Zero on success or negative error code. |
*/ |
int udebug_set_evmask(udebug_evmask_t mask) |
{ |
LOG("udebug_set_mask()\n"); |
mutex_lock(&TASK->udebug.lock); |
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_set_mask(): not active debuging session\n"); |
return EINVAL; |
} |
TASK->udebug.evmask = mask; |
mutex_unlock(&TASK->udebug.lock); |
return 0; |
} |
/** Give thread GO. |
* |
* Upon recieving a go message, the thread is given GO. Being GO |
* means the thread is allowed to execute userspace code (until |
* a debugging event or STOP occurs, at which point the thread loses GO. |
* |
* @param t The thread to operate on (unlocked and need not be valid). |
* @param call The GO call that we are servicing. |
*/ |
int udebug_go(thread_t *t, call_t *call) |
{ |
int rc; |
/* On success, this will lock t->udebug.lock. */ |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
return rc; |
} |
t->udebug.go_call = call; |
t->udebug.go = true; |
t->udebug.cur_event = 0; /* none */ |
/* |
* Neither t's lock nor threads_lock may be held during wakeup. |
*/ |
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST); |
_thread_op_end(t); |
return 0; |
} |
/** Stop a thread (i.e. take its GO away) |
* |
* Generates a STOP event as soon as the thread becomes stoppable (i.e. |
* can be considered stopped). |
* |
* @param t The thread to operate on (unlocked and need not be valid). |
* @param call The GO call that we are servicing. |
*/ |
int udebug_stop(thread_t *t, call_t *call) |
{ |
int rc; |
LOG("udebug_stop()\n"); |
/* |
* On success, this will lock t->udebug.lock. Note that this makes sure |
* the thread is not stopped. |
*/ |
rc = _thread_op_begin(t, true); |
if (rc != EOK) { |
return rc; |
} |
/* Take GO away from the thread. */ |
t->udebug.go = false; |
if (t->udebug.stoppable != true) { |
/* Answer will be sent when the thread becomes stoppable. */ |
_thread_op_end(t); |
return 0; |
} |
/* |
* Answer GO call. |
*/ |
LOG("udebug_stop - answering go call\n"); |
/* Make sure nobody takes this call away from us. */ |
call = t->udebug.go_call; |
t->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP); |
LOG("udebug_stop/ipc_answer\n"); |
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP; |
_thread_op_end(t); |
mutex_lock(&TASK->udebug.lock); |
ipc_answer(&TASK->answerbox, call); |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebog_stop/done\n"); |
return 0; |
} |
/** Read the list of userspace threads in the current task. |
* |
* The list takes the form of a sequence of thread hashes (i.e. the pointers |
* to thread structures). A buffer of size @a buf_size is allocated and |
* a pointer to it written to @a buffer. The sequence of hashes is written |
* into this buffer. |
* |
* If the sequence is longer than @a buf_size bytes, only as much hashes |
* as can fit are copied. The number of thread hashes copied is stored |
* in @a n. |
* |
* The rationale for having @a buf_size is that this function is only |
* used for servicing the THREAD_READ message, which always specifies |
* a maximum size for the userspace buffer. |
* |
* @param buffer The buffer for storing thread hashes. |
* @param buf_size Buffer size in bytes. |
* @param n The actual number of hashes copied will be stored here. |
*/ |
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n) |
{ |
thread_t *t; |
link_t *cur; |
unative_t tid; |
unsigned copied_ids; |
ipl_t ipl; |
unative_t *id_buffer; |
int flags; |
size_t max_ids; |
LOG("udebug_thread_read()\n"); |
/* Allocate a buffer to hold thread IDs */ |
id_buffer = malloc(buf_size, 0); |
mutex_lock(&TASK->udebug.lock); |
/* Verify task state */ |
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
return EINVAL; |
} |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
/* Copy down the thread IDs */ |
max_ids = buf_size / sizeof(unative_t); |
copied_ids = 0; |
/* FIXME: make sure the thread isn't past debug shutdown... */ |
for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
/* Do not write past end of buffer */ |
if (copied_ids >= max_ids) break; |
t = list_get_instance(cur, thread_t, th_link); |
spinlock_lock(&t->lock); |
flags = t->flags; |
spinlock_unlock(&t->lock); |
/* Not interested in kernel threads. */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Using thread struct pointer as identification hash */ |
tid = (unative_t) t; |
id_buffer[copied_ids++] = tid; |
} |
} |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
mutex_unlock(&TASK->udebug.lock); |
*buffer = id_buffer; |
*n = copied_ids * sizeof(unative_t); |
return 0; |
} |
/** Read the arguments of a system call. |
* |
* The arguments of the system call being being executed are copied |
* to an allocated buffer and a pointer to it is written to @a buffer. |
* The size of the buffer is exactly such that it can hold the maximum number |
* of system-call arguments. |
* |
* Unless the thread is currently blocked in a SYSCALL_B or SYSCALL_E event, |
* this function will fail with an EINVAL error code. |
* |
* @param buffer The buffer for storing thread hashes. |
*/ |
int udebug_args_read(thread_t *t, void **buffer) |
{ |
int rc; |
unative_t *arg_buffer; |
/* Prepare a buffer to hold the arguments. */ |
arg_buffer = malloc(6 * sizeof(unative_t), 0); |
/* On success, this will lock t->udebug.lock. */ |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
return rc; |
} |
/* Additionally we need to verify that we are inside a syscall. */ |
if (t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_B && |
t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_E) { |
_thread_op_end(t); |
return EINVAL; |
} |
/* Copy to a local buffer before releasing the lock. */ |
memcpy(arg_buffer, t->udebug.syscall_args, 6 * sizeof(unative_t)); |
_thread_op_end(t); |
*buffer = arg_buffer; |
return 0; |
} |
/** Read the memory of the debugged task. |
* |
* Reads @a n bytes from the address space of the debugged task, starting |
* from @a uspace_addr. The bytes are copied into an allocated buffer |
* and a pointer to it is written into @a buffer. |
* |
* @param uspace_addr Address from where to start reading. |
* @param n Number of bytes to read. |
* @param buffer For storing a pointer to the allocated buffer. |
*/ |
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer) |
{ |
void *data_buffer; |
int rc; |
/* Verify task state */ |
mutex_lock(&TASK->udebug.lock); |
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
return EBUSY; |
} |
data_buffer = malloc(n, 0); |
/* NOTE: this is not strictly from a syscall... but that shouldn't |
* be a problem */ |
rc = copy_from_uspace(data_buffer, (void *)uspace_addr, n); |
mutex_unlock(&TASK->udebug.lock); |
if (rc != 0) return rc; |
*buffer = data_buffer; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/udebug/udebug_ipc.c |
---|
0,0 → 1,343 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Udebug IPC message handling. |
* |
* This module handles udebug IPC messages and calls the appropriate |
* functions from the udebug_ops module which implement them. |
*/ |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <errno.h> |
#include <ipc/ipc.h> |
#include <syscall/copy.h> |
#include <udebug/udebug.h> |
#include <udebug/udebug_ops.h> |
#include <udebug/udebug_ipc.h> |
int udebug_request_preprocess(call_t *call, phone_t *phone) |
{ |
switch (IPC_GET_ARG1(call->data)) { |
/* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */ |
default: |
break; |
} |
return 0; |
} |
/** Process a BEGIN call. |
* |
* Initiates a debugging session for the current task. The reply |
* to this call may or may not be sent before this function returns. |
* |
* @param call The call structure. |
*/ |
static void udebug_receive_begin(call_t *call) |
{ |
int rc; |
rc = udebug_begin(call); |
if (rc < 0) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
/* |
* If the initialization of the debugging session has finished, |
* send a reply. |
*/ |
if (rc != 0) { |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kb.box, call); |
} |
} |
/** Process an END call. |
* |
* Terminates the debugging session for the current task. |
* @param call The call structure. |
*/ |
static void udebug_receive_end(call_t *call) |
{ |
int rc; |
rc = udebug_end(); |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
} |
/** Process a SET_EVMASK call. |
* |
* Sets an event mask for the current debugging session. |
* @param call The call structure. |
*/ |
static void udebug_receive_set_evmask(call_t *call) |
{ |
int rc; |
udebug_evmask_t mask; |
mask = IPC_GET_ARG2(call->data); |
rc = udebug_set_evmask(mask); |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
} |
/** Process a GO call. |
* |
* Resumes execution of the specified thread. |
* @param call The call structure. |
*/ |
static void udebug_receive_go(call_t *call) |
{ |
thread_t *t; |
int rc; |
t = (thread_t *)IPC_GET_ARG2(call->data); |
rc = udebug_go(t, call); |
if (rc < 0) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
} |
/** Process a STOP call. |
* |
* Suspends execution of the specified thread. |
* @param call The call structure. |
*/ |
static void udebug_receive_stop(call_t *call) |
{ |
thread_t *t; |
int rc; |
t = (thread_t *)IPC_GET_ARG2(call->data); |
rc = udebug_stop(t, call); |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
} |
/** Process a THREAD_READ call. |
* |
* Reads the list of hashes of the (userspace) threads in the current task. |
* @param call The call structure. |
*/ |
static void udebug_receive_thread_read(call_t *call) |
{ |
unative_t uspace_addr; |
unative_t to_copy; |
unsigned total_bytes; |
unsigned buf_size; |
void *buffer; |
size_t n; |
int rc; |
uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */ |
buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */ |
/* |
* Read thread list. Variable n will be filled with actual number |
* of threads times thread-id size. |
*/ |
rc = udebug_thread_read(&buffer, buf_size, &n); |
if (rc < 0) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
total_bytes = n; |
/* Copy MAX(buf_size, total_bytes) bytes */ |
if (buf_size > total_bytes) |
to_copy = total_bytes; |
else |
to_copy = buf_size; |
/* |
* Make use of call->buffer to transfer data to caller's userspace |
*/ |
IPC_SET_RETVAL(call->data, 0); |
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
same code in process_answer() can be used |
(no way to distinguish method in answer) */ |
IPC_SET_ARG1(call->data, uspace_addr); |
IPC_SET_ARG2(call->data, to_copy); |
IPC_SET_ARG3(call->data, total_bytes); |
call->buffer = buffer; |
ipc_answer(&TASK->kb.box, call); |
} |
/** Process an ARGS_READ call. |
* |
* Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E). |
* @param call The call structure. |
*/ |
static void udebug_receive_args_read(call_t *call) |
{ |
thread_t *t; |
unative_t uspace_addr; |
int rc; |
void *buffer; |
t = (thread_t *)IPC_GET_ARG2(call->data); |
rc = udebug_args_read(t, &buffer); |
if (rc != EOK) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
/* |
* Make use of call->buffer to transfer data to caller's userspace |
*/ |
uspace_addr = IPC_GET_ARG3(call->data); |
IPC_SET_RETVAL(call->data, 0); |
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
same code in process_answer() can be used |
(no way to distinguish method in answer) */ |
IPC_SET_ARG1(call->data, uspace_addr); |
IPC_SET_ARG2(call->data, 6 * sizeof(unative_t)); |
call->buffer = buffer; |
ipc_answer(&TASK->kb.box, call); |
} |
/** Process an MEM_READ call. |
* |
* Reads memory of the current (debugged) task. |
* @param call The call structure. |
*/ |
static void udebug_receive_mem_read(call_t *call) |
{ |
unative_t uspace_dst; |
unative_t uspace_src; |
unsigned size; |
void *buffer; |
int rc; |
uspace_dst = IPC_GET_ARG2(call->data); |
uspace_src = IPC_GET_ARG3(call->data); |
size = IPC_GET_ARG4(call->data); |
rc = udebug_mem_read(uspace_src, size, &buffer); |
if (rc < 0) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
IPC_SET_RETVAL(call->data, 0); |
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
same code in process_answer() can be used |
(no way to distinguish method in answer) */ |
IPC_SET_ARG1(call->data, uspace_dst); |
IPC_SET_ARG2(call->data, size); |
call->buffer = buffer; |
ipc_answer(&TASK->kb.box, call); |
} |
/** Handle a debug call received on the kernel answerbox. |
* |
* This is called by the kbox servicing thread. Verifies that the sender |
* is indeed the debugger and calls the appropriate processing function. |
*/ |
void udebug_call_receive(call_t *call) |
{ |
int debug_method; |
debug_method = IPC_GET_ARG1(call->data); |
if (debug_method != UDEBUG_M_BEGIN) { |
/* |
* Verify that the sender is this task's debugger. |
* Note that this is the only thread that could change |
* TASK->debugger. Therefore no locking is necessary |
* and the sender can be safely considered valid until |
* control exits this function. |
*/ |
if (TASK->udebug.debugger != call->sender) { |
IPC_SET_RETVAL(call->data, EINVAL); |
ipc_answer(&TASK->kb.box, call); |
return; |
} |
} |
switch (debug_method) { |
case UDEBUG_M_BEGIN: |
udebug_receive_begin(call); |
break; |
case UDEBUG_M_END: |
udebug_receive_end(call); |
break; |
case UDEBUG_M_SET_EVMASK: |
udebug_receive_set_evmask(call); |
break; |
case UDEBUG_M_GO: |
udebug_receive_go(call); |
break; |
case UDEBUG_M_STOP: |
udebug_receive_stop(call); |
break; |
case UDEBUG_M_THREAD_READ: |
udebug_receive_thread_read(call); |
break; |
case UDEBUG_M_ARGS_READ: |
udebug_receive_args_read(call); |
break; |
case UDEBUG_M_MEM_READ: |
udebug_receive_mem_read(call); |
break; |
} |
} |
/** @} |
*/ |
/branches/dd/kernel/Makefile |
---|
30,24 → 30,28 |
## Include configuration |
# |
-include ../version |
-include Makefile.config |
include ../version |
-include ../Makefile.config |
-include ../config.defs |
INCLUDES = generic/include |
OPTIMIZATION = 3 |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
## Common compiler flags |
# |
DEFS = -D$(ARCH) -DARCH=\"$(ARCH)\" -DRELEASE=\"$(RELEASE)\" "-DNAME=\"$(NAME)\"" \ |
-DKERNEL |
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)" |
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -fomit-frame-pointer -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc |
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \ |
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc -pipe |
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -fomit-frame-pointer -Wall -Wmissing-prototypes -Werror \ |
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \ |
-fno-builtin -Wall -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc \ |
-wd170 |
58,15 → 62,7 |
LFLAGS = -M |
AFLAGS = |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
-include arch/$(ARCH)/Makefile.inc |
-include arch/$(KARCH)/Makefile.inc |
-include genarch/Makefile.inc |
## The at-sign |
84,68 → 80,6 |
# |
SYMTAB_SECTION=".section symtab.data, \"a\", $(ATSIGN)progbits;" |
## Setup kernel configuration |
# |
ifeq ($(CONFIG_DEBUG),y) |
DEFS += -DCONFIG_DEBUG |
endif |
ifeq ($(CONFIG_DEBUG_SPINLOCK),y) |
DEFS += -DCONFIG_DEBUG_SPINLOCK |
endif |
ifeq ($(CONFIG_DEBUG_AS_WATCHPOINT),y) |
DEFS += -DCONFIG_DEBUG_AS_WATCHPOINT |
endif |
ifeq ($(CONFIG_FPU_LAZY),y) |
DEFS += -DCONFIG_FPU_LAZY |
endif |
ifeq ($(CONFIG_DEBUG_ALLREGS),y) |
DEFS += -DCONFIG_DEBUG_ALLREGS |
endif |
ifeq ($(CONFIG_VHPT),y) |
DEFS += -DCONFIG_VHPT |
endif |
ifeq ($(CONFIG_TSB),y) |
DEFS += -DCONFIG_TSB |
endif |
ifeq ($(CONFIG_Z8530),y) |
DEFS += -DCONFIG_Z8530 |
endif |
ifeq ($(CONFIG_NS16550),y) |
DEFS += -DCONFIG_NS16550 |
endif |
ifeq ($(CONFIG_VIRT_IDX_DCACHE),y) |
DEFS += -DCONFIG_VIRT_IDX_DCACHE |
endif |
ifeq ($(CONFIG_FB),y) |
ifeq ($(ARCH),ia32) |
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH) |
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT) |
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP) |
endif |
ifeq ($(ARCH),amd64) |
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH) |
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT) |
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP) |
endif |
ifeq ($(ARCH),ia32xen) |
DEFS += -DCONFIG_VESA_WIDTH=$(CONFIG_VESA_WIDTH) |
DEFS += -DCONFIG_VESA_HEIGHT=$(CONFIG_VESA_HEIGHT) |
DEFS += -DCONFIG_VESA_BPP=$(CONFIG_VESA_BPP) |
endif |
endif |
## Simple detection for the type of the host system |
# |
HOST = $(shell uname) |
170,6 → 104,7 |
OBJDUMP = $(BINUTILS_PREFIX)objdump |
LIBDIR = /usr/lib |
CFLAGS = $(GCC_CFLAGS) |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),icc_native) |
181,6 → 116,7 |
OBJDUMP = objdump |
LIBDIR = /usr/lib |
CFLAGS = $(ICC_CFLAGS) |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),suncc_native) |
192,6 → 128,8 |
OBJDUMP = $(BINUTILS_PREFIX)objdump |
LIBDIR = /usr/lib |
CFLAGS = $(SUNCC_CFLAGS) |
DEFS += $(CONFIG_DEFS) |
DEPEND_DEFS = $(DEFS) |
endif |
ifeq ($(COMPILER),gcc_cross) |
203,6 → 141,7 |
OBJDUMP = $(TOOLCHAIN_DIR)/bin/$(TARGET)-objdump |
LIBDIR = $(TOOLCHAIN_DIR)/lib |
CFLAGS = $(GCC_CFLAGS) |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
## Generic kernel sources |
216,9 → 155,6 |
generic/src/adt/list.c \ |
generic/src/console/chardev.c \ |
generic/src/console/console.c \ |
generic/src/console/kconsole.c \ |
generic/src/console/klog.c \ |
generic/src/console/cmd.c \ |
generic/src/cpu/cpu.c \ |
generic/src/ddi/ddi.c \ |
generic/src/ddi/irq.c \ |
229,6 → 165,7 |
generic/src/main/uinit.c \ |
generic/src/main/version.c \ |
generic/src/main/shutdown.c \ |
generic/src/proc/program.c \ |
generic/src/proc/scheduler.c \ |
generic/src/proc/thread.c \ |
generic/src/proc/task.c \ |
248,6 → 185,7 |
generic/src/lib/func.c \ |
generic/src/lib/memstr.c \ |
generic/src/lib/sort.c \ |
generic/src/lib/string.c \ |
generic/src/lib/elf.c \ |
generic/src/lib/rd.c \ |
generic/src/printf/printf_core.c \ |
267,6 → 205,7 |
generic/src/synch/rwlock.c \ |
generic/src/synch/mutex.c \ |
generic/src/synch/semaphore.c \ |
generic/src/synch/smc.c \ |
generic/src/synch/waitq.c \ |
generic/src/synch/futex.c \ |
generic/src/smp/ipi.c \ |
278,11 → 217,30 |
generic/src/security/cap.c \ |
generic/src/sysinfo/sysinfo.c |
## Kernel console support |
# |
ifeq ($(CONFIG_KCONSOLE),y) |
GENERIC_SOURCES += \ |
generic/src/console/kconsole.c \ |
generic/src/console/cmd.c |
endif |
## Udebug interface sources |
# |
ifeq ($(CONFIG_UDEBUG),y) |
GENERIC_SOURCES += \ |
generic/src/ipc/kbox.c \ |
generic/src/udebug/udebug.c \ |
generic/src/udebug/udebug_ops.c \ |
generic/src/udebug/udebug_ipc.c |
endif |
## Test sources |
# |
ifeq ($(CONFIG_TEST),y) |
DEFS += -DCONFIG_TEST |
CFLAGS += -Itest/ |
GENERIC_SOURCES += \ |
test/test.c \ |
289,17 → 247,12 |
test/atomic/atomic1.c \ |
test/btree/btree1.c \ |
test/avltree/avltree1.c \ |
test/debug/mips1.c \ |
test/fault/fault1.c \ |
test/fpu/fpu1.c \ |
test/fpu/sse1.c \ |
test/fpu/mips2.c \ |
test/mm/falloc1.c \ |
test/mm/falloc2.c \ |
test/mm/mapping1.c \ |
test/mm/slab1.c \ |
test/mm/slab2.c \ |
test/mm/purge1.c \ |
test/synch/rwlock1.c \ |
test/synch/rwlock2.c \ |
test/synch/rwlock3.c \ |
310,41 → 263,76 |
test/print/print1.c \ |
test/thread/thread1.c \ |
test/sysinfo/sysinfo1.c |
ifeq ($(KARCH),mips32) |
GENERIC_SOURCES += test/debug/mips1.c |
else |
GENERIC_SOURCES += test/debug/mips1_skip.c |
endif |
ifeq ($(KARCH),ia64) |
GENERIC_SOURCES += test/mm/purge1.c |
else |
GENERIC_SOURCES += test/mm/purge1_skip.c |
endif |
ifeq ($(CONFIG_FPU),y) |
ifeq ($(KARCH),ia32) |
TEST_FPU1 = y |
TEST_SSE1 = y |
GENERIC_SOURCES += test/fpu/fpu1_x86.c |
endif |
ifeq ($(KARCH),amd64) |
TEST_FPU1 = y |
TEST_SSE1 = y |
GENERIC_SOURCES += test/fpu/fpu1_x86.c |
endif |
ifeq ($(KARCH),ia64) |
TEST_FPU1 = y |
GENERIC_SOURCES += test/fpu/fpu1_ia64.c |
endif |
ifeq ($(KARCH),mips32) |
TEST_MIPS2 = y |
endif |
endif |
ifneq ($(TEST_FPU1),y) |
GENERIC_SOURCES += test/fpu/fpu1_skip.c |
endif |
ifeq ($(TEST_SSE1),y) |
GENERIC_SOURCES += test/fpu/sse1.c |
else |
GENERIC_SOURCES += test/fpu/sse1_skip.c |
endif |
ifeq ($(TEST_MIPS2),y) |
GENERIC_SOURCES += test/fpu/mips2.c |
else |
GENERIC_SOURCES += test/fpu/mips2_skip.c |
endif |
endif |
## Experimental features |
# |
ifeq ($(CONFIG_EXPERIMENTAL),y) |
GENERIC_SOURCES += generic/src/lib/objc_ext.c \ |
generic/src/lib/objc.c |
EXTRA_OBJECTS = $(LIBDIR)/libobjc.a |
EXTRA_FLAGS += -x objective-c |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES))) |
.PHONY: all build config distclean clean archlinks depend disasm |
.PHONY: all build clean archlinks depend disasm |
all: |
../tools/config.py kernel.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) $(MACHINE) |
all: ../Makefile.config ../config.h ../config.defs |
-rm Makefile.depend |
$(MAKE) -C . build |
build: kernel.bin disasm |
config: |
-rm Makefile.depend |
../tools/config.py kernel.config |
-include Makefile.depend |
distclean: clean |
-rm Makefile.config |
clean: |
-rm -f kernel.bin kernel.raw kernel.map kernel.map.pre kernel.objdump kernel.disasm generic/src/debug/real_map.bin Makefile.depend* generic/include/arch generic/include/genarch arch/$(ARCH)/_link.ld |
-rm -f kernel.bin kernel.raw kernel.map kernel.map.pre kernel.objdump kernel.disasm generic/src/debug/real_map.bin Makefile.depend* generic/include/arch generic/include/genarch arch/$(KARCH)/_link.ld |
find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \; |
for arch in arch/* ; do \ |
[ -e $$arch/_link.ld ] && rm $$arch/_link.ld 2>/dev/null ; \ |
351,24 → 339,24 |
done ; exit 0 |
archlinks: |
ln -sfn ../../arch/$(ARCH)/include/ generic/include/arch |
ln -sfn ../../arch/$(KARCH)/include/ generic/include/arch |
ln -sfn ../../genarch/include/ generic/include/genarch |
depend: archlinks |
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
arch/$(KARCH)/_link.ld: arch/$(KARCH)/_link.ld.in |
$(GCC) $(DEFS) $(GCC_CFLAGS) -D__ASM__ -D__LINKER__ -E -x c $< | grep -v "^\#" > $@ |
generic/src/debug/real_map.bin: depend arch/$(ARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) |
generic/src/debug/real_map.bin: depend arch/$(KARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) |
echo $(SYMTAB_SECTION) | $(AS) $(AFLAGS) -o generic/src/debug/empty_map.o |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/empty_map.o -o $@ -Map kernel.map.pre |
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/empty_map.o -o $@ -Map kernel.map.pre |
$(OBJDUMP) -t $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) > kernel.objdump |
tools/genmap.py kernel.map.pre kernel.objdump generic/src/debug/real_map.bin |
# Do it once again, this time to get correct even the symbols |
# on architectures, that have bss after symtab |
echo $(SYMTAB_SECTION)" .incbin \"$@\"" | $(AS) $(AFLAGS) -o generic/src/debug/sizeok_map.o |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/sizeok_map.o -o $@ -Map kernel.map.pre |
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/sizeok_map.o -o $@ -Map kernel.map.pre |
$(OBJDUMP) -t $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) > kernel.objdump |
tools/genmap.py kernel.map.pre kernel.objdump generic/src/debug/real_map.bin |
375,8 → 363,8 |
generic/src/debug/real_map.o: generic/src/debug/real_map.bin |
echo $(SYMTAB_SECTION)" .incbin \"$<\"" | $(AS) $(AFLAGS) -o $@ |
kernel.raw: depend arch/$(ARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) generic/src/debug/real_map.o |
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/real_map.o -o $@ -Map kernel.map |
kernel.raw: depend arch/$(KARCH)/_link.ld $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) generic/src/debug/real_map.o |
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) generic/src/debug/real_map.o -o $@ -Map kernel.map |
kernel.bin: kernel.raw |
$(OBJCOPY) -O $(BFD) kernel.raw kernel.bin |
390,5 → 378,15 |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
# |
# The FPU tests are the only objects for which we allow the compiler to generate |
# FPU instructions. |
# |
test/fpu/%.o: test/fpu/%.c |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@ |
# |
# Ordinary objects. |
# |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@ |
$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -c $< -o $@ |
/branches/dd/kernel/arch/ppc64/include/debug.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/barrier.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/cpu.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/drivers/pic.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/asm/regname.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/context_offset.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/interrupt.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/fpu_context.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/exception.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/cycle.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/byteorder.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/cpuid.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/types.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/elf.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/memstr.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/arg.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/atomic.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/arch.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/proc/task.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/proc/thread.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/boot/boot.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/faddr.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/asm.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/mm/page.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/mm/asid.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/mm/tlb.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/mm/as.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/mm/frame.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/include/context.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/Makefile.inc |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/cpu/cpu.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/mm/tlb.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/mm/as.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/mm/frame.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/mm/page.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/dummy.s |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/interrupt.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/ppc64.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/drivers/pic.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/exception.S |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/fpu_context.S |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/ddi/ddi.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/asm.S |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/proc/scheduler.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/boot/boot.S |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/context.S |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/src/debug/panic.s |
---|
File deleted |
/branches/dd/kernel/arch/ppc64/_link.ld.in |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/faddr.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/asm.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/hypercall.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/mm/frame.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/mm/page.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/mm/asid.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/mm/tlb.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/mm/as.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/debugger.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/context.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/barrier.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/debug.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/cpu.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/drivers/xconsole.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/context_offset.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/interrupt.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/fpu_context.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/cycle.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/byteorder.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/types.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/cpuid.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/elf.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/bios |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/memstr.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/smp |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/arg.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/ddi |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/pm.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/include/atomic.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/arch.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/include/proc |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/Makefile.inc |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/boot/boot.S |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/proc/scheduler.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/proc/task.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/proc/thread.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/debugger.c |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/mm/frame.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/mm/page.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/mm/tlb.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/mm/as.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/userspace.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/atomic.S |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/interrupt.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/drivers/xconsole.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/fpu_context.c |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/asm.S |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/context.S |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/debug |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/cpu |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/ia32xen.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/bios |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/pm.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/delay.s |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/src/smp/ipi.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/smp/apic.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/smp/mps.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/smp/smp.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32xen/src/ddi |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32xen/_link.ld.in |
---|
File deleted |
/branches/dd/kernel/arch/sparc64/_link.ld.in |
---|
1,8 → 1,8 |
/** SPARC64 linker script |
* |
* It is ELF format, but its only section looks like this: |
* kernel text |
* kernel data |
* kernel text |
* kernel data |
* |
*/ |
11,7 → 11,7 |
ENTRY(kernel_image_start) |
SECTIONS { |
.image VMA: AT (LMA) { |
.image VMA: AT (LMA) { |
ktext_start = .; |
*(K_TEXT_START) |
*(.text); |
21,23 → 21,23 |
*(K_DATA_START) |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
. = ALIGN(8); |
hardcoded_ktext_size = .; |
QUAD(ktext_end - ktext_start); |
QUAD(ktext_end - ktext_start); |
hardcoded_kdata_size = .; |
QUAD(kdata_end - kdata_start); |
hardcoded_load_address = .; |
QUAD(VMA); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
symbol_table = .; |
*(symtab.*); /* Symbol table, must be LAST symbol!*/ |
*(symtab.*); /* Symbol table, must be LAST symbol!*/ |
kdata_end = .; |
} |
44,5 → 44,5 |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/kernel/arch/sparc64/include/regdef.h |
---|
55,8 → 55,11 |
#define WSTATE_NORMAL(n) (n) |
#define WSTATE_OTHER(n) ((n) << 3) |
#define UPA_CONFIG_MID_SHIFT 17 |
#define UPA_CONFIG_MID_MASK 0x1f |
/* |
* The following definitions concern the UPA_CONFIG register on US and the |
* FIREPLANE_CONFIG register on US3. |
*/ |
#define ICBUS_CONFIG_MID_SHIFT 17 |
#endif |
/branches/dd/kernel/arch/sparc64/include/cpu_node.h |
---|
0,0 → 1,59 |
/* |
* Copyright (c) 2005 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_CPU_NODE_H_ |
#define KERN_sparc64_CPU_NODE_H_ |
#include <genarch/ofw/ofw_tree.h> |
/** Finds the parent node of all the CPU nodes (nodes named "cpu" or "cmp"). |
* |
* Depending on the machine type (and possibly the OFW version), CPUs can be |
* at "/" or at "/ssm@0,0". |
*/ |
static inline ofw_tree_node_t *cpus_parent(void) |
{ |
ofw_tree_node_t *parent; |
parent = ofw_tree_find_child(ofw_tree_lookup("/"), "ssm@0,0"); |
if (parent == NULL) |
parent = ofw_tree_lookup("/"); |
return parent; |
} |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/include/fpu_context.h |
---|
37,7 → 37,6 |
#include <arch/types.h> |
#define ARCH_HAS_FPU |
#define FPU_CONTEXT_ALIGN 8 |
typedef struct { |
/branches/dd/kernel/arch/sparc64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_sparc64_TYPES_H_ |
#define KERN_sparc64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,13 → 57,34 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "llx" |
#define PRIs "llu" |
#define PRIc "llu" |
#define PRIi "llu" |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "lld" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "llu" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "llx" |
typedef uint8_t asi_t; |
#endif |
/branches/dd/kernel/arch/sparc64/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/dd/kernel/arch/sparc64/include/atomic.h |
---|
37,6 → 37,7 |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <preemption.h> |
/** Atomic add operation. |
* |
56,7 → 57,8 |
a = *((uint64_t *) x); |
b = a + i; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), |
"+r" (b) : "r" (a)); |
} while (a != b); |
return a; |
97,7 → 99,8 |
uint64_t v = 1; |
volatile uintptr_t x = (uint64_t) &val->count; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), |
"+r" (v) : "r" (0)); |
return v; |
} |
109,6 → 112,8 |
volatile uintptr_t x = (uint64_t) &val->count; |
preemption_disable(); |
asm volatile ( |
"0:\n" |
"casx %0, %3, %1\n" |
/branches/dd/kernel/arch/sparc64/include/boot/boot.h |
---|
48,9 → 48,12 |
#define TASKMAP_MAX_RECORDS 32 |
#define MEMMAP_MAX_RECORDS 32 |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
typedef struct { |
void * addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} utask_t; |
typedef struct { |
/branches/dd/kernel/arch/sparc64/include/arch.h |
---|
41,10 → 41,16 |
#define ASI_AIUS 0x11 /** Access to secondary context with user privileges. */ |
#define ASI_NUCLEUS_QUAD_LDD 0x24 /** ASI for 16-byte atomic loads. */ |
#define ASI_DCACHE_TAG 0x47 /** ASI D-Cache Tag. */ |
#define ASI_UPA_CONFIG 0x4a /** ASI of the UPA_CONFIG register. */ |
#define ASI_ICBUS_CONFIG 0x4a /** ASI of the UPA_CONFIG/FIREPLANE_CONFIG register. */ |
#define NWINDOWS 8 /** Number of register window sets. */ |
#ifndef __ASM__ |
extern void arch_pre_main(void); |
#endif /* __ASM__ */ |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/asm.h |
---|
37,11 → 37,61 |
#include <arch/arch.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <align.h> |
#include <arch/register.h> |
#include <config.h> |
#include <arch/stack.h> |
#include <arch/barrier.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uint8_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uint16_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uint32_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
/** Read Processor State register. |
* |
* @return Value of PSTATE register. |
86,6 → 136,28 |
asm volatile ("wr %0, %1, %%tick_cmpr\n" : : "r" (v), "i" (0)); |
} |
/** Read STICK_compare Register. |
* |
* @return Value of STICK_compare register. |
*/ |
static inline uint64_t stick_compare_read(void) |
{ |
uint64_t v; |
asm volatile ("rd %%asr25, %0\n" : "=r" (v)); |
return v; |
} |
/** Write STICK_compare Register. |
* |
* @param v New value of STICK_comapre register. |
*/ |
static inline void stick_compare_write(uint64_t v) |
{ |
asm volatile ("wr %0, %1, %%asr25\n" : : "r" (v), "i" (0)); |
} |
/** Read TICK Register. |
* |
* @return Value of TICK register. |
357,15 → 429,6 |
asm volatile ("wrpr %g0, %g0, %tl\n"); |
} |
/** Read UPA_CONFIG register. |
* |
* @return Value of the UPA_CONFIG register. |
*/ |
static inline uint64_t upa_config_read(void) |
{ |
return asi_u64_read(ASI_UPA_CONFIG, 0); |
} |
extern void cpu_halt(void); |
extern void cpu_sleep(void); |
extern void asm_delay_loop(const uint32_t usec); |
/branches/dd/kernel/arch/sparc64/include/trap/syscall.h |
---|
31,26 → 31,14 |
*/ |
/** |
* @file |
* @brief This file contains the trap_instruction handler. |
* |
* The trap_instruction trap is used to implement syscalls. |
* @brief |
*/ |
#ifndef KERN_sparc64_SYSCALL_TRAP_H_ |
#define KERN_sparc64_SYSCALL_TRAP_H_ |
#define TT_TRAP_INSTRUCTION(n) (0x100 + (n)) |
#define TT_TRAP_INSTRUCTION_LAST TT_TRAP_INSTRUCTION(127) |
#define TT_TRAP_INSTRUCTION_0 0x100 |
#ifdef __ASM__ |
.macro TRAP_INSTRUCTION n |
ba trap_instruction_handler |
mov TT_TRAP_INSTRUCTION(\n) - TT_TRAP_INSTRUCTION(0), %g2 |
.endm |
#endif /* __ASM__ */ |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/trap/regwin.h |
---|
39,6 → 39,7 |
#include <arch/stack.h> |
#include <arch/arch.h> |
#include <align.h> |
#define TT_CLEAN_WINDOW 0x24 |
#define TT_SPILL_0_NORMAL 0x80 /* kernel spills */ |
72,6 → 73,11 |
#define I6_OFFSET 112 |
#define I7_OFFSET 120 |
/* Uspace Window Buffer constants. */ |
#define UWB_SIZE ((NWINDOWS - 1) * STACK_WINDOW_SAVE_AREA_SIZE) |
#define UWB_ALIGNMENT 1024 |
#define UWB_ASIZE ALIGN_UP(UWB_SIZE, UWB_ALIGNMENT) |
#ifdef __ASM__ |
/* |
/branches/dd/kernel/arch/sparc64/include/trap/interrupt.h |
---|
49,21 → 49,43 |
/* Interrupt ASI registers. */ |
#define ASI_UDB_INTR_W 0x77 |
#define ASI_INTR_W 0x77 |
#define ASI_INTR_DISPATCH_STATUS 0x48 |
#define ASI_UDB_INTR_R 0x7f |
#define ASI_INTR_R 0x7f |
#define ASI_INTR_RECEIVE 0x49 |
/* VA's used with ASI_UDB_INTR_W register. */ |
/* VA's used with ASI_INTR_W register. */ |
#if defined (US) |
#define ASI_UDB_INTR_W_DATA_0 0x40 |
#define ASI_UDB_INTR_W_DATA_1 0x50 |
#define ASI_UDB_INTR_W_DATA_2 0x60 |
#define ASI_UDB_INTR_W_DISPATCH 0x70 |
#elif defined (US3) |
#define VA_INTR_W_DATA_0 0x40 |
#define VA_INTR_W_DATA_1 0x48 |
#define VA_INTR_W_DATA_2 0x50 |
#define VA_INTR_W_DATA_3 0x58 |
#define VA_INTR_W_DATA_4 0x60 |
#define VA_INTR_W_DATA_5 0x68 |
#define VA_INTR_W_DATA_6 0x80 |
#define VA_INTR_W_DATA_7 0x88 |
#endif |
#define VA_INTR_W_DISPATCH 0x70 |
/* VA's used with ASI_UDB_INTR_R register. */ |
/* VA's used with ASI_INTR_R register. */ |
#if defined(US) |
#define ASI_UDB_INTR_R_DATA_0 0x40 |
#define ASI_UDB_INTR_R_DATA_1 0x50 |
#define ASI_UDB_INTR_R_DATA_2 0x60 |
#elif defined (US3) |
#define VA_INTR_R_DATA_0 0x40 |
#define VA_INTR_R_DATA_1 0x48 |
#define VA_INTR_R_DATA_2 0x50 |
#define VA_INTR_R_DATA_3 0x58 |
#define VA_INTR_R_DATA_4 0x60 |
#define VA_INTR_R_DATA_5 0x68 |
#define VA_INTR_R_DATA_6 0x80 |
#define VA_INTR_R_DATA_7 0x88 |
#endif |
/* Shifts in the Interrupt Vector Dispatch virtual address. */ |
#define INTR_VEC_DISPATCH_MID_SHIFT 14 |
/branches/dd/kernel/arch/sparc64/include/mm/frame.h |
---|
59,8 → 59,13 |
union frame_address { |
uintptr_t address; |
struct { |
#if defined (US) |
unsigned : 23; |
uint64_t pfn : 28; /**< Physical Frame Number. */ |
#elif defined (US3) |
unsigned : 21; |
uint64_t pfn : 30; /**< Physical Frame Number. */ |
#endif |
unsigned offset : 13; /**< Offset. */ |
} __attribute__ ((packed)); |
}; |
/branches/dd/kernel/arch/sparc64/include/mm/page.h |
---|
53,11 → 53,6 |
#define MMU_PAGES_PER_PAGE (1 << (PAGE_WIDTH - MMU_PAGE_WIDTH)) |
/* |
* With 16K pages, there is only one page color. |
*/ |
#define PAGE_COLOR_BITS 0 /**< 14 - 14; 2^14 == 16K == alias boundary. */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/dd/kernel/arch/sparc64/include/mm/tte.h |
---|
50,6 → 50,7 |
#include <arch/types.h> |
/* TTE tag's VA_tag field contains bits <63:VA_TAG_PAGE_SHIFT> of the VA */ |
#define VA_TAG_PAGE_SHIFT 22 |
/** Translation Table Entry - Tag. */ |
75,8 → 76,13 |
unsigned nfo : 1; /**< No-Fault-Only. */ |
unsigned ie : 1; /**< Invert Endianness. */ |
unsigned soft2 : 9; /**< Software defined field. */ |
#if defined (US) |
unsigned diag : 9; /**< Diagnostic data. */ |
unsigned pfn : 28; /**< Physical Address bits, bits 40:13. */ |
#elif defined (US3) |
unsigned : 7; /**< Reserved. */ |
unsigned pfn : 30; /**< Physical Address bits, bits 42:13 */ |
#endif |
unsigned soft : 6; /**< Software defined field. */ |
unsigned l : 1; /**< Lock. */ |
unsigned cp : 1; /**< Cacheable in physically indexed cache. */ |
/branches/dd/kernel/arch/sparc64/include/mm/cache_spec.h |
---|
0,0 → 1,58 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64mm |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_CACHE_SPEC_H_ |
#define KERN_sparc64_CACHE_SPEC_H_ |
/* |
* The following macros are valid for the following processors: |
* |
* UltraSPARC, UltraSPARC II, UltraSPARC IIi, UltraSPARC III, |
* UltraSPARC III+, UltraSPARC IV, UltraSPARC IV+ |
* |
* Should we support other UltraSPARC processors, we need to make sure that |
* the macros are defined correctly for them. |
*/ |
#if defined (US) |
#define DCACHE_SIZE (16 * 1024) |
#elif defined (US3) |
#define DCACHE_SIZE (64 * 1024) |
#endif |
#define DCACHE_LINE_SIZE 32 |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/include/mm/mmu.h |
---|
35,8 → 35,10 |
#ifndef KERN_sparc64_MMU_H_ |
#define KERN_sparc64_MMU_H_ |
#if defined(US) |
/* LSU Control Register ASI. */ |
#define ASI_LSU_CONTROL_REG 0x45 /**< Load/Store Unit Control Register. */ |
#endif |
/* I-MMU ASIs. */ |
#define ASI_IMMU 0x50 |
52,7 → 54,12 |
#define VA_IMMU_SFSR 0x18 /**< IMMU sync fault status register. */ |
#define VA_IMMU_TSB_BASE 0x28 /**< IMMU TSB base register. */ |
#define VA_IMMU_TAG_ACCESS 0x30 /**< IMMU TLB tag access register. */ |
#if defined (US3) |
#define VA_IMMU_PRIMARY_EXTENSION 0x48 /**< IMMU TSB primary extension register */ |
#define VA_IMMU_NUCLEUS_EXTENSION 0x58 /**< IMMU TSB nucleus extension register */ |
#endif |
/* D-MMU ASIs. */ |
#define ASI_DMMU 0x58 |
#define ASI_DMMU_TSB_8KB_PTR_REG 0x59 |
73,6 → 80,11 |
#define VA_DMMU_TAG_ACCESS 0x30 /**< DMMU TLB tag access register. */ |
#define VA_DMMU_VA_WATCHPOINT_REG 0x38 /**< DMMU VA data watchpoint register. */ |
#define VA_DMMU_PA_WATCHPOINT_REG 0x40 /**< DMMU PA data watchpoint register. */ |
#if defined (US3) |
#define VA_DMMU_PRIMARY_EXTENSION 0x48 /**< DMMU TSB primary extension register */ |
#define VA_DMMU_SECONDARY_EXTENSION 0x50 /**< DMMU TSB secondary extension register */ |
#define VA_DMMU_NUCLEUS_EXTENSION 0x58 /**< DMMU TSB nucleus extension register */ |
#endif |
#ifndef __ASM__ |
80,6 → 92,7 |
#include <arch/barrier.h> |
#include <arch/types.h> |
#if defined(US) |
/** LSU Control Register. */ |
typedef union { |
uint64_t value; |
100,6 → 113,7 |
} __attribute__ ((packed)); |
} lsu_cr_reg_t; |
#endif /* US */ |
#endif /* !def __ASM__ */ |
/branches/dd/kernel/arch/sparc64/include/mm/tlb.h |
---|
35,9 → 35,17 |
#ifndef KERN_sparc64_TLB_H_ |
#define KERN_sparc64_TLB_H_ |
#if defined (US) |
#define ITLB_ENTRY_COUNT 64 |
#define DTLB_ENTRY_COUNT 64 |
#define DTLB_MAX_LOCKED_ENTRIES DTLB_ENTRY_COUNT |
#endif |
/** TLB_DSMALL is the only of the three DMMUs that can hold locked entries. */ |
#if defined (US3) |
#define DTLB_MAX_LOCKED_ENTRIES 16 |
#endif |
#define MEM_CONTEXT_KERNEL 0 |
#define MEM_CONTEXT_TEMP 1 |
53,6 → 61,9 |
/* TLB Demap Operation types. */ |
#define TLB_DEMAP_PAGE 0 |
#define TLB_DEMAP_CONTEXT 1 |
#if defined (US3) |
#define TLB_DEMAP_ALL 2 |
#endif |
#define TLB_DEMAP_TYPE_SHIFT 6 |
61,6 → 72,18 |
#define TLB_DEMAP_SECONDARY 1 |
#define TLB_DEMAP_NUCLEUS 2 |
/* There are more TLBs in one MMU in US3, their codes are defined here. */ |
#if defined (US3) |
/* D-MMU: one small (16-entry) TLB and two big (512-entry) TLBs */ |
#define TLB_DSMALL 0 |
#define TLB_DBIG_0 2 |
#define TLB_DBIG_1 3 |
/* I-MMU: one small (16-entry) TLB and one big TLB */ |
#define TLB_ISMALL 0 |
#define TLB_IBIG 2 |
#endif |
#define TLB_DEMAP_CONTEXT_SHIFT 4 |
/* TLB Tag Access shifts */ |
76,6 → 99,8 |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <arch/register.h> |
#include <arch/cpu.h> |
union tlb_context_reg { |
uint64_t v; |
90,6 → 115,9 |
typedef tte_data_t tlb_data_t; |
/** I-/D-TLB Data Access Address in Alternate Space. */ |
#if defined (US) |
union tlb_data_access_addr { |
uint64_t value; |
struct { |
98,9 → 126,54 |
unsigned : 3; |
} __attribute__ ((packed)); |
}; |
typedef union tlb_data_access_addr tlb_data_access_addr_t; |
typedef union tlb_data_access_addr tlb_tag_read_addr_t; |
typedef union tlb_data_access_addr dtlb_data_access_addr_t; |
typedef union tlb_data_access_addr dtlb_tag_read_addr_t; |
typedef union tlb_data_access_addr itlb_data_access_addr_t; |
typedef union tlb_data_access_addr itlb_tag_read_addr_t; |
#elif defined (US3) |
/* |
* In US3, I-MMU and D-MMU have different formats of the data |
* access register virtual address. In the corresponding |
* structures the member variable for the entry number is |
* called "local_tlb_entry" - it contrasts with the "tlb_entry" |
* for the US data access register VA structure. The rationale |
* behind this is to prevent careless mistakes in the code |
* caused by setting only the entry number and not the TLB |
* number in the US3 code (when taking the code from US). |
*/ |
union dtlb_data_access_addr { |
uint64_t value; |
struct { |
uint64_t : 45; |
unsigned : 1; |
unsigned tlb_number : 2; |
unsigned : 4; |
unsigned local_tlb_entry : 9; |
unsigned : 3; |
} __attribute__ ((packed)); |
}; |
typedef union dtlb_data_access_addr dtlb_data_access_addr_t; |
typedef union dtlb_data_access_addr dtlb_tag_read_addr_t; |
union itlb_data_access_addr { |
uint64_t value; |
struct { |
uint64_t : 45; |
unsigned : 1; |
unsigned tlb_number : 2; |
unsigned : 6; |
unsigned local_tlb_entry : 7; |
unsigned : 3; |
} __attribute__ ((packed)); |
}; |
typedef union itlb_data_access_addr itlb_data_access_addr_t; |
typedef union itlb_data_access_addr itlb_tag_read_addr_t; |
#endif |
/** I-/D-TLB Tag Read Register. */ |
union tlb_tag_read_reg { |
uint64_t value; |
118,8 → 191,13 |
uint64_t value; |
struct { |
uint64_t vpn: 51; /**< Virtual Address bits 63:13. */ |
#if defined (US) |
unsigned : 6; /**< Ignored. */ |
unsigned type : 1; /**< The type of demap operation. */ |
#elif defined (US3) |
unsigned : 5; /**< Ignored. */ |
unsigned type: 2; /**< The type of demap operation. */ |
#endif |
unsigned context : 2; /**< Context register selection. */ |
unsigned : 4; /**< Zero. */ |
} __attribute__ ((packed)); |
130,10 → 208,19 |
union tlb_sfsr_reg { |
uint64_t value; |
struct { |
#if defined (US) |
unsigned long : 40; /**< Implementation dependent. */ |
unsigned asi : 8; /**< ASI. */ |
unsigned : 2; |
unsigned ft : 7; /**< Fault type. */ |
#elif defined (US3) |
unsigned long : 39; /**< Implementation dependent. */ |
unsigned nf : 1; /**< Non-faulting load. */ |
unsigned asi : 8; /**< ASI. */ |
unsigned tm : 1; /**< I-TLB miss. */ |
unsigned : 3; /**< Reserved. */ |
unsigned ft : 5; /**< Fault type. */ |
#endif |
unsigned e : 1; /**< Side-effect bit. */ |
unsigned ct : 2; /**< Context Register selection. */ |
unsigned pr : 1; /**< Privilege bit. */ |
144,9 → 231,53 |
}; |
typedef union tlb_sfsr_reg tlb_sfsr_reg_t; |
#if defined (US3) |
/* |
* Functions for determining the number of entries in TLBs. They either return |
* a constant value or a value based on the CPU autodetection. |
*/ |
/** |
* Determine the number of entries in the DMMU's small TLB. |
*/ |
static inline uint16_t tlb_dsmall_size(void) |
{ |
return 16; |
} |
/** |
* Determine the number of entries in each DMMU's big TLB. |
*/ |
static inline uint16_t tlb_dbig_size(void) |
{ |
return 512; |
} |
/** |
* Determine the number of entries in the IMMU's small TLB. |
*/ |
static inline uint16_t tlb_ismall_size(void) |
{ |
return 16; |
} |
/** |
* Determine the number of entries in the IMMU's big TLB. |
*/ |
static inline uint16_t tlb_ibig_size(void) |
{ |
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIV_PLUS) |
return 512; |
else |
return 128; |
} |
#endif |
/** Read MMU Primary Context Register. |
* |
* @return Current value of Primary Context Register. |
* @return Current value of Primary Context Register. |
*/ |
static inline uint64_t mmu_primary_context_read(void) |
{ |
155,17 → 286,17 |
/** Write MMU Primary Context Register. |
* |
* @param v New value of Primary Context Register. |
* @param v New value of Primary Context Register. |
*/ |
static inline void mmu_primary_context_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v); |
flush(); |
flush_pipeline(); |
} |
/** Read MMU Secondary Context Register. |
* |
* @return Current value of Secondary Context Register. |
* @return Current value of Secondary Context Register. |
*/ |
static inline uint64_t mmu_secondary_context_read(void) |
{ |
174,23 → 305,26 |
/** Write MMU Primary Context Register. |
* |
* @param v New value of Primary Context Register. |
* @param v New value of Primary Context Register. |
*/ |
static inline void mmu_secondary_context_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v); |
flush(); |
flush_pipeline(); |
} |
#if defined (US) |
/** Read IMMU TLB Data Access Register. |
* |
* @param entry TLB Entry index. |
* @param entry TLB Entry index. |
* |
* @return Current value of specified IMMU TLB Data Access Register. |
* @return Current value of specified IMMU TLB Data Access |
* Register. |
*/ |
static inline uint64_t itlb_data_access_read(index_t entry) |
{ |
tlb_data_access_addr_t reg; |
itlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_entry = entry; |
199,28 → 333,29 |
/** Write IMMU TLB Data Access Register. |
* |
* @param entry TLB Entry index. |
* @param value Value to be written. |
* @param entry TLB Entry index. |
* @param value Value to be written. |
*/ |
static inline void itlb_data_access_write(index_t entry, uint64_t value) |
{ |
tlb_data_access_addr_t reg; |
itlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_entry = entry; |
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value); |
flush(); |
flush_pipeline(); |
} |
/** Read DMMU TLB Data Access Register. |
* |
* @param entry TLB Entry index. |
* @param entry TLB Entry index. |
* |
* @return Current value of specified DMMU TLB Data Access Register. |
* @return Current value of specified DMMU TLB Data Access |
* Register. |
*/ |
static inline uint64_t dtlb_data_access_read(index_t entry) |
{ |
tlb_data_access_addr_t reg; |
dtlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_entry = entry; |
229,12 → 364,12 |
/** Write DMMU TLB Data Access Register. |
* |
* @param entry TLB Entry index. |
* @param value Value to be written. |
* @param entry TLB Entry index. |
* @param value Value to be written. |
*/ |
static inline void dtlb_data_access_write(index_t entry, uint64_t value) |
{ |
tlb_data_access_addr_t reg; |
dtlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_entry = entry; |
244,13 → 379,13 |
/** Read IMMU TLB Tag Read Register. |
* |
* @param entry TLB Entry index. |
* @param entry TLB Entry index. |
* |
* @return Current value of specified IMMU TLB Tag Read Register. |
* @return Current value of specified IMMU TLB Tag Read Register. |
*/ |
static inline uint64_t itlb_tag_read_read(index_t entry) |
{ |
tlb_tag_read_addr_t tag; |
itlb_tag_read_addr_t tag; |
tag.value = 0; |
tag.tlb_entry = entry; |
259,13 → 394,13 |
/** Read DMMU TLB Tag Read Register. |
* |
* @param entry TLB Entry index. |
* @param entry TLB Entry index. |
* |
* @return Current value of specified DMMU TLB Tag Read Register. |
* @return Current value of specified DMMU TLB Tag Read Register. |
*/ |
static inline uint64_t dtlb_tag_read_read(index_t entry) |
{ |
tlb_tag_read_addr_t tag; |
dtlb_tag_read_addr_t tag; |
tag.value = 0; |
tag.tlb_entry = entry; |
272,19 → 407,130 |
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value); |
} |
#elif defined (US3) |
/** Read IMMU TLB Data Access Register. |
* |
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG) |
* @param entry TLB Entry index. |
* |
* @return Current value of specified IMMU TLB Data Access |
* Register. |
*/ |
static inline uint64_t itlb_data_access_read(int tlb, index_t entry) |
{ |
itlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_number = tlb; |
reg.local_tlb_entry = entry; |
return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value); |
} |
/** Write IMMU TLB Data Access Register. |
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG) |
* @param entry TLB Entry index. |
* @param value Value to be written. |
*/ |
static inline void itlb_data_access_write(int tlb, index_t entry, |
uint64_t value) |
{ |
itlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_number = tlb; |
reg.local_tlb_entry = entry; |
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value); |
flush_pipeline(); |
} |
/** Read DMMU TLB Data Access Register. |
* |
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG, TLB_DBIG) |
* @param entry TLB Entry index. |
* |
* @return Current value of specified DMMU TLB Data Access |
* Register. |
*/ |
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry) |
{ |
dtlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_number = tlb; |
reg.local_tlb_entry = entry; |
return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value); |
} |
/** Write DMMU TLB Data Access Register. |
* |
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1) |
* @param entry TLB Entry index. |
* @param value Value to be written. |
*/ |
static inline void dtlb_data_access_write(int tlb, index_t entry, |
uint64_t value) |
{ |
dtlb_data_access_addr_t reg; |
reg.value = 0; |
reg.tlb_number = tlb; |
reg.local_tlb_entry = entry; |
asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value); |
membar(); |
} |
/** Read IMMU TLB Tag Read Register. |
* |
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG) |
* @param entry TLB Entry index. |
* |
* @return Current value of specified IMMU TLB Tag Read Register. |
*/ |
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry) |
{ |
itlb_tag_read_addr_t tag; |
tag.value = 0; |
tag.tlb_number = tlb; |
tag.local_tlb_entry = entry; |
return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value); |
} |
/** Read DMMU TLB Tag Read Register. |
* |
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1) |
* @param entry TLB Entry index. |
* |
* @return Current value of specified DMMU TLB Tag Read Register. |
*/ |
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry) |
{ |
dtlb_tag_read_addr_t tag; |
tag.value = 0; |
tag.tlb_number = tlb; |
tag.local_tlb_entry = entry; |
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value); |
} |
#endif |
/** Write IMMU TLB Tag Access Register. |
* |
* @param v Value to be written. |
* @param v Value to be written. |
*/ |
static inline void itlb_tag_access_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v); |
flush(); |
flush_pipeline(); |
} |
/** Read IMMU TLB Tag Access Register. |
* |
* @return Current value of IMMU TLB Tag Access Register. |
* @return Current value of IMMU TLB Tag Access Register. |
*/ |
static inline uint64_t itlb_tag_access_read(void) |
{ |
293,7 → 539,7 |
/** Write DMMU TLB Tag Access Register. |
* |
* @param v Value to be written. |
* @param v Value to be written. |
*/ |
static inline void dtlb_tag_access_write(uint64_t v) |
{ |
303,7 → 549,7 |
/** Read DMMU TLB Tag Access Register. |
* |
* @return Current value of DMMU TLB Tag Access Register. |
* @return Current value of DMMU TLB Tag Access Register. |
*/ |
static inline uint64_t dtlb_tag_access_read(void) |
{ |
313,17 → 559,17 |
/** Write IMMU TLB Data in Register. |
* |
* @param v Value to be written. |
* @param v Value to be written. |
*/ |
static inline void itlb_data_in_write(uint64_t v) |
{ |
asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v); |
flush(); |
flush_pipeline(); |
} |
/** Write DMMU TLB Data in Register. |
* |
* @param v Value to be written. |
* @param v Value to be written. |
*/ |
static inline void dtlb_data_in_write(uint64_t v) |
{ |
333,7 → 579,7 |
/** Read ITLB Synchronous Fault Status Register. |
* |
* @return Current content of I-SFSR register. |
* @return Current content of I-SFSR register. |
*/ |
static inline uint64_t itlb_sfsr_read(void) |
{ |
342,17 → 588,17 |
/** Write ITLB Synchronous Fault Status Register. |
* |
* @param v New value of I-SFSR register. |
* @param v New value of I-SFSR register. |
*/ |
static inline void itlb_sfsr_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v); |
flush(); |
flush_pipeline(); |
} |
/** Read DTLB Synchronous Fault Status Register. |
* |
* @return Current content of D-SFSR register. |
* @return Current content of D-SFSR register. |
*/ |
static inline uint64_t dtlb_sfsr_read(void) |
{ |
361,7 → 607,7 |
/** Write DTLB Synchronous Fault Status Register. |
* |
* @param v New value of D-SFSR register. |
* @param v New value of D-SFSR register. |
*/ |
static inline void dtlb_sfsr_write(uint64_t v) |
{ |
371,7 → 617,7 |
/** Read DTLB Synchronous Fault Address Register. |
* |
* @return Current content of D-SFAR register. |
* @return Current content of D-SFAR register. |
*/ |
static inline uint64_t dtlb_sfar_read(void) |
{ |
380,10 → 626,11 |
/** Perform IMMU TLB Demap Operation. |
* |
* @param type Selects between context and page demap. |
* @param type Selects between context and page demap (and entire MMU |
* demap on US3). |
* @param context_encoding Specifies which Context register has Context ID for |
* demap. |
* @param page Address which is on the page to be demapped. |
* demap. |
* @param page Address which is on the page to be demapped. |
*/ |
static inline void itlb_demap(int type, int context_encoding, uintptr_t page) |
{ |
397,18 → 644,19 |
da.context = context_encoding; |
da.vpn = pg.vpn; |
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); /* da.value is the |
* address within the |
* ASI */ |
flush(); |
/* da.value is the address within the ASI */ |
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); |
flush_pipeline(); |
} |
/** Perform DMMU TLB Demap Operation. |
* |
* @param type Selects between context and page demap. |
* @param type Selects between context and page demap (and entire MMU |
* demap on US3). |
* @param context_encoding Specifies which Context register has Context ID for |
* demap. |
* @param page Address which is on the page to be demapped. |
* demap. |
* @param page Address which is on the page to be demapped. |
*/ |
static inline void dtlb_demap(int type, int context_encoding, uintptr_t page) |
{ |
422,17 → 670,17 |
da.context = context_encoding; |
da.vpn = pg.vpn; |
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); /* da.value is the |
* address within the |
* ASI */ |
/* da.value is the address within the ASI */ |
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); |
membar(); |
} |
extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate); |
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate); |
extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate); |
extern void fast_instruction_access_mmu_miss(unative_t, istate_t *); |
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t, istate_t *); |
extern void fast_data_access_protection(tlb_tag_access_reg_t , istate_t *); |
extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable); |
extern void dtlb_insert_mapping(uintptr_t, uintptr_t, int, bool, bool); |
extern void dump_sfsr_and_sfar(void); |
/branches/dd/kernel/arch/sparc64/include/mm/cache.h |
---|
38,15 → 38,6 |
#include <mm/page.h> |
#include <mm/frame.h> |
#define dcache_flush_page(p) \ |
dcache_flush_color(PAGE_COLOR((p))) |
#define dcache_flush_frame(p, f) \ |
dcache_flush_tag(PAGE_COLOR((p)), ADDR2PFN((f))); |
extern void dcache_flush(void); |
extern void dcache_flush_color(int c); |
extern void dcache_flush_tag(int c, pfn_t tag); |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/mm/tsb.h |
---|
107,6 → 107,55 |
asi_u64_write(ASI_DMMU, VA_DMMU_TSB_BASE, v); |
} |
#if defined (US3) |
/** Write DTSB Primary Extension register. |
* |
* @param v New content of the DTSB Primary Extension register. |
*/ |
static inline void dtsb_primary_extension_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_DMMU_PRIMARY_EXTENSION, v); |
} |
/** Write DTSB Secondary Extension register. |
* |
* @param v New content of the DTSB Secondary Extension register. |
*/ |
static inline void dtsb_secondary_extension_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_DMMU_SECONDARY_EXTENSION, v); |
} |
/** Write DTSB Nucleus Extension register. |
* |
* @param v New content of the DTSB Nucleus Extension register. |
*/ |
static inline void dtsb_nucleus_extension_write(uint64_t v) |
{ |
asi_u64_write(ASI_DMMU, VA_DMMU_NUCLEUS_EXTENSION, v); |
} |
/** Write ITSB Primary Extension register. |
* |
* @param v New content of the ITSB Primary Extension register. |
*/ |
static inline void itsb_primary_extension_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_PRIMARY_EXTENSION, v); |
} |
/** Write ITSB Nucleus Extension register. |
* |
* @param v New content of the ITSB Nucleus Extension register. |
*/ |
static inline void itsb_nucleus_extension_write(uint64_t v) |
{ |
asi_u64_write(ASI_IMMU, VA_IMMU_NUCLEUS_EXTENSION, v); |
} |
#endif |
/* Forward declarations. */ |
struct as; |
struct pte; |
/branches/dd/kernel/arch/sparc64/include/register.h |
---|
117,23 → 117,6 |
}; |
typedef union fprs_reg fprs_reg_t; |
/** UPA_CONFIG register. |
* |
* Note that format of this register differs significantly from |
* processor version to version. The format defined here |
* is the common subset for all supported processor versions. |
*/ |
union upa_config { |
uint64_t value; |
struct { |
uint64_t : 34; |
unsigned pcon : 8; /**< Processor configuration. */ |
unsigned mid : 5; /**< Module (processor) ID register. */ |
unsigned pcap : 17; /**< Processor capabilities. */ |
} __attribute__ ((packed)); |
}; |
typedef union upa_config upa_config_t; |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/barrier.h |
---|
57,8 → 57,11 |
#define write_barrier() \ |
asm volatile ("membar #StoreStore\n" ::: "memory") |
/** Flush Instruction Memory instruction. */ |
static inline void flush(void) |
#define flush(a) \ |
asm volatile ("flush %0\n" :: "r" ((a)) : "memory") |
/** Flush Instruction pipeline. */ |
static inline void flush_pipeline(void) |
{ |
/* |
* The FLUSH instruction takes address parameter. |
79,6 → 82,39 |
asm volatile ("membar #Sync\n"); |
} |
#if defined (US) |
#define smc_coherence(a) \ |
{ \ |
write_barrier(); \ |
flush((a)); \ |
} |
#define FLUSH_INVAL_MIN 4 |
#define smc_coherence_block(a, l) \ |
{ \ |
unsigned long i; \ |
write_barrier(); \ |
for (i = 0; i < (l); i += FLUSH_INVAL_MIN) \ |
flush((void *)(a) + i); \ |
} |
#elif defined (US3) |
#define smc_coherence(a) \ |
{ \ |
write_barrier(); \ |
flush_pipeline(); \ |
} |
#define smc_coherence_block(a, l) \ |
{ \ |
write_barrier(); \ |
flush_pipeline(); \ |
} |
#endif /* defined(US3) */ |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/cpu.h |
---|
35,14 → 35,6 |
#ifndef KERN_sparc64_CPU_H_ |
#define KERN_sparc64_CPU_H_ |
#include <arch/types.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
#ifdef CONFIG_SMP |
#include <arch/mm/cache.h> |
#endif |
#define MANUF_FUJITSU 0x04 |
#define MANUF_ULTRASPARC 0x17 /**< UltraSPARC I, UltraSPARC II */ |
#define MANUF_SUN 0x3e |
51,14 → 43,29 |
#define IMPL_ULTRASPARCII 0x11 |
#define IMPL_ULTRASPARCII_I 0x12 |
#define IMPL_ULTRASPARCII_E 0x13 |
#define IMPL_ULTRASPARCIII 0x15 |
#define IMPL_ULTRASPARCIII 0x14 |
#define IMPL_ULTRASPARCIII_PLUS 0x15 |
#define IMPL_ULTRASPARCIII_I 0x16 |
#define IMPL_ULTRASPARCIV 0x18 |
#define IMPL_ULTRASPARCIV_PLUS 0x19 |
#define IMPL_SPARC64V 0x5 |
#ifndef __ASM__ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/register.h> |
#include <arch/regdef.h> |
#include <arch/asm.h> |
#ifdef CONFIG_SMP |
#include <arch/mm/cache.h> |
#endif |
typedef struct { |
uint32_t mid; /**< Processor ID as read from |
UPA_CONFIG. */ |
UPA_CONFIG/FIREPLANE_CONFIG. */ |
ver_reg_t ver; |
uint32_t clock_frequency; /**< Processor frequency in Hz. */ |
uint64_t next_tick_cmpr; /**< Next clock interrupt should be |
65,8 → 72,28 |
generated when the TICK register |
matches this value. */ |
} cpu_arch_t; |
/** |
* Reads the module ID (agent ID/CPUID) of the current CPU. |
*/ |
static inline uint32_t read_mid(void) |
{ |
uint64_t icbus_config = asi_u64_read(ASI_ICBUS_CONFIG, 0); |
icbus_config = icbus_config >> ICBUS_CONFIG_MID_SHIFT; |
#if defined (US) |
return icbus_config & 0x1f; |
#elif defined (US3) |
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIII_I) |
return icbus_config & 0x1f; |
else |
return icbus_config & 0x3ff; |
#endif |
} |
#endif |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/include/drivers/z8530.h |
---|
File deleted |
/branches/dd/kernel/arch/sparc64/include/drivers/ns16550.h |
---|
File deleted |
/branches/dd/kernel/arch/sparc64/include/drivers/sgcn.h |
---|
0,0 → 1,126 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_SGCN_H_ |
#define KERN_sparc64_SGCN_H_ |
#include <arch/types.h> |
/* number of bytes in the TOC magic, including the terminating '\0' */ |
#define TOC_MAGIC_BYTES 8 |
/* number of bytes in the TOC key, including the terminating '\0' */ |
#define TOC_KEY_SIZE 8 |
/* maximum number of entries in the SRAM table of contents */ |
#define MAX_TOC_ENTRIES 32 |
/* number of bytes in the SGCN buffer magic, including the terminating '\0' */ |
#define SGCN_MAGIC_BYTES 4 |
/** |
* Entry in the SRAM table of contents. Describes one segment of the SRAM |
* which serves a particular purpose (e.g. OBP serial console, Solaris serial |
* console, Solaris mailbox,...). |
*/ |
typedef struct { |
/** key (e.g. "OBPCONS", "SOLCONS", "SOLMBOX",...) */ |
char key[TOC_KEY_SIZE]; |
/** size of the segment in bytes */ |
uint32_t size; |
/** offset of the segment within SRAM */ |
uint32_t offset; |
} __attribute ((packed)) toc_entry_t; |
/** |
* SRAM table of contents. Describes all segments within the SRAM. |
*/ |
typedef struct { |
/** hard-wired to "TOCSRAM" */ |
char magic[TOC_MAGIC_BYTES]; |
/** we don't need this */ |
char unused[8]; |
/** TOC entries */ |
toc_entry_t keys[MAX_TOC_ENTRIES]; |
} __attribute__ ((packed)) iosram_toc_t; |
/** |
* SGCN buffer header. It is placed at the very beginning of the SGCN |
* buffer. |
*/ |
typedef struct { |
/** hard-wired to "CON" */ |
char magic[SGCN_MAGIC_BYTES]; |
/** we don't need this */ |
char unused[8]; |
/** offset within the SGCN buffer of the input buffer start */ |
uint32_t in_begin; |
/** offset within the SGCN buffer of the input buffer end */ |
uint32_t in_end; |
/** offset within the SGCN buffer of the input buffer read pointer */ |
uint32_t in_rdptr; |
/** offset within the SGCN buffer of the input buffer write pointer */ |
uint32_t in_wrptr; |
/** offset within the SGCN buffer of the output buffer start */ |
uint32_t out_begin; |
/** offset within the SGCN buffer of the output buffer end */ |
uint32_t out_end; |
/** offset within the SGCN buffer of the output buffer read pointer */ |
uint32_t out_rdptr; |
/** offset within the SGCN buffer of the output buffer write pointer */ |
uint32_t out_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
void sgcn_grab(void); |
void sgcn_release(void); |
void sgcn_poll(void); |
void sgcn_init(void); |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/include/drivers/pci.h |
---|
51,8 → 51,8 |
}; |
struct pci_operations { |
void (* enable_interrupt)(pci_t *pci, int inr); |
void (* clear_interrupt)(pci_t *pci, int inr); |
void (* enable_interrupt)(pci_t *, int); |
void (* clear_interrupt)(pci_t *, int); |
}; |
struct pci { |
61,9 → 61,9 |
volatile uint64_t *reg; /**< Registers including interrupt registers. */ |
}; |
extern pci_t *pci_init(ofw_tree_node_t *node); |
extern void pci_enable_interrupt(pci_t *pci, int inr); |
extern void pci_clear_interrupt(pci_t *pci, int inr); |
extern pci_t *pci_init(ofw_tree_node_t *); |
extern void pci_enable_interrupt(pci_t *, int); |
extern void pci_clear_interrupt(void *, int); |
#endif |
/branches/dd/kernel/arch/sparc64/include/drivers/fhc.h |
---|
44,9 → 44,9 |
extern fhc_t *central_fhc; |
extern fhc_t *fhc_init(ofw_tree_node_t *node); |
extern void fhc_enable_interrupt(fhc_t *fhc, int inr); |
extern void fhc_clear_interrupt(fhc_t *fhc, int inr); |
extern fhc_t *fhc_init(ofw_tree_node_t *); |
extern void fhc_enable_interrupt(fhc_t *, int); |
extern void fhc_clear_interrupt(void *, int); |
#endif |
/branches/dd/kernel/arch/sparc64/include/drivers/kbd.h |
---|
41,7 → 41,8 |
typedef enum { |
KBD_UNKNOWN, |
KBD_Z8530, |
KBD_NS16550 |
KBD_NS16550, |
KBD_SGCN |
} kbd_type_t; |
extern kbd_type_t kbd_type; |
/branches/dd/kernel/arch/sparc64/include/drivers/scr.h |
---|
42,12 → 42,14 |
SCR_UNKNOWN, |
SCR_ATYFB, |
SCR_FFB, |
SCR_CGSIX |
SCR_CGSIX, |
SCR_XVR |
} scr_type_t; |
extern scr_type_t scr_type; |
extern void scr_init(ofw_tree_node_t *node); |
extern void scr_redraw(void); |
#endif |
/branches/dd/kernel/arch/sparc64/include/cpu_family.h |
---|
0,0 → 1,83 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_CPU_FAMILY_H_ |
#define KERN_sparc64_CPU_FAMILY_H_ |
#include <arch.h> |
#include <cpu.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
/** |
* Find the processor (sub)family. |
* |
* @return true iff the CPU belongs to the US family |
*/ |
static inline bool is_us(void) |
{ |
int impl = ((ver_reg_t) ver_read()).impl; |
return (impl == IMPL_ULTRASPARCI) || (impl == IMPL_ULTRASPARCII) || |
(impl == IMPL_ULTRASPARCII_I) || (impl == IMPL_ULTRASPARCII_E); |
} |
/** |
* Find the processor (sub)family. |
* |
* @return true iff the CPU belongs to the US-III subfamily |
*/ |
static inline bool is_us_iii(void) |
{ |
int impl = ((ver_reg_t) ver_read()).impl; |
return (impl == IMPL_ULTRASPARCIII) || |
(impl == IMPL_ULTRASPARCIII_PLUS) || |
(impl == IMPL_ULTRASPARCIII_I); |
} |
/** |
* Find the processor (sub)family. |
* |
* @return true iff the CPU belongs to the US-IV subfamily |
*/ |
static inline bool is_us_iv(void) |
{ |
int impl = ((ver_reg_t) ver_read()).impl; |
return (impl == IMPL_ULTRASPARCIV) || (impl == IMPL_ULTRASPARCIV_PLUS); |
} |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/Makefile.inc |
---|
33,7 → 33,7 |
BFD_ARCH = sparc |
BFD = binary |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64 |
GCC_CFLAGS += -m64 -mcpu=ultrasparc |
SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float |
42,80 → 42,59 |
DEFS += -D__64_BITS__ |
## Own configuration directives |
# |
ifeq ($(PROCESSOR),us) |
DEFS += -DUS |
endif |
## Compile with page hash table support. |
# |
ifeq ($(PROCESSOR),us3) |
DEFS += -DUS3 |
endif |
CONFIG_PAGE_HT = y |
DEFS += -DCONFIG_PAGE_HT |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/fpu_context.c \ |
arch/$(KARCH)/src/dummy.s \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/cache.S \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/sparc64.c \ |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/proc/thread.c \ |
arch/$(KARCH)/src/trap/mmu.S \ |
arch/$(KARCH)/src/trap/trap_table.S \ |
arch/$(KARCH)/src/trap/trap.c \ |
arch/$(KARCH)/src/trap/exception.c \ |
arch/$(KARCH)/src/trap/interrupt.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/tick.c \ |
arch/$(KARCH)/src/drivers/kbd.c \ |
arch/$(KARCH)/src/drivers/sgcn.c \ |
arch/$(KARCH)/src/drivers/pci.c |
## Compile with support for address space identifiers. |
# |
CONFIG_ASID = y |
CONFIG_ASID_FIFO = y |
## Compile with support for framebuffer. |
# |
CONFIG_FB = y |
## Compile with support for Sun keyboard. |
# |
CONFIG_SUN_KBD = y |
## Compile with support for OpenFirmware device tree. |
# |
CONFIG_OFW_TREE = y |
ifeq ($(CONFIG_SMP),y) |
DEFS += -DCONFIG_SMP |
ifeq ($(CONFIG_FB),y) |
ARCH_SOURCES += \ |
arch/$(KARCH)/src/drivers/scr.c |
endif |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/panic.S \ |
arch/$(ARCH)/src/console.c \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/dummy.s \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/cache.S \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/sparc64.c \ |
arch/$(ARCH)/src/start.S \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/proc/thread.c \ |
arch/$(ARCH)/src/trap/mmu.S \ |
arch/$(ARCH)/src/trap/trap_table.S \ |
arch/$(ARCH)/src/trap/trap.c \ |
arch/$(ARCH)/src/trap/exception.c \ |
arch/$(ARCH)/src/trap/interrupt.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/tick.c \ |
arch/$(ARCH)/src/drivers/kbd.c \ |
arch/$(ARCH)/src/drivers/scr.c \ |
arch/$(ARCH)/src/drivers/pci.c |
ifeq ($(CONFIG_SMP),y) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/smp/ipi.c \ |
arch/$(ARCH)/src/smp/smp.c |
ARCH_SOURCES += \ |
arch/$(KARCH)/src/smp/ipi.c \ |
arch/$(KARCH)/src/smp/smp.c |
endif |
ifeq ($(CONFIG_TSB),y) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/mm/tsb.c |
ARCH_SOURCES += \ |
arch/$(KARCH)/src/mm/tsb.c |
endif |
ifdef CONFIG_Z8530 |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/drivers/fhc.c |
ARCH_SOURCES += \ |
arch/$(KARCH)/src/drivers/fhc.c |
endif |
/branches/dd/kernel/arch/sparc64/src/smp/smp.c |
---|
35,6 → 35,7 |
#include <smp/smp.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <cpu.h> |
#include <arch/cpu_family.h> |
#include <arch/cpu.h> |
#include <arch.h> |
#include <config.h> |
43,6 → 44,7 |
#include <synch/synch.h> |
#include <synch/waitq.h> |
#include <print.h> |
#include <arch/cpu_node.h> |
/** |
* This global variable is used to pick-up application processors |
61,15 → 63,55 |
ofw_tree_node_t *node; |
count_t cnt = 0; |
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); |
while (node) { |
cnt++; |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
if (is_us() || is_us_iii()) { |
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); |
while (node) { |
cnt++; |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
} |
} else if (is_us_iv()) { |
node = ofw_tree_find_child(cpus_parent(), "cmp"); |
while (node) { |
cnt += 2; |
node = ofw_tree_find_peer_by_name(node, "cmp"); |
} |
} |
config.cpu_count = max(1, cnt); |
} |
/** |
* Wakes up the CPU which is represented by the "node" OFW tree node. |
* If "node" represents the current CPU, calling the function has |
* no effect. |
*/ |
static void wakeup_cpu(ofw_tree_node_t *node) |
{ |
uint32_t mid; |
ofw_tree_property_t *prop; |
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */ |
prop = ofw_tree_getprop(node, "upa-portid"); |
if ((!prop) || (!prop->value)) |
prop = ofw_tree_getprop(node, "portid"); |
if ((!prop) || (!prop->value)) |
prop = ofw_tree_getprop(node, "cpuid"); |
if (!prop || prop->value == NULL) |
return; |
mid = *((uint32_t *) prop->value); |
if (CPU->arch.mid == mid) |
return; |
waking_up_mid = mid; |
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == |
ESYNCH_TIMEOUT) |
printf("%s: waiting for processor (mid = %" PRIu32 |
") timed out\n", __func__, mid); |
} |
/** Wake application processors up. */ |
void kmp(void *arg) |
{ |
76,31 → 118,18 |
ofw_tree_node_t *node; |
int i; |
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); |
for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) { |
uint32_t mid; |
ofw_tree_property_t *prop; |
prop = ofw_tree_getprop(node, "upa-portid"); |
if (!prop || !prop->value) |
continue; |
mid = *((uint32_t *) prop->value); |
if (CPU->arch.mid == mid) { |
/* |
* Skip the current CPU. |
*/ |
continue; |
if (is_us() || is_us_iii()) { |
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); |
for (i = 0; node; |
node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) |
wakeup_cpu(node); |
} else if (is_us_iv()) { |
node = ofw_tree_find_child(cpus_parent(), "cmp"); |
while (node) { |
wakeup_cpu(ofw_tree_find_child(node, "cpu@0")); |
wakeup_cpu(ofw_tree_find_child(node, "cpu@1")); |
node = ofw_tree_find_peer_by_name(node, "cmp"); |
} |
/* |
* Processor with ID == mid can proceed with its initialization. |
*/ |
waking_up_mid = mid; |
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) |
printf("%s: waiting for processor (mid = %d) timed out\n", |
__func__, mid); |
} |
} |
/branches/dd/kernel/arch/sparc64/src/smp/ipi.c |
---|
46,6 → 46,33 |
#include <time/delay.h> |
#include <panic.h> |
/** Set the contents of the outgoing interrupt vector data. |
* |
* The first data item (data 0) will be set to the value of func, the |
* rest of the vector will contain zeros. |
* |
* This is a helper function used from within the cross_call function. |
* |
* @param func value the first data item of the vector will be set to |
*/ |
static inline void set_intr_w_data(void (* func)(void)) |
{ |
#if defined (US) |
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func); |
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0); |
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0); |
#elif defined (US3) |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0); |
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0); |
#endif |
} |
/** Invoke function on another processor. |
* |
* Currently, only functions without arguments are supported. |
71,16 → 98,15 |
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0); |
if (status & INTR_DISPATCH_STATUS_BUSY) |
panic("Interrupt Dispatch Status busy bit set\n"); |
panic("Interrupt Dispatch Status busy bit set."); |
ASSERT(!(pstate_read() & PSTATE_IE_BIT)); |
do { |
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0, |
(uintptr_t) func); |
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0); |
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0); |
asi_u64_write(ASI_UDB_INTR_W, |
set_intr_w_data(func); |
asi_u64_write(ASI_INTR_W, |
(mid << INTR_VEC_DISPATCH_MID_SHIFT) | |
ASI_UDB_INTR_W_DISPATCH, 0); |
VA_INTR_W_DISPATCH, 0); |
membar(); |
125,7 → 151,7 |
func = tlb_shootdown_ipi_recv; |
break; |
default: |
panic("Unknown IPI (%d).\n", ipi); |
panic("Unknown IPI (%d).", ipi); |
break; |
} |
/branches/dd/kernel/arch/sparc64/src/ddi/ddi.c |
---|
41,7 → 41,7 |
* Interrupts are disabled and task is locked. |
* |
* @param task Task. |
* @param ioaddr Startign I/O space address. |
* @param ioaddr Starting I/O space address. |
* @param size Size of the enabled I/O range. |
* |
* @return 0 on success or an error code from errno.h. |
/branches/dd/kernel/arch/sparc64/src/asm.S |
---|
41,6 → 41,7 |
*/ |
.global memcpy |
memcpy: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
59,7 → 60,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
93,7 → 94,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
/* |
* Almost the same as memcpy() except the loads are from userspace. |
100,6 → 101,7 |
*/ |
.global memcpy_from_uspace |
memcpy_from_uspace: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
118,7 → 120,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
152,7 → 154,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
/* |
* Almost the same as memcpy() except the stores are to userspace. |
159,6 → 161,7 |
*/ |
.global memcpy_to_uspace |
memcpy_to_uspace: |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
177,7 → 180,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
211,7 → 214,7 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
274,6 → 277,8 |
wrpr %g0, 0, %cleanwin ! avoid information leak |
mov %i2, %o0 ! uarg |
xor %o1, %o1, %o1 ! %o1 is defined to hold pcb_ptr |
! set it to 0 |
clr %i2 |
clr %i3 |
/branches/dd/kernel/arch/sparc64/src/console.c |
---|
38,12 → 38,7 |
#include <arch/drivers/scr.h> |
#include <arch/drivers/kbd.h> |
#ifdef CONFIG_Z8530 |
#include <genarch/kbd/z8530.h> |
#endif |
#ifdef CONFIG_NS16550 |
#include <genarch/kbd/ns16550.h> |
#endif |
#include <arch/drivers/sgcn.h> |
#include <console/chardev.h> |
#include <console/console.h> |
54,47 → 49,81 |
#include <genarch/ofw/ofw_tree.h> |
#include <arch.h> |
#include <panic.h> |
#include <string.h> |
#include <print.h> |
#define KEYBOARD_POLL_PAUSE 50000 /* 50ms */ |
/** Initialize kernel console to use framebuffer and keyboard directly. */ |
void standalone_sparc64_console_init(void) |
/** |
* Initialize kernel console to use framebuffer and keyboard directly. |
* Called on UltraSPARC machines with standard keyboard and framebuffer. |
* |
* @param aliases the "/aliases" OBP node |
*/ |
static void standard_console_init(ofw_tree_node_t *aliases) |
{ |
stdin = NULL; |
ofw_tree_node_t *aliases; |
#ifdef CONFIG_FB |
ofw_tree_property_t *prop; |
ofw_tree_node_t *screen; |
ofw_tree_node_t *keyboard; |
aliases = ofw_tree_lookup("/aliases"); |
if (!aliases) |
panic("Can't find /aliases.\n"); |
prop = ofw_tree_getprop(aliases, "screen"); |
if (!prop) |
panic("Can't find property \"screen\".\n"); |
panic("Cannot find property 'screen'."); |
if (!prop->value) |
panic("Can't find screen alias.\n"); |
panic("Cannot find screen alias."); |
screen = ofw_tree_lookup(prop->value); |
if (!screen) |
panic("Can't find %s\n", prop->value); |
panic("Cannot find %s.", prop->value); |
scr_init(screen); |
prop = ofw_tree_getprop(aliases, "keyboard"); |
if (!prop) |
panic("Can't find property \"keyboard\".\n"); |
panic("Cannot find property 'keyboard'."); |
if (!prop->value) |
panic("Can't find keyboard alias.\n"); |
panic("Cannot find keyboard alias."); |
keyboard = ofw_tree_lookup(prop->value); |
if (!keyboard) |
panic("Can't find %s\n", prop->value); |
panic("Cannot find %s.", prop->value); |
kbd_init(keyboard); |
#else |
panic("Standard console requires FB, " |
"but the kernel is not compiled with FB support."); |
#endif |
} |
/** Initilize I/O on the Serengeti machine. */ |
static void serengeti_init(void) |
{ |
sgcn_init(); |
} |
/** |
* Initialize input/output. Auto-detects the type of machine |
* and calls the appropriate I/O init routine. |
*/ |
void standalone_sparc64_console_init(void) |
{ |
ofw_tree_node_t *aliases; |
ofw_tree_property_t *prop; |
aliases = ofw_tree_lookup("/aliases"); |
if (!aliases) |
panic("Cannot find '/aliases'."); |
/* "def-cn" = "default console" */ |
prop = ofw_tree_getprop(aliases, "def-cn"); |
if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) { |
standard_console_init(aliases); |
} else { |
serengeti_init(); |
} |
} |
/** Kernel thread for polling keyboard. |
* |
* @param arg Ignored. |
103,19 → 132,13 |
{ |
thread_detach(THREAD); |
#ifdef CONFIG_Z8530 |
if (kbd_type == KBD_Z8530) { |
/* |
* The z8530 driver is interrupt-driven. |
*/ |
if (kbd_type != KBD_SGCN) |
return; |
} |
#endif |
while (1) { |
#ifdef CONFIG_NS16550 |
if (kbd_type == KBD_NS16550) |
ns16550_poll(); |
#ifdef CONFIG_SGCN |
if (kbd_type == KBD_SGCN) |
sgcn_poll(); |
#endif |
thread_usleep(KEYBOARD_POLL_PAUSE); |
} |
126,17 → 149,15 |
*/ |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
scr_redraw(); |
#endif |
switch (kbd_type) { |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
z8530_grab(); |
#ifdef CONFIG_SGCN |
case KBD_SGCN: |
sgcn_grab(); |
break; |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550_grab(); |
break; |
#endif |
default: |
break; |
} |
148,16 → 169,11 |
void arch_release_console(void) |
{ |
switch (kbd_type) { |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
z8530_release(); |
#ifdef CONFIG_SGCN |
case KBD_SGCN: |
sgcn_release(); |
break; |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550_release(); |
break; |
#endif |
default: |
break; |
} |
/branches/dd/kernel/arch/sparc64/src/proc/thread.c |
---|
34,9 → 34,8 |
#include <proc/thread.h> |
#include <arch/proc/thread.h> |
#include <mm/frame.h> |
#include <mm/page.h> |
#include <arch/mm/page.h> |
#include <mm/slab.h> |
#include <arch/trap/regwin.h> |
#include <align.h> |
void thr_constructor_arch(thread_t *t) |
50,12 → 49,12 |
void thr_destructor_arch(thread_t *t) |
{ |
if (t->arch.uspace_window_buffer) { |
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer; |
/* |
* Mind the possible alignment of the userspace window buffer |
* belonging to a killed thread. |
*/ |
frame_free(KA2PA(ALIGN_DOWN((uintptr_t) |
t->arch.uspace_window_buffer, PAGE_SIZE))); |
free((uint8_t *) ALIGN_DOWN(uw_buf, UWB_ALIGNMENT)); |
} |
} |
67,7 → 66,7 |
* The thread needs userspace window buffer and the object |
* returned from the slab allocator doesn't have any. |
*/ |
t->arch.uspace_window_buffer = frame_alloc(ONE_FRAME, FRAME_KA); |
t->arch.uspace_window_buffer = malloc(UWB_ASIZE, 0); |
} else { |
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer; |
76,7 → 75,7 |
* belonging to a killed thread. |
*/ |
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf, |
PAGE_SIZE); |
UWB_ASIZE); |
} |
} |
/branches/dd/kernel/arch/sparc64/src/sparc64.c |
---|
47,10 → 47,11 |
#include <genarch/ofw/ofw_tree.h> |
#include <userspace.h> |
#include <ddi/irq.h> |
#include <string.h> |
bootinfo_t bootinfo; |
/** Perform sparc64 specific initialization before main_bsp() is called. */ |
/** Perform sparc64-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
{ |
/* Copy init task info. */ |
61,6 → 62,8 |
for (i = 0; i < bootinfo.taskmap.count; i++) { |
init.tasks[i].addr = (uintptr_t) bootinfo.taskmap.tasks[i].addr; |
init.tasks[i].size = bootinfo.taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
} |
/* Copy boot allocations info. */ |
86,8 → 89,6 |
* But we only create 128 buckets. |
*/ |
irq_init(1 << 11, 128); |
standalone_sparc64_console_init(); |
} |
} |
101,16 → 102,16 |
void arch_post_smp_init(void) |
{ |
static thread_t *t = NULL; |
if (config.cpu_active == 1) { |
standalone_sparc64_console_init(); |
if (!t) { |
/* |
* Create thread that polls keyboard. |
*/ |
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
/* Create thread that polls keyboard. |
* XXX: this is only used by sgcn now |
*/ |
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", |
true); |
if (!t) |
panic("cannot create kkbdpoll\n"); |
panic("Cannot create kkbdpoll."); |
thread_ready(t); |
} |
} |
161,5 → 162,19 |
while (1); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/src/trap/exception.c |
---|
45,57 → 45,57 |
void dump_istate(istate_t *istate) |
{ |
printf("TSTATE=%#llx\n", istate->tstate); |
printf("TPC=%#llx (%s)\n", istate->tpc, get_symtab_entry(istate->tpc)); |
printf("TNPC=%#llx (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc)); |
printf("TSTATE=%#" PRIx64 "\n", istate->tstate); |
printf("TPC=%#" PRIx64 " (%s)\n", istate->tpc, get_symtab_entry(istate->tpc)); |
printf("TNPC=%#" PRIx64 " (%s)\n", istate->tnpc, get_symtab_entry(istate->tnpc)); |
} |
/** Handle instruction_access_exception. (0x8) */ |
void instruction_access_exception(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle instruction_access_error. (0xa) */ |
void instruction_access_error(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle illegal_instruction. (0x10) */ |
void illegal_instruction(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle privileged_opcode. (0x11) */ |
void privileged_opcode(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle unimplemented_LDD. (0x12) */ |
void unimplemented_LDD(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle unimplemented_STD. (0x13) */ |
void unimplemented_STD(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle fp_disabled. (0x20) */ |
113,9 → 113,9 |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#else |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
#endif |
} |
122,98 → 122,98 |
/** Handle fp_exception_ieee_754. (0x21) */ |
void fp_exception_ieee_754(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle fp_exception_other. (0x22) */ |
void fp_exception_other(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle tag_overflow. (0x23) */ |
void tag_overflow(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle division_by_zero. (0x28) */ |
void division_by_zero(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle data_access_exception. (0x30) */ |
void data_access_exception(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
dump_sfsr_and_sfar(); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle data_access_error. (0x32) */ |
void data_access_error(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle mem_address_not_aligned. (0x34) */ |
void mem_address_not_aligned(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle LDDF_mem_address_not_aligned. (0x35) */ |
void LDDF_mem_address_not_aligned(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle STDF_mem_address_not_aligned. (0x36) */ |
void STDF_mem_address_not_aligned(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle privileged_action. (0x37) */ |
void privileged_action(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle LDQF_mem_address_not_aligned. (0x38) */ |
void LDQF_mem_address_not_aligned(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Handle STQF_mem_address_not_aligned. (0x39) */ |
void STQF_mem_address_not_aligned(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "%s\n", __func__); |
fault_if_from_uspace(istate, "%s.", __func__); |
dump_istate(istate); |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** @} |
/branches/dd/kernel/arch/sparc64/src/trap/interrupt.c |
---|
67,11 → 67,19 |
*/ |
void interrupt(int n, istate_t *istate) |
{ |
uint64_t status; |
uint64_t intrcv; |
uint64_t data0; |
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0); |
if (status & (!INTR_DISPATCH_STATUS_BUSY)) |
panic("Interrupt Dispatch Status busy bit not set."); |
intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0); |
data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0); |
#if defined (US) |
data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0); |
#elif defined (US3) |
data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0); |
#endif |
irq_t *irq = irq_dispatch_and_lock(data0); |
if (irq) { |
78,7 → 86,13 |
/* |
* The IRQ handler was found. |
*/ |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
/* |
* See if there is a clear-interrupt-routine and call it. |
*/ |
if (irq->cir) { |
irq->cir(irq->cir_arg, irq->inr); |
} |
spinlock_unlock(&irq->lock); |
} else if (data0 > config.base) { |
/* |
97,8 → 111,8 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (intrcv=%#llx, " |
"data0=%#llx)\n", CPU->id, intrcv, data0); |
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64 |
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0); |
#endif |
} |
/branches/dd/kernel/arch/sparc64/src/trap/trap_table.S |
---|
329,198 → 329,22 |
fill_1_normal_tl0: |
FILL_NORMAL_HANDLER_USERSPACE |
/* TT = 0x100, TL = 0, trap_instruction_0 */ |
.org trap_table + TT_TRAP_INSTRUCTION(0)*ENTRY_SIZE |
.global trap_instruction_0_tl0 |
trap_instruction_0_tl0: |
TRAP_INSTRUCTION 0 |
/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */ |
.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\ |
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\ |
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\ |
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\ |
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\ |
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\ |
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\ |
127 |
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE |
.global trap_instruction_\cur\()_tl0 |
trap_instruction_\cur\()_tl0: |
ba trap_instruction_handler |
mov \cur, %g2 |
.endr |
/* TT = 0x101, TL = 0, trap_instruction_1 */ |
.org trap_table + TT_TRAP_INSTRUCTION(1)*ENTRY_SIZE |
.global trap_instruction_1_tl0 |
trap_instruction_1_tl0: |
TRAP_INSTRUCTION 1 |
/* TT = 0x102, TL = 0, trap_instruction_2 */ |
.org trap_table + TT_TRAP_INSTRUCTION(2)*ENTRY_SIZE |
.global trap_instruction_2_tl0 |
trap_instruction_2_tl0: |
TRAP_INSTRUCTION 2 |
/* TT = 0x103, TL = 0, trap_instruction_3 */ |
.org trap_table + TT_TRAP_INSTRUCTION(3)*ENTRY_SIZE |
.global trap_instruction_3_tl0 |
trap_instruction_3_tl0: |
TRAP_INSTRUCTION 3 |
/* TT = 0x104, TL = 0, trap_instruction_4 */ |
.org trap_table + TT_TRAP_INSTRUCTION(4)*ENTRY_SIZE |
.global trap_instruction_4_tl0 |
trap_instruction_4_tl0: |
TRAP_INSTRUCTION 4 |
/* TT = 0x105, TL = 0, trap_instruction_5 */ |
.org trap_table + TT_TRAP_INSTRUCTION(5)*ENTRY_SIZE |
.global trap_instruction_5_tl0 |
trap_instruction_5_tl0: |
TRAP_INSTRUCTION 5 |
/* TT = 0x106, TL = 0, trap_instruction_6 */ |
.org trap_table + TT_TRAP_INSTRUCTION(6)*ENTRY_SIZE |
.global trap_instruction_6_tl0 |
trap_instruction_6_tl0: |
TRAP_INSTRUCTION 6 |
/* TT = 0x107, TL = 0, trap_instruction_7 */ |
.org trap_table + TT_TRAP_INSTRUCTION(7)*ENTRY_SIZE |
.global trap_instruction_7_tl0 |
trap_instruction_7_tl0: |
TRAP_INSTRUCTION 7 |
/* TT = 0x108, TL = 0, trap_instruction_8 */ |
.org trap_table + TT_TRAP_INSTRUCTION(8)*ENTRY_SIZE |
.global trap_instruction_8_tl0 |
trap_instruction_8_tl0: |
TRAP_INSTRUCTION 8 |
/* TT = 0x109, TL = 0, trap_instruction_9 */ |
.org trap_table + TT_TRAP_INSTRUCTION(9)*ENTRY_SIZE |
.global trap_instruction_9_tl0 |
trap_instruction_9_tl0: |
TRAP_INSTRUCTION 9 |
/* TT = 0x10a, TL = 0, trap_instruction_10 */ |
.org trap_table + TT_TRAP_INSTRUCTION(10)*ENTRY_SIZE |
.global trap_instruction_10_tl0 |
trap_instruction_10_tl0: |
TRAP_INSTRUCTION 10 |
/* TT = 0x10b, TL = 0, trap_instruction_11 */ |
.org trap_table + TT_TRAP_INSTRUCTION(11)*ENTRY_SIZE |
.global trap_instruction_11_tl0 |
trap_instruction_11_tl0: |
TRAP_INSTRUCTION 11 |
/* TT = 0x10c, TL = 0, trap_instruction_12 */ |
.org trap_table + TT_TRAP_INSTRUCTION(12)*ENTRY_SIZE |
.global trap_instruction_12_tl0 |
trap_instruction_12_tl0: |
TRAP_INSTRUCTION 12 |
/* TT = 0x10d, TL = 0, trap_instruction_13 */ |
.org trap_table + TT_TRAP_INSTRUCTION(13)*ENTRY_SIZE |
.global trap_instruction_13_tl0 |
trap_instruction_13_tl0: |
TRAP_INSTRUCTION 13 |
/* TT = 0x10e, TL = 0, trap_instruction_14 */ |
.org trap_table + TT_TRAP_INSTRUCTION(14)*ENTRY_SIZE |
.global trap_instruction_14_tl0 |
trap_instruction_14_tl0: |
TRAP_INSTRUCTION 14 |
/* TT = 0x10f, TL = 0, trap_instruction_15 */ |
.org trap_table + TT_TRAP_INSTRUCTION(15)*ENTRY_SIZE |
.global trap_instruction_15_tl0 |
trap_instruction_15_tl0: |
TRAP_INSTRUCTION 15 |
/* TT = 0x110, TL = 0, trap_instruction_16 */ |
.org trap_table + TT_TRAP_INSTRUCTION(16)*ENTRY_SIZE |
.global trap_instruction_16_tl0 |
trap_instruction_16_tl0: |
TRAP_INSTRUCTION 16 |
/* TT = 0x111, TL = 0, trap_instruction_17 */ |
.org trap_table + TT_TRAP_INSTRUCTION(17)*ENTRY_SIZE |
.global trap_instruction_17_tl0 |
trap_instruction_17_tl0: |
TRAP_INSTRUCTION 17 |
/* TT = 0x112, TL = 0, trap_instruction_18 */ |
.org trap_table + TT_TRAP_INSTRUCTION(18)*ENTRY_SIZE |
.global trap_instruction_18_tl0 |
trap_instruction_18_tl0: |
TRAP_INSTRUCTION 18 |
/* TT = 0x113, TL = 0, trap_instruction_19 */ |
.org trap_table + TT_TRAP_INSTRUCTION(19)*ENTRY_SIZE |
.global trap_instruction_19_tl0 |
trap_instruction_19_tl0: |
TRAP_INSTRUCTION 19 |
/* TT = 0x114, TL = 0, trap_instruction_20 */ |
.org trap_table + TT_TRAP_INSTRUCTION(20)*ENTRY_SIZE |
.global trap_instruction_20_tl0 |
trap_instruction_20_tl0: |
TRAP_INSTRUCTION 20 |
/* TT = 0x115, TL = 0, trap_instruction_21 */ |
.org trap_table + TT_TRAP_INSTRUCTION(21)*ENTRY_SIZE |
.global trap_instruction_21_tl0 |
trap_instruction_21_tl0: |
TRAP_INSTRUCTION 21 |
/* TT = 0x116, TL = 0, trap_instruction_22 */ |
.org trap_table + TT_TRAP_INSTRUCTION(22)*ENTRY_SIZE |
.global trap_instruction_22_tl0 |
trap_instruction_22_tl0: |
TRAP_INSTRUCTION 22 |
/* TT = 0x117, TL = 0, trap_instruction_23 */ |
.org trap_table + TT_TRAP_INSTRUCTION(23)*ENTRY_SIZE |
.global trap_instruction_23_tl0 |
trap_instruction_23_tl0: |
TRAP_INSTRUCTION 23 |
/* TT = 0x118, TL = 0, trap_instruction_24 */ |
.org trap_table + TT_TRAP_INSTRUCTION(24)*ENTRY_SIZE |
.global trap_instruction_24_tl0 |
trap_instruction_24_tl0: |
TRAP_INSTRUCTION 24 |
/* TT = 0x119, TL = 0, trap_instruction_25 */ |
.org trap_table + TT_TRAP_INSTRUCTION(25)*ENTRY_SIZE |
.global trap_instruction_25_tl0 |
trap_instruction_25_tl0: |
TRAP_INSTRUCTION 25 |
/* TT = 0x11a, TL = 0, trap_instruction_26 */ |
.org trap_table + TT_TRAP_INSTRUCTION(26)*ENTRY_SIZE |
.global trap_instruction_26_tl0 |
trap_instruction_26_tl0: |
TRAP_INSTRUCTION 26 |
/* TT = 0x11b, TL = 0, trap_instruction_27 */ |
.org trap_table + TT_TRAP_INSTRUCTION(27)*ENTRY_SIZE |
.global trap_instruction_27_tl0 |
trap_instruction_27_tl0: |
TRAP_INSTRUCTION 27 |
/* TT = 0x11c, TL = 0, trap_instruction_28 */ |
.org trap_table + TT_TRAP_INSTRUCTION(28)*ENTRY_SIZE |
.global trap_instruction_28_tl0 |
trap_instruction_28_tl0: |
TRAP_INSTRUCTION 28 |
/* TT = 0x11d, TL = 0, trap_instruction_29 */ |
.org trap_table + TT_TRAP_INSTRUCTION(29)*ENTRY_SIZE |
.global trap_instruction_29_tl0 |
trap_instruction_29_tl0: |
TRAP_INSTRUCTION 29 |
/* TT = 0x11e, TL = 0, trap_instruction_30 */ |
.org trap_table + TT_TRAP_INSTRUCTION(30)*ENTRY_SIZE |
.global trap_instruction_30_tl0 |
trap_instruction_30_tl0: |
TRAP_INSTRUCTION 30 |
/* TT = 0x11f, TL = 0, trap_instruction_31 */ |
.org trap_table + TT_TRAP_INSTRUCTION(31)*ENTRY_SIZE |
.global trap_instruction_31_tl0 |
trap_instruction_31_tl0: |
TRAP_INSTRUCTION 31 |
/* |
* Handlers for TL>0. |
*/ |
782,10 → 606,10 |
add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1 |
.else |
/* |
* Call the higher-level syscall handler. |
* Call the higher-level syscall handler and enable interrupts. |
*/ |
call syscall_handler |
nop |
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate |
mov %o0, %i0 ! copy the value returned by the syscall |
.endif |
924,9 → 748,8 |
* Fill all windows stored in the buffer. |
*/ |
clr %g4 |
set PAGE_SIZE - 1, %g5 |
0: andcc %g7, %g5, %g0 ! PAGE_SIZE alignment check |
bz 0f ! %g7 is page-aligned, no more windows to refill |
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check |
bz 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill |
nop |
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7 |
/branches/dd/kernel/arch/sparc64/src/cpu/cpu.c |
---|
32,12 → 32,46 |
/** @file |
*/ |
#include <arch/cpu_family.h> |
#include <cpu.h> |
#include <arch.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/drivers/tick.h> |
#include <print.h> |
#include <arch/cpu_node.h> |
/** |
* Finds out the clock frequency of the current CPU. |
* |
* @param node node representing the current CPU in the OFW tree |
* @return clock frequency if "node" is the current CPU and no error |
* occurs, -1 if "node" is not the current CPU or on error |
*/ |
static int find_cpu_frequency(ofw_tree_node_t *node) |
{ |
ofw_tree_property_t *prop; |
uint32_t mid; |
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */ |
prop = ofw_tree_getprop(node, "upa-portid"); |
if ((!prop) || (!prop->value)) |
prop = ofw_tree_getprop(node, "portid"); |
if ((!prop) || (!prop->value)) |
prop = ofw_tree_getprop(node, "cpuid"); |
if (prop && prop->value) { |
mid = *((uint32_t *) prop->value); |
if (mid == CPU->arch.mid) { |
prop = ofw_tree_getprop(node, "clock-frequency"); |
if (prop && prop->value) { |
return *((uint32_t *) prop->value); |
} |
} |
} |
return -1; |
} |
/** Perform sparc64 specific initialization of the processor structure for the |
* current processor. |
*/ |
44,34 → 78,37 |
void cpu_arch_init(void) |
{ |
ofw_tree_node_t *node; |
uint32_t mid; |
uint32_t clock_frequency = 0; |
upa_config_t upa_config; |
upa_config.value = upa_config_read(); |
CPU->arch.mid = upa_config.mid; |
CPU->arch.mid = read_mid(); |
/* |
* Detect processor frequency. |
*/ |
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu"); |
while (node) { |
ofw_tree_property_t *prop; |
prop = ofw_tree_getprop(node, "upa-portid"); |
if (prop && prop->value) { |
mid = *((uint32_t *) prop->value); |
if (mid == CPU->arch.mid) { |
prop = ofw_tree_getprop(node, |
"clock-frequency"); |
if (prop && prop->value) |
clock_frequency = *((uint32_t *) |
prop->value); |
} |
if (is_us() || is_us_iii()) { |
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu"); |
while (node) { |
int f = find_cpu_frequency(node); |
if (f != -1) |
clock_frequency = (uint32_t) f; |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
} |
node = ofw_tree_find_peer_by_device_type(node, "cpu"); |
} else if (is_us_iv()) { |
node = ofw_tree_find_child(cpus_parent(), "cmp"); |
while (node) { |
int f; |
f = find_cpu_frequency( |
ofw_tree_find_child(node, "cpu@0")); |
if (f != -1) |
clock_frequency = (uint32_t) f; |
f = find_cpu_frequency( |
ofw_tree_find_child(node, "cpu@1")); |
if (f != -1) |
clock_frequency = (uint32_t) f; |
node = ofw_tree_find_peer_by_name(node, "cmp"); |
} |
} |
CPU->arch.clock_frequency = clock_frequency; |
tick_init(); |
} |
124,6 → 161,15 |
case IMPL_ULTRASPARCIII: |
impl = "UltraSPARC III"; |
break; |
case IMPL_ULTRASPARCIII_PLUS: |
impl = "UltraSPARC III+"; |
break; |
case IMPL_ULTRASPARCIII_I: |
impl = "UltraSPARC IIIi"; |
break; |
case IMPL_ULTRASPARCIV: |
impl = "UltraSPARC IV"; |
break; |
case IMPL_ULTRASPARCIV_PLUS: |
impl = "UltraSPARC IV+"; |
break; |
135,7 → 181,7 |
break; |
} |
printf("cpu%d: manuf=%s, impl=%s, mask=%d (%dMHz)\n", m->id, manuf, |
printf("cpu%d: manuf=%s, impl=%s, mask=%d (%d MHz)\n", m->id, manuf, |
impl, m->arch.ver.mask, m->arch.clock_frequency / 1000000); |
} |
/branches/dd/kernel/arch/sparc64/src/mm/tlb.c |
---|
54,14 → 54,13 |
#include <arch/mm/tsb.h> |
#endif |
static void dtlb_pte_copy(pte_t *t, index_t index, bool ro); |
static void itlb_pte_copy(pte_t *t, index_t index); |
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
const char *str); |
static void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
tlb_tag_access_reg_t tag, const char *str); |
static void do_fast_data_access_protection_fault(istate_t *istate, |
tlb_tag_access_reg_t tag, const char *str); |
static void dtlb_pte_copy(pte_t *, index_t, bool); |
static void itlb_pte_copy(pte_t *, index_t); |
static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *); |
static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t, |
const char *); |
static void do_fast_data_access_protection_fault(istate_t *, |
tlb_tag_access_reg_t, const char *); |
char *context_encoding[] = { |
"Primary", |
86,11 → 85,11 |
/** Insert privileged mapping into DMMU TLB. |
* |
* @param page Virtual page address. |
* @param frame Physical frame address. |
* @param pagesize Page size. |
* @param locked True for permanent mappings, false otherwise. |
* @param cacheable True if the mapping is cacheable, false otherwise. |
* @param page Virtual page address. |
* @param frame Physical frame address. |
* @param pagesize Page size. |
* @param locked True for permanent mappings, false otherwise. |
* @param cacheable True if the mapping is cacheable, false otherwise. |
*/ |
void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, |
bool locked, bool cacheable) |
103,7 → 102,7 |
pg.address = page; |
fr.address = frame; |
tag.value = ASID_KERNEL; |
tag.context = ASID_KERNEL; |
tag.vpn = pg.vpn; |
dtlb_tag_access_write(tag.value); |
126,10 → 125,10 |
/** Copy PTE to TLB. |
* |
* @param t Page Table Entry to be copied. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
* @param ro If true, the entry will be created read-only, regardless of its |
* w field. |
* @param t Page Table Entry to be copied. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
* @param ro If true, the entry will be created read-only, regardless |
* of its w field. |
*/ |
void dtlb_pte_copy(pte_t *t, index_t index, bool ro) |
{ |
165,8 → 164,8 |
/** Copy PTE to ITLB. |
* |
* @param t Page Table Entry to be copied. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
* @param t Page Table Entry to be copied. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
*/ |
void itlb_pte_copy(pte_t *t, index_t index) |
{ |
235,10 → 234,11 |
* Note that some faults (e.g. kernel faults) were already resolved by the |
* low-level, assembly language part of the fast_data_access_mmu_miss handler. |
* |
* @param tag Content of the TLB Tag Access register as it existed when the |
* trap happened. This is to prevent confusion created by clobbered |
* Tag Access register during a nested DTLB miss. |
* @param istate Interrupted state saved on the stack. |
* @param tag Content of the TLB Tag Access register as it existed |
* when the trap happened. This is to prevent confusion |
* created by clobbered Tag Access register during a nested |
* DTLB miss. |
* @param istate Interrupted state saved on the stack. |
*/ |
void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
287,10 → 287,11 |
/** DTLB protection fault handler. |
* |
* @param tag Content of the TLB Tag Access register as it existed when the |
* trap happened. This is to prevent confusion created by clobbered |
* Tag Access register during a nested DTLB miss. |
* @param istate Interrupted state saved on the stack. |
* @param tag Content of the TLB Tag Access register as it existed |
* when the trap happened. This is to prevent confusion |
* created by clobbered Tag Access register during a nested |
* DTLB miss. |
* @param istate Interrupted state saved on the stack. |
*/ |
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
{ |
331,6 → 332,26 |
} |
} |
/** Print TLB entry (for debugging purposes). |
* |
* The diag field has been left out in order to make this function more generic |
* (there is no diag field in US3 architeture). |
* |
* @param i TLB entry number |
* @param t TLB entry tag |
* @param d TLB entry data |
*/ |
static void print_tlb_entry(int i, tlb_tag_read_reg_t t, tlb_data_t d) |
{ |
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " |
"ie=%d, soft2=%#x, pfn=%#x, soft=%#x, l=%d, " |
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, |
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, |
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); |
} |
#if defined (US) |
/** Print contents of both TLBs. */ |
void tlb_print(void) |
{ |
342,12 → 363,7 |
for (i = 0; i < ITLB_ENTRY_COUNT; i++) { |
d.value = itlb_data_access_read(i); |
t.value = itlb_tag_read_read(i); |
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " |
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, " |
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, |
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, |
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); |
print_tlb_entry(i, t, d); |
} |
printf("D-TLB contents:\n"); |
354,22 → 370,63 |
for (i = 0; i < DTLB_ENTRY_COUNT; i++) { |
d.value = dtlb_data_access_read(i); |
t.value = dtlb_tag_read_read(i); |
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, " |
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, " |
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn, |
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, |
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g); |
print_tlb_entry(i, t, d); |
} |
} |
#elif defined (US3) |
/** Print contents of all TLBs. */ |
void tlb_print(void) |
{ |
int i; |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
printf("TLB_ISMALL contents:\n"); |
for (i = 0; i < tlb_ismall_size(); i++) { |
d.value = dtlb_data_access_read(TLB_ISMALL, i); |
t.value = dtlb_tag_read_read(TLB_ISMALL, i); |
print_tlb_entry(i, t, d); |
} |
printf("TLB_IBIG contents:\n"); |
for (i = 0; i < tlb_ibig_size(); i++) { |
d.value = dtlb_data_access_read(TLB_IBIG, i); |
t.value = dtlb_tag_read_read(TLB_IBIG, i); |
print_tlb_entry(i, t, d); |
} |
printf("TLB_DSMALL contents:\n"); |
for (i = 0; i < tlb_dsmall_size(); i++) { |
d.value = dtlb_data_access_read(TLB_DSMALL, i); |
t.value = dtlb_tag_read_read(TLB_DSMALL, i); |
print_tlb_entry(i, t, d); |
} |
printf("TLB_DBIG_1 contents:\n"); |
for (i = 0; i < tlb_dbig_size(); i++) { |
d.value = dtlb_data_access_read(TLB_DBIG_0, i); |
t.value = dtlb_tag_read_read(TLB_DBIG_0, i); |
print_tlb_entry(i, t, d); |
} |
printf("TLB_DBIG_2 contents:\n"); |
for (i = 0; i < tlb_dbig_size(); i++) { |
d.value = dtlb_data_access_read(TLB_DBIG_1, i); |
t.value = dtlb_tag_read_read(TLB_DBIG_1, i); |
print_tlb_entry(i, t, d); |
} |
} |
#endif |
void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
const char *str) |
{ |
fault_if_from_uspace(istate, "%s\n", str); |
fault_if_from_uspace(istate, "%s.", str); |
dump_istate(istate); |
panic("%s\n", str); |
panic("%s.", str); |
} |
void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
379,12 → 436,12 |
va = tag.vpn << MMU_PAGE_WIDTH; |
if (tag.context) { |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va, |
tag.context); |
} |
dump_istate(istate); |
printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
panic("%s\n", str); |
printf("Faulting page: %p, ASID=%d.\n", va, tag.context); |
panic("%s.", str); |
} |
void do_fast_data_access_protection_fault(istate_t *istate, |
395,12 → 452,12 |
va = tag.vpn << MMU_PAGE_WIDTH; |
if (tag.context) { |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va, |
tag.context); |
} |
printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
dump_istate(istate); |
panic("%s\n", str); |
panic("%s.", str); |
} |
void dump_sfsr_and_sfar(void) |
411,30 → 468,71 |
sfsr.value = dtlb_sfsr_read(); |
sfar = dtlb_sfar_read(); |
#if defined (US) |
printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, " |
"fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, |
sfsr.ow, sfsr.fv); |
#elif defined (US3) |
printf("DTLB SFSR: nf=%d, asi=%#x, tm=%d, ft=%#x, e=%d, ct=%d, pr=%d, " |
"w=%d, ow=%d, fv=%d\n", sfsr.nf, sfsr.asi, sfsr.tm, sfsr.ft, |
sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, sfsr.ow, sfsr.fv); |
#endif |
printf("DTLB SFAR: address=%p\n", sfar); |
dtlb_sfsr_write(0); |
} |
#if defined (US3) |
/** Invalidates given TLB entry if and only if it is non-locked or global. |
* |
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1, |
* TLB_ISMALL, TLB_IBIG). |
* @param entry Entry index within the given TLB. |
*/ |
static void tlb_invalidate_entry(int tlb, index_t entry) |
{ |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) { |
d.value = dtlb_data_access_read(tlb, entry); |
if (!d.l || d.g) { |
t.value = dtlb_tag_read_read(tlb, entry); |
d.v = false; |
dtlb_tag_access_write(t.value); |
dtlb_data_access_write(tlb, entry, d.value); |
} |
} else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) { |
d.value = itlb_data_access_read(tlb, entry); |
if (!d.l || d.g) { |
t.value = itlb_tag_read_read(tlb, entry); |
d.v = false; |
itlb_tag_access_write(t.value); |
itlb_data_access_write(tlb, entry, d.value); |
} |
} |
} |
#endif |
/** Invalidate all unlocked ITLB and DTLB entries. */ |
void tlb_invalidate_all(void) |
{ |
int i; |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
/* |
* Walk all ITLB and DTLB entries and remove all unlocked mappings. |
* |
* The kernel doesn't use global mappings so any locked global mappings |
* found must have been created by someone else. Their only purpose now |
* found must have been created by someone else. Their only purpose now |
* is to collide with proper mappings. Invalidate immediately. It should |
* be safe to invalidate them as late as now. |
*/ |
#if defined (US) |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
for (i = 0; i < ITLB_ENTRY_COUNT; i++) { |
d.value = itlb_data_access_read(i); |
if (!d.l || d.g) { |
444,7 → 542,7 |
itlb_data_access_write(i, d.value); |
} |
} |
for (i = 0; i < DTLB_ENTRY_COUNT; i++) { |
d.value = dtlb_data_access_read(i); |
if (!d.l || d.g) { |
454,7 → 552,21 |
dtlb_data_access_write(i, d.value); |
} |
} |
#elif defined (US3) |
for (i = 0; i < tlb_ismall_size(); i++) |
tlb_invalidate_entry(TLB_ISMALL, i); |
for (i = 0; i < tlb_ibig_size(); i++) |
tlb_invalidate_entry(TLB_IBIG, i); |
for (i = 0; i < tlb_dsmall_size(); i++) |
tlb_invalidate_entry(TLB_DSMALL, i); |
for (i = 0; i < tlb_dbig_size(); i++) |
tlb_invalidate_entry(TLB_DBIG_0, i); |
for (i = 0; i < tlb_dbig_size(); i++) |
tlb_invalidate_entry(TLB_DBIG_1, i); |
#endif |
} |
/** Invalidate all ITLB and DTLB entries that belong to specified ASID |
484,9 → 596,9 |
/** Invalidate all ITLB and DTLB entries for specified page range in specified |
* address space. |
* |
* @param asid Address Space ID. |
* @param page First page which to sweep out from ITLB and DTLB. |
* @param cnt Number of ITLB and DTLB entries to invalidate. |
* @param asid Address Space ID. |
* @param page First page which to sweep out from ITLB and DTLB. |
* @param cnt Number of ITLB and DTLB entries to invalidate. |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
/branches/dd/kernel/arch/sparc64/src/mm/as.c |
---|
76,7 → 76,7 |
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT * |
sizeof(tsb_entry_t)); |
memsetb((uintptr_t) as->arch.itsb, |
memsetb(as->arch.itsb, |
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0); |
#endif |
return 0; |
164,7 → 164,25 |
itsb_base_write(tsb_base.value); |
tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH; |
dtsb_base_write(tsb_base.value); |
#if defined (US3) |
/* |
* Clear the extension registers. |
* In HelenOS, primary and secondary context registers contain |
* equal values and kernel misses (context 0, ie. the nucleus context) |
* are excluded from the TSB miss handler, so it makes no sense |
* to have separate TSBs for primary, secondary and nucleus contexts. |
* Clearing the extension registers will ensure that the value of the |
* TSB Base register will be used as an address of TSB, making the code |
* compatible with the US port. |
*/ |
itsb_primary_extension_write(0); |
itsb_nucleus_extension_write(0); |
dtsb_primary_extension_write(0); |
dtsb_secondary_extension_write(0); |
dtsb_nucleus_extension_write(0); |
#endif |
#endif |
} |
/** Perform sparc64-specific tasks when an address space is removed from the |
/branches/dd/kernel/arch/sparc64/src/mm/cache.S |
---|
27,10 → 27,8 |
*/ |
#include <arch/arch.h> |
#include <arch/mm/cache_spec.h> |
#define DCACHE_SIZE (16 * 1024) |
#define DCACHE_LINE_SIZE 32 |
#define DCACHE_TAG_SHIFT 2 |
.register %g2, #scratch |
49,45 → 47,3 |
retl |
! beware SF Erratum #51, do not put the MEMBAR here |
nop |
/** Flush only D-cache lines of one virtual color. |
* |
* @param o0 Virtual color to be flushed. |
*/ |
.global dcache_flush_color |
dcache_flush_color: |
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1 |
set DCACHE_SIZE / 2, %g2 |
sllx %g2, %o0, %g2 |
sub %g2, DCACHE_LINE_SIZE, %g2 |
0: stxa %g0, [%g2] ASI_DCACHE_TAG |
membar #Sync |
subcc %g1, 1, %g1 |
bnz,pt %xcc, 0b |
sub %g2, DCACHE_LINE_SIZE, %g2 |
retl |
nop |
/** Flush only D-cache lines of one virtual color and one tag. |
* |
* @param o0 Virtual color to lookup the tag. |
* @param o1 Tag of the cachelines to be flushed. |
*/ |
.global dcache_flush_tag |
dcache_flush_tag: |
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1 |
set DCACHE_SIZE / 2, %g2 |
sllx %g2, %o0, %g2 |
sub %g2, DCACHE_LINE_SIZE, %g2 |
0: ldxa [%g2] ASI_DCACHE_TAG, %g3 |
srlx %g3, DCACHE_TAG_SHIFT, %g3 |
cmp %g3, %o1 |
bnz 1f |
nop |
stxa %g0, [%g2] ASI_DCACHE_TAG |
membar #Sync |
1: subcc %g1, 1, %g1 |
bnz,pt %xcc, 0b |
sub %g2, DCACHE_LINE_SIZE, %g2 |
retl |
nop |
/branches/dd/kernel/arch/sparc64/src/mm/tsb.c |
---|
112,9 → 112,9 |
tsb->data.value = 0; |
tsb->data.size = PAGESIZE_8K; |
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; |
tsb->data.cp = t->c; |
tsb->data.p = t->k; /* p as privileged */ |
tsb->data.v = t->p; |
tsb->data.cp = t->c; /* cp as cache in phys.-idxed, c as cacheable */ |
tsb->data.p = t->k; /* p as privileged, k as kernel */ |
tsb->data.v = t->p; /* v as valid, p as present */ |
write_barrier(); |
173,3 → 173,4 |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/src/mm/frame.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64mm |
/** @addtogroup sparc64mm |
* @{ |
*/ |
/** @file |
79,7 → 79,6 |
*/ |
frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1); |
} |
} |
/** @} |
/branches/dd/kernel/arch/sparc64/src/mm/page.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64mm |
/** @addtogroup sparc64mm |
* @{ |
*/ |
/** @file |
52,7 → 52,7 |
uintptr_t virt_page; |
uintptr_t phys_page; |
int pagesize_code; |
} bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT]; |
} bsp_locked_dtlb_entry[DTLB_MAX_LOCKED_ENTRIES]; |
/** Number of entries in bsp_locked_dtlb_entry array. */ |
static count_t bsp_locked_dtlb_entries = 0; |
147,7 → 147,7 |
physaddr + i * sizemap[order].increment, |
sizemap[order].pagesize_code, true, false); |
#ifdef CONFIG_SMP |
#ifdef CONFIG_SMP |
/* |
* Second, save the information about the mapping for APs. |
*/ |
/branches/dd/kernel/arch/sparc64/src/drivers/fhc.c |
---|
45,6 → 45,7 |
#include <mm/slab.h> |
#include <arch/types.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <sysinfo/sysinfo.h> |
fhc_t *central_fhc = NULL; |
86,6 → 87,13 |
fhc->uart_imap = (uint32_t *) hw_map(paddr, reg->size); |
/* |
* Set sysinfo data needed by the uspace FHC driver. |
*/ |
sysinfo_set_item_val("fhc.uart.size", NULL, reg->size); |
sysinfo_set_item_val("fhc.uart.physical", NULL, paddr); |
sysinfo_set_item_val("kbd.cir.fhc", NULL, 1); |
return fhc; |
} |
96,13 → 104,14 |
fhc->uart_imap[FHC_UART_IMAP] |= IMAP_V_MASK; |
break; |
default: |
panic("Unexpected INR (%d)\n", inr); |
panic("Unexpected INR (%d).", inr); |
break; |
} |
} |
void fhc_clear_interrupt(fhc_t *fhc, int inr) |
void fhc_clear_interrupt(void *fhcp, int inr) |
{ |
fhc_t *fhc = (fhc_t *)fhcp; |
ASSERT(fhc->uart_imap); |
switch (inr) { |
110,7 → 119,7 |
fhc->uart_imap[FHC_UART_ICLR] = 0; |
break; |
default: |
panic("Unexpected INR (%d)\n", inr); |
panic("Unexpected INR (%d).", inr); |
break; |
} |
} |
/branches/dd/kernel/arch/sparc64/src/drivers/kbd.c |
---|
34,19 → 34,26 |
#include <arch/drivers/kbd.h> |
#include <genarch/ofw/ofw_tree.h> |
#ifdef CONFIG_SUN_KBD |
#include <genarch/kbrd/kbrd.h> |
#endif |
#ifdef CONFIG_Z8530 |
#include <genarch/kbd/z8530.h> |
#include <genarch/drivers/z8530/z8530.h> |
#endif |
#ifdef CONFIG_NS16550 |
#include <genarch/kbd/ns16550.h> |
#include <genarch/drivers/ns16550/ns16550.h> |
#endif |
#include <console/console.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <arch/mm/page.h> |
#include <arch/types.h> |
#include <align.h> |
#include <func.h> |
#include <string.h> |
#include <print.h> |
#include <sysinfo/sysinfo.h> |
kbd_type_t kbd_type = KBD_UNKNOWN; |
63,6 → 70,15 |
uintptr_t aligned_addr; |
ofw_tree_property_t *prop; |
const char *name; |
cir_t cir; |
void *cir_arg; |
#ifdef CONFIG_NS16550 |
ns16550_t *ns16550; |
#endif |
#ifdef CONFIG_Z8530 |
z8530_t *z8530; |
#endif |
name = ofw_tree_node_name(node); |
84,30 → 100,33 |
*/ |
uint32_t interrupts; |
prop = ofw_tree_getprop(node, "interrupts"); |
if (!prop || !prop->value) |
panic("Can't find \"interrupts\" property.\n"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'interrupt' property."); |
interrupts = *((uint32_t *) prop->value); |
/* |
* Read 'reg' property. |
*/ |
prop = ofw_tree_getprop(node, "reg"); |
if (!prop || !prop->value) |
panic("Can't find \"reg\" property.\n"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'reg' property."); |
uintptr_t pa; |
size_t size; |
devno_t devno; |
inr_t inr; |
devno_t devno = device_assign_devno(); |
switch (kbd_type) { |
case KBD_Z8530: |
size = ((ofw_fhc_reg_t *) prop->value)->size; |
if (!ofw_fhc_apply_ranges(node->parent, ((ofw_fhc_reg_t *) prop->value) , &pa)) { |
if (!ofw_fhc_apply_ranges(node->parent, |
((ofw_fhc_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_fhc_map_interrupt(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &inr)) { |
if (!ofw_fhc_map_interrupt(node->parent, |
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
} |
115,18 → 134,20 |
case KBD_NS16550: |
size = ((ofw_ebus_reg_t *) prop->value)->size; |
if (!ofw_ebus_apply_ranges(node->parent, ((ofw_ebus_reg_t *) prop->value) , &pa)) { |
if (!ofw_ebus_apply_ranges(node->parent, |
((ofw_ebus_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_ebus_map_interrupt(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &inr)) { |
if (!ofw_ebus_map_interrupt(node->parent, |
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
}; |
break; |
default: |
panic("Unexpected type.\n"); |
panic("Unexpected keyboard type."); |
} |
/* |
137,21 → 158,53 |
*/ |
aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
offset = pa - aligned_addr; |
uintptr_t vaddr = hw_map(aligned_addr, offset + size) + offset; |
switch (kbd_type) { |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
z8530_init(devno, inr, vaddr); |
devno = device_assign_devno(); |
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) + |
offset; |
kbrd_init(stdin); |
(void) z8530_init(z8530, devno, inr, cir, cir_arg, &kbrdin); |
/* |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) z8530); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550_init(devno, inr, vaddr); |
devno = device_assign_devno(); |
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) + |
offset; |
kbrd_init(stdin); |
(void) ns16550_init(ns16550, devno, inr, cir, cir_arg, &kbrdin); |
/* |
* This is the necessary evil until the userspace driver is |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) ns16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
#endif |
default: |
printf("Kernel is not compiled with the necessary keyboard driver this machine requires.\n"); |
printf("Kernel is not compiled with the necessary keyboard " |
"driver this machine requires.\n"); |
} |
} |
/branches/dd/kernel/arch/sparc64/src/drivers/scr.c |
---|
37,7 → 37,7 |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <arch/types.h> |
#include <func.h> |
#include <string.h> |
#include <align.h> |
#include <print.h> |
55,6 → 55,10 |
void scr_init(ofw_tree_node_t *node) |
{ |
ofw_tree_property_t *prop; |
ofw_pci_reg_t *pci_reg; |
ofw_pci_reg_t pci_abs_reg; |
ofw_upa_reg_t *upa_reg; |
ofw_sbus_reg_t *sbus_reg; |
const char *name; |
name = ofw_tree_node_name(node); |
61,6 → 65,8 |
if (strcmp(name, "SUNW,m64B") == 0) |
scr_type = SCR_ATYFB; |
else if (strcmp(name, "SUNW,XVR-100") == 0) |
scr_type = SCR_XVR; |
else if (strcmp(name, "SUNW,ffb") == 0) |
scr_type = SCR_FFB; |
else if (strcmp(name, "cgsix") == 0) |
67,11 → 73,12 |
scr_type = SCR_CGSIX; |
if (scr_type == SCR_UNKNOWN) { |
printf("Unknown keyboard device.\n"); |
printf("Unknown screen device.\n"); |
return; |
} |
uintptr_t fb_addr; |
unsigned int fb_offset = 0; |
uint32_t fb_width = 0; |
uint32_t fb_height = 0; |
uint32_t fb_depth = 0; |
97,7 → 104,7 |
prop = ofw_tree_getprop(node, "reg"); |
if (!prop) |
panic("Can't find \"reg\" property.\n"); |
panic("Cannot find 'reg' property."); |
switch (scr_type) { |
case SCR_ATYFB: |
106,15 → 113,15 |
return; |
} |
ofw_pci_reg_t *fb_reg = &((ofw_pci_reg_t *) prop->value)[1]; |
ofw_pci_reg_t abs_reg; |
pci_reg = &((ofw_pci_reg_t *) prop->value)[1]; |
if (!ofw_pci_reg_absolutize(node, fb_reg, &abs_reg)) { |
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) { |
printf("Failed to absolutize fb register.\n"); |
return; |
} |
if (!ofw_pci_apply_ranges(node->parent, &abs_reg , &fb_addr)) { |
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg, |
&fb_addr)) { |
printf("Failed to determine screen address.\n"); |
return; |
} |
142,12 → 149,56 |
} |
break; |
case SCR_XVR: |
if (prop->size / sizeof(ofw_pci_reg_t) < 2) { |
printf("Too few screen registers.\n"); |
return; |
} |
pci_reg = &((ofw_pci_reg_t *) prop->value)[1]; |
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) { |
printf("Failed to absolutize fb register.\n"); |
return; |
} |
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg, |
&fb_addr)) { |
printf("Failed to determine screen address.\n"); |
return; |
} |
fb_offset = 4 * 0x2000; |
switch (fb_depth) { |
case 8: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
visual = VISUAL_INDIRECT_8; |
break; |
case 16: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
visual = VISUAL_RGB_5_6_5; |
break; |
case 24: |
fb_scanline = fb_linebytes * 4; |
visual = VISUAL_RGB_8_8_8_0; |
break; |
case 32: |
fb_scanline = fb_linebytes * (fb_depth >> 3); |
visual = VISUAL_RGB_0_8_8_8; |
break; |
default: |
printf("Unsupported bits per pixel.\n"); |
return; |
} |
break; |
case SCR_FFB: |
fb_scanline = 8192; |
visual = VISUAL_BGR_0_8_8_8; |
ofw_upa_reg_t *reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP]; |
if (!ofw_upa_apply_ranges(node->parent, reg, &fb_addr)) { |
upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP]; |
if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) { |
printf("Failed to determine screen address.\n"); |
return; |
} |
164,8 → 215,8 |
return; |
} |
ofw_sbus_reg_t *cg6_reg = &((ofw_sbus_reg_t *) prop->value)[0]; |
if (!ofw_sbus_apply_ranges(node->parent, cg6_reg, &fb_addr)) { |
sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0]; |
if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) { |
printf("Failed to determine screen address.\n"); |
return; |
} |
172,11 → 223,24 |
break; |
default: |
panic("Unexpected type.\n"); |
panic("Unexpected type."); |
} |
fb_init(fb_addr, fb_width, fb_height, fb_scanline, visual); |
fb_properties_t props = { |
.addr = fb_addr, |
.offset = fb_offset, |
.x = fb_width, |
.y = fb_height, |
.scan = fb_scanline, |
.visual = visual, |
}; |
fb_init(&props); |
} |
void scr_redraw(void) |
{ |
fb_redraw(); |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/src/drivers/tick.c |
---|
45,11 → 45,12 |
#define TICK_RESTART_TIME 50 /* Worst case estimate. */ |
/** Initialize tick interrupt. */ |
/** Initialize tick and stick interrupt. */ |
void tick_init(void) |
{ |
/* initialize TICK interrupt */ |
tick_compare_reg_t compare; |
interrupt_register(14, "tick_int", tick_interrupt); |
compare.int_dis = false; |
compare.tick_cmpr = CPU->arch.clock_frequency / HZ; |
56,6 → 57,21 |
CPU->arch.next_tick_cmpr = compare.tick_cmpr; |
tick_compare_write(compare.value); |
tick_write(0); |
#if defined (US3) |
/* disable STICK interrupts and clear any pending ones */ |
tick_compare_reg_t stick_compare; |
softint_reg_t clear; |
stick_compare.value = stick_compare_read(); |
stick_compare.int_dis = true; |
stick_compare.tick_cmpr = 0; |
stick_compare_write(stick_compare.value); |
clear.value = 0; |
clear.stick_int = 1; |
clear_softint_write(clear.value); |
#endif |
} |
/** Process tick interrupt. |
67,7 → 83,7 |
{ |
softint_reg_t softint, clear; |
uint64_t drift; |
softint.value = softint_read(); |
/* |
/branches/dd/kernel/arch/sparc64/src/drivers/sgcn.c |
---|
0,0 → 1,436 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** |
* @file |
* @brief SGCN driver. |
*/ |
#include <arch/drivers/sgcn.h> |
#include <arch/drivers/kbd.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <debug.h> |
#include <string.h> |
#include <print.h> |
#include <mm/page.h> |
#include <ipc/irq.h> |
#include <ddi/ddi.h> |
#include <ddi/device.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <ddi/device.h> |
#include <sysinfo/sysinfo.h> |
#include <synch/spinlock.h> |
/* |
* Physical address at which the SBBC starts. This value has been obtained |
* by inspecting (using Simics) memory accesses made by OBP. It is valid |
* for the Simics-simulated Serengeti machine. The author of this code is |
* not sure whether this value is valid generally. |
*/ |
#define SBBC_START 0x63000000000 |
/* offset of SRAM within the SBBC memory */ |
#define SBBC_SRAM_OFFSET 0x900000 |
/* size (in bytes) of the physical memory area which will be mapped */ |
#define MAPPED_AREA_SIZE (128 * 1024) |
/* magic string contained at the beginning of SRAM */ |
#define SRAM_TOC_MAGIC "TOCSRAM" |
/* |
* Key into the SRAM table of contents which identifies the entry |
* describing the OBP console buffer. It is worth mentioning |
* that the OBP console buffer is not the only console buffer |
* which can be used. It is, however, used because when the kernel |
* is running, the OBP buffer is not used by OBP any more but OBP |
* has already made neccessary arangements so that the output will |
* be read from the OBP buffer and input will go to the OBP buffer. |
* Therefore HelenOS needs to make no such arrangements any more. |
*/ |
#define CONSOLE_KEY "OBPCONS" |
/* magic string contained at the beginning of the console buffer */ |
#define SGCN_BUFFER_MAGIC "CON" |
/** |
* The driver is polling based, but in order to notify the userspace |
* of a key being pressed, we need to supply the interface with some |
* interrupt number. The interrupt number can be arbitrary as it it |
* will never be used for identifying HW interrupts, but only in |
* notifying the userspace. |
*/ |
#define FICTIONAL_INR 1 |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the SRAM beginning. |
*/ |
#define SRAM(type, offset) ((type *) (sram_begin + (offset))) |
/* Returns a pointer to the SRAM table of contents. */ |
#define SRAM_TOC (SRAM(iosram_toc_t, 0)) |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the console buffer beginning. |
*/ |
#define SGCN_BUFFER(type, offset) \ |
((type *) (sgcn_buffer_begin + (offset))) |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** defined in drivers/kbd.c */ |
extern kbd_type_t kbd_type; |
/** starting address of SRAM, will be set by the init_sram_begin function */ |
static uintptr_t sram_begin; |
/** |
* starting address of the SGCN buffer, will be set by the |
* init_sgcn_buffer_begin function |
*/ |
static uintptr_t sgcn_buffer_begin; |
/** |
* SGCN IRQ structure. So far used only for notifying the userspace of the |
* key being pressed, not for kernel being informed about keyboard interrupts. |
*/ |
static irq_t sgcn_irq; |
// TODO think of a way how to synchronize accesses to SGCN buffer between the kernel and the userspace |
/* |
* Ensures that writing to the buffer and consequent update of the write pointer |
* are together one atomic operation. |
*/ |
SPINLOCK_INITIALIZE(sgcn_output_lock); |
/* |
* Prevents the input buffer read/write pointers from getting to inconsistent |
* state. |
*/ |
SPINLOCK_INITIALIZE(sgcn_input_lock); |
/* functions referenced from definitions of I/O operations structures */ |
static void sgcn_noop(chardev_t *); |
static void sgcn_putchar(chardev_t *, const char, bool); |
static char sgcn_key_read(chardev_t *); |
/** character device operations */ |
static chardev_operations_t sgcn_ops = { |
.suspend = sgcn_noop, |
.resume = sgcn_noop, |
.read = sgcn_key_read, |
.write = sgcn_putchar |
}; |
/** SGCN character device */ |
chardev_t sgcn_io; |
/** |
* Set some sysinfo values (SRAM address and SRAM size). |
*/ |
static void register_sram(uintptr_t sram_begin_physical) |
{ |
sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE); |
sysinfo_set_item_val("sram.address.physical", NULL, |
sram_begin_physical); |
} |
/** |
* Initializes the starting address of SRAM. |
* |
* The SRAM starts 0x900000 + C bytes behind the SBBC start in the |
* physical memory, where C is the value read from the "iosram-toc" |
* property of the "/chosen" OBP node. The sram_begin variable will |
* be set to the virtual address which maps to the SRAM physical |
* address. |
* |
* It also registers the physical area of SRAM and sets some sysinfo |
* values (SRAM address and SRAM size). |
*/ |
static void init_sram_begin(void) |
{ |
ofw_tree_node_t *chosen; |
ofw_tree_property_t *iosram_toc; |
uintptr_t sram_begin_physical; |
chosen = ofw_tree_lookup("/chosen"); |
if (!chosen) |
panic("Cannot find '/chosen'."); |
iosram_toc = ofw_tree_getprop(chosen, "iosram-toc"); |
if (!iosram_toc) |
panic("Cannot find property 'iosram-toc'."); |
if (!iosram_toc->value) |
panic("Cannot find SRAM TOC."); |
sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET |
+ *((uint32_t *) iosram_toc->value); |
sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE); |
register_sram(sram_begin_physical); |
} |
/** |
* Initializes the starting address of the SGCN buffer. |
* |
* The offset of the SGCN buffer within SRAM is obtained from the |
* SRAM table of contents. The table of contents contains |
* information about several buffers, among which there is an OBP |
* console buffer - this one will be used as the SGCN buffer. |
* |
* This function also writes the offset of the SGCN buffer within SRAM |
* under the sram.buffer.offset sysinfo key. |
*/ |
static void sgcn_buffer_begin_init(void) |
{ |
init_sram_begin(); |
ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0); |
/* lookup TOC entry with the correct key */ |
uint32_t i; |
for (i = 0; i < MAX_TOC_ENTRIES; i++) { |
if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0) |
break; |
} |
ASSERT(i < MAX_TOC_ENTRIES); |
sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset; |
sysinfo_set_item_val("sram.buffer.offset", NULL, |
SRAM_TOC->keys[i].offset); |
} |
/** |
* Default suspend/resume operation for the input device. |
*/ |
static void sgcn_noop(chardev_t *d) |
{ |
} |
/** |
* Writes a single character to the SGCN (circular) output buffer |
* and updates the output write pointer so that SGCN gets to know |
* that the character has been written. |
*/ |
static void sgcn_do_putchar(const char c) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->out_begin; |
uint32_t end = SGCN_BUFFER_HEADER->out_end; |
uint32_t size = end - begin; |
/* we need pointers to volatile variables */ |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr); |
/* |
* Write the character and increment the write pointer modulo the |
* output buffer size. Note that if we are to rewrite a character |
* which has not been read by the SGCN controller yet (i.e. the output |
* buffer is full), we need to wait until the controller reads some more |
* characters. We wait actively, which means that all threads waiting |
* for the lock are blocked. However, this situation is |
* 1) rare - the output buffer is big, so filling the whole |
* output buffer is improbable |
* 2) short-lasting - it will take the controller only a fraction |
* of millisecond to pick the unread characters up |
* 3) not serious - the blocked threads are those that print something |
* to user console, which is not a time-critical operation |
*/ |
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin; |
while (*out_rdptr_ptr == new_wrptr) |
; |
*buf_ptr = c; |
*out_wrptr_ptr = new_wrptr; |
} |
/** |
* SGCN output operation. Prints a single character to the SGCN. If the line |
* feed character is written ('\n'), the carriage return character ('\r') is |
* written straight away. |
*/ |
static void sgcn_putchar(struct chardev * cd, const char c, bool silent) |
{ |
if (!silent) { |
spinlock_lock(&sgcn_output_lock); |
sgcn_do_putchar(c); |
if (c == '\n') |
sgcn_do_putchar('\r'); |
spinlock_unlock(&sgcn_output_lock); |
} |
} |
/** |
* Called when actively reading the character. Not implemented yet. |
*/ |
static char sgcn_key_read(chardev_t *d) |
{ |
return (char) 0; |
} |
/** |
* The driver works in polled mode, so no interrupt should be handled by it. |
*/ |
static irq_ownership_t sgcn_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
/** |
* The driver works in polled mode, so no interrupt should be handled by it. |
*/ |
static void sgcn_irq_handler(irq_t *irq) |
{ |
panic("Not yet implemented, SGCN works in polled mode."); |
} |
/** |
* Grabs the input for kernel. |
*/ |
void sgcn_grab(void) |
{ |
ipl_t ipl = interrupts_disable(); |
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
/* skip all the user typed before the grab and hasn't been processed */ |
spinlock_lock(&sgcn_input_lock); |
*in_rdptr_ptr = *in_wrptr_ptr; |
spinlock_unlock(&sgcn_input_lock); |
spinlock_lock(&sgcn_irq.lock); |
sgcn_irq.notif_cfg.notify = false; |
spinlock_unlock(&sgcn_irq.lock); |
interrupts_restore(ipl); |
} |
/** |
* Releases the input so that userspace can use it. |
*/ |
void sgcn_release(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&sgcn_irq.lock); |
if (sgcn_irq.notif_cfg.answerbox) |
sgcn_irq.notif_cfg.notify = true; |
spinlock_unlock(&sgcn_irq.lock); |
interrupts_restore(ipl); |
} |
/** |
* Function regularly called by the keyboard polling thread. Finds out whether |
* there are some unread characters in the input queue. If so, it picks them up |
* and sends them to the upper layers of HelenOS. |
*/ |
void sgcn_poll(void) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
uint32_t size = end - begin; |
spinlock_lock(&sgcn_input_lock); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&sgcn_irq.lock); |
/* we need pointers to volatile variables */ |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
if (*in_rdptr_ptr != *in_wrptr_ptr) { |
/* XXX: send notification to userspace */ |
} |
spinlock_unlock(&sgcn_irq.lock); |
interrupts_restore(ipl); |
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
char c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
if (c == '\r') { |
c = '\n'; |
} |
chardev_push_character(&sgcn_io, c); |
} |
spinlock_unlock(&sgcn_input_lock); |
} |
/** |
* A public function which initializes I/O from/to Serengeti console |
* and sets it as a default input/output. |
*/ |
void sgcn_init(void) |
{ |
sgcn_buffer_begin_init(); |
kbd_type = KBD_SGCN; |
devno_t devno = device_assign_devno(); |
irq_initialize(&sgcn_irq); |
sgcn_irq.devno = devno; |
sgcn_irq.inr = FICTIONAL_INR; |
sgcn_irq.claim = sgcn_claim; |
sgcn_irq.handler = sgcn_irq_handler; |
irq_register(&sgcn_irq); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR); |
sysinfo_set_item_val("fb.kind", NULL, 4); |
chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops); |
stdin = &sgcn_io; |
stdout = &sgcn_io; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/src/drivers/pci.c |
---|
42,43 → 42,41 |
#include <arch/types.h> |
#include <debug.h> |
#include <print.h> |
#include <func.h> |
#include <string.h> |
#include <arch/asm.h> |
#include <sysinfo/sysinfo.h> |
#define PCI_SABRE_REGS_REG 0 |
#define SABRE_INTERNAL_REG 0 |
#define PSYCHO_INTERNAL_REG 2 |
#define PCI_SABRE_IMAP_BASE 0x200 |
#define PCI_SABRE_ICLR_BASE 0x300 |
#define OBIO_IMR_BASE 0x200 |
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK)) |
#define PCI_PSYCHO_REGS_REG 2 |
#define OBIO_CIR_BASE 0x300 |
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK)) |
#define PCI_PSYCHO_IMAP_BASE 0x200 |
#define PCI_PSYCHO_ICLR_BASE 0x300 |
static void obio_enable_interrupt(pci_t *, int); |
static void obio_clear_interrupt(pci_t *, int); |
static pci_t *pci_sabre_init(ofw_tree_node_t *node); |
static void pci_sabre_enable_interrupt(pci_t *pci, int inr); |
static void pci_sabre_clear_interrupt(pci_t *pci, int inr); |
static pci_t *pci_sabre_init(ofw_tree_node_t *); |
static pci_t *pci_psycho_init(ofw_tree_node_t *); |
static pci_t *pci_psycho_init(ofw_tree_node_t *node); |
static void pci_psycho_enable_interrupt(pci_t *pci, int inr); |
static void pci_psycho_clear_interrupt(pci_t *pci, int inr); |
/** PCI operations for Sabre model. */ |
static pci_operations_t pci_sabre_ops = { |
.enable_interrupt = pci_sabre_enable_interrupt, |
.clear_interrupt = pci_sabre_clear_interrupt |
.enable_interrupt = obio_enable_interrupt, |
.clear_interrupt = obio_clear_interrupt |
}; |
/** PCI operations for Psycho model. */ |
static pci_operations_t pci_psycho_ops = { |
.enable_interrupt = pci_psycho_enable_interrupt, |
.clear_interrupt = pci_psycho_clear_interrupt |
.enable_interrupt = obio_enable_interrupt, |
.clear_interrupt = obio_clear_interrupt |
}; |
/** Initialize PCI controller (model Sabre). |
* |
* @param node OpenFirmware device tree node of the Sabre. |
* @param node OpenFirmware device tree node of the Sabre. |
* |
* @return Address of the initialized PCI structure. |
* @return Address of the initialized PCI structure. |
*/ |
pci_t *pci_sabre_init(ofw_tree_node_t *node) |
{ |
95,11 → 93,12 |
ofw_upa_reg_t *reg = prop->value; |
count_t regs = prop->size / sizeof(ofw_upa_reg_t); |
if (regs < PCI_SABRE_REGS_REG + 1) |
if (regs < SABRE_INTERNAL_REG + 1) |
return NULL; |
uintptr_t paddr; |
if (!ofw_upa_apply_ranges(node->parent, ®[PCI_SABRE_REGS_REG], &paddr)) |
if (!ofw_upa_apply_ranges(node->parent, ®[SABRE_INTERNAL_REG], |
&paddr)) |
return NULL; |
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC); |
108,8 → 107,14 |
pci->model = PCI_SABRE; |
pci->op = &pci_sabre_ops; |
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size); |
pci->reg = (uint64_t *) hw_map(paddr, reg[SABRE_INTERNAL_REG].size); |
/* |
* Set sysinfo data needed by the uspace OBIO driver. |
*/ |
sysinfo_set_item_val("obio.base.physical", NULL, paddr); |
sysinfo_set_item_val("kbd.cir.obio", NULL, 1); |
return pci; |
} |
116,9 → 121,9 |
/** Initialize the Psycho PCI controller. |
* |
* @param node OpenFirmware device tree node of the Psycho. |
* @param node OpenFirmware device tree node of the Psycho. |
* |
* @return Address of the initialized PCI structure. |
* @return Address of the initialized PCI structure. |
*/ |
pci_t *pci_psycho_init(ofw_tree_node_t *node) |
{ |
135,11 → 140,12 |
ofw_upa_reg_t *reg = prop->value; |
count_t regs = prop->size / sizeof(ofw_upa_reg_t); |
if (regs < PCI_PSYCHO_REGS_REG + 1) |
if (regs < PSYCHO_INTERNAL_REG + 1) |
return NULL; |
uintptr_t paddr; |
if (!ofw_upa_apply_ranges(node->parent, ®[PCI_PSYCHO_REGS_REG], &paddr)) |
if (!ofw_upa_apply_ranges(node->parent, ®[PSYCHO_INTERNAL_REG], |
&paddr)) |
return NULL; |
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC); |
148,31 → 154,27 |
pci->model = PCI_PSYCHO; |
pci->op = &pci_psycho_ops; |
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_PSYCHO_REGS_REG].size); |
pci->reg = (uint64_t *) hw_map(paddr, reg[PSYCHO_INTERNAL_REG].size); |
/* |
* Set sysinfo data needed by the uspace OBIO driver. |
*/ |
sysinfo_set_item_val("obio.base.physical", NULL, paddr); |
sysinfo_set_item_val("kbd.cir.obio", NULL, 1); |
return pci; |
} |
void pci_sabre_enable_interrupt(pci_t *pci, int inr) |
void obio_enable_interrupt(pci_t *pci, int inr) |
{ |
pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK; |
pci->reg[OBIO_IMR(inr & INO_MASK)] |= IMAP_V_MASK; |
} |
void pci_sabre_clear_interrupt(pci_t *pci, int inr) |
void obio_clear_interrupt(pci_t *pci, int inr) |
{ |
pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0; |
pci->reg[OBIO_CIR(inr & INO_MASK)] = 0; /* set IDLE */ |
} |
void pci_psycho_enable_interrupt(pci_t *pci, int inr) |
{ |
pci->reg[PCI_PSYCHO_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK; |
} |
void pci_psycho_clear_interrupt(pci_t *pci, int inr) |
{ |
pci->reg[PCI_PSYCHO_ICLR_BASE + (inr & INO_MASK)] = 0; |
} |
/** Initialize PCI controller. */ |
pci_t *pci_init(ofw_tree_node_t *node) |
{ |
215,14 → 217,14 |
void pci_enable_interrupt(pci_t *pci, int inr) |
{ |
ASSERT(pci->model); |
ASSERT(pci->op && pci->op->enable_interrupt); |
pci->op->enable_interrupt(pci, inr); |
} |
void pci_clear_interrupt(pci_t *pci, int inr) |
void pci_clear_interrupt(void *pcip, int inr) |
{ |
ASSERT(pci->model); |
pci_t *pci = (pci_t *)pcip; |
ASSERT(pci->op && pci->op->clear_interrupt); |
pci->op->clear_interrupt(pci, inr); |
} |
/branches/dd/kernel/arch/sparc64/src/start.S |
---|
27,6 → 27,7 |
# |
#include <arch/arch.h> |
#include <arch/cpu.h> |
#include <arch/regdef.h> |
#include <arch/boot/boot.h> |
#include <arch/stack.h> |
47,6 → 48,16 |
#define BSP_FLAG 1 |
/* |
* 2^PHYSMEM_ADDR_SIZE is the size of the physical address space on |
* a given processor. |
*/ |
#if defined (US) |
#define PHYSMEM_ADDR_SIZE 41 |
#elif defined (US3) |
#define PHYSMEM_ADDR_SIZE 43 |
#endif |
/* |
* Here is where the kernel is passed control from the boot loader. |
* |
* The registers are expected to be in this state: |
67,11 → 78,13 |
and %o0, %l0, %l7 ! l7 <= bootstrap processor? |
andn %o0, %l0, %l6 ! l6 <= start of physical memory |
! Get bits 40:13 of physmem_base. |
! Get bits (PHYSMEM_ADDR_SIZE - 1):13 of physmem_base. |
srlx %l6, 13, %l5 |
sllx %l5, 13 + (63 - 40), %l5 |
srlx %l5, 63 - 40, %l5 ! l5 <= physmem_base[40:13] |
! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13] |
sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5 |
srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5 |
/* |
* Setup basic runtime environment. |
*/ |
83,6 → 96,8 |
! consistent |
wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent needless clean_window |
! traps for kernel |
wrpr %g0, 0, %wstate ! use default spill/fill trap |
wrpr %g0, 0, %tl ! TL = 0, primary context |
! register is used |
244,7 → 259,8 |
/* |
* Precompute kernel 8K TLB data template. |
* %l5 contains starting physical address bits [40:13] |
* %l5 contains starting physical address |
* bits [(PHYSMEM_ADDR_SIZE - 1):13] |
*/ |
sethi %hi(kernel_8k_tlb_data_template), %l4 |
ldx [%l4 + %lo(kernel_8k_tlb_data_template)], %l3 |
282,15 → 298,32 |
nop |
1: |
#ifdef CONFIG_SMP |
/* |
* Determine the width of the MID and save its mask to %g3. The width |
* is |
* * 5 for US and US-IIIi, |
* * 10 for US3 except US-IIIi. |
*/ |
#if defined(US) |
mov 0x1f, %g3 |
#elif defined(US3) |
mov 0x3ff, %g3 |
rdpr %ver, %g2 |
sllx %g2, 16, %g2 |
srlx %g2, 48, %g2 |
cmp %g2, IMPL_ULTRASPARCIII_I |
move %xcc, 0x1f, %g3 |
#endif |
/* |
* Read MID from the processor. |
*/ |
1: |
ldxa [%g0] ASI_UPA_CONFIG, %g1 |
srlx %g1, UPA_CONFIG_MID_SHIFT, %g1 |
and %g1, UPA_CONFIG_MID_MASK, %g1 |
ldxa [%g0] ASI_ICBUS_CONFIG, %g1 |
srlx %g1, ICBUS_CONFIG_MID_SHIFT, %g1 |
and %g1, %g3, %g1 |
#ifdef CONFIG_SMP |
/* |
* Active loop for APs until the BSP picks them up. A processor cannot |
* leave the loop until the global variable 'waking_up_mid' equals its |
/branches/dd/kernel/arch/ia64/include/interrupt.h |
---|
50,10 → 50,13 |
#define IVT_FIRST 0 |
/** External Interrupt vectors. */ |
#define VECTOR_TLB_SHOOTDOWN_IPI 0xf0 |
#define INTERRUPT_TIMER 255 |
#define IRQ_KBD 241 |
#define IRQ_MOUSE 252 |
#define IRQ_KBD (0x01 + LEGACY_INTERRUPT_BASE) |
#define IRQ_MOUSE (0x0c + LEGACY_INTERRUPT_BASE) |
#define INTERRUPT_SPURIOUS 15 |
#define LEGACY_INTERRUPT_BASE 0x20 |
/** General Exception codes. */ |
#define GE_ILLEGALOP 0 |
114,7 → 117,7 |
/* |
* The following variables are defined only for break_instruction |
* handler. |
* handler. |
*/ |
uint64_t in0; |
uint64_t in1; |
150,6 → 153,8 |
extern void external_interrupt(uint64_t vector, istate_t *istate); |
extern void disabled_fp_register(uint64_t vector, istate_t *istate); |
extern void trap_virtual_enable_irqs(uint16_t irqmask); |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/fpu_context.h |
---|
35,7 → 35,6 |
#ifndef KERN_ia64_FPU_CONTEXT_H_ |
#define KERN_ia64_FPU_CONTEXT_H_ |
#define ARCH_HAS_FPU 1 |
#define FPU_CONTEXT_ALIGN 16 |
#include <arch/types.h> |
/branches/dd/kernel/arch/ia64/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ia64_TYPES_H_ |
#define KERN_ia64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
69,14 → 65,34 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
unative_t fnc; |
unative_t gp; |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRIp "lx" /**< Format for uintptr_t. */ |
#define PRIs "lu" /**< Format for size_t. */ |
#define PRIc "lu" /**< Format for count_t. */ |
#define PRIi "lu" /**< Format for index_t. */ |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "ld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "lu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "lx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/dd/kernel/arch/ia64/include/atomic.h |
---|
37,29 → 37,65 |
/** Atomic addition. |
* |
* @param val Atomic value. |
* @param imm Value to add. |
* @param val Atomic value. |
* @param imm Value to add. |
* |
* @return Value before addition. |
* @return Value before addition. |
*/ |
static inline long atomic_add(atomic_t *val, int imm) |
{ |
long v; |
asm volatile ("fetchadd8.rel %0 = %1, %2\n" : "=r" (v), "+m" (val->count) : "i" (imm)); |
asm volatile ("fetchadd8.rel %0 = %1, %2\n" : "=r" (v), |
"+m" (val->count) : "i" (imm)); |
return v; |
} |
static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); } |
static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); } |
static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1) + 1; } |
static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1) - 1; } |
static inline uint64_t test_and_set(atomic_t *val) { |
uint64_t v; |
asm volatile ( |
"movl %0 = 0x01;;\n" |
"xchg8 %0 = %1, %0;;\n" |
: "=r" (v), "+m" (val->count) |
); |
return v; |
} |
static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1); } |
static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1); } |
static inline void atomic_inc(atomic_t *val) |
{ |
atomic_add(val, 1); |
} |
static inline void atomic_dec(atomic_t *val) |
{ |
atomic_add(val, -1); |
} |
static inline long atomic_preinc(atomic_t *val) |
{ |
return atomic_add(val, 1) + 1; |
} |
static inline long atomic_predec(atomic_t *val) |
{ |
return atomic_add(val, -1) - 1; |
} |
static inline long atomic_postinc(atomic_t *val) |
{ |
return atomic_add(val, 1); |
} |
static inline long atomic_postdec(atomic_t *val) |
{ |
return atomic_add(val, -1); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/arch.h |
---|
39,6 → 39,8 |
#include <arch/ski/ski.h> |
extern void arch_pre_main(void); |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/proc/task.h |
---|
31,14 → 31,19 |
*/ |
/** @file |
*/ |
#include <proc/task.h> |
#ifndef KERN_ia64_TASK_H_ |
#define KERN_ia64_TASK_H_ |
#include <adt/bitmap.h> |
typedef struct { |
bitmap_t *iomap; |
} task_arch_t; |
#define task_create_arch(t) |
#define task_create_arch(t) { (t)->arch.iomap = NULL; } |
#define task_destroy_arch(t) |
#endif |
/branches/dd/kernel/arch/ia64/include/bootinfo.h |
---|
29,13 → 29,23 |
#ifndef KERN_ia64_BOOTINFO_H_ |
#define KERN_ia64_BOOTINFO_H_ |
#define BOOTINFO_ADDRESS 0x4401000 |
#define CONFIG_INIT_TASKS 32 |
#define MEMMAP_ITEMS 128 |
#define EFI_MEMMAP_FREE_MEM 0 |
#define EFI_MEMMAP_IO 1 |
#define EFI_MEMMAP_IO_PORTS 2 |
/** Size of buffer for storing task name in binit_task_t. */ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
typedef struct { |
void *addr; |
unsigned long size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} binit_task_t; |
typedef struct { |
43,9 → 53,24 |
binit_task_t tasks[CONFIG_INIT_TASKS]; |
} binit_t; |
typedef struct { |
unsigned int type; |
unsigned long base; |
unsigned long size; |
}efi_memmap_item_t; |
typedef struct { |
binit_t taskmap; |
efi_memmap_item_t memmap[MEMMAP_ITEMS]; |
unsigned int memmap_items; |
unsigned long * sapic; |
unsigned long sys_freq; |
unsigned long freq_scale; |
unsigned int wakeup_intno; |
int hello_configured; |
} bootinfo_t; |
extern bootinfo_t *bootinfo; |
/branches/dd/kernel/arch/ia64/include/asm.h |
---|
36,29 → 36,72 |
#define KERN_ia64_ASM_H_ |
#include <config.h> |
#include <typedefs.h> |
#include <arch/types.h> |
#include <arch/register.h> |
#define IA64_IOSPACE_ADDRESS 0xE001000000000000ULL |
static inline void outb(uint64_t port,uint8_t v) |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
static inline uint8_t inb(uint64_t port) |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
return *((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))); |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
/** Return base address of current stack |
* |
* Return the base address of the current stack. |
69,9 → 112,14 |
{ |
uint64_t v; |
asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1))); |
//I'm not sure why but this code bad inlines in scheduler, |
//so THE shifts about 16B and causes kernel panic |
//asm volatile ("and %0 = %1, r12" : "=r" (v) : "r" (~(STACK_SIZE-1))); |
//return v; |
return v; |
//this code have the same meaning but inlines well |
asm volatile ("mov %0 = r12" : "=r" (v) ); |
return v & (~(STACK_SIZE-1)); |
} |
/** Return Processor State Register. |
123,6 → 171,16 |
return v; |
} |
static inline uint64_t cr64_read(void) |
{ |
uint64_t v; |
asm volatile ("mov %0 = cr64\n" : "=r" (v)); |
return v; |
} |
/** Write ITC (Interval Timer Counter) register. |
* |
* @param v New counter value. |
297,7 → 355,8 |
extern void cpu_sleep(void); |
extern void asm_delay_loop(uint32_t t); |
extern void switch_to_userspace(uintptr_t entry, uintptr_t sp, uintptr_t bsp, uintptr_t uspace_uarg, uint64_t ipsr, uint64_t rsc); |
extern void switch_to_userspace(uintptr_t, uintptr_t, uintptr_t, uintptr_t, |
uint64_t, uint64_t); |
#endif |
/branches/dd/kernel/arch/ia64/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64mm |
/** @addtogroup ia64mm |
* @{ |
*/ |
/** @file |
35,12 → 35,16 |
#ifndef KERN_ia64_FRAME_H_ |
#define KERN_ia64_FRAME_H_ |
#define FRAME_WIDTH 14 /* 16K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 14 /* 16K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
#include <arch/types.h> |
extern uintptr_t last_frame; |
extern void frame_arch_init(void); |
#define physmem_print() |
/branches/dd/kernel/arch/ia64/include/mm/page.h |
---|
41,15 → 41,30 |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
/** Bit width of the TLB-locked portion of kernel address space. */ |
#define KERNEL_PAGE_WIDTH 28 /* 256M */ |
#define IO_PAGE_WIDTH 26 /* 64M */ |
#define FW_PAGE_WIDTH 28 /* 256M */ |
#define USPACE_IO_PAGE_WIDTH 12 /* 4K */ |
/* |
* Statically mapped IO spaces - offsets to 0xe...00 of virtual addresses |
* because of "minimal virtual bits implemented is 51" it is possible to |
* have values up to 0x0007000000000000 |
*/ |
/* Firmware area (bellow 4GB in phys mem) */ |
#define FW_OFFSET 0x00000000F0000000 |
/* Legacy IO space */ |
#define IO_OFFSET 0x0001000000000000 |
/* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000 */ |
#define VIO_OFFSET 0x0002000000000000 |
#define PPN_SHIFT 12 |
#define VRN_SHIFT 61 |
64,8 → 79,8 |
#define REGION_REGISTERS 8 |
#define KA2PA(x) ((uintptr_t) (x-(VRN_KERNEL<<VRN_SHIFT))) |
#define PA2KA(x) ((uintptr_t) (x+(VRN_KERNEL<<VRN_SHIFT))) |
#define KA2PA(x) ((uintptr_t) (x - (VRN_KERNEL << VRN_SHIFT))) |
#define PA2KA(x) ((uintptr_t) (x + (VRN_KERNEL << VRN_SHIFT))) |
#define VHPT_WIDTH 20 /* 1M */ |
#define VHPT_SIZE (1 << VHPT_WIDTH) |
/branches/dd/kernel/arch/ia64/include/mm/tlb.h |
---|
35,9 → 35,6 |
#ifndef KERN_ia64_TLB_H_ |
#define KERN_ia64_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#include <arch/mm/page.h> |
#include <arch/mm/asid.h> |
#include <arch/interrupt.h> |
46,8 → 43,8 |
/** Data and instruction Translation Register indices. */ |
#define DTR_KERNEL 0 |
#define ITR_KERNEL 0 |
#define DTR_KSTACK1 1 |
#define DTR_KSTACK2 2 |
#define DTR_KSTACK1 4 |
#define DTR_KSTACK2 5 |
/** Portion of TLB insertion format data structure. */ |
union tlb_entry { |
/branches/dd/kernel/arch/ia64/include/mm/vhpt.h |
---|
44,8 → 44,8 |
{ |
vhpt_entry_t ventry; |
ventry.word[0]=tentry.word[0]; |
ventry.word[1]=tentry.word[1]; |
ventry.word[0] = tentry.word[0]; |
ventry.word[1] = tentry.word[1]; |
return ventry; |
} |
/branches/dd/kernel/arch/ia64/include/register.h |
---|
40,11 → 40,11 |
#define PSR_I_MASK 0x4000 |
#define PSR_PK_MASK 0x8000 |
#define PSR_DT_MASK (1<<17) |
#define PSR_RT_MASK (1<<27) |
#define PSR_DT_MASK (1 << 17) |
#define PSR_RT_MASK (1 << 27) |
#define PSR_DFL_MASK (1<<18) |
#define PSR_DFH_MASK (1<<19) |
#define PSR_DFL_MASK (1 << 18) |
#define PSR_DFH_MASK (1 << 19) |
#define PSR_IT_MASK 0x0000001000000000 |
/branches/dd/kernel/arch/ia64/include/debug.h |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2005 |
* Copyright (c) 2005 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
/branches/dd/kernel/arch/ia64/include/barrier.h |
---|
45,9 → 45,33 |
#define read_barrier() memory_barrier() |
#define write_barrier() memory_barrier() |
#define srlz_i() asm volatile (";; srlz.i ;;\n" ::: "memory") |
#define srlz_d() asm volatile (";; srlz.d\n" ::: "memory") |
#define srlz_i() \ |
asm volatile (";; srlz.i ;;\n" ::: "memory") |
#define srlz_d() \ |
asm volatile (";; srlz.d\n" ::: "memory") |
#define fc_i(a) \ |
asm volatile ("fc.i %0\n" :: "r" ((a)) : "memory") |
#define sync_i() \ |
asm volatile (";; sync.i\n" ::: "memory") |
#define smc_coherence(a) \ |
{ \ |
fc_i((a)); \ |
sync_i(); \ |
srlz_i(); \ |
} |
#define FC_INVAL_MIN 32 |
#define smc_coherence_block(a, l) \ |
{ \ |
unsigned long i; \ |
for (i = 0; i < (l); i += FC_INVAL_MIN) \ |
fc_i((void *)(a) + i); \ |
sync_i(); \ |
srlz_i(); \ |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/cpu.h |
---|
38,6 → 38,7 |
#include <arch/types.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
#include <arch/bootinfo.h> |
#define FAMILY_ITANIUM 0x7 |
#define FAMILY_ITANIUM2 0x1f |
63,6 → 64,32 |
return v; |
} |
#define CR64_ID_SHIFT 24 |
#define CR64_ID_MASK 0xff000000 |
#define CR64_EID_SHIFT 16 |
#define CR64_EID_MASK 0xff0000 |
static inline int ia64_get_cpu_id(void) |
{ |
uint64_t cr64=cr64_read(); |
return ((CR64_ID_MASK)&cr64)>>CR64_ID_SHIFT; |
} |
static inline int ia64_get_cpu_eid(void) |
{ |
uint64_t cr64=cr64_read(); |
return ((CR64_EID_MASK)&cr64)>>CR64_EID_SHIFT; |
} |
static inline void ipi_send_ipi(int id, int eid, int intno) |
{ |
(bootinfo->sapic)[2 * (id * 256 + eid)] = intno; |
srlz_d(); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ia64/include/drivers/i8042.h |
---|
File deleted |
/branches/dd/kernel/arch/ia64/include/drivers/ega.h |
---|
File deleted |
/branches/dd/kernel/arch/ia64/include/drivers/it.h |
---|
41,7 → 41,7 |
* from firmware. |
* |
*/ |
#define IT_DELTA 100000 |
#define IT_DELTA it_delta |
extern void it_init(void); |
/branches/dd/kernel/arch/ia64/include/drivers/kbd.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2006 Jakub Jermar, Jakub Vana |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia6464 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_ia64_KBD_H_ |
#define KERN_ia64_KBD_H_ |
#define KBD_UNKNOWN 0 |
#define KBD_SKI 1 |
#define KBD_LEGACY 2 |
#define KBD_NS16550 3 |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/Makefile.inc |
---|
32,11 → 32,8 |
BFD_NAME = elf64-little |
BFD_ARCH = ia64-elf64 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64 |
INIT0_ADDRESS = 0xe000000004404000 |
INIT0_SIZE = 0x100000 |
CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127 |
GCC_CFLAGS += $(CMN1) |
ICC_CFLAGS += $(CMN1) |
44,58 → 41,35 |
LFLAGS += -EL |
AFLAGS += -mconstant-gp |
DEFS += -D__64_BITS__ -DINIT0_ADDRESS=$(INIT0_ADDRESS) -DINIT0_SIZE=$(INIT0_SIZE) -D$(MACHINE) |
DEFS += -D__64_BITS__ |
## Compile with page hash table support. |
# |
CONFIG_PAGE_HT = y |
DEFS += -DCONFIG_PAGE_HT |
## Compile with support for address space identifiers. |
# |
CONFIG_ASID = y |
CONFIG_ASID_FIFO = y |
## Compile with support for software integer division. |
# |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/start.S \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/dummy.s \ |
arch/$(ARCH)/src/ia64.c \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/ivt.S \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/mm/vhpt.c \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/it.c |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/dummy.s \ |
arch/$(KARCH)/src/ia64.c \ |
arch/$(KARCH)/src/fpu_context.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/ivt.S \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/mm/vhpt.c \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/smp/smp.c \ |
arch/$(KARCH)/src/drivers/it.c |
ifeq ($(MACHINE),ski) |
ARCH_SOURCES += arch/$(ARCH)/src/ski/ski.c |
ARCH_SOURCES += arch/$(KARCH)/src/ski/ski.c |
DEFS += -DSKI |
# BFD = elf64-ia64-little |
BFD = binary |
endif |
ifeq ($(MACHINE),i460GX) |
ARCH_SOURCES += arch/$(ARCH)/src/drivers/ega.c |
CONFIG_I8042 = y |
DEFS += -DI460GX -DCONFIG_I8042 |
DEFS += -DI460GX |
BFD = binary |
endif |
/branches/dd/kernel/arch/ia64/src/putchar.c |
---|
File deleted |
/branches/dd/kernel/arch/ia64/src/fpu_context.c |
---|
149,8 → 149,10 |
"stf.spill [%7] = f127, 0x80\n;;" |
: |
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), "r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])), |
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), "r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7])) |
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), |
"r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])), |
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), |
"r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7])) |
); |
} |
267,14 → 269,16 |
"ldf.fill f127 = [%7], 0x80\n;;" |
: |
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), "r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])), |
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), "r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7])) |
: "r" (&((fctx->fr)[0])), "r" (&((fctx->fr)[1])), |
"r" (&((fctx->fr)[2])), "r" (&((fctx->fr)[3])), |
"r" (&((fctx->fr)[4])), "r" (&((fctx->fr)[5])), |
"r" (&((fctx->fr)[6])), "r" (&((fctx->fr)[7])) |
); |
} |
void fpu_enable(void) |
{ |
uint64_t a = 0 ; |
uint64_t a = 0; |
asm volatile ( |
"rsm %0 ;;" |
/branches/dd/kernel/arch/ia64/src/smp/smp.c |
---|
0,0 → 1,167 |
/* |
* Copyright (c) 2005 Jakub Vana |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
#include <arch/asm.h> |
#include <arch/register.h> |
#include <arch/types.h> |
#include <arch/context.h> |
#include <arch/stack.h> |
#include <arch/mm/page.h> |
#include <mm/as.h> |
#include <config.h> |
#include <userspace.h> |
#include <console/console.h> |
#include <proc/uarg.h> |
#include <syscall/syscall.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <arch/bootinfo.h> |
#include <smp/smp.h> |
#include <smp/ipi.h> |
#include <arch/atomic.h> |
#include <panic.h> |
#include <print.h> |
#ifdef CONFIG_SMP |
extern char cpu_by_id_eid_list[256][256]; |
static void sapic_init(void) |
{ |
bootinfo->sapic = (unative_t *)(PA2KA((unative_t)(bootinfo->sapic)) | |
FW_OFFSET); |
} |
static void ipi_broadcast_arch_all(int ipi) |
{ |
int id, eid; |
int myid, myeid; |
myid = ia64_get_cpu_id(); |
myeid = ia64_get_cpu_eid(); |
for (id = 0; id < 256; id++) |
for (eid = 0; eid < 256; eid++) |
if ((id != myid) || (eid != myeid)) |
ipi_send_ipi(id, eid, ipi); |
} |
void ipi_broadcast_arch(int ipi ) |
{ |
int id, eid; |
int myid, myeid; |
myid = ia64_get_cpu_id(); |
myeid = ia64_get_cpu_eid(); |
for (id = 0; id < 256; id++) |
for (eid = 0; eid < 256; eid++) |
if ((id != myid) || (eid != myeid)) |
if (cpu_by_id_eid_list[id][eid]) |
ipi_send_ipi(id, eid, ipi); |
} |
void smp_init(void) |
{ |
if (!bootinfo->hello_configured) |
return; |
/* |
* If we have not got system prepared by hello, we are not able to start |
* AP's. This means we are running on a simulator. |
*/ |
sapic_init(); |
ipi_broadcast_arch_all(bootinfo->wakeup_intno); |
volatile long long brk; |
for (brk = 0; brk < 100LL * 1024LL * 1024LL; brk++) |
; /* wait a while before CPUs starts */ |
config.cpu_count = 0; |
int id, eid; |
for (id = 0; id < 256; id++) |
for (eid = 0; eid < 256; eid++) |
if (cpu_by_id_eid_list[id][eid] == 1) { |
config.cpu_count++; |
cpu_by_id_eid_list[id][eid] = 2; |
} |
} |
void kmp(void *arg __attribute__((unused))) |
{ |
int id, eid; |
int myid, myeid; |
myid = ia64_get_cpu_id(); |
myeid = ia64_get_cpu_eid(); |
for (id = 0; id < 256; id++) |
for (eid = 0; eid < 256; eid++) |
if ((id != myid) || (eid != myeid)) |
if (cpu_by_id_eid_list[id][eid] != 0) { |
if (cpu_by_id_eid_list[id][eid] == 1) { |
printf("Found Late CPU ID:%d " |
"EDI:%d Not added to " |
"system!!!\n", id, eid); |
continue; |
} |
cpu_by_id_eid_list[id][eid] = 3; |
/* |
* There may be just one AP being |
* initialized at the time. After |
* it comes completely up, it is |
* supposed to wake us up. |
*/ |
if (waitq_sleep_timeout( |
&ap_completion_wq, 1000000, |
SYNCH_FLAGS_NONE) == |
ESYNCH_TIMEOUT) { |
printf("%s: waiting for cpu " |
"ID:%d EID:%d timed out\n", |
__FUNCTION__, id, eid); |
} |
} |
} |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/src/ddi/ddi.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jakub vana |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
35,19 → 36,39 |
#include <ddi/ddi.h> |
#include <proc/task.h> |
#include <arch/types.h> |
#include <mm/slab.h> |
#include <errno.h> |
#define IO_MEMMAP_PAGES 16384 |
#define PORTS_PER_PAGE 4 |
/** Enable I/O space range for task. |
* |
* Interrupts are disabled and task is locked. |
* |
* @param task Task. |
* @param ioaddr Startign I/O space address. |
* @param size Size of the enabled I/O range. |
* @param task Task. |
* @param ioaddr Starting I/O space address. |
* @param size Size of the enabled I/O range. |
* |
* @return 0 on success or an error code from errno.h. |
*/ |
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size) |
{ |
if (!task->arch.iomap) { |
uint8_t *map; |
task->arch.iomap = malloc(sizeof(bitmap_t), 0); |
map = malloc(BITS2BYTES(IO_MEMMAP_PAGES), 0); |
if(!map) |
return ENOMEM; |
bitmap_initialize(task->arch.iomap, map, IO_MEMMAP_PAGES); |
bitmap_clear_range(task->arch.iomap, 0, IO_MEMMAP_PAGES); |
} |
uintptr_t iopage = ioaddr / PORTS_PER_PAGE; |
size = ALIGN_UP(size + ioaddr - 4 * iopage, PORTS_PER_PAGE); |
bitmap_set_range(task->arch.iomap, iopage, size / 4); |
return 0; |
} |
/branches/dd/kernel/arch/ia64/src/asm.S |
---|
51,7 → 51,7 |
adds r14 = 7, in1 |
mov r2 = ar.lc |
mov r8 = in1 ;; |
mov r8 = in0 |
and r14 = -8, r14 ;; |
cmp.ne p6, p7 = r14, in1 |
(p7) br.cond.dpnt 3f ;; |
63,7 → 63,7 |
(p6) mov r17 = r0 ;; |
(p6) mov ar.lc = r14 |
1: |
add r14 = r16, r8 |
add r14 = r16, in1 |
add r15 = r16, in0 |
adds r17 = 1, r17 ;; |
ld1 r14 = [r14] |
72,7 → 72,6 |
br.cloop.sptk.few 1b ;; |
2: |
mov ar.lc = r2 |
mov ar.pfs = loc0 |
br.ret.sptk.many rp |
3: |
90,7 → 89,7 |
4: |
shladd r14 = r16, 3, r0 |
adds r16 = 1, r17 ;; |
add r15 = r8, r14 |
add r15 = in1, r14 |
add r14 = in0, r14 |
mov r17 = r16 ;; |
ld8 r15 = [r15] ;; |
104,7 → 103,7 |
cmp.eq p6, p7 = 0, r15 |
add in0 = r14, in0 |
adds r15 = -1, r15 |
add r17 = r14, r8 |
add r17 = r14, in1 |
(p6) br.cond.dpnt 2b ;; |
mov ar.lc = r15 |
6: |
116,7 → 115,6 |
st1 [r15] = r14 |
br.cloop.sptk.few 6b ;; |
mov ar.lc = r2 |
mov ar.pfs = loc0 |
br.ret.sptk.many rp |
130,6 → 128,10 |
memsetb: |
br _memsetb |
.global memsetw |
memsetw: |
br _memsetw |
.global cpu_halt |
cpu_halt: |
br cpu_halt |
163,6 → 165,9 |
xor r1 = r1, r1 |
/* r2 is defined to hold pcb_ptr - set it to 0 */ |
xor r2 = r2, r2 |
mov loc1 = cr.ifs |
movl loc2 = PFM_MASK ;; |
and loc1 = loc2, loc1 ;; |
/branches/dd/kernel/arch/ia64/src/proc/scheduler.c |
---|
47,14 → 47,17 |
{ |
} |
/** Prepare kernel stack pointers in bank 0 r22 and r23 and make sure the stack is mapped in DTR. */ |
/** Prepare kernel stack pointers in bank 0 r22 and r23 and make sure the stack |
* is mapped in DTR. |
*/ |
void before_thread_runs_arch(void) |
{ |
uintptr_t base; |
base = ALIGN_DOWN(config.base, 1<<KERNEL_PAGE_WIDTH); |
base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH); |
if ((uintptr_t) THREAD->kstack < base || (uintptr_t) THREAD->kstack > base + (1<<(KERNEL_PAGE_WIDTH))) { |
if ((uintptr_t) THREAD->kstack < base || |
(uintptr_t) THREAD->kstack > base + (1 << (KERNEL_PAGE_WIDTH))) { |
/* |
* Kernel stack of this thread is not mapped by DTR[TR_KERNEL]. |
* Use DTR[TR_KSTACK1] and DTR[TR_KSTACK2] to map it. |
64,8 → 67,11 |
dtr_purge((uintptr_t) THREAD->kstack, PAGE_WIDTH+1); |
/* insert DTR[TR_STACK1] and DTR[TR_STACK2] */ |
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack, KA2PA(THREAD->kstack), true, DTR_KSTACK1); |
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack + PAGE_SIZE, KA2PA(THREAD->kstack) + FRAME_SIZE, true, DTR_KSTACK2); |
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack, |
KA2PA(THREAD->kstack), true, DTR_KSTACK1); |
dtlb_kernel_mapping_insert((uintptr_t) THREAD->kstack + |
PAGE_SIZE, KA2PA(THREAD->kstack) + FRAME_SIZE, true, |
DTR_KSTACK2); |
} |
/* |
/branches/dd/kernel/arch/ia64/src/ia64.c |
---|
51,64 → 51,99 |
#include <syscall/syscall.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <arch/drivers/ega.h> |
#include <arch/bootinfo.h> |
#include <genarch/kbd/i8042.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <genarch/drivers/ega/ega.h> |
#include <genarch/kbrd/kbrd.h> |
#include <genarch/srln/srln.h> |
#include <genarch/drivers/i8042/i8042.h> |
#include <genarch/drivers/ns16550/ns16550.h> |
#include <arch/drivers/kbd.h> |
#include <smp/smp.h> |
#include <smp/ipi.h> |
#include <arch/atomic.h> |
#include <panic.h> |
#include <print.h> |
#include <sysinfo/sysinfo.h> |
#include <string.h> |
/* NS16550 as a COM 1 */ |
#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE) |
bootinfo_t *bootinfo; |
static uint64_t iosapic_base = 0xfec00000; |
/** Performs ia64-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
{ |
/* Setup usermode init tasks. */ |
//#ifdef I460GX |
unsigned int i; |
init.cnt = bootinfo->taskmap.count; |
for (i = 0; i < init.cnt; i++) { |
init.tasks[i].addr = ((unsigned long) bootinfo->taskmap.tasks[i].addr) | VRN_MASK; |
init.tasks[i].addr = |
((unsigned long) bootinfo->taskmap.tasks[i].addr) | |
VRN_MASK; |
init.tasks[i].size = bootinfo->taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo->taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
} |
/* |
#else |
init.cnt = 8; |
init.tasks[0].addr = INIT0_ADDRESS; |
init.tasks[0].size = INIT0_SIZE; |
init.tasks[1].addr = INIT0_ADDRESS + 0x400000; |
init.tasks[1].size = INIT0_SIZE; |
init.tasks[2].addr = INIT0_ADDRESS + 0x800000; |
init.tasks[2].size = INIT0_SIZE; |
init.tasks[3].addr = INIT0_ADDRESS + 0xc00000; |
init.tasks[3].size = INIT0_SIZE; |
init.tasks[4].addr = INIT0_ADDRESS + 0x1000000; |
init.tasks[4].size = INIT0_SIZE; |
init.tasks[5].addr = INIT0_ADDRESS + 0x1400000; |
init.tasks[5].size = INIT0_SIZE; |
init.tasks[6].addr = INIT0_ADDRESS + 0x1800000; |
init.tasks[6].size = INIT0_SIZE; |
init.tasks[7].addr = INIT0_ADDRESS + 0x1c00000; |
init.tasks[7].size = INIT0_SIZE; |
#endif*/ |
} |
void arch_pre_mm_init(void) |
{ |
/* Set Interruption Vector Address (i.e. location of interruption vector table). */ |
/* |
* Set Interruption Vector Address (i.e. location of interruption vector |
* table). |
*/ |
iva_write((uintptr_t) &ivt); |
srlz_d(); |
} |
static void iosapic_init(void) |
{ |
uint64_t IOSAPIC = PA2KA((unative_t)(iosapic_base)) | FW_OFFSET; |
int i; |
int myid, myeid; |
myid = ia64_get_cpu_id(); |
myeid = ia64_get_cpu_eid(); |
for (i = 0; i < 16; i++) { |
if (i == 2) |
continue; /* Disable Cascade interrupt */ |
((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i; |
srlz_d(); |
((uint32_t *)(IOSAPIC + 0x10))[0] = LEGACY_INTERRUPT_BASE + i; |
srlz_d(); |
((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i + 1; |
srlz_d(); |
((uint32_t *)(IOSAPIC + 0x10))[0] = myid << (56 - 32) | |
myeid << (48 - 32); |
srlz_d(); |
} |
} |
void arch_post_mm_init(void) |
{ |
irq_init(INR_COUNT, INR_COUNT); |
if (config.cpu_active == 1) { |
iosapic_init(); |
irq_init(INR_COUNT, INR_COUNT); |
#ifdef SKI |
ski_init_console(); |
#else |
ega_init(); |
#endif |
it_init(); |
ski_init_console(); |
#else |
ega_init(EGA_BASE, EGA_VIDEORAM); |
#endif |
} |
it_init(); |
} |
void arch_post_cpu_init(void) |
119,51 → 154,54 |
{ |
} |
#ifdef I460GX |
#define POLL_INTERVAL 50000 /* 50 ms */ |
/** Kernel thread for polling keyboard. */ |
static void i8042_kkbdpoll(void *arg) |
{ |
while (1) { |
i8042_poll(); |
thread_usleep(POLL_INTERVAL); |
} |
} |
#endif |
void arch_post_smp_init(void) |
{ |
if (config.cpu_active == 1) { |
/* |
* Create thread that polls keyboard. |
*/ |
/* |
* Create thread that polls keyboard. |
*/ |
#ifdef SKI |
thread_t *t; |
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
panic("cannot create kkbdpoll\n"); |
thread_ready(t); |
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
panic("Cannot create kkbdpoll."); |
thread_ready(t); |
#endif |
#ifdef I460GX |
devno_t kbd = device_assign_devno(); |
devno_t mouse = device_assign_devno(); |
/* keyboard controller */ |
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE); |
devno_t devno = device_assign_devno(); |
inr_t inr; |
thread_t *t; |
t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
panic("cannot create kkbdpoll\n"); |
thread_ready(t); |
#ifdef CONFIG_NS16550 |
inr = NS16550_IRQ; |
srln_init(stdin); |
(void) ns16550_init((ns16550_t *)NS16550_BASE, devno, inr, NULL, NULL, |
&srlnin); |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, |
(uintptr_t) NS16550_BASE); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) NS16550_BASE); |
#else |
inr = IRQ_KBD; |
kbrd_init(stdin); |
(void) i8042_init((i8042_t *)I8042_BASE, devno, inr, &kbrdin); |
trap_virtual_enable_irqs(1 << inr); |
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY); |
sysinfo_set_item_val("kbd.address.physical", NULL, |
(uintptr_t) I8042_BASE); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) I8042_BASE); |
#endif |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
#endif |
} |
sysinfo_set_item_val("ia64_iospace", NULL, true); |
sysinfo_set_item_val("ia64_iospace.address", NULL, true); |
sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, IO_OFFSET); |
} |
/** Enter userspace and never return. */ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
172,26 → 210,25 |
psr.value = psr_read(); |
psr.cpl = PL_USER; |
psr.i = true; /* start with interrupts enabled */ |
psr.i = true; /* start with interrupts enabled */ |
psr.ic = true; |
psr.ri = 0; /* start with instruction #0 */ |
psr.bn = 1; /* start in bank 0 */ |
psr.ri = 0; /* start with instruction #0 */ |
psr.bn = 1; /* start in bank 0 */ |
asm volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value)); |
rsc.loadrs = 0; |
rsc.be = false; |
rsc.pl = PL_USER; |
rsc.mode = 3; /* eager mode */ |
rsc.mode = 3; /* eager mode */ |
switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry, |
((uintptr_t) kernel_uarg->uspace_stack)+PAGE_SIZE-ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT), |
((uintptr_t) kernel_uarg->uspace_stack)+PAGE_SIZE, |
(uintptr_t) kernel_uarg->uspace_uarg, |
psr.value, rsc.value); |
((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE - |
ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT), |
((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE, |
(uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value); |
while (1) { |
while (1) |
; |
} |
} |
/** Set thread-local-storage pointer. |
210,8 → 247,9 |
{ |
#ifdef SKI |
ski_kbd_grab(); |
#endif |
#endif |
} |
/** Return console to userspace |
* |
*/ |
224,9 → 262,27 |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
pio_write_8((ioport8_t *)0x64, 0xfe); |
while (1) |
; |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
fptr->fnc = (unative_t) addr; |
fptr->gp = ((unative_t *) caller)[1]; |
return (void *) fptr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/src/ski/ski.c |
---|
44,8 → 44,9 |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/drivers/kbd.h> |
#define SKI_KBD_INR 0 |
#define SKI_KBD_INR 0 |
static irq_t ski_kbd_irq; |
static devno_t ski_kbd_devno; |
55,9 → 56,6 |
static bool kbd_disabled; |
static void ski_putchar(chardev_t *d, const char ch); |
static int32_t ski_getchar(void); |
/** Display character on debug console |
* |
* Use SSC (Simulator System Call) to |
66,19 → 64,21 |
* @param d Character device. |
* @param ch Character to be printed. |
*/ |
void ski_putchar(chardev_t *d, const char ch) |
static void ski_putchar(chardev_t *d, const char ch, bool silent) |
{ |
asm volatile ( |
"mov r15 = %0\n" |
"mov r32 = %1\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: "i" (SKI_PUTCHAR), "r" (ch) |
: "r15", "in0", "r8" |
); |
if (ch == '\n') |
ski_putchar(d, '\r'); |
if (!silent) { |
asm volatile ( |
"mov r15 = %0\n" |
"mov r32 = %1\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: "i" (SKI_PUTCHAR), "r" (ch) |
: "r15", "in0", "r8" |
); |
if (ch == '\n') |
ski_putchar(d, '\r', false); |
} |
} |
/** Ask debug console if a key was pressed. |
90,7 → 90,7 |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
*/ |
int32_t ski_getchar(void) |
static int32_t ski_getchar(void) |
{ |
uint64_t ch; |
114,10 → 114,10 |
static char ski_getchar_blocking(chardev_t *d) |
{ |
int ch; |
while(!(ch = ski_getchar())) |
; |
if(ch == '\r') |
while(!(ch = ski_getchar())); |
if (ch == '\r') |
ch = '\n'; |
return (char) ch; |
} |
128,23 → 128,24 |
char ch; |
static char last; |
ipl_t ipl; |
ipl = interrupts_disable(); |
if (kbd_disabled) { |
interrupts_restore(ipl); |
return; |
} |
spinlock_lock(&ski_kbd_irq.lock); |
ch = ski_getchar(); |
if(ch == '\r') |
ch = '\n'; |
if (ch) { |
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) { |
if (ski_kbd_irq.notif_cfg.notify && |
ski_kbd_irq.notif_cfg.answerbox) { |
chardev_push_character(&ski_uconsole, ch); |
ipc_irq_send_notif(&ski_kbd_irq); |
/* XXX: send notification to userspace */ |
} else { |
chardev_push_character(&ski_console, ch); |
} |
155,9 → 156,10 |
} |
if (last) { |
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) { |
if (ski_kbd_irq.notif_cfg.notify && |
ski_kbd_irq.notif_cfg.answerbox) { |
chardev_push_character(&ski_uconsole, 0); |
ipc_irq_send_notif(&ski_kbd_irq); |
/* XXX: send notification to userspace */ |
} |
last = 0; |
} |
175,7 → 177,7 |
/* Called from getc(). */ |
static void ski_kbd_disable(chardev_t *d) |
{ |
kbd_disabled = true; |
kbd_disabled = true; |
} |
/** Decline to service hardware IRQ. |
184,7 → 186,7 |
* |
* @return Always IRQ_DECLINE. |
*/ |
static irq_ownership_t ski_kbd_claim(void) |
static irq_ownership_t ski_kbd_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
227,6 → 229,9 |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, SKI_KBD_INR); |
sysinfo_set_item_val("kbd.devno", NULL, ski_kbd_devno); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI); |
sysinfo_set_item_val("fb", NULL, false); |
} |
void ski_kbd_grab(void) |
255,7 → 260,9 |
void kkbdpoll(void *arg) |
{ |
while (1) { |
poll_keyboard(); |
if (!silent) { |
poll_keyboard(); |
} |
thread_usleep(POLL_INTERVAL); |
} |
} |
/branches/dd/kernel/arch/ia64/src/cpu/cpu.c |
---|
70,8 → 70,8 |
} |
printf("cpu%d: %s (%s), archrev=%d, model=%d, revision=%d\n", CPU->id, |
family_str, vendor, CPU->arch.cpuid3.archrev, CPU->arch.cpuid3.model, |
CPU->arch.cpuid3.revision); |
family_str, vendor, CPU->arch.cpuid3.archrev, |
CPU->arch.cpuid3.model, CPU->arch.cpuid3.revision); |
} |
/** @} |
/branches/dd/kernel/arch/ia64/src/mm/tlb.c |
---|
92,7 → 92,7 |
/** Invalidate entries belonging to an address space. |
* |
* @param asid Address space identifier. |
* @param asid Address space identifier. |
*/ |
void tlb_invalidate_asid(asid_t asid) |
{ |
131,59 → 131,45 |
uint64_t ps; |
switch (b) { |
case 0: /*cnt 1-3*/ |
case 0: /* cnt 1 - 3 */ |
ps = PAGE_WIDTH; |
break; |
case 1: /*cnt 4-15*/ |
/*cnt=((cnt-1)/4)+1;*/ |
ps = PAGE_WIDTH+2; |
va &= ~((1<<ps)-1); |
case 1: /* cnt 4 - 15 */ |
ps = PAGE_WIDTH + 2; |
va &= ~((1 << ps) - 1); |
break; |
case 2: /*cnt 16-63*/ |
/*cnt=((cnt-1)/16)+1;*/ |
ps = PAGE_WIDTH+4; |
va &= ~((1<<ps)-1); |
case 2: /* cnt 16 - 63 */ |
ps = PAGE_WIDTH + 4; |
va &= ~((1 << ps) - 1); |
break; |
case 3: /*cnt 64-255*/ |
/*cnt=((cnt-1)/64)+1;*/ |
ps = PAGE_WIDTH+6; |
va &= ~((1<<ps)-1); |
case 3: /* cnt 64 - 255 */ |
ps = PAGE_WIDTH + 6; |
va &= ~((1 << ps) - 1); |
break; |
case 4: /*cnt 256-1023*/ |
/*cnt=((cnt-1)/256)+1;*/ |
ps = PAGE_WIDTH+8; |
va &= ~((1<<ps)-1); |
case 4: /* cnt 256 - 1023 */ |
ps = PAGE_WIDTH + 8; |
va &= ~((1 << ps) - 1); |
break; |
case 5: /*cnt 1024-4095*/ |
/*cnt=((cnt-1)/1024)+1;*/ |
ps = PAGE_WIDTH+10; |
va &= ~((1<<ps)-1); |
case 5: /* cnt 1024 - 4095 */ |
ps = PAGE_WIDTH + 10; |
va &= ~((1 << ps) - 1); |
break; |
case 6: /*cnt 4096-16383*/ |
/*cnt=((cnt-1)/4096)+1;*/ |
ps = PAGE_WIDTH+12; |
va &= ~((1<<ps)-1); |
case 6: /* cnt 4096 - 16383 */ |
ps = PAGE_WIDTH + 12; |
va &= ~((1 << ps) - 1); |
break; |
case 7: /*cnt 16384-65535*/ |
case 8: /*cnt 65536-(256K-1)*/ |
/*cnt=((cnt-1)/16384)+1;*/ |
ps = PAGE_WIDTH+14; |
va &= ~((1<<ps)-1); |
case 7: /* cnt 16384 - 65535 */ |
case 8: /* cnt 65536 - (256K - 1) */ |
ps = PAGE_WIDTH + 14; |
va &= ~((1 << ps) - 1); |
break; |
default: |
/*cnt=((cnt-1)/(16384*16))+1;*/ |
ps=PAGE_WIDTH+18; |
va&=~((1<<ps)-1); |
ps = PAGE_WIDTH + 18; |
va &= ~((1 << ps) - 1); |
break; |
} |
/*cnt+=(page!=va);*/ |
for(; va<(page+cnt*(PAGE_SIZE)); va += (1<<ps)) { |
asm volatile ( |
"ptc.l %0,%1;;" |
: |
: "r" (va), "r" (ps<<2) |
); |
} |
for(; va < (page + cnt * PAGE_SIZE); va += (1 << ps)) |
asm volatile ("ptc.l %0, %1;;" :: "r" (va), "r" (ps << 2)); |
srlz_d(); |
srlz_i(); |
196,9 → 182,10 |
/** Insert data into data translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
*/ |
void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry) |
{ |
207,9 → 194,10 |
/** Insert data into instruction translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
*/ |
void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry) |
{ |
218,10 → 206,12 |
/** Insert data into instruction or data translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param dtc If true, insert into data translation cache, use instruction translation cache otherwise. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
* @param dtc If true, insert into data translation cache, use |
* instruction translation cache otherwise. |
*/ |
void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc) |
{ |
244,19 → 234,20 |
} |
asm volatile ( |
"mov r8=psr;;\n" |
"mov r8 = psr;;\n" |
"rsm %0;;\n" /* PSR_IC_MASK */ |
"srlz.d;;\n" |
"srlz.i;;\n" |
"mov cr.ifa=%1\n" /* va */ |
"mov cr.itir=%2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7 = %4,r0;;\n" /* decide between itc and dtc */ |
"mov cr.ifa = %1\n" /* va */ |
"mov cr.itir = %2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7 = %4,r0;;\n" /* decide between itc and dtc */ |
"(p6) itc.i %3;;\n" |
"(p7) itc.d %3;;\n" |
"mov psr.l=r8;;\n" |
"mov psr.l = r8;;\n" |
"srlz.d;;\n" |
: |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc) |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), |
"r" (entry.word[0]), "r" (dtc) |
: "p6", "p7", "r8" |
); |
269,12 → 260,14 |
/** Insert data into instruction translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param tr Translation register. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
* @param tr Translation register. |
*/ |
void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr) |
void |
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr) |
{ |
tr_mapping_insert(va, asid, entry, false, tr); |
} |
281,12 → 274,14 |
/** Insert data into data translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param tr Translation register. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
* @param tr Translation register. |
*/ |
void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr) |
void |
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr) |
{ |
tr_mapping_insert(va, asid, entry, true, tr); |
} |
293,13 → 288,17 |
/** Insert data into instruction or data translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param dtr If true, insert into data translation register, use instruction translation register otherwise. |
* @param tr Translation register. |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion |
* format. |
* @param dtr If true, insert into data translation register, use |
* instruction translation register otherwise. |
* @param tr Translation register. |
*/ |
void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr) |
void |
tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, |
index_t tr) |
{ |
region_register rr; |
bool restore_rr = false; |
320,19 → 319,20 |
} |
asm volatile ( |
"mov r8=psr;;\n" |
"mov r8 = psr;;\n" |
"rsm %0;;\n" /* PSR_IC_MASK */ |
"srlz.d;;\n" |
"srlz.i;;\n" |
"mov cr.ifa=%1\n" /* va */ |
"mov cr.itir=%2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7=%5,r0;;\n" /* decide between itr and dtr */ |
"(p6) itr.i itr[%4]=%3;;\n" |
"(p7) itr.d dtr[%4]=%3;;\n" |
"mov psr.l=r8;;\n" |
"mov cr.ifa = %1\n" /* va */ |
"mov cr.itir = %2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7 = %5,r0;;\n" /* decide between itr and dtr */ |
"(p6) itr.i itr[%4] = %3;;\n" |
"(p7) itr.d dtr[%4] = %3;;\n" |
"mov psr.l = r8;;\n" |
"srlz.d;;\n" |
: |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr) |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), |
"r" (entry.word[0]), "r" (tr), "r" (dtr) |
: "p6", "p7", "r8" |
); |
345,12 → 345,15 |
/** Insert data into DTLB. |
* |
* @param page Virtual page address including VRN bits. |
* @param frame Physical frame address. |
* @param dtr If true, insert into data translation register, use data translation cache otherwise. |
* @param tr Translation register if dtr is true, ignored otherwise. |
* @param page Virtual page address including VRN bits. |
* @param frame Physical frame address. |
* @param dtr If true, insert into data translation register, use data |
* translation cache otherwise. |
* @param tr Translation register if dtr is true, ignored otherwise. |
*/ |
void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr) |
void |
dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, |
index_t tr) |
{ |
tlb_entry_t entry; |
376,18 → 379,18 |
* |
* Purge DTR entries used by the kernel. |
* |
* @param page Virtual page address including VRN bits. |
* @param width Width of the purge in bits. |
* @param page Virtual page address including VRN bits. |
* @param width Width of the purge in bits. |
*/ |
void dtr_purge(uintptr_t page, count_t width) |
{ |
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width<<2)); |
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width << 2)); |
} |
/** Copy content of PTE into data translation cache. |
* |
* @param t PTE. |
* @param t PTE. |
*/ |
void dtc_pte_copy(pte_t *t) |
{ |
413,7 → 416,7 |
/** Copy content of PTE into instruction translation cache. |
* |
* @param t PTE. |
* @param t PTE. |
*/ |
void itc_pte_copy(pte_t *t) |
{ |
440,8 → 443,8 |
/** Instruction TLB fault handler for faults with VHPT turned off. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate) |
{ |
469,16 → 472,77 |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip); |
fault_if_from_uspace(istate,"Page fault at %p.",va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
} |
} |
static int is_io_page_accessible(int page) |
{ |
if (TASK->arch.iomap) |
return bitmap_get(TASK->arch.iomap, page); |
else |
return 0; |
} |
#define IO_FRAME_BASE 0xFFFFC000000 |
/** |
* There is special handling of memory mapped legacy io, because of 4KB sized |
* access for userspace. |
* |
* @param va Virtual address of page fault. |
* @param istate Structure with saved interruption state. |
* |
* @return One on success, zero on failure. |
*/ |
static int try_memmap_io_insertion(uintptr_t va, istate_t *istate) |
{ |
if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) { |
if (TASK) { |
uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >> |
USPACE_IO_PAGE_WIDTH; |
if (is_io_page_accessible(io_page)) { |
uint64_t page, frame; |
page = IO_OFFSET + |
(1 << USPACE_IO_PAGE_WIDTH) * io_page; |
frame = IO_FRAME_BASE + |
(1 << USPACE_IO_PAGE_WIDTH) * io_page; |
tlb_entry_t entry; |
entry.word[0] = 0; |
entry.word[1] = 0; |
entry.p = true; /* present */ |
entry.ma = MA_UNCACHEABLE; |
entry.a = true; /* already accessed */ |
entry.d = true; /* already dirty */ |
entry.pl = PL_USER; |
entry.ar = AR_READ | AR_WRITE; |
entry.ppn = frame >> PPN_SHIFT; |
entry.ps = USPACE_IO_PAGE_WIDTH; |
dtc_mapping_insert(page, TASK->as->asid, entry); |
return 1; |
} else { |
fault_if_from_uspace(istate, |
"IO access fault at %p.", va); |
} |
} |
} |
return 0; |
} |
/** Data TLB fault handler for faults with VHPT turned off. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void alternate_data_tlb_fault(uint64_t vector, istate_t *istate) |
{ |
511,13 → 575,17 |
dtc_pte_copy(t); |
page_table_unlock(AS, true); |
} else { |
page_table_unlock(AS, true); |
if (try_memmap_io_insertion(va, istate)) |
return; |
/* |
* Forward the page fault to the address space page fault handler. |
* Forward the page fault to the address space page fault |
* handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip); |
fault_if_from_uspace(istate,"Page fault at %p.",va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
} |
} |
526,18 → 594,18 |
* |
* This fault should not occur. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void data_nested_tlb_fault(uint64_t vector, istate_t *istate) |
{ |
panic("%s\n", __func__); |
panic("%s.", __func__); |
} |
/** Data Dirty bit fault handler. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void data_dirty_bit_fault(uint64_t vector, istate_t *istate) |
{ |
562,10 → 630,9 |
dtc_pte_copy(t); |
} else { |
if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip); |
t->d = true; |
dtc_pte_copy(t); |
fault_if_from_uspace(istate,"Page fault at %p.",va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
} |
page_table_unlock(AS, true); |
573,8 → 640,8 |
/** Instruction access bit fault handler. |
* |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
* @param vector Interruption vector. |
* @param istate Structure with saved interruption state. |
*/ |
void instruction_access_bit_fault(uint64_t vector, istate_t *istate) |
{ |
599,10 → 666,9 |
itc_pte_copy(t); |
} else { |
if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip); |
t->a = true; |
itc_pte_copy(t); |
fault_if_from_uspace(istate, "Page fault at %p.", va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
} |
page_table_unlock(AS, true); |
636,10 → 702,9 |
dtc_pte_copy(t); |
} else { |
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip); |
t->a = true; |
itc_pte_copy(t); |
fault_if_from_uspace(istate, "Page fault at %p.", va); |
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid, |
istate->cr_iip); |
} |
} |
page_table_unlock(AS, true); |
678,11 → 743,19 |
} else { |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate,"Page fault at %p",va); |
panic("%s: va=%p, rid=%d\n", __func__, va, rid); |
fault_if_from_uspace(istate, "Page fault at %p.", va); |
panic("%s: va=%p, rid=%d.", __func__, va, rid); |
} |
} |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/src/mm/vhpt.c |
---|
41,7 → 41,8 |
uintptr_t vhpt_set_up(void) |
{ |
vhpt_base = frame_alloc(VHPT_WIDTH - FRAME_WIDTH, FRAME_KA | FRAME_ATOMIC); |
vhpt_base = frame_alloc(VHPT_WIDTH - FRAME_WIDTH, |
FRAME_KA | FRAME_ATOMIC); |
if (!vhpt_base) |
panic("Kernel configured with VHPT but no memory for table."); |
vhpt_invalidate_all(); |
81,7 → 82,7 |
void vhpt_invalidate_all() |
{ |
memsetb((uintptr_t) vhpt_base, 1 << VHPT_WIDTH, 0); |
memsetb(vhpt_base, 1 << VHPT_WIDTH, 0); |
} |
void vhpt_invalidate_asid(asid_t asid) |
/branches/dd/kernel/arch/ia64/src/mm/as.c |
---|
68,7 → 68,7 |
continue; |
rr.word = rr_read(i); |
rr.map.ve = false; /* disable VHPT walker */ |
rr.map.ve = false; /* disable VHPT walker */ |
rr.map.rid = ASID2RID(as->asid, i); |
rr.map.ps = PAGE_WIDTH; |
rr_write(i, rr.word); |
/branches/dd/kernel/arch/ia64/src/mm/frame.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64mm |
/** @addtogroup ia64mm |
* @{ |
*/ |
/** @file |
36,26 → 36,55 |
#include <mm/frame.h> |
#include <config.h> |
#include <panic.h> |
#include <arch/bootinfo.h> |
#include <align.h> |
#include <macros.h> |
/* |
* This is Ski-specific and certainly not sufficient |
* for real ia64 systems that provide memory map. |
*/ |
#define MEMORY_SIZE (64 * 1024 * 1024) |
#define MEMORY_BASE (64 * 1024 * 1024) |
#define KERNEL_RESERVED_AREA_BASE (0x4400000) |
#define KERNEL_RESERVED_AREA_SIZE (16 * 1024 * 1024) |
#define ROM_BASE 0xa0000 //For ski |
#define ROM_SIZE (384 * 1024) //For ski |
void poke_char(int x,int y,char ch, char c); |
#define ROM_BASE 0xa0000 /* for simulators */ |
#define ROM_SIZE (384 * 1024) /* for simulators */ |
#define MIN_ZONE_SIZE (64 * 1024) |
#define MINCONF 1 |
uintptr_t last_frame = 0; |
void frame_arch_init(void) |
{ |
zone_create(MEMORY_BASE >> FRAME_WIDTH, SIZE2FRAMES(MEMORY_SIZE), (MEMORY_SIZE) >> FRAME_WIDTH, 0); |
/* |
* Blacklist ROM regions. |
*/ |
frame_mark_unavailable(ADDR2PFN(ROM_BASE), SIZE2FRAMES(ROM_SIZE)); |
if (config.cpu_active == 1) { |
unsigned int i; |
for (i = 0; i < bootinfo->memmap_items; i++) { |
if (bootinfo->memmap[i].type == EFI_MEMMAP_FREE_MEM) { |
uint64_t base = bootinfo->memmap[i].base; |
uint64_t size = bootinfo->memmap[i].size; |
uint64_t abase = ALIGN_UP(base, FRAME_SIZE); |
if (size > FRAME_SIZE) |
size -= abase - base; |
if (size > MIN_ZONE_SIZE) { |
zone_create(abase >> FRAME_WIDTH, |
size >> FRAME_WIDTH, |
max(MINCONF, abase >> FRAME_WIDTH), |
0); |
} |
if (abase + size > last_frame) |
last_frame = abase + size; |
} |
} |
/* |
* Blacklist ROM regions. |
*/ |
frame_mark_unavailable(ADDR2PFN(ROM_BASE), |
SIZE2FRAMES(ROM_SIZE)); |
frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE), |
SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE)); |
} |
} |
/** @} |
/branches/dd/kernel/arch/ia64/src/mm/page.c |
---|
27,7 → 27,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64mm |
/** @addtogroup ia64mm |
* @{ |
*/ |
/** @file |
47,6 → 47,7 |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <memstr.h> |
#include <align.h> |
static void set_environment(void); |
62,9 → 63,9 |
void set_environment(void) |
{ |
region_register rr; |
pta_register pta; |
pta_register pta; |
int i; |
#ifdef CONFIG_VHPT |
#ifdef CONFIG_VHPT |
uintptr_t vhpt_base; |
#endif |
122,10 → 123,10 |
* |
* Interrupts must be disabled. |
* |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* |
* @return VHPT entry address. |
* @return VHPT entry address. |
*/ |
vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid) |
{ |
166,10 → 167,11 |
* |
* Interrupts must be disabled. |
* |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* |
* @return True if page and asid match the page and asid of t, false otherwise. |
* @return True if page and asid match the page and asid of t, |
* false otherwise. |
*/ |
bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v) |
{ |
210,12 → 212,15 |
/** Set up one VHPT entry. |
* |
* @param v VHPT entry to be set up. |
* @param page Virtual address of the page mapped by the entry. |
* @param asid Address space identifier of the address space to which page belongs. |
* @param frame Physical address of the frame to wich page is mapped. |
* @param flags Different flags for the mapping. |
* @param page Virtual address of the page mapped by the entry. |
* @param asid Address space identifier of the address space to which |
* page belongs. |
* @param frame Physical address of the frame to wich page is mapped. |
* @param flags Different flags for the mapping. |
*/ |
void vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame, int flags) |
void |
vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame, |
int flags) |
{ |
region_register rr_save, rr; |
index_t vrn; |
249,7 → 254,8 |
v->word[3] = 0; |
v->present.p = true; |
v->present.ma = (flags & PAGE_CACHEABLE) ? MA_WRITEBACK : MA_UNCACHEABLE; |
v->present.ma = (flags & PAGE_CACHEABLE) ? |
MA_WRITEBACK : MA_UNCACHEABLE; |
v->present.a = false; /* not accessed */ |
v->present.d = false; /* not dirty */ |
v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL; |
262,5 → 268,11 |
v->present.tag.tag_word = tag; |
} |
uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused))) |
{ |
/* THIS is a dirty hack. */ |
return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET); |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/src/interrupt.c |
---|
53,6 → 53,7 |
#include <ipc/irq.h> |
#include <ipc/ipc.h> |
#include <synch/spinlock.h> |
#include <mm/tlb.h> |
#define VECTORS_64_BUNDLE 20 |
#define VECTORS_16_BUNDLE 48 |
185,21 → 186,21 |
break; |
} |
fault_if_from_uspace(istate, "General Exception (%s)", desc); |
fault_if_from_uspace(istate, "General Exception (%s).", desc); |
dump_interrupted_context(istate); |
panic("General Exception (%s)\n", desc); |
panic("General Exception (%s).", desc); |
} |
void disabled_fp_register(uint64_t vector, istate_t *istate) |
{ |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#else |
fault_if_from_uspace(istate, "Interruption: %#hx (%s)", |
fault_if_from_uspace(istate, "Interruption: %#hx (%s).", |
(uint16_t) vector, vector_to_string(vector)); |
dump_interrupted_context(istate); |
panic("Interruption: %#hx (%s)\n", (uint16_t) vector, |
panic("Interruption: %#hx (%s).", (uint16_t) vector, |
vector_to_string(vector)); |
#endif |
} |
227,40 → 228,82 |
void universal_handler(uint64_t vector, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "Interruption: %#hx (%s)\n", |
fault_if_from_uspace(istate, "Interruption: %#hx (%s).", |
(uint16_t) vector, vector_to_string(vector)); |
dump_interrupted_context(istate); |
panic("Interruption: %#hx (%s)\n", (uint16_t) vector, |
panic("Interruption: %#hx (%s).", (uint16_t) vector, |
vector_to_string(vector)); |
} |
static void end_of_local_irq(void) |
{ |
asm volatile ("mov cr.eoi=r0;;"); |
} |
void external_interrupt(uint64_t vector, istate_t *istate) |
{ |
cr_ivr_t ivr; |
irq_t *irq; |
cr_ivr_t ivr; |
ivr.value = ivr_read(); |
srlz_d(); |
irq = irq_dispatch_and_lock(ivr.vector); |
if (irq) { |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
switch (ivr.vector) { |
case INTERRUPT_SPURIOUS: |
switch (ivr.vector) { |
case INTERRUPT_SPURIOUS: |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt\n", CPU->id); |
printf("cpu%d: spurious interrupt\n", CPU->id); |
#endif |
break; |
break; |
default: |
panic("\nUnhandled External Interrupt Vector %d\n", |
#ifdef CONFIG_SMP |
case VECTOR_TLB_SHOOTDOWN_IPI: |
tlb_shootdown_ipi_recv(); |
end_of_local_irq(); |
break; |
#endif |
case INTERRUPT_TIMER: |
irq = irq_dispatch_and_lock(ivr.vector); |
if (irq) { |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
panic("Unhandled Internal Timer Interrupt (%d).", |
ivr.vector); |
break; |
} |
break; |
default: |
irq = irq_dispatch_and_lock(ivr.vector); |
if (irq) { |
/* |
* The IRQ handler was found. |
*/ |
if (irq->preack) { |
/* Send EOI before processing the interrupt */ |
end_of_local_irq(); |
} |
irq->handler(irq); |
if (!irq->preack) |
end_of_local_irq(); |
spinlock_unlock(&irq->lock); |
} else { |
/* |
* Unhandled interrupt. |
*/ |
end_of_local_irq(); |
#ifdef CONFIG_DEBUG |
printf("\nUnhandled External Interrupt Vector %d\n", |
ivr.vector); |
#endif |
} |
break; |
} |
} |
void trap_virtual_enable_irqs(uint16_t irqmask) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia64/src/drivers/ega.c |
---|
File deleted |
/branches/dd/kernel/arch/ia64/src/drivers/it.c |
---|
44,25 → 44,44 |
#include <ddi/device.h> |
#include <arch.h> |
#define IT_SERVICE_CLOCKS 64 |
#define IT_SERVICE_CLOCKS 64 |
#define FREQ_NUMERATOR_SHIFT 32 |
#define FREQ_NUMERATOR_MASK 0xffffffff00000000ULL |
#define FREQ_DENOMINATOR_SHIFT 0 |
#define FREQ_DENOMINATOR_MASK 0xffffffffULL |
uint64_t it_delta; |
static irq_t it_irq; |
static irq_ownership_t it_claim(void); |
static void it_interrupt(irq_t *irq, void *arg, ...); |
static irq_ownership_t it_claim(irq_t *); |
static void it_interrupt(irq_t *); |
/** Initialize Interval Timer. */ |
void it_init(void) |
{ |
cr_itv_t itv; |
irq_initialize(&it_irq); |
it_irq.inr = INTERRUPT_TIMER; |
it_irq.devno = device_assign_devno(); |
it_irq.claim = it_claim; |
it_irq.handler = it_interrupt; |
irq_register(&it_irq); |
if (config.cpu_active == 1) { |
irq_initialize(&it_irq); |
it_irq.inr = INTERRUPT_TIMER; |
it_irq.devno = device_assign_devno(); |
it_irq.claim = it_claim; |
it_irq.handler = it_interrupt; |
irq_register(&it_irq); |
uint64_t base_freq; |
base_freq = ((bootinfo->freq_scale) & FREQ_NUMERATOR_MASK) >> |
FREQ_NUMERATOR_SHIFT; |
base_freq *= bootinfo->sys_freq; |
base_freq /= ((bootinfo->freq_scale) & FREQ_DENOMINATOR_MASK) >> |
FREQ_DENOMINATOR_SHIFT; |
it_delta = base_freq / HZ; |
} |
/* initialize Interval Timer external interrupt vector */ |
itv.value = itv_read(); |
itv.vector = INTERRUPT_TIMER; |
85,13 → 104,13 |
* |
* @return Always IRQ_ACCEPT. |
*/ |
irq_ownership_t it_claim(void) |
irq_ownership_t it_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
/** Process Interval Timer interrupt. */ |
void it_interrupt(irq_t *irq, void *arg, ...) |
void it_interrupt(irq_t *irq) |
{ |
int64_t c; |
int64_t m; |
/branches/dd/kernel/arch/ia64/src/start.S |
---|
32,19 → 32,15 |
#include <mm/asid.h> |
#define RR_MASK (0xFFFFFFFF00000002) |
#define RID_SHIFT 8 |
#define PS_SHIFT 2 |
#define RID_SHIFT 8 |
#define PS_SHIFT 2 |
#define KERNEL_TRANSLATION_I 0x0010000000000661 |
#define KERNEL_TRANSLATION_D 0x0010000000000661 |
#define KERNEL_TRANSLATION_VIO 0x0010000000000671 |
#define KERNEL_TRANSLATION_IO 0x00100FFFFC000671 |
#define VIO_OFFSET 0x0002000000000000 |
#define KERNEL_TRANSLATION_I 0x0010000000000661 |
#define KERNEL_TRANSLATION_D 0x0010000000000661 |
#define KERNEL_TRANSLATION_VIO 0x0010000000000671 |
#define KERNEL_TRANSLATION_IO 0x00100FFFFC000671 |
#define KERNEL_TRANSLATION_FW 0x00100000F0000671 |
#define IO_OFFSET 0x0001000000000000 |
.section K_TEXT_START, "ax" |
.global kernel_image_start |
53,6 → 49,19 |
kernel_image_start: |
.auto |
#ifdef CONFIG_SMP |
# Identify self(CPU) in OS structures by ID / EID |
mov r9 = cr64 |
mov r10 = 1 |
movl r12 = 0xffffffff |
movl r8 = cpu_by_id_eid_list |
and r8 = r8, r12 |
shr r9 = r9, 16 |
add r8 = r8, r9 |
st1 [r8] = r10 |
#endif |
mov psr.l = r0 |
srlz.i |
srlz.d |
59,39 → 68,29 |
# Fill TR.i and TR.d using Region Register #VRN_KERNEL |
movl r8 = (VRN_KERNEL << VRN_SHIFT) |
mov r9 = rr[r8] |
movl r10 = (RR_MASK) |
and r9 = r10, r9 |
movl r10 = ((RID_KERNEL << RID_SHIFT) | (KERNEL_PAGE_WIDTH << PS_SHIFT)) |
or r9 = r10, r9 |
mov rr[r8] = r9 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) |
mov cr.ifa = r8 |
mov r11 = cr.itir ;; |
movl r10 = (KERNEL_PAGE_WIDTH << PS_SHIFT);; |
or r10 =r10 , r11 ;; |
mov cr.itir = r10;; |
mov r11 = cr.itir |
movl r10 = (KERNEL_PAGE_WIDTH << PS_SHIFT) |
or r10 = r10, r11 |
mov cr.itir = r10 |
movl r10 = (KERNEL_TRANSLATION_I) |
itr.i itr[r0] = r10 |
movl r10 = (KERNEL_TRANSLATION_D) |
itr.d dtr[r0] = r10 |
movl r7 = 1 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) | VIO_OFFSET |
mov cr.ifa = r8 |
98,15 → 97,13 |
movl r10 = (KERNEL_TRANSLATION_VIO) |
itr.d dtr[r7] = r10 |
mov r11 = cr.itir |
movl r10 = ~0xfc |
and r10 = r10, r11 |
movl r11 = (IO_PAGE_WIDTH << PS_SHIFT) |
or r10 = r10, r11 |
mov cr.itir = r10 |
mov r11 = cr.itir ;; |
movl r10 = ~0xfc;; |
and r10 =r10 , r11 ;; |
movl r11 = (IO_PAGE_WIDTH << PS_SHIFT);; |
or r10 =r10 , r11 ;; |
mov cr.itir = r10;; |
movl r7 = 2 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) | IO_OFFSET |
mov cr.ifa = r8 |
113,12 → 110,26 |
movl r10 = (KERNEL_TRANSLATION_IO) |
itr.d dtr[r7] = r10 |
# Setup mapping for fimware arrea (also SAPIC) |
mov r11 = cr.itir |
movl r10 = ~0xfc |
and r10 = r10, r11 |
movl r11 = (FW_PAGE_WIDTH << PS_SHIFT) |
or r10 = r10, r11 |
mov cr.itir = r10 |
movl r7 = 3 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) | FW_OFFSET |
mov cr.ifa = r8 |
movl r10 = (KERNEL_TRANSLATION_FW) |
itr.d dtr[r7] = r10 |
# initialize PSR |
# Initialize PSR |
movl r10 = (PSR_DT_MASK | PSR_RT_MASK | PSR_IT_MASK | PSR_IC_MASK) /* Enable paging */ |
mov r9 = psr |
or r10 = r10, r9 |
mov cr.ipsr = r10 |
mov cr.ifs = r0 |
128,11 → 139,14 |
srlz.i |
.explicit |
/* |
* Return From Interupt is the only the way to fill upper half word of PSR. |
* Return From Interrupt is the only way to |
* fill the upper half word of PSR. |
*/ |
rfi;; |
rfi ;; |
.global paging_start |
paging_start: |
140,45 → 154,64 |
* Now we are paging. |
*/ |
# switch to register bank 1 |
# Switch to register bank 1 |
bsw.1 |
#ifdef CONFIG_SMP |
# Am I BSP or AP? |
movl r20 = bsp_started ;; |
ld8 r20 = [r20] ;; |
cmp.eq p3, p2 = r20, r0 ;; |
#else |
cmp.eq p3, p2 = r0, r0 ;; /* you are BSP */ |
#endif /* CONFIG_SMP */ |
# initialize register stack |
# Initialize register stack |
mov ar.rsc = r0 |
movl r8 = (VRN_KERNEL << VRN_SHIFT) ;; |
mov ar.bspstore = r8 |
loadrs |
# initialize memory stack to some sane value |
# Initialize memory stack to some sane value |
movl r12 = stack0 ;; |
add r12 = -16, r12 /* allocate a scratch area on the stack */ |
# initialize gp (Global Pointer) register |
# Initialize gp (Global Pointer) register |
movl r20 = (VRN_KERNEL << VRN_SHIFT);; |
or r20 = r20,r1;; |
movl r1 = _hardcoded_load_address |
/* |
* Initialize hardcoded_* variables. |
* Initialize hardcoded_* variables. Do only BSP |
*/ |
movl r14 = _hardcoded_ktext_size |
movl r15 = _hardcoded_kdata_size |
movl r16 = _hardcoded_load_address ;; |
addl r17 = @gprel(hardcoded_ktext_size), gp |
addl r18 = @gprel(hardcoded_kdata_size), gp |
addl r19 = @gprel(hardcoded_load_address), gp |
addl r21 = @gprel(bootinfo), gp |
(p3) movl r14 = _hardcoded_ktext_size |
(p3) movl r15 = _hardcoded_kdata_size |
(p3) movl r16 = _hardcoded_load_address ;; |
(p3) addl r17 = @gprel(hardcoded_ktext_size), gp |
(p3) addl r18 = @gprel(hardcoded_kdata_size), gp |
(p3) addl r19 = @gprel(hardcoded_load_address), gp |
(p3) addl r21 = @gprel(bootinfo), gp |
;; |
st8 [r17] = r14 |
st8 [r18] = r15 |
st8 [r19] = r16 |
st8 [r21] = r20 |
(p3) st8 [r17] = r14 |
(p3) st8 [r18] = r15 |
(p3) st8 [r19] = r16 |
(p3) st8 [r21] = r20 |
ssm (1 << 19) ;; /* Disable f32 - f127 */ |
srlz.i |
srlz.d ;; |
#ifdef CONFIG_SMP |
(p2) movl r18 = main_ap ;; |
(p2) mov b1 = r18 ;; |
(p2) br.call.sptk.many b0 = b1 |
# Mark that BSP is on |
mov r20 = 1 ;; |
movl r21 = bsp_started ;; |
st8 [r21] = r20 ;; |
#endif |
br.call.sptk.many b0 = arch_pre_main |
movl r18 = main_bsp ;; |
185,6 → 218,51 |
mov b1 = r18 ;; |
br.call.sptk.many b0 = b1 |
0: |
br 0b |
#ifdef CONFIG_SMP |
.align 4096 |
kernel_image_ap_start: |
.auto |
# Identify self(CPU) in OS structures by ID / EID |
mov r9 = cr64 |
mov r10 = 1 |
movl r12 = 0xffffffff |
movl r8 = cpu_by_id_eid_list |
and r8 = r8, r12 |
shr r9 = r9, 16 |
add r8 = r8, r9 |
st1 [r8] = r10 |
# Wait for wakeup synchro signal (#3 in cpu_by_id_eid_list) |
kernel_image_ap_start_loop: |
movl r11 = kernel_image_ap_start_loop |
and r11 = r11, r12 |
mov b1 = r11 |
ld1 r20 = [r8] ;; |
movl r21 = 3 ;; |
cmp.eq p2, p3 = r20, r21 ;; |
(p3) br.call.sptk.many b0 = b1 |
movl r11 = kernel_image_start |
and r11 = r11, r12 |
mov b1 = r11 |
br.call.sptk.many b0 = b1 |
.align 16 |
.global bsp_started |
bsp_started: |
.space 8 |
.align 4096 |
.global cpu_by_id_eid_list |
cpu_by_id_eid_list: |
.space 65536 |
#endif /* CONFIG_SMP */ |
/branches/dd/kernel/arch/arm32/_link.ld.in |
---|
1,15 → 1,16 |
/* |
* ARM linker script |
* |
* ARM linker script |
* |
* kernel text |
* kernel data |
* |
* |
*/ |
#define KERNEL_LOAD_ADDRESS 0x80200000 |
OUTPUT_ARCH(arm) |
ENTRY(kernel_image_start) |
ENTRY(kernel_image_start) |
SECTIONS { |
. = KERNEL_LOAD_ADDRESS; |
.text : { |
19,29 → 20,29 |
} |
.data : { |
kdata_start = .; |
*(.data); /* initialized data */ |
*(.data); /* initialized data */ |
hardcoded_ktext_size = .; |
LONG(ktext_end - ktext_start); |
LONG(ktext_end - ktext_start); |
hardcoded_kdata_size = .; |
LONG(kdata_end - kdata_start); |
hardcoded_load_address = .; |
LONG(KERNEL_LOAD_ADDRESS); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.rodata*); |
*(.sdata); |
*(.reginfo); |
symbol_table = .; |
*(symtab.*); |
*(symtab.*); |
} |
.sbss : { |
*(.sbss); |
*(.scommon); |
} |
kdata_end = .; |
/DISCARD/ : { |
*(.mdebug*); |
*(.pdr); |
48,5 → 49,4 |
*(.comment); |
*(.note); |
} |
} |
/branches/dd/kernel/arch/arm32/include/boot.h |
---|
File deleted |
/branches/dd/kernel/arch/arm32/include/asm/boot.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
39,24 → 39,7 |
/** Size of a temporary stack used for initial kernel start. */ |
#define TEMP_STACK_SIZE 0x100 |
#ifndef __ASM__ |
/** Kernel entry point. |
* |
* Implemented in assembly. Copies boot_bootinfo (declared as bootinfo in |
* boot/arch/arm32/loader/main.c) to #bootinfo struct. Then jumps to |
* #arch_pre_main and #main_bsp. |
* |
* @param entry Entry point address (not used). |
* @param boot_bootinfo Struct holding information about loaded tasks. |
* @param bootinfo_size Size of the bootinfo structure. |
*/ |
extern void kernel_image_start(void *entry, void *boot_bootinfo, |
unsigned int bootinfo_size); |
#endif |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/arm32/include/interrupt.h |
---|
37,6 → 37,7 |
#define KERN_arm32_INTERRUPT_H_ |
#include <arch/types.h> |
#include <arch/exception.h> |
/** Initial size of exception dispatch table. */ |
#define IVT_ITEMS 6 |
/branches/dd/kernel/arch/arm32/include/regutils.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** |
57,7 → 57,10 |
static inline uint32_t nm## _status_reg_read(void) \ |
{ \ |
uint32_t retval; \ |
asm volatile("mrs %0, " #reg : "=r" (retval)); \ |
asm volatile( \ |
"mrs %[retval], " #reg \ |
: [retval] "=r" (retval) \ |
); \ |
return retval; \ |
} |
64,7 → 67,10 |
#define GEN_STATUS_WRITE(nm,reg,fieldname, field) \ |
static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \ |
{ \ |
asm volatile("msr " #reg "_" #field ", %0" : : "r" (value)); \ |
asm volatile( \ |
"msr " #reg "_" #field ", %[value]" \ |
:: [value] "r" (value) \ |
); \ |
} |
/branches/dd/kernel/arch/arm32/include/console.h |
---|
36,13 → 36,6 |
#ifndef KERN_arm32_CONSOLE_H_ |
#define KERN_arm32_CONSOLE_H_ |
/** Initializes console. |
* |
* @param devno Console device number. |
*/ |
extern void console_init(devno_t devno); |
#endif |
/** @} |
/branches/dd/kernel/arch/arm32/include/machine.h |
---|
102,18 → 102,15 |
extern uintptr_t machine_get_fb_address(void); |
#ifdef MACHINE_GXEMUL_TESTARM |
#define machine_console_init(devno) gxemul_console_init(devno) |
#define machine_grab_console gxemul_grab_console |
#define machine_release_console gxemul_release_console |
#define machine_hw_map_init gxemul_hw_map_init |
#define machine_timer_irq_start gxemul_timer_irq_start |
#define machine_cpu_halt gxemul_cpu_halt |
#define machine_get_memory_size gxemul_get_memory_size |
#define machine_debug_putc(ch) gxemul_debug_putc(ch) |
#define machine_irq_exception(exc_no, istate) \ |
gxemul_irq_exception(exc_no, istate) |
#define machine_get_fb_address gxemul_get_fb_address |
#ifdef MACHINE_gxemul |
#define machine_console_init(devno) gxemul_console_init(devno) |
#define machine_hw_map_init gxemul_hw_map_init |
#define machine_timer_irq_start gxemul_timer_irq_start |
#define machine_cpu_halt gxemul_cpu_halt |
#define machine_get_memory_size gxemul_get_memory_size |
#define machine_debug_putc(ch) gxemul_debug_putc(ch) |
#define machine_irq_exception(exc_no, istate) gxemul_irq_exception(exc_no, istate) |
#define machine_get_fb_address gxemul_get_fb_address |
#endif |
#endif |
/branches/dd/kernel/arch/arm32/include/types.h |
---|
42,10 → 42,6 |
# define ATTRIBUTE_PACKED |
#endif |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
68,15 → 64,32 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page table entry. |
* |
* We have different structs for level 0 and level 1 page table entries. |
/branches/dd/kernel/arch/arm32/include/memstr.h |
---|
38,10 → 38,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/dd/kernel/arch/arm32/include/atomic.h |
---|
26,10 → 26,10 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
/** @file |
* @brief Atomic operations. |
*/ |
42,26 → 42,26 |
* @param i Value to be added. |
* |
* @return Value after addition. |
* |
*/ |
static inline long atomic_add(atomic_t *val, int i) |
{ |
int ret; |
volatile long *mem = &(val->count); |
asm volatile ( |
"1:\n" |
"ldr r2, [%1] \n" |
"add r3, r2, %2 \n" |
"str r3, %0 \n" |
"swp r3, r3, [%1] \n" |
"cmp r3, r2 \n" |
"bne 1b \n" |
: "=m" (ret) |
: "r" (mem), "r" (i) |
"1:\n" |
"ldr r2, [%[mem]]\n" |
"add r3, r2, %[i]\n" |
"str r3, %[ret]\n" |
"swp r3, r3, [%[mem]]\n" |
"cmp r3, r2\n" |
"bne 1b\n" |
: [ret] "=m" (ret) |
: [mem] "r" (mem), [i] "r" (i) |
: "r3", "r2" |
); |
return ret; |
} |
/branches/dd/kernel/arch/arm32/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
36,6 → 36,26 |
#ifndef KERN_arm32_ARCH_H_ |
#define KERN_arm32_ARCH_H_ |
#define TASKMAP_MAX_RECORDS 32 |
#define CPUMAP_MAX_RECORDS 32 |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
#include <typedefs.h> |
typedef struct { |
uintptr_t addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} utask_t; |
typedef struct { |
uint32_t cnt; |
utask_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
extern void arch_pre_main(void *entry, bootinfo_t *bootinfo); |
#endif |
/** @} |
/branches/dd/kernel/arch/arm32/include/asm.h |
---|
26,10 → 26,10 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
/** @file |
* @brief Declarations of functions implemented in assembly. |
*/ |
36,6 → 36,7 |
#ifndef KERN_arm32_ASM_H_ |
#define KERN_arm32_ASM_H_ |
#include <typedefs.h> |
#include <arch/types.h> |
#include <arch/stack.h> |
#include <config.h> |
46,19 → 47,50 |
{ |
} |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
/** Return base address of current stack. |
* |
* |
* Return the base address of the current stack. |
* The stack is assumed to be STACK_SIZE bytes long. |
* The stack must start on page boundary. |
* |
*/ |
static inline uintptr_t get_stack_base(void) |
{ |
uintptr_t v; |
asm volatile ( |
"and %0, sp, %1\n" |
: "=r" (v) |
: "r" (~(STACK_SIZE - 1)) |
"and %[v], sp, %[size]\n" |
: [v] "=r" (v) |
: [size] "r" (~(STACK_SIZE - 1)) |
); |
return v; |
} |
/branches/dd/kernel/arch/arm32/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32mm |
/** @addtogroup arm32mm |
* @{ |
*/ |
/** @file |
36,8 → 36,8 |
#ifndef KERN_arm32_FRAME_H_ |
#define KERN_arm32_FRAME_H_ |
#define FRAME_WIDTH 12 /* 4KB frames */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 12 /* 4KB frames */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
44,8 → 44,8 |
#include <arch/types.h> |
#define BOOT_PAGE_TABLE_SIZE 0x4000 |
#define BOOT_PAGE_TABLE_ADDRESS 0x4000 |
#define BOOT_PAGE_TABLE_SIZE 0x4000 |
#define BOOT_PAGE_TABLE_ADDRESS 0x4000 |
#define BOOT_PAGE_TABLE_START_FRAME (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH) |
#define BOOT_PAGE_TABLE_SIZE_IN_FRAMES (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH) |
/branches/dd/kernel/arch/arm32/include/mm/page.h |
---|
43,8 → 43,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
195,9 → 193,8 |
static inline void set_ptl0_addr(pte_level0_t *pt) |
{ |
asm volatile ( |
"mcr p15, 0, %0, c2, c0, 0 \n" |
: |
: "r"(pt) |
"mcr p15, 0, %[pt], c2, c0, 0\n" |
:: [pt] "r" (pt) |
); |
} |
/branches/dd/kernel/arch/arm32/include/mm/tlb.h |
---|
36,9 → 36,6 |
#ifndef KERN_arm32_TLB_H_ |
#define KERN_arm32_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/dd/kernel/arch/arm32/include/barrier.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32 |
/** @addtogroup arm32 |
* @{ |
*/ |
/** @file |
39,13 → 39,16 |
/* |
* TODO: implement true ARM memory barriers for macros below. |
*/ |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
#define memory_barrier() asm volatile ("" ::: "memory") |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define memory_barrier() asm volatile ("" ::: "memory") |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/dd/kernel/arch/arm32/Makefile.inc |
---|
33,64 → 33,31 |
BFD_ARCH = arm |
BFD = binary |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm |
KERNEL_LOAD_ADDRESS = 0x80200000 |
ifeq ($(MACHINE), gxemul_testarm) |
DMACHINE = MACHINE_GXEMUL_TESTARM |
endif |
ATSIGN = % |
GCC_CFLAGS += -fno-zero-initialized-in-bss |
DEFS += -D__32_BITS__ -DKERNEL_LOAD_ADDRESS=$(KERNEL_LOAD_ADDRESS) -D$(DMACHINE) |
DEFS += -D__32_BITS__ |
# Compile with framebuffer support |
ifeq ($(CONFIG_FB), y) |
DEFS += -DCONFIG_FB -DFB_INVERT_ENDIAN |
endif |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with support for address space identifiers. |
# |
# no HW support for ASIDs |
#CONFIG_ASID = y |
#CONFIG_ASID_FIFO = y |
## Compile with support with software division and multiplication. |
# |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/start.S \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/arm32.c \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/dummy.S \ |
arch/$(ARCH)/src/panic.S \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/debug/print.c \ |
arch/$(ARCH)/src/console.c \ |
arch/$(ARCH)/src/exception.c \ |
arch/$(ARCH)/src/userspace.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/mm/page_fault.c |
ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += arch/$(ARCH)/src/drivers/gxemul.c |
endif |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/arm32.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/dummy.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/debug/print.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/mm/page_fault.c \ |
arch/$(KARCH)/src/drivers/gxemul.c |
/branches/dd/kernel/arch/arm32/src/exception.c |
---|
40,6 → 40,7 |
#include <interrupt.h> |
#include <arch/machine.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <print.h> |
#include <syscall/syscall.h> |
62,57 → 63,60 |
* |
* Temporary exception stack is used to save a few registers |
* before stack switch takes place. |
* |
*/ |
inline static void setup_stack_and_save_regs() |
{ |
asm volatile( |
"ldr r13, =exc_stack \n" |
"stmfd r13!, {r0} \n" |
"mrs r0, spsr \n" |
"and r0, r0, #0x1f \n" |
"cmp r0, #0x10 \n" |
"bne 1f \n" |
asm volatile ( |
"ldr r13, =exc_stack\n" |
"stmfd r13!, {r0}\n" |
"mrs r0, spsr\n" |
"and r0, r0, #0x1f\n" |
"cmp r0, #0x10\n" |
"bne 1f\n" |
/* prev mode was usermode */ |
"ldmfd r13!, {r0} \n" |
"ldr r13, =supervisor_sp \n" |
"ldr r13, [r13] \n" |
"stmfd r13!, {lr} \n" |
"stmfd r13!, {r0-r12} \n" |
"stmfd r13!, {r13, lr}^ \n" |
"mrs r0, spsr \n" |
"stmfd r13!, {r0} \n" |
"b 2f \n" |
"ldmfd r13!, {r0}\n" |
"ldr r13, =supervisor_sp\n" |
"ldr r13, [r13]\n" |
"stmfd r13!, {lr}\n" |
"stmfd r13!, {r0-r12}\n" |
"stmfd r13!, {r13, lr}^\n" |
"mrs r0, spsr\n" |
"stmfd r13!, {r0}\n" |
"b 2f\n" |
/* mode was not usermode */ |
"1:\n" |
"stmfd r13!, {r1, r2, r3} \n" |
"mrs r1, cpsr \n" |
"mov r2, lr \n" |
"bic r1, r1, #0x1f \n" |
"orr r1, r1, r0 \n" |
"mrs r0, cpsr \n" |
"msr cpsr_c, r1 \n" |
"mov r3, r13 \n" |
"stmfd r13!, {r2} \n" |
"mov r2, lr \n" |
"stmfd r13!, {r4-r12} \n" |
"mov r1, r13 \n" |
/* the following two lines are for debugging */ |
"mov sp, #0 \n" |
"mov lr, #0 \n" |
"msr cpsr_c, r0 \n" |
"ldmfd r13!, {r4, r5, r6, r7} \n" |
"stmfd r1!, {r4, r5, r6} \n" |
"stmfd r1!, {r7} \n" |
"stmfd r1!, {r2} \n" |
"stmfd r1!, {r3} \n" |
"mrs r0, spsr \n" |
"stmfd r1!, {r0} \n" |
"mov r13, r1 \n" |
"2:\n" |
"1:\n" |
"stmfd r13!, {r1, r2, r3}\n" |
"mrs r1, cpsr\n" |
"mov r2, lr\n" |
"bic r1, r1, #0x1f\n" |
"orr r1, r1, r0\n" |
"mrs r0, cpsr\n" |
"msr cpsr_c, r1\n" |
"mov r3, r13\n" |
"stmfd r13!, {r2}\n" |
"mov r2, lr\n" |
"stmfd r13!, {r4-r12}\n" |
"mov r1, r13\n" |
/* the following two lines are for debugging */ |
"mov sp, #0\n" |
"mov lr, #0\n" |
"msr cpsr_c, r0\n" |
"ldmfd r13!, {r4, r5, r6, r7}\n" |
"stmfd r1!, {r4, r5, r6}\n" |
"stmfd r1!, {r7}\n" |
"stmfd r1!, {r2}\n" |
"stmfd r1!, {r3}\n" |
"mrs r0, spsr\n" |
"stmfd r1!, {r0}\n" |
"mov r13, r1\n" |
"2:\n" |
); |
} |
188,10 → 192,13 |
} |
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
asm("mov r1, r13"); \ |
asm("bl exc_dispatch"); |
#define CALL_EXC_DISPATCH(exception) \ |
asm volatile ( \ |
"mov r0, %[exc]\n" \ |
"mov r1, r13\n" \ |
"bl exc_dispatch\n" \ |
:: [exc] "i" (exception) \ |
);\ |
/** General exception handler. |
* |
200,9 → 207,9 |
* |
* @param exception Exception number. |
*/ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
load_regs(); |
/** Updates specified exception vector to jump to given handler. |
209,7 → 216,7 |
* |
* Addresses of handlers are stored in memory following exception vectors. |
*/ |
static void install_handler (unsigned handler_addr, unsigned* vector) |
static void install_handler(unsigned handler_addr, unsigned *vector) |
{ |
/* relative address (related to exc. vector) of the word |
* where handler's address is stored |
219,6 → 226,7 |
/* make it LDR instruction and store at exception vector */ |
*vector = handler_address_ptr | LDR_OPCODE; |
smc_coherence(*vector); |
/* store handler's address */ |
*(vector + EXC_VECTORS) = handler_addr; |
226,31 → 234,31 |
} |
/** Low-level Reset Exception handler. */ |
static void reset_exception_entry() |
static void reset_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_RESET); |
} |
/** Low-level Software Interrupt Exception handler. */ |
static void swi_exception_entry() |
static void swi_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_SWI); |
} |
/** Low-level Undefined Instruction Exception handler. */ |
static void undef_instr_exception_entry() |
static void undef_instr_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_UNDEF_INSTR); |
} |
/** Low-level Fast Interrupt Exception handler. */ |
static void fiq_exception_entry() |
static void fiq_exception_entry(void) |
{ |
PROCESS_EXCEPTION(EXC_FIQ); |
} |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry() |
static void prefetch_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
257,7 → 265,7 |
} |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry() |
static void data_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #8"); |
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
269,7 → 277,7 |
* because of possible occurence of nested interrupt exception, which |
* would overwrite (and thus spoil) stack pointer. |
*/ |
static void irq_exception_entry() |
static void irq_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
setup_stack_and_save_regs(); |
331,17 → 339,23 |
{ |
uint32_t control_reg; |
asm volatile("mrc p15, 0, %0, c1, c1" : "=r" (control_reg)); |
asm volatile ( |
"mrc p15, 0, %[control_reg], c1, c1" |
: [control_reg] "=r" (control_reg) |
); |
/* switch on the high vectors bit */ |
control_reg |= CP15_R1_HIGH_VECTORS_BIT; |
asm volatile("mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
asm volatile ( |
"mcr p15, 0, %[control_reg], c1, c1" |
:: [control_reg] "r" (control_reg) |
); |
} |
#endif |
/** Initializes exception handling. |
* |
* |
* Installs low-level exception handlers and then registers |
* exceptions and their handlers to kernel exception dispatcher. |
*/ |
/branches/dd/kernel/arch/arm32/src/asm.S |
---|
45,7 → 45,8 |
add r3, r1, #3 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, lr} |
stmdb sp!, {r4, r5, lr} |
mov r5, r0 /* save dst */ |
beq 4f |
1: |
cmp r2, #0 |
58,8 → 59,8 |
cmp ip, r2 |
bne 2b |
3: |
mov r0, r1 |
ldmia sp!, {r4, pc} |
mov r0, r5 |
ldmia sp!, {r4, r5, pc} |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
94,5 → 95,5 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
mov r0, #0 |
ldmia sp!, {r4, pc} |
mov r0, #0 |
ldmia sp!, {r4, r5, pc} |
/branches/dd/kernel/arch/arm32/src/console.c |
---|
37,21 → 37,19 |
#include <arch/console.h> |
#include <arch/machine.h> |
void console_init(devno_t devno) |
{ |
machine_console_init(devno); |
} |
#include <genarch/fb/fb.h> |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
machine_grab_console(); |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
machine_release_console(); |
} |
/** @} |
/branches/dd/kernel/arch/arm32/src/arm32.c |
---|
34,7 → 34,6 |
*/ |
#include <arch.h> |
#include <arch/boot.h> |
#include <config.h> |
#include <arch/console.h> |
#include <ddi/device.h> |
48,22 → 47,22 |
#include <arch/regutils.h> |
#include <arch/machine.h> |
#include <userspace.h> |
#include <macros.h> |
#include <string.h> |
/** Information about loaded tasks. */ |
bootinfo_t bootinfo; |
/** Performs arm32 specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
/** Performs arm32-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo) |
{ |
unsigned int i; |
init.cnt = bootinfo.cnt; |
for (i = 0; i < bootinfo.cnt; ++i) { |
init.tasks[i].addr = bootinfo.tasks[i].addr; |
init.tasks[i].size = bootinfo.tasks[i].size; |
init.cnt = bootinfo->cnt; |
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); ++i) { |
init.tasks[i].addr = bootinfo->tasks[i].addr; |
init.tasks[i].size = bootinfo->tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo->tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
} |
} |
/** Performs arm32 specific initialization before mm is initialized. */ |
83,10 → 82,18 |
interrupt_init(); |
console_init(device_assign_devno()); |
machine_console_init(device_assign_devno()); |
#ifdef CONFIG_FB |
fb_init(machine_get_fb_address(), 640, 480, 1920, VISUAL_RGB_8_8_8); |
fb_properties_t prop = { |
.addr = machine_get_fb_address(), |
.offset = 0, |
.x = 640, |
.y = 480, |
.scan = 1920, |
.visual = VISUAL_BGR_8_8_8, |
}; |
fb_init(&prop); |
#endif |
} |
156,9 → 163,22 |
void arch_reboot() |
{ |
/* not implemented */ |
for (;;) |
; |
while (1); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/arm32/src/cpu/cpu.c |
---|
36,7 → 36,7 |
#include <arch/cpu.h> |
#include <cpu.h> |
#include <arch.h> |
#include <print.h> |
#include <print.h> |
/** Number of indexes left out in the #imp_data array */ |
#define IMP_DATA_START_OFFSET 0x40 |
82,10 → 82,10 |
{ |
uint32_t ident; |
asm volatile ( |
"mrc p15, 0, %0, c0, c0, 0\n" |
: "=r" (ident) |
"mrc p15, 0, %[ident], c0, c0, 0\n" |
: [ident] "=r" (ident) |
); |
cpu->imp_num = ident >> 24; |
cpu->variant_num = (ident << 8) >> 28; |
cpu->arch_num = (ident << 12) >> 28; |
/branches/dd/kernel/arch/arm32/src/mm/tlb.c |
---|
48,7 → 48,7 |
asm volatile ( |
"eor r1, r1\n" |
"mcr p15, 0, r1, c8, c7, 0\n" |
: : : "r1" |
::: "r1" |
); |
} |
68,9 → 68,8 |
static inline void invalidate_page(uintptr_t page) |
{ |
asm volatile ( |
"mcr p15, 0, %0, c8, c7, 1" |
: |
: "r" (page) |
"mcr p15, 0, %[page], c8, c7, 1\n" |
:: [page] "r" (page) |
); |
} |
81,7 → 80,7 |
* @param page Address of the first page whose entry is to be invalidated. |
* @param cnt Number of entries to invalidate. |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt) |
{ |
unsigned int i; |
89,5 → 88,13 |
invalidate_page(page + i * PAGE_SIZE); |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/arm32/src/mm/page_fault.c |
---|
40,6 → 40,7 |
#include <genarch/mm/page_pt.h> |
#include <arch.h> |
#include <interrupt.h> |
#include <print.h> |
/** Returns value stored in fault status register. |
* |
48,12 → 49,13 |
static inline fault_status_t read_fault_status_register(void) |
{ |
fault_status_union_t fsu; |
/* fault status is stored in CP15 register 5 */ |
asm volatile ( |
"mrc p15, 0, %0, c5, c0, 0" |
: "=r"(fsu.dummy) |
"mrc p15, 0, %[dummy], c5, c0, 0" |
: [dummy] "=r" (fsu.dummy) |
); |
return fsu.fs; |
} |
60,17 → 62,18 |
/** Returns FAR (fault address register) content. |
* |
* @return FAR (fault address register) content (address that caused a page |
* fault) |
* fault) |
*/ |
static inline uintptr_t read_fault_address_register(void) |
{ |
uintptr_t ret; |
/* fault adress is stored in CP15 register 6 */ |
asm volatile ( |
"mrc p15, 0, %0, c6, c0, 0" |
: "=r"(ret) |
"mrc p15, 0, %[ret], c6, c0, 0" |
: [ret] "=r" (ret) |
); |
return ret; |
} |
79,29 → 82,26 |
* @param instr Instruction |
* |
* @return true when instruction is load/store, false otherwise |
* |
*/ |
static inline bool is_load_store_instruction(instruction_t instr) |
{ |
/* load store immediate offset */ |
if (instr.type == 0x2) { |
if (instr.type == 0x2) |
return true; |
} |
/* load store register offset */ |
if (instr.type == 0x3 && instr.bit4 == 0) { |
if ((instr.type == 0x3) && (instr.bit4 == 0)) |
return true; |
} |
/* load store multiple */ |
if (instr.type == 0x4) { |
if (instr.type == 0x4) |
return true; |
} |
/* oprocessor load/store */ |
if (instr.type == 0x6) { |
if (instr.type == 0x6) |
return true; |
} |
return false; |
} |
114,12 → 114,11 |
static inline bool is_swap_instruction(instruction_t instr) |
{ |
/* swap, swapb instruction */ |
if (instr.type == 0x0 && |
(instr.opcode == 0x8 || instr.opcode == 0xa) && |
instr.access == 0x0 && instr.bits567 == 0x4 && instr.bit4 == 1) { |
if ((instr.type == 0x0) && |
((instr.opcode == 0x8) || (instr.opcode == 0xa)) && |
(instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1)) |
return true; |
} |
return false; |
} |
141,8 → 140,8 |
/* undefined instructions */ |
if (instr.condition == 0xf) { |
panic("page_fault - instruction doesn't access memory " |
"(instr_code: %x, badvaddr:%x)", instr, badvaddr); |
panic("page_fault - instruction does not access memory " |
"(instr_code: %x, badvaddr:%x).", instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
161,7 → 160,7 |
} |
panic("page_fault - instruction doesn't access memory " |
"(instr_code: %x, badvaddr:%x)", instr, badvaddr); |
"(instr_code: %x, badvaddr:%x).", instr, badvaddr); |
return PF_ACCESS_EXEC; |
} |
187,8 → 186,8 |
"access:%d\n", istate->pc, badvaddr, fsr.status, fsr, |
access); |
fault_if_from_uspace(istate, "Page fault: %#x", badvaddr); |
panic("page fault\n"); |
fault_if_from_uspace(istate, "Page fault: %#x.", badvaddr); |
panic("Page fault."); |
} |
} |
204,7 → 203,7 |
if (ret == AS_PF_FAULT) { |
dprintf("prefetch_abort\n"); |
print_istate(istate); |
panic("page fault - prefetch_abort at address: %x\n", |
panic("page fault - prefetch_abort at address: %x.", |
istate->pc); |
} |
} |
/branches/dd/kernel/arch/arm32/src/mm/frame.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup arm32mm |
/** @addtogroup arm32mm |
* @{ |
*/ |
/** @file |
49,7 → 49,7 |
zone_create(0, ADDR2PFN(machine_get_memory_size()), |
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0); |
last_frame = machine_get_memory_size(); |
/* blacklist boot page table */ |
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME, |
BOOT_PAGE_TABLE_SIZE_IN_FRAMES); |
/branches/dd/kernel/arch/arm32/src/mm/page.c |
---|
90,7 → 90,7 |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > |
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) { |
panic("Unable to map physical memory %p (%d bytes)", |
panic("Unable to map physical memory %p (%d bytes).", |
physaddr, size) |
} |
/branches/dd/kernel/arch/arm32/src/userspace.c |
---|
70,8 → 70,11 |
/* set first parameter */ |
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg; |
/* %r1 is defined to hold pcb_ptr - set it to 0 */ |
ustate.r1 = 0; |
/* clear other registers */ |
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 = |
ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 = |
ustate.r11 = ustate.r12 = ustate.lr = 0; |
87,12 → 90,11 |
/* set user mode, set registers, jump */ |
asm volatile ( |
"mov sp, %0 \n" |
"msr spsr_c, %1 \n" |
"ldmfd sp!, {r0-r12, sp, lr}^ \n" |
"mov sp, %[ustate]\n" |
"msr spsr_c, %[user_mode]\n" |
"ldmfd sp!, {r0-r12, sp, lr}^\n" |
"ldmfd sp!, {pc}^\n" |
: |
: "r" (&ustate), "r" (user_mode) |
:: [ustate] "r" (&ustate), [user_mode] "r" (user_mode) |
); |
/* unreachable */ |
/branches/dd/kernel/arch/arm32/src/drivers/gxemul.c |
---|
34,7 → 34,6 |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/gxemul.h> |
#include <console/console.h> |
72,7 → 71,7 |
static void gxemul_kbd_enable(chardev_t *dev); |
static void gxemul_kbd_disable(chardev_t *dev); |
static void gxemul_write(chardev_t *dev, const char ch); |
static void gxemul_write(chardev_t *dev, const char ch, bool silent); |
static char gxemul_do_read(chardev_t *dev); |
static chardev_operations_t gxemul_ops = { |
133,9 → 132,10 |
* @param dev Not used. |
* @param ch Characted to be printed. |
*/ |
static void gxemul_write(chardev_t *dev, const char ch) |
static void gxemul_write(chardev_t *dev, const char ch, bool silent) |
{ |
*((char *) gxemul_hw_map.videoram) = ch; |
if (!silent) |
*((char *) gxemul_hw_map.videoram) = ch; |
} |
/** Enables gxemul keyboard (interrupt unmasked). |
183,54 → 183,26 |
/** Process keyboard interrupt. |
* |
* @param irq IRQ information. |
* @param arg Not used. |
*/ |
static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
static void gxemul_irq_handler(irq_t *irq) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
ipc_irq_send_notif(irq); |
} else { |
char ch = 0; |
char ch = 0; |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
static irq_ownership_t gxemul_claim(void) |
static irq_ownership_t gxemul_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
/** Acquire console back for kernel. */ |
void gxemul_grab_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&gxemul_console_irq.lock); |
gxemul_console_irq.notif_cfg.notify = false; |
spinlock_unlock(&gxemul_console_irq.lock); |
interrupts_restore(ipl); |
} |
/** Return console to userspace. */ |
void gxemul_release_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&gxemul_console_irq.lock); |
if (gxemul_console_irq.notif_cfg.answerbox) { |
gxemul_console_irq.notif_cfg.notify = true; |
} |
spinlock_unlock(&gxemul_console_irq.lock); |
interrupts_restore(ipl); |
} |
/** Initializes console object representing gxemul console. |
* |
* @param devno device number. |
265,7 → 237,7 |
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency; |
} |
static irq_ownership_t gxemul_timer_claim(void) |
static irq_ownership_t gxemul_timer_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
275,7 → 247,7 |
* @param irq Interrupt information. |
* @param arg Not used. |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
static void gxemul_timer_irq_handler(irq_t *irq) |
{ |
/* |
* We are holding a lock which prevents preemption. |
369,7 → 341,7 |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
/branches/dd/kernel/arch/arm32/src/start.S |
---|
40,30 → 40,12 |
mrs r3, cpsr |
bic r3, r3, #0x1f |
orr r3, r3, #0x13 |
msr cpsr_c, r3 |
msr cpsr_c, r3 |
ldr sp, =temp_stack |
cmp r2, #0 |
beq bootinfo_end |
ldr r3, =bootinfo |
bootinfo_loop: |
ldr r4, [r1] |
str r4, [r3] |
add r1, r1, #4 |
add r3, r3, #4 |
add r2, r2, #-4 |
cmp r2, #0 |
bne bootinfo_loop |
bootinfo_end: |
bl arch_pre_main |
bl main_bsp |
.space TEMP_STACK_SIZE |
74,4 → 56,3 |
supervisor_sp: |
.space 4 |
/branches/dd/kernel/arch/ppc32/_link.ld.in |
---|
1,11 → 1,11 |
/** PPC32 linker script |
* |
* umapped section: |
* kernel text |
* kernel data |
* kernel text |
* kernel data |
* mapped section: |
* kernel text |
* kernel data |
* kernel text |
* kernel data |
* |
*/ |
27,7 → 27,7 |
unmapped_kdata_start = .; |
} |
.mapped PA2KA(BOOT_OFFSET): AT (BOOT_OFFSET) { |
.mapped PA2KA(BOOT_OFFSET): AT (BOOT_OFFSET) { |
ktext_start = .; |
*(K_TEXT_START); |
*(.text); |
37,22 → 37,22 |
*(K_DATA_START); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
hardcoded_ktext_size = .; |
LONG(ktext_end - ktext_start); |
LONG(ktext_end - ktext_start); |
hardcoded_kdata_size = .; |
LONG(kdata_end - kdata_start); |
hardcoded_load_address = .; |
LONG(PA2KA(BOOT_OFFSET)); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
symbol_table = .; |
*(symtab.*); /* Symbol table, must be LAST symbol!*/ |
*(symtab.*); /* Symbol table, must be LAST symbol!*/ |
kdata_end = .; |
} |
} |
/branches/dd/kernel/arch/ppc32/include/asm/regname.h |
---|
211,15 → 211,19 |
#define dbat2l 541 |
#define dbat3u 542 |
#define dbat3l 543 |
#define tlbmiss 980 |
#define ptehi 981 |
#define ptelo 982 |
#define hid0 1008 |
/* MSR bits */ |
#define msr_ir (1 << 4) |
#define msr_dr (1 << 5) |
#define msr_dr (1 << 4) |
#define msr_ir (1 << 5) |
#define msr_pr (1 << 14) |
#define msr_ee (1 << 15) |
/* HID0 bits */ |
#define hid0_sten (1 << 24) |
#define hid0_ice (1 << 15) |
#define hid0_dce (1 << 14) |
#define hid0_icfi (1 << 11) |
/branches/dd/kernel/arch/ppc32/include/exception.h |
---|
36,6 → 36,7 |
#define KERN_ppc32_EXCEPTION_H_ |
#include <arch/types.h> |
#include <arch/regutils.h> |
typedef struct { |
uint32_t r0; |
74,6 → 75,7 |
uint32_t lr; |
uint32_t ctr; |
uint32_t xer; |
uint32_t dar; |
uint32_t r12; |
uint32_t sp; |
} istate_t; |
82,13 → 84,14 |
{ |
istate->pc = retaddr; |
} |
/** Return true if exception happened while in userspace */ |
#include <panic.h> |
static inline int istate_from_uspace(istate_t *istate) |
{ |
panic("istate_from_uspace not yet implemented"); |
return 0; |
/* true if privilege level PR (copied from MSR) == 1 */ |
return (istate->srr1 & MSR_PR) != 0; |
} |
static inline unative_t istate_get_pc(istate_t *istate) |
{ |
return istate->pc; |
/branches/dd/kernel/arch/ppc32/include/regutils.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** |
* @file |
* @brief Utilities for convenient manipulation with ppc32 registers. |
*/ |
#ifndef KERN_ppc32_REGUTILS_H_ |
#define KERN_ppc32_REGUTILS_H_ |
#define MSR_PR (1 << 14) |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/ppc32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ppc32_TYPES_H_ |
#define KERN_ppc32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,21 → 57,43 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "x" |
#define PRIs "u" |
#define PRIc "u" |
#define PRIi "u" |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "d" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "u" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "x" |
/** Page Table Entry. */ |
typedef struct { |
unsigned p : 1; /**< Present bit. */ |
unsigned a : 1; /**< Accessed bit. */ |
unsigned g : 1; /**< Global bit. */ |
unsigned valid : 1; /**< Valid content even if not present. */ |
unsigned pfn : 20; /**< Physical frame number. */ |
unsigned present : 1; /**< Present bit. */ |
unsigned page_write_through : 1; /**< Write thought caching. */ |
unsigned page_cache_disable : 1; /**< No caching. */ |
unsigned accessed : 1; /**< Accessed bit. */ |
unsigned global : 1; /**< Global bit. */ |
unsigned valid : 1; /**< Valid content even if not present. */ |
unsigned pfn : 20; /**< Physical frame number. */ |
} pte_t; |
#endif |
/branches/dd/kernel/arch/ppc32/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/dd/kernel/arch/ppc32/include/boot/boot.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
35,21 → 35,24 |
#ifndef KERN_ppc32_BOOT_H_ |
#define KERN_ppc32_BOOT_H_ |
#define BOOT_OFFSET 0x8000 |
#define BOOT_OFFSET 0x8000 |
/* Temporary stack size for boot process */ |
#define TEMP_STACK_SIZE 0x100 |
#define TEMP_STACK_SIZE 0x1000 |
#define TASKMAP_MAX_RECORDS 32 |
#define MEMMAP_MAX_RECORDS 32 |
#define TASKMAP_MAX_RECORDS 32 |
#define MEMMAP_MAX_RECORDS 32 |
#ifndef __ASM__ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
#include <arch/types.h> |
typedef struct { |
uintptr_t addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} utask_t; |
typedef struct { |
79,13 → 82,13 |
typedef struct { |
uintptr_t addr; |
unsigned int size; |
} keyboard_t; |
} macio_t; |
typedef struct { |
memmap_t memmap; |
taskmap_t taskmap; |
screen_t screen; |
keyboard_t keyboard; |
macio_t macio; |
} bootinfo_t; |
extern bootinfo_t bootinfo; |
/branches/dd/kernel/arch/ppc32/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
35,7 → 35,7 |
#ifndef KERN_ppc32_ARCH_H_ |
#define KERN_ppc32_ARCH_H_ |
#include <arch/drivers/cuda.h> |
extern void arch_pre_main(void); |
#endif |
/branches/dd/kernel/arch/ppc32/include/asm.h |
---|
36,6 → 36,7 |
#define KERN_ppc32_ASM_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <config.h> |
/** Enable interrupts. |
149,6 → 150,36 |
extern void userspace_asm(uintptr_t uspace_uarg, uintptr_t stack, uintptr_t entry); |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ppc32/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32mm |
/** @addtogroup ppc32mm |
* @{ |
*/ |
/** @file |
35,13 → 35,13 |
#ifndef KERN_ppc32_FRAME_H_ |
#define KERN_ppc32_FRAME_H_ |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
#include <arch/types.h> |
#include <arch/types.h> |
extern uintptr_t last_frame; |
/branches/dd/kernel/arch/ppc32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
122,7 → 120,7 |
/* Macros for querying the last-level PTEs. */ |
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0) |
#define PTE_PRESENT_ARCH(pte) ((pte)->p != 0) |
#define PTE_PRESENT_ARCH(pte) ((pte)->present != 0) |
#define PTE_GET_FRAME_ARCH(pte) ((pte)->pfn << 12) |
#define PTE_WRITABLE_ARCH(pte) 1 |
#define PTE_EXECUTABLE_ARCH(pte) 1 |
136,13 → 134,13 |
{ |
pte_t *p = &pt[i]; |
return ((1 << PAGE_CACHEABLE_SHIFT) | |
((!p->p) << PAGE_PRESENT_SHIFT) | |
return (((!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT) | |
((!p->present) << PAGE_PRESENT_SHIFT) | |
(1 << PAGE_USER_SHIFT) | |
(1 << PAGE_READ_SHIFT) | |
(1 << PAGE_WRITE_SHIFT) | |
(1 << PAGE_EXEC_SHIFT) | |
(p->g << PAGE_GLOBAL_SHIFT)); |
(p->global << PAGE_GLOBAL_SHIFT)); |
} |
static inline void set_pt_flags(pte_t *pt, index_t i, int flags) |
149,8 → 147,9 |
{ |
pte_t *p = &pt[i]; |
p->p = !(flags & PAGE_NOT_PRESENT); |
p->g = (flags & PAGE_GLOBAL) != 0; |
p->page_cache_disable = !(flags & PAGE_CACHEABLE); |
p->present = !(flags & PAGE_NOT_PRESENT); |
p->global = (flags & PAGE_GLOBAL) != 0; |
p->valid = 1; |
} |
/branches/dd/kernel/arch/ppc32/include/mm/tlb.h |
---|
36,7 → 36,14 |
#define KERN_ppc32_TLB_H_ |
#include <arch/interrupt.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#define WIMG_GUARDED 0x01 |
#define WIMG_COHERENT 0x02 |
#define WIMG_NO_CACHE 0x04 |
#define WIMG_WRITETHRU 0x08 |
typedef struct { |
unsigned v : 1; /**< Valid */ |
unsigned vsid : 24; /**< Virtual Segment ID */ |
51,9 → 58,27 |
unsigned pp : 2; /**< Page protection */ |
} phte_t; |
typedef struct { |
unsigned v : 1; |
unsigned vsid : 24; |
unsigned reserved0 : 1; |
unsigned api : 6; |
} ptehi_t; |
typedef struct { |
unsigned rpn : 20; |
unsigned xpn : 3; |
unsigned reserved0 : 1; |
unsigned c : 1; |
unsigned wimg : 4; |
unsigned x : 1; |
unsigned pp : 2; |
} ptelo_t; |
extern void pht_init(void); |
extern void pht_refill(int n, istate_t *istate); |
extern bool pht_real_refill(int n, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START"))); |
extern void pht_init(void); |
extern bool pht_refill_real(int n, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START"))); |
extern void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate) __attribute__ ((section("K_UNMAPPED_TEXT_START"))); |
#endif |
/branches/dd/kernel/arch/ppc32/include/barrier.h |
---|
42,6 → 42,47 |
#define read_barrier() asm volatile ("sync" ::: "memory") |
#define write_barrier() asm volatile ("eieio" ::: "memory") |
/* |
* The IMB sequence used here is valid for all possible cache models |
* on uniprocessor. SMP might require a different sequence. |
* See PowerPC Programming Environment for 32-Bit Microprocessors, |
* chapter 5.1.5.2 |
*/ |
static inline void smc_coherence(void *addr) |
{ |
asm volatile ( |
"dcbst 0, %0\n" |
"sync\n" |
"icbi 0, %0\n" |
"sync\n" |
"isync\n" |
:: "r" (addr) |
); |
} |
#define COHERENCE_INVAL_MIN 4 |
static inline void smc_coherence_block(void *addr, unsigned long len) |
{ |
unsigned long i; |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("dcbst 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ("sync"); |
for (i = 0; i < len; i += COHERENCE_INVAL_MIN) { |
asm volatile ("icbi 0, %0\n" :: "r" (addr + i)); |
} |
asm volatile ( |
"sync\n" |
"isync\n" |
); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ppc32/include/drivers/cuda.h |
---|
36,11 → 36,10 |
#define KERN_ppc32_CUDA_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
extern void cuda_init(devno_t devno, uintptr_t base, size_t size); |
extern int cuda_get_scancode(void); |
extern void cuda_grab(void); |
extern void cuda_release(void); |
#endif |
/branches/dd/kernel/arch/ppc32/Makefile.inc |
---|
33,7 → 33,7 |
BFD_ARCH = powerpc:common |
BFD = binary |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc |
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
41,44 → 41,22 |
DEFS += -D__32_BITS__ |
## Own configuration directives |
# |
CONFIG_FB = y |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with support for address space identifiers. |
# |
CONFIG_ASID = y |
CONFIG_ASID_FIFO = y |
## Compile with support for software integer division. |
# |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/debug/panic.s \ |
arch/$(ARCH)/src/fpu_context.S \ |
arch/$(ARCH)/src/boot/boot.S \ |
arch/$(ARCH)/src/ppc32.c \ |
arch/$(ARCH)/src/dummy.s \ |
arch/$(ARCH)/src/exception.S \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/cuda.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/drivers/pic.c |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/debug/panic.s \ |
arch/$(KARCH)/src/fpu_context.S \ |
arch/$(KARCH)/src/boot/boot.S \ |
arch/$(KARCH)/src/ppc32.c \ |
arch/$(KARCH)/src/dummy.s \ |
arch/$(KARCH)/src/exception.S \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/cuda.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/drivers/pic.c |
/branches/dd/kernel/arch/ppc32/src/exception.S |
---|
60,7 → 60,7 |
2: |
subi sp, sp, 160 |
subi sp, sp, 164 |
stw r0, 8(sp) |
stw r2, 12(sp) |
stw r3, 16(sp) |
109,11 → 109,14 |
mfxer r12 |
stw r12, 148(sp) |
mfsprg1 r12 |
mfdar r12 |
stw r12, 152(sp) |
mfsprg1 r12 |
stw r12, 156(sp) |
mfsprg2 r12 |
stw r12, 156(sp) |
stw r12, 160(sp) |
.endm |
.org 0x100 |
137,16 → 140,7 |
exc_data_storage: |
CONTEXT_STORE |
li r3, 2 |
mr r4, sp |
addi r4, r4, 8 |
bl pht_real_refill |
cmpwi r3, 0 |
bne iret_real |
li r3, 2 |
b jump_to_kernel |
b data_storage |
.org 0x400 |
.global exc_instruction_storage |
153,17 → 147,8 |
exc_instruction_storage: |
CONTEXT_STORE |
li r3, 3 |
mr r4, sp |
addi r4, r4, 8 |
bl pht_real_refill |
cmpwi r3, 0 |
bne iret_real |
b instruction_storage |
li r3, 3 |
b jump_to_kernel |
.org 0x500 |
.global exc_external |
exc_external: |
223,7 → 208,7 |
.org 0xc00 |
.global exc_syscall |
exc_syscall: |
CONTEXT_STORE |
CONTEXT_STORE |
b jump_to_kernel_syscall |
235,7 → 220,63 |
li r3, 12 |
b jump_to_kernel |
.org 0x1000 |
.global exc_itlb_miss |
exc_itlb_miss: |
CONTEXT_STORE |
b tlb_miss |
.org 0x1100 |
.global exc_dtlb_miss_load |
exc_dtlb_miss_load: |
CONTEXT_STORE |
b tlb_miss |
.org 0x1200 |
.global exc_dtlb_miss_store |
exc_dtlb_miss_store: |
CONTEXT_STORE |
b tlb_miss |
.org 0x4000 |
data_storage: |
li r3, 2 |
mr r4, sp |
addi r4, r4, 8 |
bl pht_refill_real |
cmpwi r3, 0 |
bne iret_real |
li r3, 2 |
b jump_to_kernel |
instruction_storage: |
li r3, 3 |
mr r4, sp |
addi r4, r4, 8 |
bl pht_refill_real |
cmpwi r3, 0 |
bne iret_real |
li r3, 3 |
b jump_to_kernel |
tlb_miss: |
li r3, 16 |
mfspr r4, tlbmiss |
mfspr r5, ptehi |
mfspr r6, ptelo |
mr r7, sp |
addi r7, r7, 20 |
bl tlb_refill_real |
b iret_real |
jump_to_kernel: |
lis r12, iret@ha |
addi r12, r12, iret@l |
272,7 → 313,6 |
rfi |
iret_real: |
lwz r0, 8(sp) |
lwz r2, 12(sp) |
lwz r3, 16(sp) |
322,7 → 362,7 |
lwz r12, 148(sp) |
mtxer r12 |
lwz r12, 152(sp) |
lwz sp, 156(sp) |
lwz r12, 156(sp) |
lwz sp, 160(sp) |
rfi |
/branches/dd/kernel/arch/ppc32/src/asm.S |
---|
65,6 → 65,10 |
# set stack |
mr sp, r4 |
# %r6 is defined to hold pcb_ptr - set it to 0 |
xor r6, r6, r6 |
# jump to userspace |
127,8 → 131,8 |
lwz r12, 148(sp) |
mtxer r12 |
lwz r12, 152(sp) |
lwz sp, 156(sp) |
lwz r12, 156(sp) |
lwz sp, 160(sp) |
rfi |
193,53 → 197,13 |
lwz r12, 148(sp) |
mtxer r12 |
lwz r12, 152(sp) |
lwz sp, 156(sp) |
lwz r12, 156(sp) |
lwz sp, 160(sp) |
rfi |
memsetb: |
rlwimi r5, r5, 8, 16, 23 |
rlwimi r5, r5, 16, 0, 15 |
addi r14, r3, -4 |
cmplwi 0, r4, 4 |
blt 7f |
stwu r5, 4(r14) |
beqlr |
andi. r15, r14, 3 |
add r4, r15, r4 |
subf r14, r15, r14 |
srwi r15, r4, 2 |
mtctr r15 |
bdz 6f |
1: |
stwu r5, 4(r14) |
bdnz 1b |
6: |
andi. r4, r4, 3 |
7: |
cmpwi 0, r4, 0 |
beqlr |
mtctr r4 |
addi r6, r6, 3 |
8: |
stbu r5, 1(r14) |
bdnz 8b |
blr |
b _memsetb |
memcpy: |
memcpy_from_uspace: |
308,4 → 272,6 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
b memcpy_from_uspace_failover_address |
# return zero, failure |
xor r3, r3, r3 |
blr |
/branches/dd/kernel/arch/ppc32/src/boot/boot.S |
---|
33,7 → 33,7 |
.global kernel_image_start |
kernel_image_start: |
# load temporal kernel stack |
lis sp, kernel_stack@ha |
52,7 → 52,7 |
beq bootinfo_end |
addis r3, r3, 0x8000 |
lis r31, bootinfo@ha |
addi r31, r31, bootinfo@l # r31 = bootinfo |
/branches/dd/kernel/arch/ppc32/src/ppc32.c |
---|
45,21 → 45,25 |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <arch/drivers/pic.h> |
#include <macros.h> |
#include <string.h> |
#define IRQ_COUNT 64 |
#define IRQ_COUNT 64 |
bootinfo_t bootinfo; |
/** Performs ppc32-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void) |
{ |
/* Setup usermode */ |
init.cnt = bootinfo.taskmap.count; |
uint32_t i; |
for (i = 0; i < bootinfo.taskmap.count; i++) { |
for (i = 0; i < min3(bootinfo.taskmap.count, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) { |
init.tasks[i].addr = PA2KA(bootinfo.taskmap.tasks[i].addr); |
init.tasks[i].size = bootinfo.taskmap.tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo.taskmap.tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
} |
} |
76,34 → 80,47 |
{ |
if (config.cpu_active == 1) { |
/* Initialize framebuffer */ |
unsigned int visual; |
switch (bootinfo.screen.bpp) { |
case 8: |
visual = VISUAL_INDIRECT_8; |
break; |
case 16: |
visual = VISUAL_RGB_5_5_5; |
break; |
case 24: |
visual = VISUAL_RGB_8_8_8; |
break; |
case 32: |
visual = VISUAL_RGB_0_8_8_8; |
break; |
default: |
panic("Unsupported bits per pixel"); |
if (bootinfo.screen.addr) { |
unsigned int visual; |
switch (bootinfo.screen.bpp) { |
case 8: |
visual = VISUAL_INDIRECT_8; |
break; |
case 16: |
visual = VISUAL_RGB_5_5_5; |
break; |
case 24: |
visual = VISUAL_RGB_8_8_8; |
break; |
case 32: |
visual = VISUAL_RGB_0_8_8_8; |
break; |
default: |
panic("Unsupported bits per pixel."); |
} |
fb_properties_t prop = { |
.addr = bootinfo.screen.addr, |
.offset = 0, |
.x = bootinfo.screen.width, |
.y = bootinfo.screen.height, |
.scan = bootinfo.screen.scanline, |
.visual = visual, |
}; |
fb_init(&prop); |
} |
fb_init(bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.scanline, visual); |
/* Initialize IRQ routing */ |
irq_init(IRQ_COUNT, IRQ_COUNT); |
/* Initialize PIC */ |
pic_init(bootinfo.keyboard.addr, PAGE_SIZE); |
/* Initialize I/O controller */ |
cuda_init(device_assign_devno(), bootinfo.keyboard.addr + 0x16000, 2 * PAGE_SIZE); |
if (bootinfo.macio.addr) { |
/* Initialize PIC */ |
pic_init(bootinfo.macio.addr, PAGE_SIZE); |
/* Initialize I/O controller */ |
cuda_init(device_assign_devno(), |
bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE); |
} |
/* Merge all zones to 1 big zone */ |
zone_merge_all(); |
128,11 → 145,13 |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg, (uintptr_t) kernel_uarg->uspace_stack + THREAD_STACK_SIZE - SP_DELTA, (uintptr_t) kernel_uarg->uspace_entry); |
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg, |
(uintptr_t) kernel_uarg->uspace_stack + |
THREAD_STACK_SIZE - SP_DELTA, |
(uintptr_t) kernel_uarg->uspace_entry); |
/* Unreachable */ |
for (;;) |
; |
while (true); |
} |
/** Acquire console back for kernel |
140,7 → 159,7 |
*/ |
void arch_grab_console(void) |
{ |
cuda_grab(); |
fb_redraw(); |
} |
/** Return console to userspace |
148,8 → 167,21 |
*/ |
void arch_release_console(void) |
{ |
cuda_release(); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ppc32/src/mm/tlb.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32mm |
/** @addtogroup ppc32mm |
* @{ |
*/ |
/** @file |
35,12 → 35,23 |
#include <mm/tlb.h> |
#include <arch/mm/tlb.h> |
#include <arch/interrupt.h> |
#include <interrupt.h> |
#include <mm/as.h> |
#include <arch.h> |
#include <print.h> |
#include <symtab.h> |
#include <macros.h> |
static unsigned int seed = 10; |
static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42; |
#define TLB_FLUSH \ |
"tlbie %0\n" \ |
"addi %0, %0, 0x1000\n" |
/** Try to find PTE for faulting address |
* |
* Try to find PTE for faulting address. |
47,22 → 58,25 |
* The as->lock must be held on entry to this function |
* if lock is true. |
* |
* @param as Address space. |
* @param lock Lock/unlock the address space. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* @return PTE on success, NULL otherwise. |
* @param as Address space. |
* @param lock Lock/unlock the address space. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code |
* will be stored. |
* @return PTE on success, NULL otherwise. |
* |
*/ |
static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
static pte_t * |
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, |
istate_t *istate, int *pfrc) |
{ |
/* |
* Check if the mapping exists in page tables. |
*/ |
pte_t *pte = page_mapping_find(as, badvaddr); |
if ((pte) && (pte->p)) { |
if ((pte) && (pte->present)) { |
/* |
* Mapping found in page tables. |
* Immediately succeed. |
77,27 → 91,26 |
*/ |
page_table_unlock(as, lock); |
switch (rc = as_page_fault(badvaddr, access, istate)) { |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
*/ |
page_table_lock(as, lock); |
pte = page_mapping_find(as, badvaddr); |
ASSERT((pte) && (pte->p)); |
*pfrc = 0; |
return pte; |
case AS_PF_DEFER: |
page_table_lock(as, lock); |
*pfrc = rc; |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
printf("Page fault.\n"); |
*pfrc = rc; |
return NULL; |
default: |
panic("unexpected rc (%d)\n", rc); |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
*/ |
page_table_lock(as, lock); |
pte = page_mapping_find(as, badvaddr); |
ASSERT((pte) && (pte->present)); |
*pfrc = 0; |
return pte; |
case AS_PF_DEFER: |
page_table_lock(as, lock); |
*pfrc = rc; |
return NULL; |
case AS_PF_FAULT: |
page_table_lock(as, lock); |
*pfrc = rc; |
return NULL; |
default: |
panic("Unexpected rc (%d).", rc); |
} |
} |
} |
108,17 → 121,21 |
char *symbol = ""; |
char *sym2 = ""; |
char *s = get_symtab_entry(istate->pc); |
if (s) |
symbol = s; |
s = get_symtab_entry(istate->lr); |
if (s) |
sym2 = s; |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
char *str = get_symtab_entry(istate->pc); |
if (str) |
symbol = str; |
str = get_symtab_entry(istate->lr); |
if (str) |
sym2 = str; |
fault_if_from_uspace(istate, |
"PHT Refill Exception on %p.", badvaddr); |
panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr, |
istate->pc, symbol, sym2); |
} |
static void pht_insert(const uintptr_t vaddr, const pfn_t pfn) |
static void pht_insert(const uintptr_t vaddr, const pte_t *pte) |
{ |
uint32_t page = (vaddr >> 12) & 0xffff; |
uint32_t api = (vaddr >> 22) & 0x3f; |
144,10 → 161,12 |
uint32_t i; |
bool found = false; |
/* Find unused or colliding |
PTE in PTEG */ |
/* Find colliding PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) { |
if ((phte[base + i].v) |
&& (phte[base + i].vsid == vsid) |
&& (phte[base + i].api == api) |
&& (phte[base + i].h == 0)) { |
found = true; |
break; |
} |
154,13 → 173,25 |
} |
if (!found) { |
/* Find unused PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if (!phte[base + i].v) { |
found = true; |
break; |
} |
} |
} |
if (!found) { |
/* Secondary hash (not) */ |
uint32_t base2 = (~hash & 0x3ff) << 3; |
/* Find unused or colliding |
PTE in PTEG */ |
/* Find colliding PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) { |
if ((phte[base2 + i].v) |
&& (phte[base2 + i].vsid == vsid) |
&& (phte[base2 + i].api == api) |
&& (phte[base2 + i].h == 1)) { |
found = true; |
base = base2; |
h = 1; |
169,9 → 200,19 |
} |
if (!found) { |
// TODO: A/C precedence groups |
i = page % 8; |
/* Find unused PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if (!phte[base2 + i].v) { |
found = true; |
base = base2; |
h = 1; |
break; |
} |
} |
} |
if (!found) |
i = RANDI(seed) % 8; |
} |
phte[base + i].v = 1; |
178,23 → 219,106 |
phte[base + i].vsid = vsid; |
phte[base + i].h = h; |
phte[base + i].api = api; |
phte[base + i].rpn = pfn; |
phte[base + i].rpn = pte->pfn; |
phte[base + i].r = 0; |
phte[base + i].c = 0; |
phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0); |
phte[base + i].pp = 2; // FIXME |
} |
static void pht_real_insert(const uintptr_t vaddr, const pfn_t pfn) |
/** Process Instruction/Data Storage Exception |
* |
* @param n Exception vector number. |
* @param istate Interrupted register context. |
* |
*/ |
void pht_refill(int n, istate_t *istate) |
{ |
uint32_t page = (vaddr >> 12) & 0xffff; |
uint32_t api = (vaddr >> 22) & 0x3f; |
uintptr_t badvaddr; |
pte_t *pte; |
int pfrc; |
as_t *as; |
bool lock; |
if (AS == NULL) { |
as = AS_KERNEL; |
lock = false; |
} else { |
as = AS; |
lock = true; |
} |
if (n == VECTOR_DATA_STORAGE) |
badvaddr = istate->dar; |
else |
badvaddr = istate->pc; |
page_table_lock(as, lock); |
pte = find_mapping_and_check(as, lock, badvaddr, |
PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(as, lock); |
return; |
default: |
panic("Unexpected pfrc (%d).", pfrc); |
} |
} |
pte->accessed = 1; /* Record access to PTE */ |
pht_insert(badvaddr, pte); |
page_table_unlock(as, lock); |
return; |
fail: |
page_table_unlock(as, lock); |
pht_refill_fail(badvaddr, istate); |
} |
/** Process Instruction/Data Storage Exception in Real Mode |
* |
* @param n Exception vector number. |
* @param istate Interrupted register context. |
* |
*/ |
bool pht_refill_real(int n, istate_t *istate) |
{ |
uintptr_t badvaddr; |
if (n == VECTOR_DATA_STORAGE) |
badvaddr = istate->dar; |
else |
badvaddr = istate->pc; |
uint32_t physmem; |
asm volatile ( |
"mfsprg3 %0\n" |
: "=r" (physmem) |
); |
if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem))) |
return false; |
uint32_t page = (badvaddr >> 12) & 0xffff; |
uint32_t api = (badvaddr >> 22) & 0x3f; |
uint32_t vsid; |
asm volatile ( |
"mfsrin %0, %1\n" |
: "=r" (vsid) |
: "r" (vaddr) |
: "r" (badvaddr) |
); |
uint32_t sdr1; |
202,7 → 326,7 |
"mfsdr1 %0\n" |
: "=r" (sdr1) |
); |
phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000); |
phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000); |
/* Primary hash (xor) */ |
uint32_t h = 0; |
211,10 → 335,12 |
uint32_t i; |
bool found = false; |
/* Find unused or colliding |
PTE in PTEG */ |
/* Find colliding PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) { |
if ((phte_real[base + i].v) |
&& (phte_real[base + i].vsid == vsid) |
&& (phte_real[base + i].api == api) |
&& (phte_real[base + i].h == 0)) { |
found = true; |
break; |
} |
221,13 → 347,25 |
} |
if (!found) { |
/* Find unused PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if (!phte_real[base + i].v) { |
found = true; |
break; |
} |
} |
} |
if (!found) { |
/* Secondary hash (not) */ |
uint32_t base2 = (~hash & 0x3ff) << 3; |
/* Find unused or colliding |
PTE in PTEG */ |
/* Find colliding PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) { |
if ((phte_real[base2 + i].v) |
&& (phte_real[base2 + i].vsid == vsid) |
&& (phte_real[base2 + i].api == api) |
&& (phte_real[base2 + i].h == 1)) { |
found = true; |
base = base2; |
h = 1; |
236,102 → 374,48 |
} |
if (!found) { |
// TODO: A/C precedence groups |
i = page % 8; |
/* Find unused PTE in PTEG */ |
for (i = 0; i < 8; i++) { |
if (!phte_real[base2 + i].v) { |
found = true; |
base = base2; |
h = 1; |
break; |
} |
} |
} |
} |
phte_physical[base + i].v = 1; |
phte_physical[base + i].vsid = vsid; |
phte_physical[base + i].h = h; |
phte_physical[base + i].api = api; |
phte_physical[base + i].rpn = pfn; |
phte_physical[base + i].r = 0; |
phte_physical[base + i].c = 0; |
phte_physical[base + i].pp = 2; // FIXME |
} |
/** Process Instruction/Data Storage Interrupt |
* |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* |
*/ |
void pht_refill(int n, istate_t *istate) |
{ |
uintptr_t badvaddr; |
pte_t *pte; |
int pfrc; |
as_t *as; |
bool lock; |
if (AS == NULL) { |
as = AS_KERNEL; |
lock = false; |
} else { |
as = AS; |
lock = true; |
} |
if (n == VECTOR_DATA_STORAGE) { |
asm volatile ( |
"mfdar %0\n" |
: "=r" (badvaddr) |
); |
} else |
badvaddr = istate->pc; |
page_table_lock(as, lock); |
pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(as, lock); |
return; |
default: |
panic("Unexpected pfrc (%d)\n", pfrc); |
if (!found) { |
/* Use secondary hash to avoid collisions |
with usual PHT refill handler. */ |
i = RANDI(seed_real) % 8; |
base = base2; |
h = 1; |
} |
} |
pte->a = 1; /* Record access to PTE */ |
pht_insert(badvaddr, pte->pfn); |
phte_real[base + i].v = 1; |
phte_real[base + i].vsid = vsid; |
phte_real[base + i].h = h; |
phte_real[base + i].api = api; |
phte_real[base + i].rpn = KA2PA(badvaddr) >> 12; |
phte_real[base + i].r = 0; |
phte_real[base + i].c = 0; |
phte_real[base + i].wimg = 0; |
phte_real[base + i].pp = 2; // FIXME |
page_table_unlock(as, lock); |
return; |
fail: |
page_table_unlock(as, lock); |
pht_refill_fail(badvaddr, istate); |
return true; |
} |
/** Process Instruction/Data Storage Interrupt in Real Mode |
/** Process ITLB/DTLB Miss Exception in Real Mode |
* |
* @param n Interrupt vector number. |
* @param istate Interrupted register context. |
* |
*/ |
bool pht_real_refill(int n, istate_t *istate) |
void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate) |
{ |
uintptr_t badvaddr; |
uint32_t badvaddr = tlbmiss & 0xfffffffc; |
if (n == VECTOR_DATA_STORAGE) { |
asm volatile ( |
"mfdar %0\n" |
: "=r" (badvaddr) |
); |
} else |
badvaddr = istate->pc; |
uint32_t physmem; |
asm volatile ( |
"mfsprg3 %0\n" |
338,12 → 422,23 |
: "=r" (physmem) |
); |
if ((badvaddr >= PA2KA(0)) && (badvaddr < PA2KA(physmem))) { |
pht_real_insert(badvaddr, KA2PA(badvaddr) >> 12); |
return true; |
} |
if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem))) |
return; // FIXME |
return false; |
ptelo.rpn = KA2PA(badvaddr) >> 12; |
ptelo.wimg = 0; |
ptelo.pp = 2; // FIXME |
uint32_t index = 0; |
asm volatile ( |
"mtspr 981, %0\n" |
"mtspr 982, %1\n" |
"tlbld %2\n" |
"tlbli %2\n" |
: "=r" (index) |
: "r" (ptehi), |
"r" (ptelo) |
); |
} |
355,9 → 450,87 |
void tlb_invalidate_all(void) |
{ |
uint32_t index; |
asm volatile ( |
"tlbia\n" |
"li %0, 0\n" |
"sync\n" |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
TLB_FLUSH |
"eieio\n" |
"tlbsync\n" |
"sync\n" |
: "=r" (index) |
); |
} |
373,7 → 546,8 |
uint32_t i; |
for (i = 0; i < 8192; i++) { |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16))) |
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && |
(phte[i].vsid < ((asid << 4) + 16))) |
phte[i].v = 0; |
} |
tlb_invalidate_all(); |
407,7 → 581,11 |
} \ |
} else \ |
length = 0; \ |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : ""); |
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \ |
sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \ |
lower & 0xffff0000, length, mask, \ |
((upper >> 1) & 1) ? " supervisor" : "", \ |
(upper & 1) ? " user" : ""); |
void tlb_print(void) |
421,7 → 599,10 |
: "=r" (vsid) |
: "r" (sr << 28) |
); |
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : ""); |
printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr, |
sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, |
((vsid >> 30) & 1) ? " supervisor" : "", |
((vsid >> 29) & 1) ? " user" : ""); |
} |
uint32_t upper; |
/branches/dd/kernel/arch/ppc32/src/mm/frame.c |
---|
74,7 → 74,7 |
if (last_frame < ALIGN_UP(bootinfo.memmap.zones[i].start + bootinfo.memmap.zones[i].size, FRAME_SIZE)) |
last_frame = ALIGN_UP(bootinfo.memmap.zones[i].start + bootinfo.memmap.zones[i].size, FRAME_SIZE); |
} |
/* First is exception vector, second is 'implementation specific', |
third and fourth is reserved, other contain real mode code */ |
frame_mark_unavailable(0, 8); |
/branches/dd/kernel/arch/ppc32/src/mm/page.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32mm |
/** @addtogroup ppc32mm |
* @{ |
*/ |
/** @file |
47,13 → 47,16 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > |
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%" PRIs " bytes).", |
physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), |
physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
/branches/dd/kernel/arch/ppc32/src/interrupt.c |
---|
73,7 → 73,7 |
ack = true; |
} |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* |
80,7 → 80,7 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum); |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
92,8 → 92,8 |
static void exception_decrementer(int n, istate_t *istate) |
{ |
start_decrementer(); |
clock(); |
start_decrementer(); |
} |
/branches/dd/kernel/arch/ppc32/src/drivers/pic.c |
---|
38,7 → 38,7 |
#include <byteorder.h> |
#include <bitops.h> |
static volatile uint32_t *pic; |
static volatile uint32_t *pic = NULL; |
void pic_init(uintptr_t base, size_t size) |
{ |
47,10 → 47,11 |
void pic_enable_interrupt(int intnum) |
{ |
if (intnum < 32) { |
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] | (1 << intnum); |
} else { |
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] | (1 << (intnum - 32)); |
if (pic) { |
if (intnum < 32) |
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] | (1 << intnum); |
else |
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] | (1 << (intnum - 32)); |
} |
} |
57,34 → 58,39 |
void pic_disable_interrupt(int intnum) |
{ |
if (intnum < 32) { |
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] & (~(1 << intnum)); |
} else { |
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] & (~(1 << (intnum - 32))); |
if (pic) { |
if (intnum < 32) |
pic[PIC_MASK_LOW] = pic[PIC_MASK_LOW] & (~(1 << intnum)); |
else |
pic[PIC_MASK_HIGH] = pic[PIC_MASK_HIGH] & (~(1 << (intnum - 32))); |
} |
} |
void pic_ack_interrupt(int intnum) |
{ |
if (intnum < 32) |
pic[PIC_ACK_LOW] = 1 << intnum; |
else |
pic[PIC_ACK_HIGH] = 1 << (intnum - 32); |
if (pic) { |
if (intnum < 32) |
pic[PIC_ACK_LOW] = 1 << intnum; |
else |
pic[PIC_ACK_HIGH] = 1 << (intnum - 32); |
} |
} |
/** Return number of pending interrupt */ |
int pic_get_pending(void) |
{ |
int pending; |
pending = pic[PIC_PENDING_LOW]; |
if (pending) |
return fnzb32(pending); |
if (pic) { |
int pending; |
pending = pic[PIC_PENDING_LOW]; |
if (pending) |
return fnzb32(pending); |
pending = pic[PIC_PENDING_HIGH]; |
if (pending) |
return fnzb32(pending) + 32; |
} |
pending = pic[PIC_PENDING_HIGH]; |
if (pending) |
return fnzb32(pending) + 32; |
return -1; |
} |
/branches/dd/kernel/arch/ppc32/src/drivers/cuda.c |
---|
33,7 → 33,6 |
*/ |
#include <arch/drivers/cuda.h> |
#include <ipc/irq.h> |
#include <arch/asm.h> |
#include <console/console.h> |
#include <console/chardev.h> |
236,64 → 235,38 |
int cuda_get_scancode(void) |
{ |
uint8_t kind; |
uint8_t data[4]; |
if (cuda) { |
uint8_t kind; |
uint8_t data[4]; |
receive_packet(&kind, 4, data); |
if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c)) |
return data[2]; |
} |
receive_packet(&kind, 4, data); |
if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c)) |
return data[2]; |
return -1; |
} |
static void cuda_irq_handler(irq_t *irq, void *arg, ...) |
static void cuda_irq_handler(irq_t *irq) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else { |
int scan_code = cuda_get_scancode(); |
int scan_code = cuda_get_scancode(); |
if (scan_code != -1) { |
uint8_t scancode = (uint8_t) scan_code; |
if ((scancode & 0x80) != 0x80) |
chardev_push_character(&kbrd, lchars[scancode & 0x7f]); |
} |
if (scan_code != -1) { |
uint8_t scancode = (uint8_t) scan_code; |
if ((scancode & 0x80) != 0x80) |
chardev_push_character(&kbrd, lchars[scancode & 0x7f]); |
} |
} |
static irq_ownership_t cuda_claim(void) |
static irq_ownership_t cuda_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
/** Initialize keyboard and service interrupts using kernel routine */ |
void cuda_grab(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&cuda_irq.lock); |
cuda_irq.notif_cfg.notify = false; |
spinlock_unlock(&cuda_irq.lock); |
interrupts_restore(ipl); |
} |
/** Resume the former interrupt vector */ |
void cuda_release(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&cuda_irq.lock); |
if (cuda_irq.notif_cfg.answerbox) |
cuda_irq.notif_cfg.notify = true; |
spinlock_unlock(&cuda_irq.unlock); |
interrupts_restore(ipl); |
} |
void cuda_init(devno_t devno, uintptr_t base, size_t size) |
{ |
cuda = (uint8_t *) hw_map(base, size); |
cuda = (uint8_t *) hw_map(base, size); |
chardev_initialize("cuda_kbd", &kbrd, &ops); |
stdin = &kbrd; |
306,7 → 279,7 |
irq_register(&cuda_irq); |
pic_enable_interrupt(CUDA_IRQ); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, CUDA_IRQ); |
345,7 → 318,9 |
} |
void arch_reboot(void) { |
send_packet(PACKET_CUDA, 1, CUDA_RESET); |
if (cuda) |
send_packet(PACKET_CUDA, 1, CUDA_RESET); |
asm volatile ( |
"b 0\n" |
); |
/branches/dd/kernel/arch/amd64/include/drivers/ega.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/amd64/include/drivers/vesa.h |
---|
File deleted |
/branches/dd/kernel/arch/amd64/include/drivers/i8259.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/amd64/include/drivers/i8042.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/amd64/include/drivers/i8254.h |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/kernel/arch/amd64/include/interrupt.h |
---|
71,7 → 71,6 |
/** This is passed to interrupt handlers */ |
typedef struct { |
uint64_t rax; |
uint64_t rbx; |
uint64_t rcx; |
uint64_t rdx; |
uint64_t rsi; |
80,11 → 79,6 |
uint64_t r9; |
uint64_t r10; |
uint64_t r11; |
uint64_t r12; |
uint64_t r13; |
uint64_t r14; |
uint64_t r15; |
uint64_t rbp; |
uint64_t error_word; |
uint64_t rip; |
uint64_t cs; |
/branches/dd/kernel/arch/amd64/include/types.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup amd64 |
/** @addtogroup amd64 |
* @{ |
*/ |
/** @file |
35,10 → 35,6 |
#ifndef KERN_amd64_TYPES_H_ |
#define KERN_amd64_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed int int32_t; |
61,14 → 57,34 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
/**< Formats for uintptr_t, size_t, count_t and index_t */ |
#define PRIp "llx" |
#define PRIs "llu" |
#define PRIc "llu" |
#define PRIi "llu" |
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */ |
#define PRId8 "d" |
#define PRId16 "d" |
#define PRId32 "d" |
#define PRId64 "lld" |
#define PRIdn "lld" |
#define PRIu8 "u" |
#define PRIu16 "u" |
#define PRIu32 "u" |
#define PRIu64 "llu" |
#define PRIun "llu" |
#define PRIx8 "x" |
#define PRIx16 "x" |
#define PRIx32 "x" |
#define PRIx64 "llx" |
#define PRIxn "llx" |
/** Page Table Entry. */ |
typedef struct { |
unsigned present : 1; |
/branches/dd/kernel/arch/amd64/include/memstr.h |
---|
35,110 → 35,13 |
#ifndef KERN_amd64_MEMSTR_H_ |
#define KERN_amd64_MEMSTR_H_ |
/** Copy memory |
* |
* Copy a given number of bytes (3rd argument) |
* from the memory location defined by 2nd argument |
* to the memory location defined by 1st argument. |
* The memory areas cannot overlap. |
* |
* @param dst Destination |
* @param src Source |
* @param cnt Number of bytes |
* @return Destination |
*/ |
static inline void * memcpy(void * dst, const void * src, size_t cnt) |
{ |
unative_t d0, d1, d2; |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
asm volatile( |
"rep movsq\n\t" |
"movq %4, %%rcx\n\t" |
"andq $7, %%rcx\n\t" |
"jz 1f\n\t" |
"rep movsb\n\t" |
"1:\n" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
: "0" ((unative_t)(cnt / 8)), "g" ((unative_t)cnt), "1" ((unative_t) dst), "2" ((unative_t) src) |
: "memory"); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
return dst; |
} |
extern int memcmp(const void *a, const void *b, size_t cnt); |
/** Compare memory regions for equality |
* |
* Compare a given number of bytes (3rd argument) |
* at memory locations defined by 1st and 2nd argument |
* for equality. If bytes are equal function returns 0. |
* |
* @param src Region 1 |
* @param dst Region 2 |
* @param cnt Number of bytes |
* @return Zero if bytes are equal, non-zero otherwise |
*/ |
static inline int memcmp(const void * src, const void * dst, size_t cnt) |
{ |
unative_t d0, d1, d2; |
unative_t ret; |
asm ( |
"repe cmpsb\n\t" |
"je 1f\n\t" |
"movq %3, %0\n\t" |
"addq $1, %0\n\t" |
"1:\n" |
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2) |
: "0" (0), "1" (src), "2" (dst), "3" ((unative_t)cnt) |
); |
return ret; |
} |
/** Fill memory with words |
* Fill a given number of words (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of words |
* @param x Value to fill |
*/ |
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
{ |
unative_t d0, d1; |
asm volatile ( |
"rep stosw\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" ((unative_t)cnt), "2" (x) |
: "memory" |
); |
} |
/** Fill memory with bytes |
* Fill a given number of bytes (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of bytes |
* @param x Value to fill |
*/ |
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
{ |
unative_t d0, d1; |
asm volatile ( |
"rep stosb\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" ((unative_t)cnt), "2" (x) |
: "memory" |
); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/amd64/include/syscall.h |
---|
35,8 → 35,6 |
#ifndef KERN_amd64_SYSCALL_H_ |
#define KERN_amd64_SYSCALL_H_ |
#include <arch/types.h> |
extern void syscall_setup_cpu(void); |
#endif |
/branches/dd/kernel/arch/amd64/include/atomic.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup amd64 |
/** @addtogroup amd64 |
* @{ |
*/ |
/** @file |
41,17 → 41,29 |
static inline void atomic_inc(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock incq %0\n" : "=m" (val->count)); |
asm volatile ( |
"lock incq %[count]\n" |
: [count] "+m" (val->count) |
); |
#else |
asm volatile ("incq %0\n" : "=m" (val->count)); |
asm volatile ( |
"incq %[count]\n" |
: [count] "+m" (val->count) |
); |
#endif /* CONFIG_SMP */ |
} |
static inline void atomic_dec(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock decq %0\n" : "=m" (val->count)); |
asm volatile ( |
"lock decq %[count]\n" |
: [count] "+m" (val->count) |
); |
#else |
asm volatile ("decq %0\n" : "=m" (val->count)); |
asm volatile ( |
"decq %[count]\n" |
: [count] "+m" (val->count) |
); |
#endif /* CONFIG_SMP */ |
} |
58,12 → 70,12 |
static inline long atomic_postinc(atomic_t *val) |
{ |
long r = 1; |
asm volatile ( |
"lock xaddq %1, %0\n" |
: "=m" (val->count), "+r" (r) |
"lock xaddq %[r], %[count]\n" |
: [count] "+m" (val->count), [r] "+r" (r) |
); |
return r; |
} |
72,23 → 84,23 |
long r = -1; |
asm volatile ( |
"lock xaddq %1, %0\n" |
: "=m" (val->count), "+r" (r) |
"lock xaddq %[r], %[count]\n" |
: [count] "+m" (val->count), [r] "+r" (r) |
); |
return r; |
} |
#define atomic_preinc(val) (atomic_postinc(val)+1) |
#define atomic_predec(val) (atomic_postdec(val)-1) |
#define atomic_preinc(val) (atomic_postinc(val) + 1) |
#define atomic_predec(val) (atomic_postdec(val) - 1) |
static inline uint64_t test_and_set(atomic_t *val) { |
uint64_t v; |
asm volatile ( |
"movq $1, %0\n" |
"xchgq %0, %1\n" |
: "=r" (v),"=m" (val->count) |
"movq $1, %[v]\n" |
"xchgq %[v], %[count]\n" |
: [v] "=r" (v), [count] "+m" (val->count) |
); |
return v; |
99,23 → 111,23 |
static inline void atomic_lock_arch(atomic_t *val) |
{ |
uint64_t tmp; |
preemption_disable(); |
asm volatile ( |
"0:;" |
"0:\n" |
#ifdef CONFIG_HT |
"pause;" |
"pause\n" |
#endif |
"mov %0, %1;" |
"testq %1, %1;" |
"jnz 0b;" /* Lightweight looping on locked spinlock */ |
"mov %[count], %[tmp]\n" |
"testq %[tmp], %[tmp]\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
"incq %1;" /* now use the atomic operation */ |
"xchgq %0, %1;" |
"testq %1, %1;" |
"jnz 0b;" |
: "=m"(val->count),"=r"(tmp) |
); |
"incq %[tmp]\n" /* now use the atomic operation */ |
"xchgq %[count], %[tmp]\n" |
"testq %[tmp], %[tmp]\n" |
"jnz 0b\n" |
: [count] "+m" (val->count), [tmp] "=&r" (tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
*/ |
/branches/dd/kernel/arch/amd64/include/boot/boot.h |
---|
42,8 → 42,17 |
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 |
#define MULTIBOOT_HEADER_FLAGS 0x00010003 |
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002 |
#ifndef __ASM__ |
#ifdef CONFIG_SMP |
/* This is only a symbol so the type is dummy. Obtain the value using &. */ |
extern int _hardcoded_unmapped_size; |
#endif /* CONFIG_SMP */ |
#endif /* __ASM__ */ |
#endif |
/** @} |
/branches/dd/kernel/arch/amd64/include/arch.h |
---|
35,6 → 35,10 |
#ifndef KERN_amd64_ARCH_H_ |
#define KERN_amd64_ARCH_H_ |
#include <genarch/multiboot/multiboot.h> |
extern void arch_pre_main(uint32_t, const multiboot_info_t *); |
#endif |
/** @} |
/branches/dd/kernel/arch/amd64/include/asm.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup amd64 |
/** @addtogroup amd64 |
* @{ |
*/ |
/** @file |
36,6 → 36,8 |
#define KERN_amd64_ASM_H_ |
#include <config.h> |
#include <arch/types.h> |
#include <typedefs.h> |
extern void asm_delay_loop(uint32_t t); |
extern void asm_fake_loop(uint32_t t); |
45,12 → 47,17 |
* Return the base address of the current stack. |
* The stack is assumed to be STACK_SIZE bytes long. |
* The stack must start on page boundary. |
* |
*/ |
static inline uintptr_t get_stack_base(void) |
{ |
uintptr_t v; |
asm volatile ("andq %%rsp, %0\n" : "=r" (v) : "0" (~((uint64_t)STACK_SIZE-1))); |
asm volatile ( |
"andq %%rsp, %[v]\n" |
: [v] "=r" (v) |
: "0" (~((uint64_t) STACK_SIZE-1)) |
); |
return v; |
} |
72,15 → 79,63 |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint8_t inb(uint16_t port) |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uint8_t val; |
asm volatile ( |
"inb %w[port], %b[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port)); |
/** Word from port |
* |
* Get word from port |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uint16_t val; |
asm volatile ( |
"inw %w[port], %w[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
/** Double word from port |
* |
* Get double word from port |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uint32_t val; |
asm volatile ( |
"inl %w[port], %[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
/** Byte to port |
* |
* Output byte to port |
87,12 → 142,48 |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void outb(uint16_t port, uint8_t val) |
static inline void pio_write_8(ioport8_t *port, uint8_t val) |
{ |
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port)); |
asm volatile ( |
"outb %b[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Word to port |
* |
* Output word to port |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void pio_write_16(ioport16_t *port, uint16_t val) |
{ |
asm volatile ( |
"outw %w[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Double word to port |
* |
* Output double word to port |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void pio_write_32(ioport32_t *port, uint32_t val) |
{ |
asm volatile ( |
"outl %[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Swap Hidden part of GS register with visible one */ |
static inline void swapgs(void) |
{ |
105,15 → 196,18 |
* value of EFLAGS. |
* |
* @return Old interrupt priority level. |
* |
*/ |
static inline ipl_t interrupts_enable(void) { |
ipl_t v; |
__asm__ volatile ( |
asm volatile ( |
"pushfq\n" |
"popq %0\n" |
"popq %[v]\n" |
"sti\n" |
: "=r" (v) |
: [v] "=r" (v) |
); |
return v; |
} |
123,15 → 217,18 |
* value of EFLAGS. |
* |
* @return Old interrupt priority level. |
* |
*/ |
static inline ipl_t interrupts_disable(void) { |
ipl_t v; |
__asm__ volatile ( |
asm volatile ( |
"pushfq\n" |
"popq %0\n" |
"popq %[v]\n" |
"cli\n" |
: "=r" (v) |
); |
: [v] "=r" (v) |
); |
return v; |
} |
140,13 → 237,14 |
* Restore EFLAGS. |
* |
* @param ipl Saved interrupt priority level. |
* |
*/ |
static inline void interrupts_restore(ipl_t ipl) { |
__asm__ volatile ( |
"pushq %0\n" |
asm volatile ( |
"pushq %[ipl]\n" |
"popfq\n" |
: : "r" (ipl) |
); |
:: [ipl] "r" (ipl) |
); |
} |
/** Return interrupt priority level. |
154,14 → 252,17 |
* Return EFLAFS. |
* |
* @return Current interrupt priority level. |
* |
*/ |
static inline ipl_t interrupts_read(void) { |
ipl_t v; |
__asm__ volatile ( |
asm volatile ( |
"pushfq\n" |
"popq %0\n" |
: "=r" (v) |
"popq %[v]\n" |
: [v] "=r" (v) |
); |
return v; |
} |
168,21 → 269,25 |
/** Write to MSR */ |
static inline void write_msr(uint32_t msr, uint64_t value) |
{ |
__asm__ volatile ( |
"wrmsr;" : : "c" (msr), |
"a" ((uint32_t)(value)), |
"d" ((uint32_t)(value >> 32)) |
); |
asm volatile ( |
"wrmsr\n" |
:: "c" (msr), |
"a" ((uint32_t) (value)), |
"d" ((uint32_t) (value >> 32)) |
); |
} |
static inline unative_t read_msr(uint32_t msr) |
{ |
uint32_t ax, dx; |
__asm__ volatile ( |
"rdmsr;" : "=a"(ax), "=d"(dx) : "c" (msr) |
); |
return ((uint64_t)dx << 32) | ax; |
asm volatile ( |
"rdmsr\n" |
: "=a" (ax), "=d" (dx) |
: "c" (msr) |
); |
return ((uint64_t) dx << 32) | ax; |
} |
189,29 → 294,29 |
/** Enable local APIC |
* |
* Enable local APIC in MSR. |
* |
*/ |
static inline void enable_l_apic_in_msr() |
{ |
__asm__ volatile ( |
asm volatile ( |
"movl $0x1b, %%ecx\n" |
"rdmsr\n" |
"orl $(1<<11),%%eax\n" |
"orl $(1 << 11),%%eax\n" |
"orl $(0xfee00000),%%eax\n" |
"wrmsr\n" |
: |
: |
:"%eax","%ecx","%edx" |
); |
::: "%eax","%ecx","%edx" |
); |
} |
static inline uintptr_t * get_ip() |
{ |
uintptr_t *ip; |
__asm__ volatile ( |
"mov %%rip, %0" |
: "=r" (ip) |
); |
asm volatile ( |
"mov %%rip, %[ip]" |
: [ip] "=r" (ip) |
); |
return ip; |
} |
218,59 → 323,84 |
/** Invalidate TLB Entry. |
* |
* @param addr Address on a page whose TLB entry is to be invalidated. |
* |
*/ |
static inline void invlpg(uintptr_t addr) |
{ |
__asm__ volatile ("invlpg %0\n" :: "m" (*((unative_t *)addr))); |
asm volatile ( |
"invlpg %[addr]\n" |
:: [addr] "m" (*((unative_t *) addr)) |
); |
} |
/** Load GDTR register from memory. |
* |
* @param gdtr_reg Address of memory from where to load GDTR. |
* |
*/ |
static inline void gdtr_load(struct ptr_16_64 *gdtr_reg) |
{ |
__asm__ volatile ("lgdtq %0\n" : : "m" (*gdtr_reg)); |
asm volatile ( |
"lgdtq %[gdtr_reg]\n" |
:: [gdtr_reg] "m" (*gdtr_reg) |
); |
} |
/** Store GDTR register to memory. |
* |
* @param gdtr_reg Address of memory to where to load GDTR. |
* |
*/ |
static inline void gdtr_store(struct ptr_16_64 *gdtr_reg) |
{ |
__asm__ volatile ("sgdtq %0\n" : : "m" (*gdtr_reg)); |
asm volatile ( |
"sgdtq %[gdtr_reg]\n" |
:: [gdtr_reg] "m" (*gdtr_reg) |
); |
} |
/** Load IDTR register from memory. |
* |
* @param idtr_reg Address of memory from where to load IDTR. |
* |
*/ |
static inline void idtr_load(struct ptr_16_64 *idtr_reg) |
{ |
__asm__ volatile ("lidtq %0\n" : : "m" (*idtr_reg)); |
asm volatile ( |
"lidtq %[idtr_reg]\n" |
:: [idtr_reg] "m" (*idtr_reg)); |
} |
/** Load TR from descriptor table. |
* |
* @param sel Selector specifying descriptor of TSS segment. |
* |
*/ |
static inline void tr_load(uint16_t sel) |
{ |
__asm__ volatile ("ltr %0" : : "r" (sel)); |
asm volatile ( |
"ltr %[sel]" |
:: [sel] "r" (sel) |
); |
} |
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \ |
{ \ |
unative_t res; \ |
__asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \ |
return res; \ |
} |
{ \ |
unative_t res; \ |
asm volatile ( \ |
"movq %%" #reg ", %[res]" \ |
: [res] "=r" (res) \ |
); \ |
return res; \ |
} |
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \ |
{ \ |
__asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \ |
} |
{ \ |
asm volatile ( \ |
"movq %[regn], %%" #reg \ |
:: [regn] "r" (regn) \ |
); \ |
} |
GEN_READ_REG(cr0) |
GEN_READ_REG(cr2) |
/branches/dd/kernel/arch/amd64/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup amd64mm |
/** @addtogroup amd64mm |
* @{ |
*/ |
/** @file |
39,8 → 39,8 |
#include <arch/types.h> |
#endif /* __ASM__ */ |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifndef __ASM__ |
extern uintptr_t last_frame; |
/branches/dd/kernel/arch/amd64/include/mm/page.h |
---|
52,8 → 52,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/dd/kernel/arch/amd64/include/mm/tlb.h |
---|
35,9 → 35,6 |
#ifndef KERN_amd64_TLB_H_ |
#define KERN_amd64_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/dd/kernel/arch/amd64/Makefile.inc |
---|
33,90 → 33,58 |
BFD_ARCH = i386:x86-64 |
BFD = binary |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/amd64 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64 |
FPU_NO_CFLAGS = -mno-sse -mno-sse2 |
CMN1 = -m64 -mcmodel=kernel -mno-red-zone -fno-unwind-tables |
GCC_CFLAGS += $(CMN1) |
ICC_CFLAGS += $(CMN1) |
SUNCC_CFLAGS += -m64 -xmodel=kernel |
DEFS += -DMACHINE=$(MACHINE) -D__64_BITS__ |
DEFS += -D__64_BITS__ |
## Accepted CPUs |
# |
ifeq ($(MACHINE),opteron) |
ifeq ($(PROCESSOR),opteron) |
CMN2 := -march=opteron |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += -xtarget=opteron |
DEFS += -DFENCES=p4 |
endif |
## Own configuration directives |
# |
CONFIG_ACPI = y |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with i8042 support. |
# |
CONFIG_I8042 = y |
DEFS += -DCONFIG_I8042 |
## Accepted configuration directives |
# |
ifeq ($(CONFIG_SMP),y) |
DEFS += -DCONFIG_SMP |
endif |
ifeq ($(CONFIG_HT),y) |
DEFS += -DCONFIG_HT |
endif |
ifeq ($(CONFIG_SIMICS_FIX),y) |
DEFS += -DCONFIG_SIMICS_FIX |
endif |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/boot/boot.S \ |
arch/$(ARCH)/src/boot/memmap.c \ |
arch/$(ARCH)/src/pm.c \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/ega.c \ |
arch/$(ARCH)/src/drivers/vesa.c \ |
arch/$(ARCH)/src/drivers/i8254.c \ |
arch/$(ARCH)/src/drivers/i8259.c \ |
arch/$(ARCH)/src/delay.S \ |
arch/$(ARCH)/src/amd64.c \ |
arch/$(ARCH)/src/bios/bios.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/asm_utils.S \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/proc/task.c \ |
arch/$(ARCH)/src/proc/thread.c \ |
arch/$(ARCH)/src/userspace.c \ |
arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/debugger.c |
arch/$(KARCH)/src/fpu_context.c \ |
arch/$(KARCH)/src/boot/boot.S \ |
arch/$(KARCH)/src/boot/memmap.c \ |
arch/$(KARCH)/src/pm.c \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/vesa.c \ |
arch/$(KARCH)/src/drivers/i8254.c \ |
arch/$(KARCH)/src/drivers/i8259.c \ |
arch/$(KARCH)/src/delay.S \ |
arch/$(KARCH)/src/amd64.c \ |
arch/$(KARCH)/src/bios/bios.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/asm_utils.S \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/proc/task.c \ |
arch/$(KARCH)/src/proc/thread.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/syscall.c \ |
arch/$(KARCH)/src/debugger.c |
ifeq ($(CONFIG_SMP),y) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/smp/ap.S \ |
arch/$(ARCH)/src/smp/apic.c \ |
arch/$(ARCH)/src/smp/ipi.c \ |
arch/$(ARCH)/src/smp/mps.c \ |
arch/$(ARCH)/src/smp/smp.c |
arch/$(KARCH)/src/smp/ap.S \ |
arch/$(KARCH)/src/smp/apic.c \ |
arch/$(KARCH)/src/smp/ipi.c \ |
arch/$(KARCH)/src/smp/mps.c \ |
arch/$(KARCH)/src/smp/smp.c |
endif |
/branches/dd/kernel/arch/amd64/src/fpu_context.c |
---|
39,9 → 39,9 |
void fpu_context_save(fpu_context_t *fctx) |
{ |
asm volatile ( |
"fxsave %0" |
: "=m"(*fctx) |
); |
"fxsave %[fctx]\n" |
: [fctx] "=m" (*fctx) |
); |
} |
/** Restore FPU (mmx,sse) context using fxrstor instruction */ |
48,9 → 48,9 |
void fpu_context_restore(fpu_context_t *fctx) |
{ |
asm volatile ( |
"fxrstor %0" |
: "=m"(*fctx) |
); |
"fxrstor %[fctx]\n" |
: [fctx] "=m" (*fctx) |
); |
} |
void fpu_init() |
57,7 → 57,7 |
{ |
/* TODO: Zero all SSE, MMX etc. registers */ |
asm volatile ( |
"fninit;" |
"fninit\n" |
); |
} |
/branches/dd/kernel/arch/amd64/src/cpu/cpu.c |
---|
77,21 → 77,19 |
void cpu_setup_fpu(void) |
{ |
asm volatile ( |
"movq %%cr0, %%rax;" |
"btsq $1, %%rax;" /* cr0.mp */ |
"btrq $2, %%rax;" /* cr0.em */ |
"movq %%rax, %%cr0;" |
"movq %%cr4, %%rax;" |
"bts $9, %%rax;" /* cr4.osfxsr */ |
"movq %%rax, %%cr4;" |
: |
: |
:"%rax" |
); |
"movq %%cr0, %%rax\n" |
"btsq $1, %%rax\n" /* cr0.mp */ |
"btrq $2, %%rax\n" /* cr0.em */ |
"movq %%rax, %%cr0\n" |
"movq %%cr4, %%rax\n" |
"bts $9, %%rax\n" /* cr4.osfxsr */ |
"movq %%rax, %%cr4\n" |
::: "%rax" |
); |
} |
/** Set the TS flag to 1. |
/** Set the TS flag to 1. |
* |
* If a thread accesses coprocessor, exception is run, which |
* does a lazy fpu context switch. |
99,26 → 97,22 |
*/ |
void fpu_disable(void) |
{ |
asm volatile ( |
"mov %%cr0,%%rax;" |
"bts $3,%%rax;" |
"mov %%rax,%%cr0;" |
: |
: |
:"%rax" |
); |
asm volatile ( |
"mov %%cr0, %%rax\n" |
"bts $3, %%rax\n" |
"mov %%rax, %%cr0\n" |
::: "%rax" |
); |
} |
void fpu_enable(void) |
{ |
asm volatile ( |
"mov %%cr0,%%rax;" |
"btr $3,%%rax;" |
"mov %%rax,%%cr0;" |
: |
: |
:"%rax" |
); |
asm volatile ( |
"mov %%cr0, %%rax\n" |
"btr $3, %%rax\n" |
"mov %%rax, %%cr0\n" |
::: "%rax" |
); |
} |
void cpu_arch_init(void) |
/branches/dd/kernel/arch/amd64/src/amd64.c |
---|
39,11 → 39,15 |
#include <config.h> |
#include <proc/thread.h> |
#include <arch/drivers/ega.h> |
#include <genarch/multiboot/multiboot.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <genarch/drivers/ega/ega.h> |
#include <arch/drivers/vesa.h> |
#include <genarch/kbd/i8042.h> |
#include <genarch/drivers/i8042/i8042.h> |
#include <genarch/kbrd/kbrd.h> |
#include <arch/drivers/i8254.h> |
#include <arch/drivers/i8259.h> |
#include <arch/boot/boot.h> |
#ifdef CONFIG_SMP |
#include <arch/smp/apic.h> |
62,8 → 66,8 |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <sysinfo/sysinfo.h> |
/** Disable I/O on non-privileged levels |
* |
* Clean IOPL(12,13) and NT(14) flags in EFLAGS register |
70,15 → 74,13 |
*/ |
static void clean_IOPL_NT_flags(void) |
{ |
asm ( |
asm volatile ( |
"pushfq\n" |
"pop %%rax\n" |
"and $~(0x7000), %%rax\n" |
"pushq %%rax\n" |
"popfq\n" |
: |
: |
: "%rax" |
::: "%rax" |
); |
} |
88,16 → 90,31 |
*/ |
static void clean_AM_flag(void) |
{ |
asm ( |
asm volatile ( |
"mov %%cr0, %%rax\n" |
"and $~(0x40000), %%rax\n" |
"mov %%rax, %%cr0\n" |
: |
: |
: "%rax" |
::: "%rax" |
); |
} |
/** Perform amd64-specific initialization before main_bsp() is called. |
* |
* @param signature Should contain the multiboot signature. |
* @param mi Pointer to the multiboot information structure. |
*/ |
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi) |
{ |
/* Parse multiboot information obtained from the bootloader. */ |
multiboot_info_parse(signature, mi); |
#ifdef CONFIG_SMP |
/* Copy AP bootstrap routines below 1 MB. */ |
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, |
(size_t) &_hardcoded_unmapped_size); |
#endif |
} |
void arch_pre_mm_init(void) |
{ |
/* Enable no-execute pages */ |
139,7 → 156,7 |
vesa_init(); |
else |
#endif |
ega_init(); /* video */ |
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */ |
/* Enable debugger */ |
debugger_init(); |
172,8 → 189,28 |
void arch_post_smp_init(void) |
{ |
/* keyboard controller */ |
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE); |
devno_t devno = device_assign_devno(); |
/* |
* Initialize the keyboard module and conect it to stdin. Then |
* initialize the i8042 controller and connect it to kbrdin. Enable |
* keyboard interrupts. |
*/ |
kbrd_init(stdin); |
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD, &kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
/* |
* This is the necessary evil until the userspace driver is entirely |
* self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
sysinfo_set_item_val("kbd.address.physical", NULL, |
(uintptr_t) I8042_BASE); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) I8042_BASE); |
} |
void calibrate_delay_loop(void) |
208,15 → 245,33 |
*/ |
void arch_grab_console(void) |
{ |
i8042_grab(); |
#ifdef CONFIG_FB |
vesa_redraw(); |
#else |
ega_redraw(); |
#endif |
} |
/** Return console to userspace |
* |
*/ |
void arch_release_console(void) |
{ |
i8042_release(); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/amd64/src/pm.c |
---|
155,7 → 155,7 |
void tss_initialize(tss_t *t) |
{ |
memsetb((uintptr_t) t, sizeof(tss_t), 0); |
memsetb(t, sizeof(tss_t), 0); |
} |
/* |
209,7 → 209,7 |
tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC); |
if (!tss_p) |
panic("could not allocate TSS\n"); |
panic("Cannot allocate TSS."); |
} |
tss_initialize(tss_p); |
239,7 → 239,7 |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
memsetb(idt, sizeof(idt), 0); |
idtr_load(&idtr); |
interrupts_restore(ipl); |
/branches/dd/kernel/arch/amd64/src/asm_utils.S |
---|
26,23 → 26,17 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#define IREGISTER_SPACE 120 |
#define IREGISTER_SPACE 72 |
#define IOFFSET_RAX 0x0 |
#define IOFFSET_RBX 0x8 |
#define IOFFSET_RCX 0x10 |
#define IOFFSET_RDX 0x18 |
#define IOFFSET_RSI 0x20 |
#define IOFFSET_RDI 0x28 |
#define IOFFSET_R8 0x30 |
#define IOFFSET_R9 0x38 |
#define IOFFSET_R10 0x40 |
#define IOFFSET_R11 0x48 |
#define IOFFSET_R12 0x50 |
#define IOFFSET_R13 0x58 |
#define IOFFSET_R14 0x60 |
#define IOFFSET_R15 0x68 |
#define IOFFSET_RBP 0x70 |
#define IOFFSET_RAX 0x0 |
#define IOFFSET_RCX 0x8 |
#define IOFFSET_RDX 0x10 |
#define IOFFSET_RSI 0x18 |
#define IOFFSET_RDI 0x20 |
#define IOFFSET_R8 0x28 |
#define IOFFSET_R9 0x30 |
#define IOFFSET_R10 0x38 |
#define IOFFSET_R11 0x40 |
# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word |
# and 1 means interrupt with error word |
65,6 → 59,8 |
.global get_cycle |
.global read_efer_flag |
.global set_efer_flag |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
71,6 → 67,14 |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
# Wrapper for generic memsetb |
memsetb: |
jmp _memsetb |
# Wrapper for generic memsetw |
memsetw: |
jmp _memsetw |
#define MEMCPY_DST %rdi |
#define MEMCPY_SRC %rsi |
#define MEMCPY_SIZE %rdx |
88,12 → 92,12 |
* @param MEMCPY_SRC Source address. |
* @param MEMCPY_SIZE Number of bytes to copy. |
* |
* @retrun MEMCPY_SRC on success, 0 on failure. |
* @retrun MEMCPY_DST on success, 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
movq MEMCPY_SRC, %rax |
movq MEMCPY_DST, %rax |
movq MEMCPY_SIZE, %rcx |
shrq $3, %rcx /* size / 8 */ |
163,7 → 167,7 |
rdmsr |
ret |
# Push all general purpose registers on stack except %rbp, %rsp |
# Push all volatile general purpose registers on stack |
.macro save_all_gpr |
movq %rax, IOFFSET_RAX(%rsp) |
movq %rcx, IOFFSET_RCX(%rsp) |
174,14 → 178,6 |
movq %r9, IOFFSET_R9(%rsp) |
movq %r10, IOFFSET_R10(%rsp) |
movq %r11, IOFFSET_R11(%rsp) |
#ifdef CONFIG_DEBUG_ALLREGS |
movq %rbx, IOFFSET_RBX(%rsp) |
movq %rbp, IOFFSET_RBP(%rsp) |
movq %r12, IOFFSET_R12(%rsp) |
movq %r13, IOFFSET_R13(%rsp) |
movq %r14, IOFFSET_R14(%rsp) |
movq %r15, IOFFSET_R15(%rsp) |
#endif |
.endm |
.macro restore_all_gpr |
194,21 → 190,9 |
movq IOFFSET_R9(%rsp), %r9 |
movq IOFFSET_R10(%rsp), %r10 |
movq IOFFSET_R11(%rsp), %r11 |
#ifdef CONFIG_DEBUG_ALLREGS |
movq IOFFSET_RBX(%rsp), %rbx |
movq IOFFSET_RBP(%rsp), %rbp |
movq IOFFSET_R12(%rsp), %r12 |
movq IOFFSET_R13(%rsp), %r13 |
movq IOFFSET_R14(%rsp), %r14 |
movq IOFFSET_R15(%rsp), %r15 |
#endif |
.endm |
#ifdef CONFIG_DEBUG_ALLREGS |
# define INTERRUPT_ALIGN 256 |
#else |
# define INTERRUPT_ALIGN 128 |
#endif |
#define INTERRUPT_ALIGN 128 |
## Declare interrupt handlers |
# |
/branches/dd/kernel/arch/amd64/src/proc/scheduler.c |
---|
39,7 → 39,6 |
#include <arch.h> |
#include <arch/context.h> /* SP_DELTA */ |
#include <arch/asm.h> |
#include <arch/debugger.h> |
#include <print.h> |
#include <arch/pm.h> |
#include <arch/ddi/ddi.h> |
68,13 → 67,6 |
/* TLS support - set FS to thread local storage */ |
write_msr(AMD_MSR_FS, THREAD->arch.tls); |
#ifdef CONFIG_DEBUG_AS_WATCHPOINT |
/* Set watchpoint on AS to ensure that nobody sets it to zero */ |
if (CPU->id < BKPOINTS_MAX) |
breakpoint_add(&((the_t *) THREAD->kstack)->as, |
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, CPU->id); |
#endif |
} |
void after_thread_ran_arch(void) |
/branches/dd/kernel/arch/amd64/src/proc/thread.c |
---|
46,7 → 46,7 |
* Kernel RSP can be precalculated at thread creation time. |
*/ |
t->arch.syscall_rsp[SYSCALL_KSTACK_RSP] = |
(uintptr_t)&t->kstack[PAGE_SIZE - sizeof(uint64_t)]; |
(uintptr_t) &t->kstack[PAGE_SIZE - sizeof(uint64_t)]; |
} |
/** @} |
/branches/dd/kernel/arch/amd64/src/boot/boot.S |
---|
1,4 → 1,4 |
# |
# Copyright (c) 2005 Ondrej Palkovsky |
# Copyright (c) 2006 Martin Decky |
# Copyright (c) 2008 Jakub Jermar |
175,119 → 175,18 |
.code64 |
start64: |
movq $(PA2KA(START_STACK)), %rsp |
movl grub_eax, %eax |
movl grub_ebx, %ebx |
# arch_pre_main(grub_eax, grub_ebx) |
xorq %rdi, %rdi |
movl grub_eax, %edi |
xorq %rsi, %rsi |
movl grub_ebx, %esi |
call arch_pre_main |
call main_bsp |
# Not reached. |
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature |
je valid_boot |
xorl %ecx, %ecx # no memory size or map available |
movl %ecx, e820counter |
jmp invalid_boot |
valid_boot: |
movl (%ebx), %eax # ebx = physical address of struct multiboot_info |
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid) |
jc mods_valid |
xorq %rcx, %rcx |
movq %rcx, init |
jmp mods_end |
mods_valid: |
xorq %rcx, %rcx |
movl 20(%ebx), %ecx # mbi->mods_count |
movq %rcx, init |
cmpl $0, %ecx |
je mods_end |
movl 24(%ebx), %esi # mbi->mods_addr |
movq $init, %rdi |
mods_loop: |
xorq %rdx, %rdx |
movl 0(%esi), %edx # mods->mod_start |
movq $0xffff800000000000, %r10 |
addq %r10, %rdx |
movq %rdx, 8(%rdi) |
xorq %rdx, %rdx |
movl 4(%esi), %edx |
subl 0(%esi), %edx # mods->mod_end - mods->mod_start |
movq %rdx, 16(%rdi) |
addl $16, %esi |
addq $16, %rdi |
loop mods_loop |
mods_end: |
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid) |
jc mmap_valid |
xorl %edx, %edx |
jmp mmap_invalid |
mmap_valid: |
movl 44(%ebx), %ecx # mbi->mmap_length |
movl 48(%ebx), %esi # mbi->mmap_addr |
movq $e820table, %rdi |
xorl %edx, %edx |
mmap_loop: |
cmpl $0, %ecx |
jle mmap_end |
movl 4(%esi), %eax # mmap->base_addr_low |
movl %eax, (%rdi) |
movl 8(%esi), %eax # mmap->base_addr_high |
movl %eax, 4(%rdi) |
movl 12(%esi), %eax # mmap->length_low |
movl %eax, 8(%rdi) |
movl 16(%esi), %eax # mmap->length_high |
movl %eax, 12(%rdi) |
movl 20(%esi), %eax # mmap->type |
movl %eax, 16(%rdi) |
movl (%esi), %eax # mmap->size |
addl $0x4, %eax |
addl %eax, %esi |
subl %eax, %ecx |
addq $MEMMAP_E820_RECORD_SIZE, %rdi |
incl %edx |
jmp mmap_loop |
mmap_end: |
mmap_invalid: |
movl %edx, e820counter |
invalid_boot: |
#ifdef CONFIG_SMP |
# copy AP bootstrap routines below 1 MB |
movq $BOOT_OFFSET, %rsi |
movq $AP_BOOT_OFFSET, %rdi |
movq $_hardcoded_unmapped_size, %rcx |
rep movsb |
#endif |
call main_bsp # never returns |
cli |
hlt |
427,7 → 326,8 |
xor %dx, %dx |
int $0x10 |
jmp vga_not_compat |
cmp $0x00, %ah |
je vga_not_compat |
vga_compat: |
/branches/dd/kernel/arch/amd64/src/debugger.c |
---|
54,6 → 54,8 |
static bpinfo_t breakpoints[BKPOINTS_MAX]; |
SPINLOCK_INITIALIZE(bkpoint_lock); |
#ifdef CONFIG_KCONSOLE |
static int cmd_print_breakpoints(cmd_arg_t *argv); |
static cmd_info_t bkpts_info = { |
.name = "bkpts", |
62,8 → 64,6 |
.argc = 0, |
}; |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
static int cmd_del_breakpoint(cmd_arg_t *argv); |
static cmd_arg_t del_argv = { |
.type = ARG_TYPE_INT |
99,36 → 99,8 |
.argv = &addw_argv |
}; |
#endif |
#endif /* CONFIG_KCONSOLE */ |
/** Print table of active breakpoints */ |
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused))) |
{ |
unsigned int i; |
char *symbol; |
if (sizeof(void *) == 4) { |
printf("# Count Address In symbol\n"); |
printf("-- ----- ---------- ---------\n"); |
} else { |
printf("# Count Address In symbol\n"); |
printf("-- ----- ------------------ ---------\n"); |
} |
for (i = 0; i < BKPOINTS_MAX; i++) |
if (breakpoints[i].address) { |
symbol = get_symtab_entry(breakpoints[i].address); |
if (sizeof(void *) == 4) |
printf("%-2u %-5d %#10zx %s\n", i, breakpoints[i].counter, |
breakpoints[i].address, symbol); |
else |
printf("%-2u %-5d %#18zx %s\n", i, breakpoints[i].counter, |
breakpoints[i].address, symbol); |
} |
return 1; |
} |
/* Setup DR register according to table */ |
static void setup_dr(int curidx) |
{ |
162,19 → 134,23 |
if ((flags & BKPOINT_INSTR)) { |
; |
} else { |
if (sizeof(int) == 4) |
dr7 |= ((unative_t) 0x3) << (18 + 4*curidx); |
else /* 8 */ |
dr7 |= ((unative_t) 0x2) << (18 + 4*curidx); |
#ifdef __32_BITS__ |
dr7 |= ((unative_t) 0x3) << (18 + 4 * curidx); |
#endif |
#ifdef __64_BITS__ |
dr7 |= ((unative_t) 0x2) << (18 + 4 * curidx); |
#endif |
if ((flags & BKPOINT_WRITE)) |
dr7 |= ((unative_t) 0x1) << (16 + 4*curidx); |
dr7 |= ((unative_t) 0x1) << (16 + 4 * curidx); |
else if ((flags & BKPOINT_READ_WRITE)) |
dr7 |= ((unative_t) 0x3) << (16 + 4*curidx); |
dr7 |= ((unative_t) 0x3) << (16 + 4 * curidx); |
} |
/* Enable global breakpoint */ |
dr7 |= 0x2 << (curidx*2); |
dr7 |= 0x2 << (curidx * 2); |
write_dr7(dr7); |
225,16 → 201,16 |
/* Send IPI */ |
#ifdef CONFIG_SMP |
// ipi_broadcast(VECTOR_DEBUG_IPI); |
// ipi_broadcast(VECTOR_DEBUG_IPI); |
#endif |
return curidx; |
} |
#ifdef amd64 |
# define getip(x) ((x)->rip) |
#ifdef __64_BITS__ |
#define getip(x) ((x)->rip) |
#else |
# define getip(x) ((x)->eip) |
#define getip(x) ((x)->eip) |
#endif |
static void handle_exception(int slot, istate_t *istate) |
246,19 → 222,21 |
if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) { |
if (*((unative_t *) breakpoints[slot].address) != 0) |
return; |
printf("**** Found ZERO on address %lx (slot %d) ****\n", |
breakpoints[slot].address, slot); |
printf("*** Found ZERO on address %lx (slot %d) ***\n", |
breakpoints[slot].address, slot); |
} else { |
printf("Data watchpoint - new data: %lx\n", |
*((unative_t *) breakpoints[slot].address)); |
*((unative_t *) breakpoints[slot].address)); |
} |
} |
printf("Reached breakpoint %d:%lx(%s)\n", slot, getip(istate), |
get_symtab_entry(getip(istate))); |
printf("***Type 'exit' to exit kconsole.\n"); |
atomic_set(&haltstate,1); |
kconsole((void *) "debug"); |
atomic_set(&haltstate,0); |
get_symtab_entry(getip(istate))); |
#ifdef CONFIG_KCONSOLE |
atomic_set(&haltstate, 1); |
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false); |
atomic_set(&haltstate, 0); |
#endif |
} |
void breakpoint_del(int slot) |
287,42 → 265,8 |
#endif |
} |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
unative_t bpno = argv->intval; |
if (bpno > BKPOINTS_MAX) { |
printf("Invalid breakpoint number.\n"); |
return 0; |
} |
breakpoint_del(argv->intval); |
return 1; |
} |
/** Add new breakpoint to table */ |
static int cmd_add_breakpoint(cmd_arg_t *argv) |
{ |
int flags; |
int id; |
if (argv == &add_argv) { |
flags = BKPOINT_INSTR; |
} else { /* addwatchp */ |
flags = BKPOINT_WRITE; |
} |
printf("Adding breakpoint on address: %p\n", argv->intval); |
id = breakpoint_add((void *)argv->intval, flags, -1); |
if (id < 0) |
printf("Add breakpoint failed.\n"); |
else |
printf("Added breakpoint %d.\n", id); |
return 1; |
} |
#endif |
static void debug_exception(int n __attribute__((unused)), istate_t *istate) |
{ |
unative_t dr6; |
329,7 → 273,7 |
int i; |
/* Set RF to restart the instruction */ |
#ifdef amd64 |
#ifdef __64_BITS__ |
istate->rflags |= RFLAGS_RF; |
#else |
istate->eflags |= EFLAGS_RF; |
347,7 → 291,9 |
} |
#ifdef CONFIG_SMP |
static void debug_ipi(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) |
static void |
debug_ipi(int n __attribute__((unused)), |
istate_t *istate __attribute__((unused))) |
{ |
int i; |
363,34 → 309,103 |
{ |
int i; |
for (i=0; i<BKPOINTS_MAX; i++) |
for (i = 0; i < BKPOINTS_MAX; i++) |
breakpoints[i].address = NULL; |
#ifdef CONFIG_KCONSOLE |
cmd_initialize(&bkpts_info); |
if (!cmd_register(&bkpts_info)) |
panic("could not register command %s\n", bkpts_info.name); |
printf("Cannot register command %s\n", bkpts_info.name); |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
cmd_initialize(&delbkpt_info); |
if (!cmd_register(&delbkpt_info)) |
panic("could not register command %s\n", delbkpt_info.name); |
printf("Cannot register command %s\n", delbkpt_info.name); |
cmd_initialize(&addbkpt_info); |
if (!cmd_register(&addbkpt_info)) |
panic("could not register command %s\n", addbkpt_info.name); |
printf("Cannot register command %s\n", addbkpt_info.name); |
cmd_initialize(&addwatchp_info); |
if (!cmd_register(&addwatchp_info)) |
panic("could not register command %s\n", addwatchp_info.name); |
#endif |
printf("Cannot register command %s\n", addwatchp_info.name); |
#endif /* CONFIG_KCONSOLE */ |
exc_register(VECTOR_DEBUG, "debugger", |
debug_exception); |
exc_register(VECTOR_DEBUG, "debugger", debug_exception); |
#ifdef CONFIG_SMP |
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", |
debug_ipi); |
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", debug_ipi); |
#endif |
} |
#ifdef CONFIG_KCONSOLE |
/** Print table of active breakpoints */ |
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused))) |
{ |
unsigned int i; |
char *symbol; |
#ifdef __32_BITS__ |
printf("# Count Address In symbol\n"); |
printf("-- ----- ---------- ---------\n"); |
#endif |
#ifdef __64_BITS__ |
printf("# Count Address In symbol\n"); |
printf("-- ----- ------------------ ---------\n"); |
#endif |
for (i = 0; i < BKPOINTS_MAX; i++) |
if (breakpoints[i].address) { |
symbol = get_symtab_entry(breakpoints[i].address); |
#ifdef __32_BITS__ |
printf("%-2u %-5d %#10zx %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
symbol); |
#endif |
#ifdef __64_BITS__ |
printf("%-2u %-5d %#18zx %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
symbol); |
#endif |
} |
return 1; |
} |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
unative_t bpno = argv->intval; |
if (bpno > BKPOINTS_MAX) { |
printf("Invalid breakpoint number.\n"); |
return 0; |
} |
breakpoint_del(argv->intval); |
return 1; |
} |
/** Add new breakpoint to table */ |
static int cmd_add_breakpoint(cmd_arg_t *argv) |
{ |
int flags; |
int id; |
if (argv == &add_argv) { |
flags = BKPOINT_INSTR; |
} else { /* addwatchp */ |
flags = BKPOINT_WRITE; |
} |
printf("Adding breakpoint on address: %p\n", argv->intval); |
id = breakpoint_add((void *)argv->intval, flags, -1); |
if (id < 0) |
printf("Add breakpoint failed.\n"); |
else |
printf("Added breakpoint %d.\n", id); |
return 1; |
} |
#endif /* CONFIG_KCONSOLE */ |
/** @} |
*/ |
/branches/dd/kernel/arch/amd64/src/mm/page.c |
---|
180,7 → 180,7 |
page = read_cr2(); |
if (istate->error_word & PFERR_CODE_RSVD) |
panic("Reserved bit set in page table entry.\n"); |
panic("Reserved bit set in page table entry."); |
if (istate->error_word & PFERR_CODE_RW) |
access = PF_ACCESS_WRITE; |
190,11 → 190,11 |
access = PF_ACCESS_READ; |
if (as_page_fault(page, access, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate, "Page fault: %#x", page); |
fault_if_from_uspace(istate, "Page fault: %#x.", page); |
decode_istate(n, istate); |
printf("Page fault address: %llx\n", page); |
panic("page fault\n"); |
printf("Page fault address: %llx.\n", page); |
panic("Page fault."); |
} |
} |
202,7 → 202,7 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
panic("Unable to map physical memory %p (%d bytes).", physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
/branches/dd/kernel/arch/amd64/src/userspace.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup amd64 |
/** @addtogroup amd64 |
* @{ |
*/ |
/** @file |
47,34 → 47,33 |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
ipl_t ipl; |
ipl_t ipl = interrupts_disable(); |
ipl = interrupts_disable(); |
/* Clear CF,PF,AF,ZF,SF,DF,OF */ |
/* Clear CF, PF, AF, ZF, SF, DF, OF */ |
ipl &= ~(0xcd4); |
asm volatile ("" |
"pushq %0\n" |
"pushq %1\n" |
"pushq %2\n" |
"pushq %3\n" |
"pushq %4\n" |
"movq %5, %%rax\n" |
"iretq\n" |
: : |
"i" (gdtselector(UDATA_DES) | PL_USER), |
"r" (kernel_uarg->uspace_stack+THREAD_STACK_SIZE), |
"r" (ipl), |
"i" (gdtselector(UTEXT_DES) | PL_USER), |
"r" (kernel_uarg->uspace_entry), |
"r" (kernel_uarg->uspace_uarg) |
: "rax" |
); |
asm volatile ( |
"pushq %[udata_des]\n" |
"pushq %[stack_size]\n" |
"pushq %[ipl]\n" |
"pushq %[utext_des]\n" |
"pushq %[entry]\n" |
"movq %[uarg], %%rax\n" |
/* %rdi is defined to hold pcb_ptr - set it to 0 */ |
"xorq %%rdi, %%rdi\n" |
"iretq\n" |
:: [udata_des] "i" (gdtselector(UDATA_DES) | PL_USER), |
[stack_size] "r" (kernel_uarg->uspace_stack + THREAD_STACK_SIZE), |
[ipl] "r" (ipl), |
[utext_des] "i" (gdtselector(UTEXT_DES) | PL_USER), |
[entry] "r" (kernel_uarg->uspace_entry), |
[uarg] "r" (kernel_uarg->uspace_uarg) |
: "rax" |
); |
/* Unreachable */ |
for(;;) |
; |
while (1); |
} |
/** @} |
/branches/dd/kernel/arch/amd64/src/interrupt.c |
---|
80,12 → 80,6 |
istate->rdi, istate->r8); |
printf("%%r9=%#llx, %%r10=%#llx, %%r11=%#llx\n", istate->r9, |
istate->r10, istate->r11); |
#ifdef CONFIG_DEBUG_ALLREGS |
printf("%%r12=%#llx, %%r13=%#llx, %%r14=%#llx\n", istate->r12, |
istate->r13, istate->r14); |
printf("%%r15=%#llx, %%rbx=%#llx, %%rbp=%#llx\n", istate->r15, |
istate->rbx, &istate->rbp); |
#endif |
printf("%%rsp=%#llx\n", &istate->stack[0]); |
} |
94,15 → 88,15 |
if (eoi_function) |
eoi_function(); |
else |
panic("no eoi_function\n"); |
panic("No eoi_function."); |
} |
static void null_interrupt(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "unserviced interrupt: %d", n); |
fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n); |
decode_istate(n, istate); |
panic("unserviced interrupt\n"); |
panic("Unserviced interrupt."); |
} |
/** General Protection Fault. */ |
126,35 → 120,37 |
io_perm_bitmap_install(); |
return; |
} |
fault_if_from_uspace(istate, "general protection fault"); |
fault_if_from_uspace(istate, "General protection fault."); |
} |
decode_istate(n, istate); |
panic("general protection fault\n"); |
panic("General protection fault."); |
} |
static void ss_fault(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "stack fault"); |
fault_if_from_uspace(istate, "Stack fault."); |
decode_istate(n, istate); |
panic("stack fault\n"); |
panic("Stack fault."); |
} |
static void nm_fault(int n, istate_t *istate) |
{ |
#ifdef CONFIG_FPU_LAZY |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#else |
fault_if_from_uspace(istate, "fpu fault"); |
panic("fpu fault"); |
fault_if_from_uspace(istate, "FPU fault."); |
panic("FPU fault."); |
#endif |
} |
#ifdef CONFIG_SMP |
static void tlb_shootdown_ipi(int n, istate_t *istate) |
{ |
trap_virtual_eoi(); |
tlb_shootdown_ipi_recv(); |
} |
#endif |
/** Handler of IRQ exceptions */ |
static void irq_interrupt(int n, istate_t *istate) |
177,7 → 173,7 |
trap_virtual_eoi(); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* |
221,7 → 217,7 |
if (enable_irqs_function) |
enable_irqs_function(irqmask); |
else |
panic("no enable_irqs_function\n"); |
panic("No enable_irqs_function."); |
} |
void trap_virtual_disable_irqs(uint16_t irqmask) |
229,7 → 225,7 |
if (disable_irqs_function) |
disable_irqs_function(irqmask); |
else |
panic("no disable_irqs_function\n"); |
panic("No disable_irqs_function."); |
} |
/** @} |
/branches/dd/kernel/arch/mips32/_link.ld.in |
---|
1,15 → 1,17 |
/* |
* MIPS32 linker script |
* |
* MIPS32 linker script |
* |
* kernel text |
* kernel data |
* |
* |
*/ |
#undef mips |
#define mips mips |
#define KERNEL_LOAD_ADDRESS 0x80100000 |
OUTPUT_ARCH(mips) |
ENTRY(kernel_image_start) |
SECTIONS { |
21,9 → 23,9 |
} |
.data : { |
kdata_start = .; |
*(.data); /* initialized data */ |
*(.data); /* initialized data */ |
hardcoded_ktext_size = .; |
LONG(ktext_end - ktext_start); |
LONG(ktext_end - ktext_start); |
hardcoded_kdata_size = .; |
LONG(kdata_end - kdata_start); |
hardcoded_load_address = .; |
33,21 → 35,21 |
*(.reginfo); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
symbol_table = .; |
*(symtab.*); |
*(symtab.*); |
} |
_gp = . + 0x8000; |
.lit8 : { *(.lit8) } |
.lit4 : { *(.lit4) } |
kdata_end = .; |
/DISCARD/ : { |
*(.mdebug*); |
*(.pdr); |
*(.comment); |
*(.note); |
*(.mdebug*); |
*(.pdr); |
*(.comment); |
*(.note); |
} |
} |
/branches/dd/kernel/arch/mips32/include/boot.h |
---|
File deleted |
/branches/dd/kernel/arch/mips32/include/context_offset.h |
---|
76,26 → 76,17 |
#define EOFFSET_T5 0x30 |
#define EOFFSET_T6 0x34 |
#define EOFFSET_T7 0x38 |
#define EOFFSET_S0 0x3c |
#define EOFFSET_S1 0x40 |
#define EOFFSET_S2 0x44 |
#define EOFFSET_S3 0x48 |
#define EOFFSET_S4 0x4c |
#define EOFFSET_S5 0x50 |
#define EOFFSET_S6 0x54 |
#define EOFFSET_S7 0x58 |
#define EOFFSET_T8 0x5c |
#define EOFFSET_T9 0x60 |
#define EOFFSET_GP 0x64 |
#define EOFFSET_SP 0x68 |
#define EOFFSET_S8 0x6c |
#define EOFFSET_RA 0x70 |
#define EOFFSET_LO 0x74 |
#define EOFFSET_HI 0x78 |
#define EOFFSET_STATUS 0x7c |
#define EOFFSET_EPC 0x80 |
#define EOFFSET_K1 0x84 |
#define REGISTER_SPACE 136 |
#define EOFFSET_T8 0x3c |
#define EOFFSET_T9 0x40 |
#define EOFFSET_GP 0x44 |
#define EOFFSET_SP 0x48 |
#define EOFFSET_RA 0x4c |
#define EOFFSET_LO 0x50 |
#define EOFFSET_HI 0x54 |
#define EOFFSET_STATUS 0x58 |
#define EOFFSET_EPC 0x5c |
#define EOFFSET_K1 0x60 |
#define REGISTER_SPACE 100 |
#ifdef __ASM__ |
114,10 → 105,10 |
sw $s8,OFFSET_S8(\ctx) |
sw $gp,OFFSET_GP(\ctx) |
#ifndef KERNEL |
#ifndef KERNEL |
sw $k1,OFFSET_TLS(\ctx) |
# ifdef CONFIG_MIPS_FPU |
#ifdef CONFIG_FPU |
mfc1 $t0,$20 |
sw $t0, OFFSET_F20(\ctx) |
150,7 → 141,7 |
mfc1 $t0,$30 |
sw $t0, OFFSET_F30(\ctx) |
# endif /* CONFIG_MIPS_FPU */ |
#endif /* CONFIG_FPU */ |
#endif /* KERNEL */ |
sw $ra,OFFSET_PC(\ctx) |
172,7 → 163,7 |
#ifndef KERNEL |
lw $k1,OFFSET_TLS(\ctx) |
# ifdef CONFIG_MIPS_FPU |
#ifdef CONFIG_FPU |
lw $t0, OFFSET_F20(\ctx) |
mtc1 $t0,$20 |
205,9 → 196,9 |
lw $t0, OFFSET_F30(\ctx) |
mtc1 $t0,$30 |
# endif /* CONFIG_MIPS_FPU */ |
#endif /* CONFIG_FPU */ |
#endif /* KERNEL */ |
lw $ra,OFFSET_PC(\ctx) |
lw $sp,OFFSET_SP(\ctx) |
.endm |
/branches/dd/kernel/arch/mips32/include/asm/boot.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32 |
/** @addtogroup mips32 |
* @{ |
*/ |
/** @file |
/branches/dd/kernel/arch/mips32/include/interrupt.h |
---|
38,9 → 38,11 |
#include <typedefs.h> |
#include <arch/exception.h> |
#define IVT_ITEMS 32 |
#define IVT_FIRST 0 |
#define IVT_ITEMS 32 |
#define IVT_FIRST 0 |
#define VECTOR_TLB_SHOOTDOWN_IPI EXC_Int |
extern function virtual_timer_fnc; |
extern uint32_t count_hi; |
/branches/dd/kernel/arch/mips32/include/exception.h |
---|
73,19 → 73,10 |
uint32_t t5; |
uint32_t t6; |
uint32_t t7; |
uint32_t s0; |
uint32_t s1; |
uint32_t s2; |
uint32_t s3; |
uint32_t s4; |
uint32_t s5; |
uint32_t s6; |
uint32_t s7; |
uint32_t t8; |
uint32_t t9; |
uint32_t gp; |
uint32_t sp; |
uint32_t s8; |
uint32_t ra; |
uint32_t lo; |
/branches/dd/kernel/arch/mips32/include/console.h |
---|
35,8 → 35,6 |
#ifndef KERN_mips32_CONSOLE_H_ |
#define KERN_mips32_CONSOLE_H_ |
extern void console_init(devno_t devno); |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_mips32_TYPES_H_ |
#define KERN_mips32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
61,14 → 57,32 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "ld" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page Table Entry. */ |
typedef struct { |
unsigned g : 1; /**< Global bit. */ |
/branches/dd/kernel/arch/mips32/include/memstr.h |
---|
37,10 → 37,10 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
extern void memsetw(uintptr_t dst, size_t cnt, uint16_t x); |
extern void memsetb(uintptr_t dst, size_t cnt, uint8_t x); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
extern int memcmp(uintptr_t src, uintptr_t dst, int cnt); |
extern int memcmp(const void *a, const void *b, size_t cnt); |
#endif |
/branches/dd/kernel/arch/mips32/include/smp/order.h |
---|
File deleted |
/branches/dd/kernel/arch/mips32/include/smp/dorder.h |
---|
0,0 → 1,34 |
/* |
* Copyright (c) 2007 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifndef KERN_mips32_DORDER_H_ |
#define KERN_mips32_DORDER_H_ |
extern void ipi_broadcast_arch(int ipi); |
#endif |
/branches/dd/kernel/arch/mips32/include/atomic.h |
---|
35,14 → 35,14 |
#ifndef KERN_mips32_ATOMIC_H_ |
#define KERN_mips32_ATOMIC_H_ |
#define atomic_inc(x) ((void) atomic_add(x, 1)) |
#define atomic_dec(x) ((void) atomic_add(x, -1)) |
#define atomic_inc(x) ((void) atomic_add(x, 1)) |
#define atomic_dec(x) ((void) atomic_add(x, -1)) |
#define atomic_postinc(x) (atomic_add(x, 1) - 1) |
#define atomic_postdec(x) (atomic_add(x, -1) + 1) |
#define atomic_postinc(x) (atomic_add(x, 1) - 1) |
#define atomic_postdec(x) (atomic_add(x, -1) + 1) |
#define atomic_preinc(x) atomic_add(x, 1) |
#define atomic_predec(x) atomic_add(x, -1) |
#define atomic_preinc(x) atomic_add(x, 1) |
#define atomic_predec(x) atomic_add(x, -1) |
/* Atomic addition of immediate value. |
* |
54,19 → 54,37 |
static inline long atomic_add(atomic_t *val, int i) |
{ |
long tmp, v; |
asm volatile ( |
"1:\n" |
" ll %0, %1\n" |
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" move %2, %0\n" |
" addu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" move %2, %0\n" |
" sc %0, %1\n" |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
" nop\n" |
: "=r" (tmp), "=m" (val->count), "=r" (v) |
: "i" (i), "i" (0) |
); |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "r" (i), "i" (0) |
); |
return v; |
} |
static inline uint32_t test_and_set(atomic_t *val) { |
uint32_t tmp, v; |
asm volatile ( |
"1:\n" |
" ll %2, %1\n" |
" bnez %2, 2f\n" |
" li %0, %3\n" |
" sc %0, %1\n" |
" beqz %0, 1b\n" |
"2:\n" |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "i" (1) |
); |
return v; |
} |
/branches/dd/kernel/arch/mips32/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32 |
/** @addtogroup mips32 |
* @{ |
*/ |
/** @file |
35,6 → 35,29 |
#ifndef KERN_mips32_ARCH_H_ |
#define KERN_mips32_ARCH_H_ |
#define TASKMAP_MAX_RECORDS 32 |
#define CPUMAP_MAX_RECORDS 32 |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
#include <typedefs.h> |
extern count_t cpu_count; |
typedef struct { |
uintptr_t addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} utask_t; |
typedef struct { |
uint32_t cpumap; |
uint32_t cnt; |
utask_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
extern void arch_pre_main(void *entry, bootinfo_t *bootinfo); |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/asm.h |
---|
36,6 → 36,7 |
#define KERN_mips32_ASM_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <config.h> |
55,7 → 56,11 |
{ |
uintptr_t v; |
asm volatile ("and %0, $29, %1\n" : "=r" (v) : "r" (~(STACK_SIZE-1))); |
asm volatile ( |
"and %0, $29, %1\n" |
: "=r" (v) |
: "r" (~(STACK_SIZE-1)) |
); |
return v; |
} |
63,13 → 68,44 |
extern void cpu_halt(void); |
extern void asm_delay_loop(uint32_t t); |
extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg, |
uintptr_t entry); |
uintptr_t entry); |
extern ipl_t interrupts_disable(void); |
extern ipl_t interrupts_enable(void); |
extern void interrupts_restore(ipl_t ipl); |
extern ipl_t interrupts_read(void); |
extern void asm_delay_loop(uint32_t t); |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32mm |
/** @addtogroup mips32mm |
* @{ |
*/ |
/** @file |
35,12 → 35,14 |
#ifndef KERN_mips32_FRAME_H_ |
#define KERN_mips32_FRAME_H_ |
#define FRAME_WIDTH 14 /* 16K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 14 /* 16K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
#include <typedefs.h> |
extern void frame_arch_init(void); |
extern void physmem_print(void); |
/branches/dd/kernel/arch/mips32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifndef __ASM__ |
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000) |
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000) |
/branches/dd/kernel/arch/mips32/include/mm/asid.h |
---|
37,7 → 37,7 |
#include <arch/types.h> |
#define ASID_MAX_ARCH 255 /* 2^8 - 1 */ |
#define ASID_MAX_ARCH 255 /* 2^8 - 1 */ |
typedef uint8_t asid_t; |
/branches/dd/kernel/arch/mips32/include/mm/tlb.h |
---|
35,6 → 35,9 |
#ifndef KERN_mips32_TLB_H_ |
#define KERN_mips32_TLB_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/mm/asid.h> |
#include <arch/exception.h> |
#ifdef TLBCNT |
46,7 → 49,13 |
#define TLB_WIRED 1 |
#define TLB_KSTACK_WIRED_INDEX 0 |
#define TLB_PAGE_MASK_16K (0x3<<13) |
#define TLB_PAGE_MASK_4K (0x000 << 13) |
#define TLB_PAGE_MASK_16K (0x003 << 13) |
#define TLB_PAGE_MASK_64K (0x00f << 13) |
#define TLB_PAGE_MASK_256K (0x03f << 13) |
#define TLB_PAGE_MASK_1M (0x0ff << 13) |
#define TLB_PAGE_MASK_4M (0x3ff << 13) |
#define TLB_PAGE_MASK_16M (0xfff << 13) |
#define PAGE_UNCACHED 2 |
#define PAGE_CACHEABLE_EXC_WRITE 5 |
159,6 → 168,8 |
extern void tlb_invalid(istate_t *istate); |
extern void tlb_refill(istate_t *istate); |
extern void tlb_modified(istate_t *istate); |
extern void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn); |
extern void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr); |
#endif |
/branches/dd/kernel/arch/mips32/include/mm/as.h |
---|
38,7 → 38,7 |
#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH 0 |
#define KERNEL_ADDRESS_SPACE_START_ARCH (unsigned long) 0x80000000 |
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0xffffffff |
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0x9fffffff |
#define USER_ADDRESS_SPACE_START_ARCH (unsigned long) 0x00000000 |
#define USER_ADDRESS_SPACE_END_ARCH (unsigned long) 0x7fffffff |
/branches/dd/kernel/arch/mips32/include/barrier.h |
---|
45,6 → 45,9 |
#define read_barrier() asm volatile ("" ::: "memory") |
#define write_barrier() asm volatile ("" ::: "memory") |
#define smc_coherence(a) |
#define smc_coherence_block(a, l) |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/cpu.h |
---|
42,7 → 42,7 |
uint32_t imp_num; |
uint32_t rev_num; |
} cpu_arch_t; |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/drivers/arc.h |
---|
File deleted |
/branches/dd/kernel/arch/mips32/include/drivers/serial.h |
---|
35,36 → 35,8 |
#ifndef KERN_mips32_SERIAL_H_ |
#define KERN_mips32_SERIAL_H_ |
#include <console/chardev.h> |
#define SERIAL_ADDRESS 0x98000000 |
#define SERIAL_MAX 4 |
#define SERIAL_COM1 0x3f8 |
#define SERIAL_COM1_IRQ 4 |
#define SERIAL_COM2 0x2f8 |
#define SERIAL_COM2_IRQ 3 |
#define P_WRITEB(where,what) (*((volatile char *) (0xB8000000+where))=what) |
#define P_READB(where) (*((volatile char *)(0xB8000000+where))) |
#define SERIAL_READ(x) P_READB(x) |
#define SERIAL_WRITE(x,c) P_WRITEB(x,c) |
/* Interrupt enable register */ |
#define SERIAL_READ_IER(x) (P_READB((x) + 1)) |
#define SERIAL_WRITE_IER(x,c) (P_WRITEB((x)+1,c)) |
/* Interrupt identification register */ |
#define SERIAL_READ_IIR(x) (P_READB((x) + 2)) |
/* Line status register */ |
#define SERIAL_READ_LSR(x) (P_READB((x) + 5)) |
#define TRANSMIT_EMPTY_BIT 5 |
typedef struct { |
int port; |
int irq; |
}serial_t; |
extern void serial_console(devno_t devno); |
extern int serial_init(void); |
#endif |
/** @} |
/branches/dd/kernel/arch/mips32/include/drivers/msim.h |
---|
35,6 → 35,11 |
#ifndef KERN_mips32_MSIM_H_ |
#define KERN_mips32_MSIM_H_ |
/** Address of devices. */ |
#define MSIM_VIDEORAM 0x90000000 |
#define MSIM_KBD_ADDRESS 0x90000000 |
#define MSIM_KBD_IRQ 2 |
#include <console/chardev.h> |
void msim_console(devno_t devno); |
/branches/dd/kernel/arch/mips32/Makefile.inc |
---|
31,57 → 31,26 |
BFD_ARCH = mips |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel |
KERNEL_LOAD_ADDRESS = 0x80100000 |
INIT_ADDRESS = 0x81000000 |
INIT_SIZE = 262144 |
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss |
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} -DINIT_ADDRESS=${INIT_ADDRESS} -DINIT_SIZE=${INIT_SIZE} |
DEFS += -D__32_BITS__ |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with support for address space identifiers. |
# |
CONFIG_ASID = y |
CONFIG_ASID_FIFO = y |
## Accepted MACHINEs |
# |
ifeq ($(MACHINE),indy) |
# GCC 4.0.1 compiled for mipsEL has problems compiling in |
# BigEndian mode with the swl/swr/lwl/lwr instructions. |
# We have to compile it with mips-sgi-irix5 to get it right. |
BFD_NAME = elf32-bigmips |
BFD = ecoff-bigmips --impure |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
KERNEL_LOAD_ADDRESS = 0x88002000 |
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -march=r4600 |
INIT_ADDRESS = 0 |
INIT_SIZE = 0 |
endif |
ifeq ($(MACHINE),lgxemul) |
BFD_NAME = elf32-tradlittlemips |
BFD = binary |
GCC_CFLAGS += -DFB_INVERT_ENDIAN -DARCH_HAS_FPU -mips3 |
GCC_CFLAGS += -mips3 |
endif |
ifeq ($(MACHINE),bgxemul) |
BFD_NAME = elf32-bigmips |
BFD = ecoff-bigmips |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3 |
INIT_ADDRESS = 0x81800000 |
GCC_CFLAGS += -EB -DBIG_ENDIAN -mips3 |
endif |
ifeq ($(MACHINE),simics) |
# SIMICS 4kc emulation is broken, although for instructions |
98,32 → 67,24 |
GCC_CFLAGS += -mhard-float -mips3 |
endif |
## Compile with support for software integer division. |
# |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/start.S \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/panic.S \ |
arch/$(ARCH)/src/mips32.c \ |
arch/$(ARCH)/src/dummy.S \ |
arch/$(ARCH)/src/console.c \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/exception.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/cache.c \ |
arch/$(ARCH)/src/debugger.c \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/arc.c \ |
arch/$(ARCH)/src/drivers/msim.c \ |
arch/$(ARCH)/src/drivers/serial.c \ |
arch/$(ARCH)/src/smp/order.c |
arch/$(KARCH)/src/start.S \ |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/mips32.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/cache.c \ |
arch/$(KARCH)/src/debugger.c \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/fpu_context.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/msim.c \ |
arch/$(KARCH)/src/smp/dorder.c \ |
arch/$(KARCH)/src/smp/smp.c |
/branches/dd/kernel/arch/mips32/src/dummy.S |
---|
File deleted |
/branches/dd/kernel/arch/mips32/src/fpu_context.c |
---|
40,7 → 40,7 |
void fpu_disable(void) |
{ |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
cp0_status_write(cp0_status_read() & ~cp0_status_fpu_bit); |
#endif |
} |
47,7 → 47,7 |
void fpu_enable(void) |
{ |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
cp0_status_write(cp0_status_read() | cp0_status_fpu_bit); |
#endif |
} |
/branches/dd/kernel/arch/mips32/src/exception.c |
---|
45,7 → 45,6 |
#include <print.h> |
#include <interrupt.h> |
#include <func.h> |
#include <console/kconsole.h> |
#include <ddi/irq.h> |
#include <arch/debugger.h> |
89,10 → 88,10 |
static void unhandled_exception(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]); |
fault_if_from_uspace(istate, "Unhandled exception %s.", exctable[n]); |
print_regdump(istate); |
panic("unhandled exception %s\n", exctable[n]); |
panic("Unhandled exception %s.", exctable[n]); |
} |
static void reserved_instr_exception(int n, istate_t *istate) |
133,8 → 132,8 |
if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id) |
scheduler_fpu_lazy_request(); |
else { |
fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception"); |
panic("unhandled Coprocessor Unusable Exception\n"); |
fault_if_from_uspace(istate, "Unhandled Coprocessor Unusable Exception."); |
panic("Unhandled Coprocessor Unusable Exception."); |
} |
} |
#endif |
145,7 → 144,7 |
int i; |
/* decode interrupt number and process the interrupt */ |
cause = (cp0_cause_read() >> 8) &0xff; |
cause = (cp0_cause_read() >> 8) & 0xff; |
for (i = 0; i < 8; i++) { |
if (cause & (1 << i)) { |
154,7 → 153,7 |
/* |
* The IRQ handler was found. |
*/ |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* |
161,7 → 160,8 |
* Spurious interrupt. |
*/ |
#ifdef CONFIG_DEBUG |
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
printf("cpu%u: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
#endif |
} |
} |
171,7 → 171,7 |
/** Handle syscall userspace call */ |
static void syscall_exception(int n, istate_t *istate) |
{ |
panic("Syscall is handled through shortcut"); |
panic("Syscall is handled through shortcut."); |
} |
void exception_init(void) |
/branches/dd/kernel/arch/mips32/src/asm.S |
---|
27,17 → 27,17 |
# |
#include <arch/asm/regname.h> |
.text |
.macro cp0_read reg |
mfc0 $2,\reg |
mfc0 $2, \reg |
j $31 |
nop |
.endm |
.macro cp0_write reg |
mtc0 $4,\reg |
mtc0 $4, \reg |
j $31 |
nop |
.endm |
46,6 → 46,11 |
.set noreorder |
.set nomacro |
.global asm_delay_loop |
asm_delay_loop: |
j $31 |
nop |
.global cpu_halt |
cpu_halt: |
j cpu_halt |
66,234 → 71,238 |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
addiu $v0,$a1,3 |
li $v1,-4 # 0xfffffffffffffffc |
and $v0,$v0,$v1 |
beq $a1,$v0,3f |
move $t0,$a0 |
move $t2, $a0 # save dst |
addiu $v0, $a1, 3 |
li $v1, -4 # 0xfffffffffffffffc |
and $v0, $v0, $v1 |
beq $a1, $v0, 3f |
move $t0, $a0 |
0: |
beq $a2, $zero, 2f |
move $a3, $zero |
1: |
addu $v0, $a1, $a3 |
lbu $a0, 0($v0) |
addu $v1, $t0, $a3 |
addiu $a3, $a3, 1 |
bne $a3, $a2, 1b |
sb $a0, 0($v1) |
2: |
jr $ra |
move $v0, $t2 |
3: |
addiu $v0, $a0, 3 |
and $v0, $v0, $v1 |
bne $a0, $v0, 0b |
srl $t1, $a2, 2 |
beq $t1, $zero, 5f |
move $a3, $zero |
move $a3, $zero |
move $a0, $zero |
4: |
addu $v0, $a1, $a0 |
lw $v1, 0($v0) |
addiu $a3, $a3, 1 |
addu $v0, $t0, $a0 |
sw $v1, 0($v0) |
bne $a3, $t1, 4b |
addiu $a0, $a0, 4 |
5: |
andi $a2, $a2, 0x3 |
beq $a2, $zero, 2b |
nop |
sll $v0, $a3, 2 |
addu $t1, $v0, $t0 |
move $a3, $zero |
addu $t0, $v0, $a1 |
6: |
addu $v0, $t0, $a3 |
lbu $a0, 0($v0) |
addu $v1, $t1, $a3 |
addiu $a3, $a3, 1 |
bne $a3, $a2, 6b |
sb $a0, 0($v1) |
jr $ra |
move $v0, $t2 |
0: |
beq $a2,$zero,2f |
move $a3,$zero |
1: |
addu $v0,$a1,$a3 |
lbu $a0,0($v0) |
addu $v1,$t0,$a3 |
addiu $a3,$a3,1 |
bne $a3,$a2,1b |
sb $a0,0($v1) |
2: |
jr $ra |
move $v0,$a1 |
3: |
addiu $v0,$a0,3 |
and $v0,$v0,$v1 |
bne $a0,$v0,0b |
srl $t1,$a2,2 |
beq $t1,$zero,5f |
move $a3,$zero |
move $a3,$zero |
move $a0,$zero |
4: |
addu $v0,$a1,$a0 |
lw $v1,0($v0) |
addiu $a3,$a3,1 |
addu $v0,$t0,$a0 |
sw $v1,0($v0) |
bne $a3,$t1,4b |
addiu $a0,$a0,4 |
5: |
andi $a2,$a2,0x3 |
beq $a2,$zero,2b |
nop |
sll $v0,$a3,2 |
addu $t1,$v0,$t0 |
move $a3,$zero |
addu $t0,$v0,$a1 |
6: |
addu $v0,$t0,$a3 |
lbu $a0,0($v0) |
addu $v1,$t1,$a3 |
addiu $a3,$a3,1 |
bne $a3,$a2,6b |
sb $a0,0($v1) |
jr $ra |
move $v0,$a1 |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
jr $ra |
move $v0, $zero |
jr $ra |
move $v0, $zero |
.macro fpu_gp_save reg ctx |
mfc1 $t0,$\reg |
sw $t0, \reg*4(\ctx) |
mfc1 $t0, $\reg |
sw $t0, \reg * 4(\ctx) |
.endm |
.macro fpu_gp_restore reg ctx |
lw $t0, \reg*4(\ctx) |
mtc1 $t0,$\reg |
lw $t0, \reg * 4(\ctx) |
mtc1 $t0, $\reg |
.endm |
.macro fpu_ct_save reg ctx |
cfc1 $t0,$1 |
sw $t0, (\reg+32)*4(\ctx) |
cfc1 $t0, $1 |
sw $t0, (\reg + 32) * 4(\ctx) |
.endm |
.macro fpu_ct_restore reg ctx |
lw $t0, (\reg+32)*4(\ctx) |
ctc1 $t0,$\reg |
lw $t0, (\reg + 32) * 4(\ctx) |
ctc1 $t0, $\reg |
.endm |
.global fpu_context_save |
fpu_context_save: |
#ifdef ARCH_HAS_FPU |
fpu_gp_save 0,$a0 |
fpu_gp_save 1,$a0 |
fpu_gp_save 2,$a0 |
fpu_gp_save 3,$a0 |
fpu_gp_save 4,$a0 |
fpu_gp_save 5,$a0 |
fpu_gp_save 6,$a0 |
fpu_gp_save 7,$a0 |
fpu_gp_save 8,$a0 |
fpu_gp_save 9,$a0 |
fpu_gp_save 10,$a0 |
fpu_gp_save 11,$a0 |
fpu_gp_save 12,$a0 |
fpu_gp_save 13,$a0 |
fpu_gp_save 14,$a0 |
fpu_gp_save 15,$a0 |
fpu_gp_save 16,$a0 |
fpu_gp_save 17,$a0 |
fpu_gp_save 18,$a0 |
fpu_gp_save 19,$a0 |
fpu_gp_save 20,$a0 |
fpu_gp_save 21,$a0 |
fpu_gp_save 22,$a0 |
fpu_gp_save 23,$a0 |
fpu_gp_save 24,$a0 |
fpu_gp_save 25,$a0 |
fpu_gp_save 26,$a0 |
fpu_gp_save 27,$a0 |
fpu_gp_save 28,$a0 |
fpu_gp_save 29,$a0 |
fpu_gp_save 30,$a0 |
fpu_gp_save 31,$a0 |
fpu_ct_save 1,$a0 |
fpu_ct_save 2,$a0 |
fpu_ct_save 3,$a0 |
fpu_ct_save 4,$a0 |
fpu_ct_save 5,$a0 |
fpu_ct_save 6,$a0 |
fpu_ct_save 7,$a0 |
fpu_ct_save 8,$a0 |
fpu_ct_save 9,$a0 |
fpu_ct_save 10,$a0 |
fpu_ct_save 11,$a0 |
fpu_ct_save 12,$a0 |
fpu_ct_save 13,$a0 |
fpu_ct_save 14,$a0 |
fpu_ct_save 15,$a0 |
fpu_ct_save 16,$a0 |
fpu_ct_save 17,$a0 |
fpu_ct_save 18,$a0 |
fpu_ct_save 19,$a0 |
fpu_ct_save 20,$a0 |
fpu_ct_save 21,$a0 |
fpu_ct_save 22,$a0 |
fpu_ct_save 23,$a0 |
fpu_ct_save 24,$a0 |
fpu_ct_save 25,$a0 |
fpu_ct_save 26,$a0 |
fpu_ct_save 27,$a0 |
fpu_ct_save 28,$a0 |
fpu_ct_save 29,$a0 |
fpu_ct_save 30,$a0 |
fpu_ct_save 31,$a0 |
#endif |
#ifdef CONFIG_FPU |
fpu_gp_save 0, $a0 |
fpu_gp_save 1, $a0 |
fpu_gp_save 2, $a0 |
fpu_gp_save 3, $a0 |
fpu_gp_save 4, $a0 |
fpu_gp_save 5, $a0 |
fpu_gp_save 6, $a0 |
fpu_gp_save 7, $a0 |
fpu_gp_save 8, $a0 |
fpu_gp_save 9, $a0 |
fpu_gp_save 10, $a0 |
fpu_gp_save 11, $a0 |
fpu_gp_save 12, $a0 |
fpu_gp_save 13, $a0 |
fpu_gp_save 14, $a0 |
fpu_gp_save 15, $a0 |
fpu_gp_save 16, $a0 |
fpu_gp_save 17, $a0 |
fpu_gp_save 18, $a0 |
fpu_gp_save 19, $a0 |
fpu_gp_save 20, $a0 |
fpu_gp_save 21, $a0 |
fpu_gp_save 22, $a0 |
fpu_gp_save 23, $a0 |
fpu_gp_save 24, $a0 |
fpu_gp_save 25, $a0 |
fpu_gp_save 26, $a0 |
fpu_gp_save 27, $a0 |
fpu_gp_save 28, $a0 |
fpu_gp_save 29, $a0 |
fpu_gp_save 30, $a0 |
fpu_gp_save 31, $a0 |
fpu_ct_save 1, $a0 |
fpu_ct_save 2, $a0 |
fpu_ct_save 3, $a0 |
fpu_ct_save 4, $a0 |
fpu_ct_save 5, $a0 |
fpu_ct_save 6, $a0 |
fpu_ct_save 7, $a0 |
fpu_ct_save 8, $a0 |
fpu_ct_save 9, $a0 |
fpu_ct_save 10, $a0 |
fpu_ct_save 11, $a0 |
fpu_ct_save 12, $a0 |
fpu_ct_save 13, $a0 |
fpu_ct_save 14, $a0 |
fpu_ct_save 15, $a0 |
fpu_ct_save 16, $a0 |
fpu_ct_save 17, $a0 |
fpu_ct_save 18, $a0 |
fpu_ct_save 19, $a0 |
fpu_ct_save 20, $a0 |
fpu_ct_save 21, $a0 |
fpu_ct_save 22, $a0 |
fpu_ct_save 23, $a0 |
fpu_ct_save 24, $a0 |
fpu_ct_save 25, $a0 |
fpu_ct_save 26, $a0 |
fpu_ct_save 27, $a0 |
fpu_ct_save 28, $a0 |
fpu_ct_save 29, $a0 |
fpu_ct_save 30, $a0 |
fpu_ct_save 31, $a0 |
#endif |
j $ra |
nop |
.global fpu_context_restore |
fpu_context_restore: |
#ifdef ARCH_HAS_FPU |
fpu_gp_restore 0,$a0 |
fpu_gp_restore 1,$a0 |
fpu_gp_restore 2,$a0 |
fpu_gp_restore 3,$a0 |
fpu_gp_restore 4,$a0 |
fpu_gp_restore 5,$a0 |
fpu_gp_restore 6,$a0 |
fpu_gp_restore 7,$a0 |
fpu_gp_restore 8,$a0 |
fpu_gp_restore 9,$a0 |
fpu_gp_restore 10,$a0 |
fpu_gp_restore 11,$a0 |
fpu_gp_restore 12,$a0 |
fpu_gp_restore 13,$a0 |
fpu_gp_restore 14,$a0 |
fpu_gp_restore 15,$a0 |
fpu_gp_restore 16,$a0 |
fpu_gp_restore 17,$a0 |
fpu_gp_restore 18,$a0 |
fpu_gp_restore 19,$a0 |
fpu_gp_restore 20,$a0 |
fpu_gp_restore 21,$a0 |
fpu_gp_restore 22,$a0 |
fpu_gp_restore 23,$a0 |
fpu_gp_restore 24,$a0 |
fpu_gp_restore 25,$a0 |
fpu_gp_restore 26,$a0 |
fpu_gp_restore 27,$a0 |
fpu_gp_restore 28,$a0 |
fpu_gp_restore 29,$a0 |
fpu_gp_restore 30,$a0 |
fpu_gp_restore 31,$a0 |
fpu_ct_restore 1,$a0 |
fpu_ct_restore 2,$a0 |
fpu_ct_restore 3,$a0 |
fpu_ct_restore 4,$a0 |
fpu_ct_restore 5,$a0 |
fpu_ct_restore 6,$a0 |
fpu_ct_restore 7,$a0 |
fpu_ct_restore 8,$a0 |
fpu_ct_restore 9,$a0 |
fpu_ct_restore 10,$a0 |
fpu_ct_restore 11,$a0 |
fpu_ct_restore 12,$a0 |
fpu_ct_restore 13,$a0 |
fpu_ct_restore 14,$a0 |
fpu_ct_restore 15,$a0 |
fpu_ct_restore 16,$a0 |
fpu_ct_restore 17,$a0 |
fpu_ct_restore 18,$a0 |
fpu_ct_restore 19,$a0 |
fpu_ct_restore 20,$a0 |
fpu_ct_restore 21,$a0 |
fpu_ct_restore 22,$a0 |
fpu_ct_restore 23,$a0 |
fpu_ct_restore 24,$a0 |
fpu_ct_restore 25,$a0 |
fpu_ct_restore 26,$a0 |
fpu_ct_restore 27,$a0 |
fpu_ct_restore 28,$a0 |
fpu_ct_restore 29,$a0 |
fpu_ct_restore 30,$a0 |
fpu_ct_restore 31,$a0 |
#endif |
#ifdef CONFIG_FPU |
fpu_gp_restore 0, $a0 |
fpu_gp_restore 1, $a0 |
fpu_gp_restore 2, $a0 |
fpu_gp_restore 3, $a0 |
fpu_gp_restore 4, $a0 |
fpu_gp_restore 5, $a0 |
fpu_gp_restore 6, $a0 |
fpu_gp_restore 7, $a0 |
fpu_gp_restore 8, $a0 |
fpu_gp_restore 9, $a0 |
fpu_gp_restore 10, $a0 |
fpu_gp_restore 11, $a0 |
fpu_gp_restore 12, $a0 |
fpu_gp_restore 13, $a0 |
fpu_gp_restore 14, $a0 |
fpu_gp_restore 15, $a0 |
fpu_gp_restore 16, $a0 |
fpu_gp_restore 17, $a0 |
fpu_gp_restore 18, $a0 |
fpu_gp_restore 19, $a0 |
fpu_gp_restore 20, $a0 |
fpu_gp_restore 21, $a0 |
fpu_gp_restore 22, $a0 |
fpu_gp_restore 23, $a0 |
fpu_gp_restore 24, $a0 |
fpu_gp_restore 25, $a0 |
fpu_gp_restore 26, $a0 |
fpu_gp_restore 27, $a0 |
fpu_gp_restore 28, $a0 |
fpu_gp_restore 29, $a0 |
fpu_gp_restore 30, $a0 |
fpu_gp_restore 31, $a0 |
fpu_ct_restore 1, $a0 |
fpu_ct_restore 2, $a0 |
fpu_ct_restore 3, $a0 |
fpu_ct_restore 4, $a0 |
fpu_ct_restore 5, $a0 |
fpu_ct_restore 6, $a0 |
fpu_ct_restore 7, $a0 |
fpu_ct_restore 8, $a0 |
fpu_ct_restore 9, $a0 |
fpu_ct_restore 10, $a0 |
fpu_ct_restore 11, $a0 |
fpu_ct_restore 12, $a0 |
fpu_ct_restore 13, $a0 |
fpu_ct_restore 14, $a0 |
fpu_ct_restore 15, $a0 |
fpu_ct_restore 16, $a0 |
fpu_ct_restore 17, $a0 |
fpu_ct_restore 18, $a0 |
fpu_ct_restore 19, $a0 |
fpu_ct_restore 20, $a0 |
fpu_ct_restore 21, $a0 |
fpu_ct_restore 22, $a0 |
fpu_ct_restore 23, $a0 |
fpu_ct_restore 24, $a0 |
fpu_ct_restore 25, $a0 |
fpu_ct_restore 26, $a0 |
fpu_ct_restore 27, $a0 |
fpu_ct_restore 28, $a0 |
fpu_ct_restore 29, $a0 |
fpu_ct_restore 30, $a0 |
fpu_ct_restore 31, $a0 |
#endif |
j $ra |
nop |
/branches/dd/kernel/arch/mips32/src/console.c |
---|
34,25 → 34,18 |
#include <console/console.h> |
#include <arch/console.h> |
#include <arch/drivers/arc.h> |
#include <arch/drivers/serial.h> |
#include <arch/drivers/msim.h> |
#include <genarch/fb/fb.h> |
void console_init(devno_t devno) |
{ |
if (!arc_console()) { |
if (serial_init()) |
serial_console(devno); |
else |
msim_console(devno); |
} |
} |
/** Acquire console back for kernel |
* |
*/ |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
msim_kbd_grab(); |
} |
/branches/dd/kernel/arch/mips32/src/cache.c |
---|
38,7 → 38,7 |
void cache_error(istate_t *istate) |
{ |
panic("cache_error exception (epc=%p)\n", istate->epc); |
panic("cache_error exception (epc=%p).", istate->epc); |
} |
/** @} |
/branches/dd/kernel/arch/mips32/src/cpu/cpu.c |
---|
48,7 → 48,7 |
{ "MIPS", "R2000" }, /* 0x01 */ |
{ "MIPS", "R3000" }, /* 0x02 */ |
{ "MIPS", "R6000" }, /* 0x03 */ |
{ "MIPS", " R4000/R4400" }, /* 0x04 */ |
{ "MIPS", "R4000/R4400" }, /* 0x04 */ |
{ "LSI Logic", "R3000" }, /* 0x05 */ |
{ "MIPS", "R6000A" }, /* 0x06 */ |
{ "IDT", "3051/3052" }, /* 0x07 */ |
123,9 → 123,9 |
data = &imp_data[m->arch.imp_num]; |
} |
printf("cpu%d: %s %s (rev=%d.%d, imp=%d)\n", |
printf("cpu%u: %s %s (rev=%d.%d, imp=%d)\n", |
m->id, data->vendor, data->model, m->arch.rev_num >> 4, |
m->arch.rev_num & 0xf, m->arch.imp_num); |
m->arch.rev_num & 0x0f, m->arch.imp_num); |
} |
/** @} |
/branches/dd/kernel/arch/mips32/src/mips32.c |
---|
33,7 → 33,6 |
*/ |
#include <arch.h> |
#include <arch/boot.h> |
#include <arch/cp0.h> |
#include <arch/exception.h> |
#include <mm/as.h> |
48,44 → 47,55 |
#include <sysinfo/sysinfo.h> |
#include <arch/interrupt.h> |
#include <arch/drivers/arc.h> |
#include <console/chardev.h> |
#include <arch/barrier.h> |
#include <arch/debugger.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <macros.h> |
#include <ddi/device.h> |
#include <config.h> |
#include <string.h> |
#include <arch/drivers/msim.h> |
#include <arch/asm/regname.h> |
/* Size of the code jumping to the exception handler code |
* - J+NOP |
/* Size of the code jumping to the exception handler code |
* - J+NOP |
*/ |
#define EXCEPTION_JUMP_SIZE 8 |
#define EXCEPTION_JUMP_SIZE 8 |
#define TLB_EXC ((char *) 0x80000000) |
#define NORM_EXC ((char *) 0x80000180) |
#define CACHE_EXC ((char *) 0x80000100) |
#define TLB_EXC ((char *) 0x80000000) |
#define NORM_EXC ((char *) 0x80000180) |
#define CACHE_EXC ((char *) 0x80000100) |
/* Why the linker moves the variable 64K away in assembler |
* when not in .text section ???????? |
* when not in .text section? |
*/ |
/* Stack pointer saved when entering user mode */ |
uintptr_t supervisor_sp __attribute__ ((section (".text"))); |
/* Stack pointer saved when entering user mode */ |
/* TODO: How do we do it on SMP system???? */ |
bootinfo_t bootinfo __attribute__ ((section (".text"))); |
void arch_pre_main(void) |
count_t cpu_count = 0; |
/** Performs mips32-specific initialization before main_bsp() is called. */ |
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo) |
{ |
/* Setup usermode */ |
init.cnt = bootinfo.cnt; |
init.cnt = bootinfo->cnt; |
uint32_t i; |
count_t i; |
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) { |
init.tasks[i].addr = bootinfo->tasks[i].addr; |
init.tasks[i].size = bootinfo->tasks[i].size; |
strncpy(init.tasks[i].name, bootinfo->tasks[i].name, |
CONFIG_TASK_NAME_BUFLEN); |
} |
for (i = 0; i < bootinfo.cnt; i++) { |
init.tasks[i].addr = bootinfo.tasks[i].addr; |
init.tasks[i].size = bootinfo.tasks[i].size; |
for (i = 0; i < CPUMAP_MAX_RECORDS; i++) { |
if ((bootinfo->cpumap & (1 << i)) != 0) |
cpu_count++; |
} |
} |
96,24 → 106,27 |
/* Initialize dispatch table */ |
exception_init(); |
arc_init(); |
/* Copy the exception vectors to the right places */ |
memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(TLB_EXC, EXCEPTION_JUMP_SIZE); |
memcpy(NORM_EXC, (char *) exception_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(NORM_EXC, EXCEPTION_JUMP_SIZE); |
memcpy(CACHE_EXC, (char *) cache_error_entry, EXCEPTION_JUMP_SIZE); |
smc_coherence_block(CACHE_EXC, EXCEPTION_JUMP_SIZE); |
/* |
* Switch to BEV normal level so that exception vectors point to the kernel. |
* Clear the error level. |
* Switch to BEV normal level so that exception vectors point to the |
* kernel. Clear the error level. |
*/ |
cp0_status_write(cp0_status_read() & ~(cp0_status_bev_bootstrap_bit|cp0_status_erl_error_bit)); |
/* |
* Mask all interrupts |
cp0_status_write(cp0_status_read() & |
~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit)); |
/* |
* Mask all interrupts |
*/ |
cp0_mask_all_int(); |
debugger_init(); |
} |
120,11 → 133,35 |
void arch_post_mm_init(void) |
{ |
interrupt_init(); |
console_init(device_assign_devno()); |
msim_console(device_assign_devno()); |
#ifdef CONFIG_FB |
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8); // gxemul framebuffer |
/* GXemul framebuffer */ |
fb_properties_t gxemul_prop = { |
.addr = 0x12000000, |
.offset = 0, |
.x = 640, |
.y = 480, |
.scan = 1920, |
.visual = VISUAL_BGR_8_8_8, |
}; |
fb_init(&gxemul_prop); |
#endif |
sysinfo_set_item_val("machine." STRING(MACHINE), NULL, 1); |
#ifdef MACHINE_msim |
sysinfo_set_item_val("machine.msim", NULL, 1); |
#endif |
#ifdef MACHINE_simics |
sysinfo_set_item_val("machine.simics", NULL, 1); |
#endif |
#ifdef MACHINE_bgxemul |
sysinfo_set_item_val("machine.bgxemul", NULL, 1); |
#endif |
#ifdef MACHINE_lgxemul |
sysinfo_set_item_val("machine.lgxemul", NULL, 1); |
#endif |
} |
void arch_post_cpu_init(void) |
139,15 → 176,19 |
{ |
} |
void calibrate_delay_loop(void) |
{ |
} |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
/* EXL = 1, UM = 1, IE = 1 */ |
cp0_status_write(cp0_status_read() | (cp0_status_exl_exception_bit | |
cp0_status_um_bit | cp0_status_ie_enabled_bit)); |
cp0_status_um_bit | cp0_status_ie_enabled_bit)); |
cp0_epc_write((uintptr_t) kernel_uarg->uspace_entry); |
userspace_asm(((uintptr_t) kernel_uarg->uspace_stack + PAGE_SIZE), |
(uintptr_t) kernel_uarg->uspace_uarg, |
(uintptr_t) kernel_uarg->uspace_entry); |
(uintptr_t) kernel_uarg->uspace_uarg, |
(uintptr_t) kernel_uarg->uspace_entry); |
while (1); |
} |
160,7 → 201,8 |
/** Perform mips32 specific tasks needed before the new thread is scheduled. */ |
void before_thread_runs_arch(void) |
{ |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA]; |
supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
SP_DELTA]; |
} |
void after_thread_ran_arch(void) |
179,11 → 221,24 |
void arch_reboot(void) |
{ |
if (!arc_reboot()) |
___halt(); |
___halt(); |
while (1); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/mips32/src/start.S |
---|
31,7 → 31,7 |
#include <arch/asm/boot.h> |
#include <arch/context_offset.h> |
#include <arch/stack.h> |
.text |
.set noat |
75,18 → 75,6 |
mfhi $at |
sw $at, EOFFSET_HI(\r) |
#ifdef CONFIG_DEBUG_ALLREGS |
sw $s0, EOFFSET_S0(\r) |
sw $s1, EOFFSET_S1(\r) |
sw $s2, EOFFSET_S2(\r) |
sw $s3, EOFFSET_S3(\r) |
sw $s4, EOFFSET_S4(\r) |
sw $s5, EOFFSET_S5(\r) |
sw $s6, EOFFSET_S6(\r) |
sw $s7, EOFFSET_S7(\r) |
sw $s8, EOFFSET_S8(\r) |
#endif |
sw $gp, EOFFSET_GP(\r) |
sw $ra, EOFFSET_RA(\r) |
sw $k1, EOFFSET_K1(\r) |
132,17 → 120,6 |
lw $t8, EOFFSET_T8(\r) |
lw $t9, EOFFSET_T9(\r) |
#ifdef CONFIG_DEBUG_ALLREGS |
lw $s0, EOFFSET_S0(\r) |
lw $s1, EOFFSET_S1(\r) |
lw $s2, EOFFSET_S2(\r) |
lw $s3, EOFFSET_S3(\r) |
lw $s4, EOFFSET_S4(\r) |
lw $s5, EOFFSET_S5(\r) |
lw $s6, EOFFSET_S6(\r) |
lw $s7, EOFFSET_S7(\r) |
lw $s8, EOFFSET_S8(\r) |
#endif |
lw $gp, EOFFSET_GP(\r) |
lw $ra, EOFFSET_RA(\r) |
lw $k1, EOFFSET_K1(\r) |
175,9 → 152,9 |
ori $k0, $k0, %lo(supervisor_sp) |
# Move $k0 (superveisor_sp) |
lw $k0, 0($k0) |
1: |
1: |
.endm |
.org 0x0 |
kernel_image_start: |
/* Load temporary stack */ |
184,31 → 161,12 |
lui $sp, %hi(end_stack) |
ori $sp, $sp, %lo(end_stack) |
/* $a1 contains physical address of bootinfo_t */ |
/* $a2 contains size of bootinfo_t */ |
beq $a2, $0, bootinfo_end |
/* Not sure about this, but might be needed for PIC code???? */ |
/* Not sure about this, but might |
be needed for PIC code */ |
lui $gp, 0x8000 |
lui $a3, %hi(bootinfo) |
ori $a3, $a3, %lo(bootinfo) |
/* $a1 contains physical address of bootinfo_t */ |
bootinfo_loop: |
lw $v0, 0($a1) |
sw $v0, 0($a3) |
addi $a1, $a1, 4 |
addi $a3, $a3, 4 |
addi $a2, $a2, -4 |
bgtz $a2, bootinfo_loop |
nop |
bootinfo_end: |
jal arch_pre_main |
nop |
228,8 → 186,8 |
exception_entry: |
j exception_handler |
nop |
nop |
exception_handler: |
KERNEL_STACK_TO_K0 |
sub $k0, REGISTER_SPACE |
238,17 → 196,17 |
mfc0 $k0, $cause |
sra $k0, $k0, 0x2 # cp0_exc_cause() part 1 |
andi $k0, $k0, 0x1f # cp0_exc_cause() part 2 |
sub $k0, 8 # 8 = SYSCALL |
sra $k0, $k0, 0x2 # cp0_exc_cause() part 1 |
andi $k0, $k0, 0x1f # cp0_exc_cause() part 2 |
sub $k0, 8 # 8 = SYSCALL |
beqz $k0, syscall_shortcut |
add $k0, 8 # Revert $k0 back to correct exc number |
add $k0, 8 # Revert $k0 back to correct exc number |
REGISTERS_STORE_AND_EXC_RESET $sp |
move $a1, $sp |
jal exc_dispatch # exc_dispatch(excno, register_space) |
jal exc_dispatch # exc_dispatch(excno, register_space) |
move $a0, $k0 |
REGISTERS_LOAD $sp |
349,5 → 307,7 |
userspace_asm: |
add $sp, $a0, 0 |
add $v0, $a1, 0 |
add $t9, $a2, 0 # Set up correct entry into PIC code |
add $t9, $a2, 0 # Set up correct entry into PIC code |
xor $a0, $a0, $a0 # $a0 is defined to hold pcb_ptr |
# set it to 0 |
eret |
/branches/dd/kernel/arch/mips32/src/smp/order.c |
---|
File deleted |
/branches/dd/kernel/arch/mips32/src/smp/dorder.c |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2007 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/smp/dorder.h> |
#define MSIM_DORDER_ADDRESS 0xB0000004 |
void ipi_broadcast_arch(int ipi) |
{ |
#ifdef CONFIG_SMP |
*((volatile unsigned int *) MSIM_DORDER_ADDRESS) = 0x7FFFFFFF; |
#endif |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/mips32/src/smp/smp.c |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32 |
* @{ |
*/ |
/** @file |
*/ |
#include <config.h> |
#include <smp/smp.h> |
#include <arch/arch.h> |
#ifdef CONFIG_SMP |
void smp_init(void) |
{ |
config.cpu_count = cpu_count; |
} |
void kmp(void *arg __attribute__((unused))) |
{ |
} |
#endif /* CONFIG_SMP */ |
/** @} |
*/ |
/branches/dd/kernel/arch/mips32/src/debugger.c |
---|
33,6 → 33,7 |
*/ |
#include <arch/debugger.h> |
#include <arch/barrier.h> |
#include <memstr.h> |
#include <console/kconsole.h> |
#include <console/cmd.h> |
46,6 → 47,8 |
bpinfo_t breakpoints[BKPOINTS_MAX]; |
SPINLOCK_INITIALIZE(bkpoint_lock); |
#ifdef CONFIG_KCONSOLE |
static int cmd_print_breakpoints(cmd_arg_t *argv); |
static cmd_info_t bkpts_info = { |
.name = "bkpts", |
72,7 → 75,8 |
}; |
static cmd_info_t addbkpt_info = { |
.name = "addbkpt", |
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.", |
.description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch " |
"insts unsupported.", |
.func = cmd_add_breakpoint, |
.argc = 1, |
.argv = &add_argv |
84,7 → 88,8 |
}; |
static cmd_info_t addbkpte_info = { |
.name = "addbkpte", |
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).", |
.description = "addebkpte <&symbol> <&func> - new bkpoint. Call " |
"func(or Nothing if 0).", |
.func = cmd_add_breakpoint, |
.argc = 2, |
.argv = adde_argv |
93,7 → 98,7 |
static struct { |
uint32_t andmask; |
uint32_t value; |
}jmpinstr[] = { |
} jmpinstr[] = { |
{0xf3ff0000, 0x41000000}, /* BCzF */ |
{0xf3ff0000, 0x41020000}, /* BCzFL */ |
{0xf3ff0000, 0x41010000}, /* BCzT */ |
117,19 → 122,21 |
{0xfc000000, 0x08000000}, /* J */ |
{0xfc000000, 0x0c000000}, /* JAL */ |
{0xfc1f07ff, 0x00000009}, /* JALR */ |
{0,0} /* EndOfTable */ |
{0, 0} /* EndOfTable */ |
}; |
/** Test, if the given instruction is a jump or branch instruction |
* |
* @param instr Instruction code |
* @return true - it is jump instruction, false otherwise |
* |
*/ |
static bool is_jump(unative_t instr) |
{ |
int i; |
for (i=0;jmpinstr[i].andmask;i++) { |
for (i = 0; jmpinstr[i].andmask; i++) { |
if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value) |
return true; |
} |
152,21 → 159,23 |
spinlock_lock(&bkpoint_lock); |
/* Check, that the breakpoints do not conflict */ |
for (i=0; i<BKPOINTS_MAX; i++) { |
for (i = 0; i < BKPOINTS_MAX; i++) { |
if (breakpoints[i].address == (uintptr_t)argv->intval) { |
printf("Duplicate breakpoint %d.\n", i); |
spinlock_unlock(&bkpoints_lock); |
spinlock_unlock(&bkpoint_lock); |
return 0; |
} else if (breakpoints[i].address == (uintptr_t)argv->intval + sizeof(unative_t) || \ |
breakpoints[i].address == (uintptr_t)argv->intval - sizeof(unative_t)) { |
printf("Adjacent breakpoints not supported, conflict with %d.\n", i); |
spinlock_unlock(&bkpoints_lock); |
} else if (breakpoints[i].address == (uintptr_t)argv->intval + |
sizeof(unative_t) || breakpoints[i].address == |
(uintptr_t)argv->intval - sizeof(unative_t)) { |
printf("Adjacent breakpoints not supported, conflict " |
"with %d.\n", i); |
spinlock_unlock(&bkpoint_lock); |
return 0; |
} |
} |
for (i=0; i<BKPOINTS_MAX; i++) |
for (i = 0; i < BKPOINTS_MAX; i++) |
if (!breakpoints[i].address) { |
cur = &breakpoints[i]; |
break; |
185,7 → 194,7 |
cur->flags = 0; |
} else { /* We are add extended */ |
cur->flags = BKPOINT_FUNCCALL; |
cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; |
cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; |
} |
if (is_jump(cur->instruction)) |
cur->flags |= BKPOINT_ONESHOT; |
193,6 → 202,7 |
/* Set breakpoint */ |
*((unative_t *)cur->address) = 0x0d; |
smc_coherence(cur->address); |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
200,8 → 210,6 |
return 1; |
} |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
229,7 → 237,9 |
return 0; |
} |
((uint32_t *)cur->address)[0] = cur->instruction; |
smc_coherence(((uint32_t *)cur->address)[0]); |
((uint32_t *)cur->address)[1] = cur->nextinstruction; |
smc_coherence(((uint32_t *)cur->address)[1]); |
cur->address = NULL; |
252,38 → 262,42 |
symbol = get_symtab_entry(breakpoints[i].address); |
printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i, |
breakpoints[i].counter, breakpoints[i].address, |
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : "false"), |
((breakpoints[i].flags & BKPOINT_ONESHOT) ? "true" : "false"), |
((breakpoints[i].flags & BKPOINT_FUNCCALL) ? "true" : "false"), |
symbol); |
breakpoints[i].counter, breakpoints[i].address, |
((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : |
"false"), ((breakpoints[i].flags & BKPOINT_ONESHOT) |
? "true" : "false"), ((breakpoints[i].flags & |
BKPOINT_FUNCCALL) ? "true" : "false"), symbol); |
} |
return 1; |
} |
#endif |
/** Initialize debugger */ |
void debugger_init() |
{ |
int i; |
for (i=0; i<BKPOINTS_MAX; i++) |
for (i = 0; i < BKPOINTS_MAX; i++) |
breakpoints[i].address = NULL; |
#ifdef CONFIG_KCONSOLE |
cmd_initialize(&bkpts_info); |
if (!cmd_register(&bkpts_info)) |
panic("could not register command %s\n", bkpts_info.name); |
printf("Cannot register command %s\n", bkpts_info.name); |
cmd_initialize(&delbkpt_info); |
if (!cmd_register(&delbkpt_info)) |
panic("could not register command %s\n", delbkpt_info.name); |
printf("Cannot register command %s\n", delbkpt_info.name); |
cmd_initialize(&addbkpt_info); |
if (!cmd_register(&addbkpt_info)) |
panic("could not register command %s\n", addbkpt_info.name); |
printf("Cannot register command %s\n", addbkpt_info.name); |
cmd_initialize(&addbkpte_info); |
if (!cmd_register(&addbkpte_info)) |
panic("could not register command %s\n", addbkpte_info.name); |
printf("Cannot register command %s\n", addbkpte_info.name); |
#endif |
} |
/** Handle breakpoint |
302,19 → 316,19 |
/* test branch delay slot */ |
if (cp0_cause_read() & 0x80000000) |
panic("Breakpoint in branch delay slot not supported.\n"); |
panic("Breakpoint in branch delay slot not supported."); |
spinlock_lock(&bkpoint_lock); |
for (i=0; i<BKPOINTS_MAX; i++) { |
for (i = 0; i < BKPOINTS_MAX; i++) { |
/* Normal breakpoint */ |
if (fireaddr == breakpoints[i].address \ |
&& !(breakpoints[i].flags & BKPOINT_REINST)) { |
if (fireaddr == breakpoints[i].address && |
!(breakpoints[i].flags & BKPOINT_REINST)) { |
cur = &breakpoints[i]; |
break; |
} |
/* Reinst only breakpoint */ |
if ((breakpoints[i].flags & BKPOINT_REINST) \ |
&& (fireaddr ==breakpoints[i].address+sizeof(unative_t))) { |
if ((breakpoints[i].flags & BKPOINT_REINST) && |
(fireaddr == breakpoints[i].address + sizeof(unative_t))) { |
cur = &breakpoints[i]; |
break; |
} |
323,8 → 337,10 |
if (cur->flags & BKPOINT_REINST) { |
/* Set breakpoint on first instruction */ |
((uint32_t *)cur->address)[0] = 0x0d; |
smc_coherence(((uint32_t *)cur->address)[0]); |
/* Return back the second */ |
((uint32_t *)cur->address)[1] = cur->nextinstruction; |
smc_coherence(((uint32_t *)cur->address)[1]); |
cur->flags &= ~BKPOINT_REINST; |
spinlock_unlock(&bkpoint_lock); |
return; |
333,11 → 349,12 |
printf("Warning: breakpoint recursion\n"); |
if (!(cur->flags & BKPOINT_FUNCCALL)) |
printf("***Breakpoint %d: %p in %s.\n", i, |
fireaddr, get_symtab_entry(istate->epc)); |
printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, |
get_symtab_entry(istate->epc)); |
/* Return first instruction back */ |
((uint32_t *)cur->address)[0] = cur->instruction; |
smc_coherence(cur->address); |
if (! (cur->flags & BKPOINT_ONESHOT)) { |
/* Set Breakpoint on next instruction */ |
358,19 → 375,20 |
if (cur->bkfunc) |
cur->bkfunc(cur, istate); |
} else { |
printf("***Type 'exit' to exit kconsole.\n"); |
#ifdef CONFIG_KCONSOLE |
/* This disables all other processors - we are not SMP, |
* actually this gets us to cpu_halt, if scheduler() is run |
* - we generally do not want scheduler to be run from debug, |
* so this is a good idea |
*/ |
atomic_set(&haltstate,1); |
atomic_set(&haltstate, 1); |
spinlock_unlock(&bkpoint_lock); |
kconsole("debug"); |
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false); |
spinlock_lock(&bkpoint_lock); |
atomic_set(&haltstate,0); |
atomic_set(&haltstate, 0); |
#endif |
} |
if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) { |
/* Remove one-shot breakpoint */ |
/branches/dd/kernel/arch/mips32/src/mm/tlb.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32mm |
/** @addtogroup mips32mm |
* @{ |
*/ |
/** @file |
41,24 → 41,20 |
#include <panic.h> |
#include <arch.h> |
#include <symtab.h> |
#include <synch/spinlock.h> |
#include <synch/mutex.h> |
#include <print.h> |
#include <debug.h> |
#include <align.h> |
#include <interrupt.h> |
static void tlb_refill_fail(istate_t *istate); |
static void tlb_invalid_fail(istate_t *istate); |
static void tlb_modified_fail(istate_t *istate); |
static void tlb_refill_fail(istate_t *); |
static void tlb_invalid_fail(istate_t *); |
static void tlb_modified_fail(istate_t *); |
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc); |
static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *, int *); |
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn); |
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr); |
/** Initialize TLB |
/** Initialize TLB. |
* |
* Initialize TLB. |
* Invalidate all entries and mark wired entries. |
*/ |
void tlb_arch_init(void) |
76,7 → 72,6 |
cp0_index_write(i); |
tlbwi(); |
} |
/* |
* The kernel is going to make use of some wired |
85,11 → 80,9 |
cp0_wired_write(TLB_WIRED); |
} |
/** Process TLB Refill Exception |
/** Process TLB Refill Exception. |
* |
* Process TLB Refill Exception. |
* |
* @param istate Interrupted register context. |
* @param istate Interrupted register context. |
*/ |
void tlb_refill(istate_t *istate) |
{ |
99,15 → 92,15 |
uintptr_t badvaddr; |
pte_t *pte; |
int pfrc; |
badvaddr = cp0_badvaddr_read(); |
spinlock_lock(&AS->lock); |
mutex_lock(&AS->lock); |
asid = AS->asid; |
spinlock_unlock(&AS->lock); |
mutex_unlock(&AS->lock); |
page_table_lock(AS, true); |
pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
122,7 → 115,7 |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
panic("Unexpected pfrc (%d).", pfrc); |
} |
} |
131,14 → 124,15 |
*/ |
pte->a = 1; |
prepare_entry_hi(&hi, asid, badvaddr); |
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
tlb_prepare_entry_hi(&hi, asid, badvaddr); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, |
pte->pfn); |
/* |
* New entry is to be inserted into TLB |
*/ |
cp0_entry_hi_write(hi.value); |
if ((badvaddr/PAGE_SIZE) % 2 == 0) { |
if ((badvaddr / PAGE_SIZE) % 2 == 0) { |
cp0_entry_lo0_write(lo.value); |
cp0_entry_lo1_write(0); |
} |
157,11 → 151,9 |
tlb_refill_fail(istate); |
} |
/** Process TLB Invalid Exception |
/** Process TLB Invalid Exception. |
* |
* Process TLB Invalid Exception. |
* |
* @param istate Interrupted register context. |
* @param istate Interrupted register context. |
*/ |
void tlb_invalid(istate_t *istate) |
{ |
178,7 → 170,7 |
* Locate the faulting entry in TLB. |
*/ |
hi.value = cp0_entry_hi_read(); |
prepare_entry_hi(&hi, hi.asid, badvaddr); |
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
index.value = cp0_index_read(); |
207,7 → 199,7 |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
panic("Unexpected pfrc (%d).", pfrc); |
} |
} |
221,12 → 213,13 |
*/ |
pte->a = 1; |
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, |
pte->pfn); |
/* |
* The entry is to be updated in TLB. |
*/ |
if ((badvaddr/PAGE_SIZE) % 2 == 0) |
if ((badvaddr / PAGE_SIZE) % 2 == 0) |
cp0_entry_lo0_write(lo.value); |
else |
cp0_entry_lo1_write(lo.value); |
241,11 → 234,9 |
tlb_invalid_fail(istate); |
} |
/** Process TLB Modified Exception |
/** Process TLB Modified Exception. |
* |
* Process TLB Modified Exception. |
* |
* @param istate Interrupted register context. |
* @param istate Interrupted register context. |
*/ |
void tlb_modified(istate_t *istate) |
{ |
262,7 → 253,7 |
* Locate the faulting entry in TLB. |
*/ |
hi.value = cp0_entry_hi_read(); |
prepare_entry_hi(&hi, hi.asid, badvaddr); |
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
index.value = cp0_index_read(); |
291,17 → 282,11 |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
panic("Unexpected pfrc (%d).", pfrc); |
} |
} |
/* |
* Fail if the page is not writable. |
*/ |
if (!pte->w) |
goto fail; |
/* |
* Read the faulting TLB entry. |
*/ |
tlbr(); |
312,12 → 297,13 |
pte->a = 1; |
pte->d = 1; |
prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, |
pte->pfn); |
/* |
* The entry is to be updated in TLB. |
*/ |
if ((badvaddr/PAGE_SIZE) % 2 == 0) |
if ((badvaddr / PAGE_SIZE) % 2 == 0) |
cp0_entry_lo0_write(lo.value); |
else |
cp0_entry_lo1_write(lo.value); |
344,8 → 330,10 |
if (s) |
sym2 = s; |
fault_if_from_uspace(istate, "TLB Refill Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), istate->epc, symbol, sym2); |
fault_if_from_uspace(istate, "TLB Refill Exception on %p.", |
cp0_badvaddr_read()); |
panic("%x: TLB Refill Exception at %x(%s<-%s).", cp0_badvaddr_read(), |
istate->epc, symbol, sym2); |
} |
356,8 → 344,10 |
char *s = get_symtab_entry(istate->epc); |
if (s) |
symbol = s; |
fault_if_from_uspace(istate, "TLB Invalid Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol); |
fault_if_from_uspace(istate, "TLB Invalid Exception on %p.", |
cp0_badvaddr_read()); |
panic("%x: TLB Invalid Exception at %x(%s).", cp0_badvaddr_read(), |
istate->epc, symbol); |
} |
void tlb_modified_fail(istate_t *istate) |
367,23 → 357,27 |
char *s = get_symtab_entry(istate->epc); |
if (s) |
symbol = s; |
fault_if_from_uspace(istate, "TLB Modified Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol); |
fault_if_from_uspace(istate, "TLB Modified Exception on %p.", |
cp0_badvaddr_read()); |
panic("%x: TLB Modified Exception at %x(%s).", cp0_badvaddr_read(), |
istate->epc, symbol); |
} |
/** Try to find PTE for faulting address |
/** Try to find PTE for faulting address. |
* |
* Try to find PTE for faulting address. |
* The AS->lock must be held on entry to this function. |
* |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code |
* will be stored. |
* |
* @return PTE on success, NULL otherwise. |
* @return PTE on success, NULL otherwise. |
*/ |
pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
pte_t * |
find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, |
int *pfrc) |
{ |
entry_hi_t hi; |
pte_t *pte; |
402,7 → 396,7 |
* Check if the mapping exists in page tables. |
*/ |
pte = page_mapping_find(AS, badvaddr); |
if (pte && pte->p) { |
if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) { |
/* |
* Mapping found in page tables. |
* Immediately succeed. |
425,6 → 419,7 |
page_table_lock(AS, true); |
pte = page_mapping_find(AS, badvaddr); |
ASSERT(pte && pte->p); |
ASSERT(pte->w || access != PF_ACCESS_WRITE); |
return pte; |
break; |
case AS_PF_DEFER: |
434,18 → 429,19 |
break; |
case AS_PF_FAULT: |
page_table_lock(AS, true); |
printf("Page fault.\n"); |
*pfrc = AS_PF_FAULT; |
return NULL; |
break; |
default: |
panic("unexpected rc (%d)\n", rc); |
panic("Unexpected rc (%d).", rc); |
} |
} |
} |
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn) |
void |
tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, |
uintptr_t pfn) |
{ |
lo->value = 0; |
lo->g = g; |
455,7 → 451,7 |
lo->pfn = pfn; |
} |
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) |
void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) |
{ |
hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2); |
hi->asid = asid; |
484,10 → 480,10 |
lo1.value = cp0_entry_lo1_read(); |
printf("%-2u %-4u %#6x %#4x %1u %1u %1u %1u %#6x\n", |
i, hi.asid, hi.vpn2, mask.mask, |
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn); |
i, hi.asid, hi.vpn2, mask.mask, |
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn); |
printf(" %1u %1u %1u %1u %#6x\n", |
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn); |
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn); |
} |
cp0_entry_hi_write(hi_save.value); |
564,11 → 560,12 |
cp0_entry_hi_write(hi_save.value); |
} |
/** Invalidate TLB entries for specified page range belonging to specified address space. |
/** Invalidate TLB entries for specified page range belonging to specified |
* address space. |
* |
* @param asid Address space identifier. |
* @param page First page whose TLB entry is to be invalidated. |
* @param cnt Number of entries to invalidate. |
* @param asid Address space identifier. |
* @param page First page whose TLB entry is to be invalidated. |
* @param cnt Number of entries to invalidate. |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
585,7 → 582,7 |
for (i = 0; i < cnt + 1; i += 2) { |
hi.value = 0; |
prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); |
tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); |
cp0_entry_hi_write(hi.value); |
tlbp(); |
592,7 → 589,10 |
index.value = cp0_index_read(); |
if (!index.p) { |
/* Entry was found, index register contains valid index. */ |
/* |
* Entry was found, index register contains valid |
* index. |
*/ |
tlbr(); |
lo0.value = cp0_entry_lo0_read(); |
/branches/dd/kernel/arch/mips32/src/mm/as.c |
---|
44,7 → 44,7 |
/** Architecture dependent address space init. */ |
void as_arch_init(void) |
{ |
as_operations = &as_pt_operations; |
as_operations = &as_pt_operations; |
asid_fifo_init(); |
} |
/branches/dd/kernel/arch/mips32/src/mm/frame.c |
---|
26,33 → 26,244 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32mm |
/** @addtogroup mips32mm |
* @{ |
*/ |
/** @file |
*/ |
#include <macros.h> |
#include <arch/mm/frame.h> |
#include <arch/mm/tlb.h> |
#include <interrupt.h> |
#include <mm/frame.h> |
#include <mm/asid.h> |
#include <config.h> |
#include <arch/drivers/arc.h> |
#include <arch/drivers/msim.h> |
#include <arch/drivers/serial.h> |
#include <print.h> |
#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K |
#define ZERO_FRAMES 2048 |
#define ZERO_PAGE_WIDTH 18 /* 256K */ |
#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH) |
#define ZERO_PAGE_ASID ASID_INVALID |
#define ZERO_PAGE_TLBI 0 |
#define ZERO_PAGE_ADDR 0 |
#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1) |
#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET]) |
#define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET]) |
#define MAX_REGIONS 32 |
typedef struct { |
pfn_t start; |
pfn_t count; |
} phys_region_t; |
static count_t phys_regions_count = 0; |
static phys_region_t phys_regions[MAX_REGIONS]; |
/** Check whether frame is available |
* |
* Returns true if given frame is generally available for use. |
* Returns false if given frame is used for physical memory |
* mapped devices and cannot be used. |
* |
*/ |
static bool frame_available(pfn_t frame) |
{ |
#ifdef MACHINE_msim |
/* MSIM device (dprinter) */ |
if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH)) |
return false; |
/* MSIM device (dkeyboard) */ |
if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH)) |
return false; |
#endif |
#ifdef MACHINE_simics |
/* Simics device (serial line) */ |
if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH)) |
return false; |
#endif |
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) |
/* gxemul devices */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
0x10000000, MB2SIZE(256))) |
return false; |
#endif |
return true; |
} |
/** Check whether frame is safe to write |
* |
* Returns true if given frame is safe for read/write test. |
* Returns false if given frame should not be touched. |
* |
*/ |
static bool frame_safe(pfn_t frame) |
{ |
/* Kernel structures */ |
if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base)) |
return false; |
/* Kernel */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(config.base), config.kernel_size)) |
return false; |
/* Kernel stack */ |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(config.stack_base), config.stack_size)) |
return false; |
/* Init tasks */ |
bool safe = true; |
count_t i; |
for (i = 0; i < init.cnt; i++) |
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, |
KA2PA(init.tasks[i].addr), init.tasks[i].size)) { |
safe = false; |
break; |
} |
return safe; |
} |
static void frame_add_region(pfn_t start_frame, pfn_t end_frame) |
{ |
if (end_frame > start_frame) { |
/* Convert 1M frames to 16K frames */ |
pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH); |
pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH); |
/* Interrupt vector frame is blacklisted */ |
pfn_t conf_frame; |
if (first == 0) |
conf_frame = 1; |
else |
conf_frame = first; |
zone_create(first, count, conf_frame, 0); |
if (phys_regions_count < MAX_REGIONS) { |
phys_regions[phys_regions_count].start = first; |
phys_regions[phys_regions_count].count = count; |
phys_regions_count++; |
} |
} |
} |
/** Create memory zones |
* |
* If ARC is known, read information from ARC, otherwise |
* assume some defaults. |
* - blacklist first FRAME because there is an exception vector |
* Walk through available 256 KB chunks of physical |
* memory and create zones. |
* |
* Note: It is assumed that the TLB is not yet being |
* used in any way, thus there is no interference. |
* |
*/ |
void frame_arch_init(void) |
{ |
if (!arc_frame_init()) { |
zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0); |
/* |
* Blacklist interrupt vector |
*/ |
frame_mark_unavailable(0, 1); |
ipl_t ipl = interrupts_disable(); |
/* Clear and initialize TLB */ |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(0); |
cp0_entry_lo1_write(0); |
cp0_entry_hi_write(0); |
count_t i; |
for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
cp0_index_write(i); |
tlbwi(); |
} |
pfn_t start_frame = 0; |
pfn_t frame; |
bool avail = true; |
/* Walk through all 1 MB frames */ |
for (frame = 0; frame < ZERO_FRAMES; frame++) { |
if (!frame_available(frame)) |
avail = false; |
else { |
if (frame_safe(frame)) { |
entry_lo_t lo0; |
entry_lo_t lo1; |
entry_hi_t hi; |
tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12)); |
tlb_prepare_entry_lo(&lo1, false, false, false, false, 0); |
tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR); |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(lo0.value); |
cp0_entry_lo1_write(lo1.value); |
cp0_entry_hi_write(hi.value); |
cp0_index_write(ZERO_PAGE_TLBI); |
tlbwi(); |
ZERO_PAGE_VALUE = 0; |
if (ZERO_PAGE_VALUE != 0) |
avail = false; |
else { |
ZERO_PAGE_VALUE = 0xdeadbeef; |
if (ZERO_PAGE_VALUE != 0xdeadbeef) |
avail = false; |
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) |
else { |
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd; |
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd) |
avail = false; |
} |
#endif |
} |
} |
} |
if (!avail) { |
frame_add_region(start_frame, frame); |
start_frame = frame + 1; |
avail = true; |
} |
} |
frame_add_region(start_frame, frame); |
/* Blacklist interrupt vector frame */ |
frame_mark_unavailable(0, 1); |
/* Cleanup */ |
cp0_pagemask_write(ZERO_PAGE_MASK); |
cp0_entry_lo0_write(0); |
cp0_entry_lo1_write(0); |
cp0_entry_hi_write(0); |
cp0_index_write(ZERO_PAGE_TLBI); |
tlbwi(); |
interrupts_restore(ipl); |
} |
void physmem_print(void) |
{ |
printf("Base Size\n"); |
printf("---------- ----------\n"); |
count_t i; |
for (i = 0; i < phys_regions_count; i++) { |
printf("%#010x %10u\n", |
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count)); |
} |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/mips32/src/mm/page.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32mm |
/** @addtogroup mips32mm |
* @{ |
*/ |
/** @file |
35,6 → 35,7 |
#include <arch/mm/page.h> |
#include <genarch/mm/page_pt.h> |
#include <mm/page.h> |
#include <mm/frame.h> |
void page_arch_init(void) |
{ |
/branches/dd/kernel/arch/mips32/src/interrupt.c |
---|
38,12 → 38,12 |
#include <arch.h> |
#include <arch/cp0.h> |
#include <time/clock.h> |
#include <arch/drivers/arc.h> |
#include <ipc/sysipc.h> |
#include <ddi/device.h> |
#define IRQ_COUNT 8 |
#define TIMER_IRQ 7 |
#define IRQ_COUNT 8 |
#define TIMER_IRQ 7 |
#define DORDER_IRQ 5 |
function virtual_timer_fnc = NULL; |
static irq_t timer_irq; |
101,12 → 101,12 |
cp0_compare_write(nextcount); |
} |
static irq_ownership_t timer_claim(void) |
static irq_ownership_t timer_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
static void timer_irq_handler(irq_t *irq, void *arg, ...) |
static void timer_irq_handler(irq_t *irq) |
{ |
unsigned long drift; |
/branches/dd/kernel/arch/mips32/src/drivers/serial.c |
---|
File deleted |
/branches/dd/kernel/arch/mips32/src/drivers/arc.c |
---|
File deleted |
/branches/dd/kernel/arch/mips32/src/drivers/msim.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup mips32 |
/** @addtogroup mips32 |
* @{ |
*/ |
/** @file |
33,22 → 33,17 |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/msim.h> |
#include <arch/cp0.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <ddi/ddi.h> |
/** Address of devices. */ |
#define MSIM_VIDEORAM 0xB0000000 |
#define MSIM_KBD_ADDRESS 0xB0000000 |
#define MSIM_KBD_IRQ 2 |
static chardev_t console; |
static irq_t msim_irq; |
static void msim_write(chardev_t *dev, const char ch); |
static void msim_write(chardev_t *dev, const char ch, bool silent); |
static void msim_enable(chardev_t *dev); |
static void msim_disable(chardev_t *dev); |
static char msim_do_read(chardev_t *dev); |
61,9 → 56,10 |
}; |
/** Putchar that works with MSIM & gxemul */ |
void msim_write(chardev_t *dev, const char ch) |
void msim_write(chardev_t *dev, const char ch, bool silent) |
{ |
*((char *) MSIM_VIDEORAM) = ch; |
if (!silent) |
*((char *) MSIM_VIDEORAM) = ch; |
} |
/* Called from getc(). */ |
78,12 → 74,11 |
cp0_mask_int(MSIM_KBD_IRQ); |
} |
#include <print.h> |
/** Read character using polling, assume interrupts disabled */ |
static char msim_do_read(chardev_t *dev) |
{ |
char ch; |
while (1) { |
ch = *((volatile char *) MSIM_KBD_ADDRESS); |
if (ch) { |
97,23 → 92,19 |
} |
/** Process keyboard interrupt. */ |
static void msim_irq_handler(irq_t *irq, void *arg, ...) |
static void msim_irq_handler(irq_t *irq) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else { |
char ch = 0; |
char ch = 0; |
ch = *((char *) MSIM_KBD_ADDRESS); |
if (ch =='\r') |
ch = '\n'; |
if (ch == 0x7f) |
ch = '\b'; |
chardev_push_character(&console, ch); |
} |
ch = *((char *) MSIM_KBD_ADDRESS); |
if (ch =='\r') |
ch = '\n'; |
if (ch == 0x7f) |
ch = '\b'; |
chardev_push_character(&console, ch); |
} |
static irq_ownership_t msim_claim(void) |
static irq_ownership_t msim_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
158,6 → 149,10 |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS); |
sysinfo_set_item_val("fb", NULL, true); |
sysinfo_set_item_val("fb.kind", NULL, 3); |
sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(MSIM_VIDEORAM)); |
} |
/** @} |
/branches/dd/kernel/arch/ia32/_link.ld.in |
---|
1,11 → 1,11 |
/** IA-32 linker script |
* |
* |
* umapped section: |
* kernel text |
* kernel data |
* kernel text |
* kernel data |
* mapped section: |
* kernel text |
* kernel data |
* kernel text |
* kernel data |
*/ |
#include <arch/boot/boot.h> |
28,9 → 28,9 |
ktext_end = .; |
kdata_start = .; |
*(.data); /* initialized data */ |
*(.rodata*); /* string literals */ |
*(COMMON); /* global variables */ |
*(.data); /* initialized data */ |
*(.rodata*); /* string literals */ |
*(COMMON); /* global variables */ |
hardcoded_load_address = .; |
LONG(PA2KA(BOOT_OFFSET)); |
hardcoded_ktext_size = .; |
42,23 → 42,23 |
hardcoded_unmapped_kdata_size = .; |
LONG(unmapped_kdata_end - unmapped_kdata_start); |
symbol_table = .; |
*(symtab.*); /* Symbol table, must be LAST symbol! */ |
*(.bss); /* uninitialized static variables */ |
*(symtab.*); /* Symbol table, must be LAST symbol! */ |
*(.bss); /* uninitialized static variables */ |
kdata_end = .; |
} |
/DISCARD/ : { |
*(.note.GNU-stack); |
*(.note.GNU-stack); |
*(.comment); |
} |
#ifdef CONFIG_SMP |
#ifdef CONFIG_SMP |
_hardcoded_unmapped_size = (unmapped_ktext_end - unmapped_ktext_start) + (unmapped_kdata_end - unmapped_kdata_start); |
ap_boot = unmapped_ap_boot - BOOT_OFFSET + AP_BOOT_OFFSET; |
ap_gdtr = unmapped_ap_gdtr - BOOT_OFFSET + AP_BOOT_OFFSET; |
protected_ap_gdtr = PA2KA(ap_gdtr); |
#endif /* CONFIG_SMP */ |
} |
/branches/dd/kernel/arch/ia32/include/interrupt.h |
---|
72,10 → 72,6 |
uint32_t eax; |
uint32_t ecx; |
uint32_t edx; |
uint32_t esi; |
uint32_t edi; |
uint32_t ebp; |
uint32_t ebx; |
uint32_t gs; |
uint32_t fs; |
/branches/dd/kernel/arch/ia32/include/fpu_context.h |
---|
37,7 → 37,6 |
#include <arch/types.h> |
#define ARCH_HAS_FPU |
#define FPU_CONTEXT_ALIGN 16 |
void fpu_fxsr(void); |
/branches/dd/kernel/arch/ia32/include/cpuid.h |
---|
74,21 → 74,21 |
uint32_t val, ret; |
asm volatile ( |
"pushf\n" /* read flags */ |
"popl %0\n" |
"movl %0, %1\n" |
"pushf\n" /* read flags */ |
"popl %[ret]\n" |
"movl %[ret], %[val]\n" |
"btcl $21, %1\n" /* swap the ID bit */ |
"btcl $21, %[val]\n" /* swap the ID bit */ |
"pushl %1\n" /* propagate the change into flags */ |
"pushl %[val]\n" /* propagate the change into flags */ |
"popf\n" |
"pushf\n" |
"popl %1\n" |
"popl %[val]\n" |
"andl $(1 << 21), %0\n" /* interrested only in ID bit */ |
"andl $(1 << 21), %1\n" |
"xorl %1, %0\n" |
: "=r" (ret), "=r" (val) |
"andl $(1 << 21), %[ret]\n" /* interrested only in ID bit */ |
"andl $(1 << 21), %[val]\n" |
"xorl %[val], %[ret]\n" |
: [ret] "=r" (ret), [val] "=r" (val) |
); |
return ret; |
98,7 → 98,8 |
{ |
asm volatile ( |
"cpuid\n" |
: "=a" (info->cpuid_eax), "=b" (info->cpuid_ebx), "=c" (info->cpuid_ecx), "=d" (info->cpuid_edx) |
: "=a" (info->cpuid_eax), "=b" (info->cpuid_ebx), |
"=c" (info->cpuid_ecx), "=d" (info->cpuid_edx) |
: "a" (cmd) |
); |
} |
/branches/dd/kernel/arch/ia32/include/types.h |
---|
35,10 → 35,6 |
#ifndef KERN_ia32_TYPES_H_ |
#define KERN_ia32_TYPES_H_ |
#define NULL 0 |
#define false 0 |
#define true 1 |
typedef signed char int8_t; |
typedef signed short int16_t; |
typedef signed long int32_t; |
61,14 → 57,32 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef uint8_t bool; |
typedef uint64_t thread_id_t; |
typedef uint64_t task_id_t; |
typedef uint32_t context_id_t; |
typedef struct { |
} fncptr_t; |
typedef int32_t inr_t; |
typedef int32_t devno_t; |
#define PRIp "x" /**< Format for uintptr_t. */ |
#define PRIs "u" /**< Format for size_t. */ |
#define PRIc "u" /**< Format for count_t. */ |
#define PRIi "u" /**< Format for index_t. */ |
#define PRId8 "d" /**< Format for int8_t. */ |
#define PRId16 "d" /**< Format for int16_t. */ |
#define PRId32 "d" /**< Format for int32_t. */ |
#define PRId64 "lld" /**< Format for int64_t. */ |
#define PRIdn "d" /**< Format for native_t. */ |
#define PRIu8 "u" /**< Format for uint8_t. */ |
#define PRIu16 "u" /**< Format for uint16_t. */ |
#define PRIu32 "u" /**< Format for uint32_t. */ |
#define PRIu64 "llu" /**< Format for uint64_t. */ |
#define PRIun "u" /**< Format for unative_t. */ |
#define PRIx8 "x" /**< Format for hexadecimal (u)int8_t. */ |
#define PRIx16 "x" /**< Format for hexadecimal (u)int16_t. */ |
#define PRIx32 "x" /**< Format for hexadecimal (u)uint32_t. */ |
#define PRIx64 "llx" /**< Format for hexadecimal (u)int64_t. */ |
#define PRIxn "x" /**< Format for hexadecimal (u)native_t. */ |
/** Page Table Entry. */ |
typedef struct { |
unsigned present : 1; |
/branches/dd/kernel/arch/ia32/include/memstr.h |
---|
35,116 → 35,13 |
#ifndef KERN_ia32_MEMSTR_H_ |
#define KERN_ia32_MEMSTR_H_ |
/** Copy memory |
* |
* Copy a given number of bytes (3rd argument) |
* from the memory location defined by 2nd argument |
* to the memory location defined by 1st argument. |
* The memory areas cannot overlap. |
* |
* @param dst Destination |
* @param src Source |
* @param cnt Number of bytes |
* @return Destination |
*/ |
static inline void * memcpy(void * dst, const void * src, size_t cnt) |
{ |
unative_t d0, d1, d2; |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
asm volatile( |
/* copy all full dwords */ |
"rep movsl\n\t" |
/* load count again */ |
"movl %4, %%ecx\n\t" |
/* ecx = ecx mod 4 */ |
"andl $3, %%ecx\n\t" |
/* are there last <=3 bytes? */ |
"jz 1f\n\t" |
/* copy last <=3 bytes */ |
"rep movsb\n\t" |
/* exit from asm block */ |
"1:\n" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
: "0" ((unative_t) (cnt / 4)), "g" ((unative_t) cnt), "1" ((unative_t) dst), "2" ((unative_t) src) |
: "memory"); |
extern void memsetw(void *dst, size_t cnt, uint16_t x); |
extern void memsetb(void *dst, size_t cnt, uint8_t x); |
return dst; |
} |
extern int memcmp(const void *a, const void *b, size_t cnt); |
/** Compare memory regions for equality |
* |
* Compare a given number of bytes (3rd argument) |
* at memory locations defined by 1st and 2nd argument |
* for equality. If bytes are equal function returns 0. |
* |
* @param src Region 1 |
* @param dst Region 2 |
* @param cnt Number of bytes |
* @return Zero if bytes are equal, non-zero otherwise |
*/ |
static inline int memcmp(const void * src, const void * dst, size_t cnt) |
{ |
uint32_t d0, d1, d2; |
int ret; |
asm ( |
"repe cmpsb\n\t" |
"je 1f\n\t" |
"movl %3, %0\n\t" |
"addl $1, %0\n\t" |
"1:\n" |
: "=a" (ret), "=%S" (d0), "=&D" (d1), "=&c" (d2) |
: "0" (0), "1" ((unative_t) src), "2" ((unative_t) dst), "3" ((unative_t) cnt) |
); |
return ret; |
} |
/** Fill memory with words |
* Fill a given number of words (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of words |
* @param x Value to fill |
*/ |
static inline void memsetw(uintptr_t dst, size_t cnt, uint16_t x) |
{ |
uint32_t d0, d1; |
asm volatile ( |
"rep stosw\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" (cnt), "2" (x) |
: "memory" |
); |
} |
/** Fill memory with bytes |
* Fill a given number of bytes (2nd argument) |
* at memory defined by 1st argument with the |
* word value defined by 3rd argument. |
* |
* @param dst Destination |
* @param cnt Number of bytes |
* @param x Value to fill |
*/ |
static inline void memsetb(uintptr_t dst, size_t cnt, uint8_t x) |
{ |
uint32_t d0, d1; |
asm volatile ( |
"rep stosb\n\t" |
: "=&D" (d0), "=&c" (d1), "=a" (x) |
: "0" (dst), "1" (cnt), "2" (x) |
: "memory" |
); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/smp/apic.h |
---|
105,8 → 105,8 |
#define MODEL_CLUSTER 0x0 |
/** Interrupt Command Register. */ |
#define ICRlo (0x300/sizeof(uint32_t)) |
#define ICRhi (0x310/sizeof(uint32_t)) |
#define ICRlo (0x300 / sizeof(uint32_t)) |
#define ICRhi (0x310 / sizeof(uint32_t)) |
typedef struct { |
union { |
uint32_t lo; |
133,10 → 133,10 |
} __attribute__ ((packed)) icr_t; |
/* End Of Interrupt. */ |
#define EOI (0x0b0/sizeof(uint32_t)) |
#define EOI (0x0b0 / sizeof(uint32_t)) |
/** Error Status Register. */ |
#define ESR (0x280/sizeof(uint32_t)) |
#define ESR (0x280 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
uint8_t err_bitmap; |
154,7 → 154,7 |
} esr_t; |
/* Task Priority Register */ |
#define TPR (0x080/sizeof(uint32_t)) |
#define TPR (0x080 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
164,7 → 164,7 |
} tpr_t; |
/** Spurious-Interrupt Vector Register. */ |
#define SVR (0x0f0/sizeof(uint32_t)) |
#define SVR (0x0f0 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
176,7 → 176,7 |
} svr_t; |
/** Time Divide Configuration Register. */ |
#define TDCR (0x3e0/sizeof(uint32_t)) |
#define TDCR (0x3e0 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
186,13 → 186,13 |
} tdcr_t; |
/* Initial Count Register for Timer */ |
#define ICRT (0x380/sizeof(uint32_t)) |
#define ICRT (0x380 / sizeof(uint32_t)) |
/* Current Count Register for Timer */ |
#define CCRT (0x390/sizeof(uint32_t)) |
#define CCRT (0x390 / sizeof(uint32_t)) |
/** LVT Timer register. */ |
#define LVT_Tm (0x320/sizeof(uint32_t)) |
#define LVT_Tm (0x320 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
207,8 → 207,8 |
} lvt_tm_t; |
/** LVT LINT registers. */ |
#define LVT_LINT0 (0x350/sizeof(uint32_t)) |
#define LVT_LINT1 (0x360/sizeof(uint32_t)) |
#define LVT_LINT0 (0x350 / sizeof(uint32_t)) |
#define LVT_LINT1 (0x360 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
225,7 → 225,7 |
} lvt_lint_t; |
/** LVT Error register. */ |
#define LVT_Err (0x370/sizeof(uint32_t)) |
#define LVT_Err (0x370 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
239,7 → 239,7 |
} lvt_error_t; |
/** Local APIC ID Register. */ |
#define L_APIC_ID (0x020/sizeof(uint32_t)) |
#define L_APIC_ID (0x020 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
249,14 → 249,14 |
} l_apic_id_t; |
/** Local APIC Version Register */ |
#define LAVR (0x030/sizeof(uint32_t)) |
#define LAVR (0x030 / sizeof(uint32_t)) |
#define LAVR_Mask 0xff |
#define is_local_apic(x) (((x)&LAVR_Mask&0xf0)==0x1) |
#define is_82489DX_apic(x) ((((x)&LAVR_Mask&0xf0)==0x0)) |
#define is_local_xapic(x) (((x)&LAVR_Mask)==0x14) |
#define is_local_apic(x) (((x) & LAVR_Mask & 0xf0) == 0x1) |
#define is_82489DX_apic(x) ((((x) & LAVR_Mask & 0xf0) == 0x0)) |
#define is_local_xapic(x) (((x) & LAVR_Mask) == 0x14) |
/** Logical Destination Register. */ |
#define LDR (0x0d0/sizeof(uint32_t)) |
#define LDR (0x0d0 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
266,7 → 266,7 |
} ldr_t; |
/** Destination Format Register. */ |
#define DFR (0x0e0/sizeof(uint32_t)) |
#define DFR (0x0e0 / sizeof(uint32_t)) |
typedef union { |
uint32_t value; |
struct { |
276,8 → 276,8 |
} dfr_t; |
/* IO APIC */ |
#define IOREGSEL (0x00/sizeof(uint32_t)) |
#define IOWIN (0x10/sizeof(uint32_t)) |
#define IOREGSEL (0x00 / sizeof(uint32_t)) |
#define IOWIN (0x10 / sizeof(uint32_t)) |
#define IOAPICID 0x00 |
#define IOAPICVER 0x01 |
/branches/dd/kernel/arch/ia32/include/syscall.h |
---|
0,0 → 1,0 |
link ../../amd64/include/syscall.h |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/dd/kernel/arch/ia32/include/atomic.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
41,17 → 41,29 |
static inline void atomic_inc(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock incl %0\n" : "=m" (val->count)); |
asm volatile ( |
"lock incl %[count]\n" |
: [count] "+m" (val->count) |
); |
#else |
asm volatile ("incl %0\n" : "=m" (val->count)); |
asm volatile ( |
"incl %[count]\n" |
: [count] "+m" (val->count) |
); |
#endif /* CONFIG_SMP */ |
} |
static inline void atomic_dec(atomic_t *val) { |
#ifdef CONFIG_SMP |
asm volatile ("lock decl %0\n" : "=m" (val->count)); |
asm volatile ( |
"lock decl %[count]\n" |
: [count] "+m" (val->count) |
); |
#else |
asm volatile ("decl %0\n" : "=m" (val->count)); |
asm volatile ( |
"decl %[count]\n" |
: "+m" (val->count) |
); |
#endif /* CONFIG_SMP */ |
} |
58,12 → 70,12 |
static inline long atomic_postinc(atomic_t *val) |
{ |
long r = 1; |
asm volatile ( |
"lock xaddl %1, %0\n" |
: "=m" (val->count), "+r" (r) |
"lock xaddl %[r], %[count]\n" |
: [count] "+m" (val->count), [r] "+r" (r) |
); |
return r; |
} |
72,23 → 84,23 |
long r = -1; |
asm volatile ( |
"lock xaddl %1, %0\n" |
: "=m" (val->count), "+r"(r) |
"lock xaddl %[r], %[count]\n" |
: [count] "+m" (val->count), [r] "+r"(r) |
); |
return r; |
} |
#define atomic_preinc(val) (atomic_postinc(val)+1) |
#define atomic_predec(val) (atomic_postdec(val)-1) |
#define atomic_preinc(val) (atomic_postinc(val) + 1) |
#define atomic_predec(val) (atomic_postdec(val) - 1) |
static inline uint32_t test_and_set(atomic_t *val) { |
uint32_t v; |
asm volatile ( |
"movl $1, %0\n" |
"xchgl %0, %1\n" |
: "=r" (v),"=m" (val->count) |
"movl $1, %[v]\n" |
"xchgl %[v], %[count]\n" |
: [v] "=r" (v), [count] "+m" (val->count) |
); |
return v; |
98,23 → 110,23 |
static inline void atomic_lock_arch(atomic_t *val) |
{ |
uint32_t tmp; |
preemption_disable(); |
asm volatile ( |
"0:;" |
"0:\n" |
#ifdef CONFIG_HT |
"pause;" /* Pentium 4's HT love this instruction */ |
"pause\n" /* Pentium 4's HT love this instruction */ |
#endif |
"mov %0, %1;" |
"testl %1, %1;" |
"jnz 0b;" /* Lightweight looping on locked spinlock */ |
"mov %[count], %[tmp]\n" |
"testl %[tmp], %[tmp]\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
"incl %1;" /* now use the atomic operation */ |
"xchgl %0, %1;" |
"testl %1, %1;" |
"jnz 0b;" |
: "=m"(val->count),"=r"(tmp) |
); |
"incl %[tmp]\n" /* now use the atomic operation */ |
"xchgl %[count], %[tmp]\n" |
"testl %[tmp], %[tmp]\n" |
"jnz 0b\n" |
: [count] "+m" (val->count), [tmp] "=&r" (tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
*/ |
/branches/dd/kernel/arch/ia32/include/boot/memmap.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
35,24 → 35,29 |
#ifndef KERN_ia32_MEMMAP_H_ |
#define KERN_ia32_MEMMAP_H_ |
/* E820h memory range types - other values*/ |
/* Free memory */ |
#define MEMMAP_MEMORY_AVAILABLE 1 |
/* Not available for OS */ |
#define MEMMAP_MEMORY_RESERVED 2 |
/* OS may use it after reading ACPI table */ |
#define MEMMAP_MEMORY_ACPI 3 |
/* Unusable, required to be saved and restored across an NVS sleep */ |
#define MEMMAP_MEMORY_NVS 4 |
/* Corrupted memory */ |
#define MEMMAP_MEMORY_UNUSABLE 5 |
/* E820h memory range types */ |
/* size of one entry */ |
#define MEMMAP_E820_RECORD_SIZE 20 |
/* maximum entries */ |
#define MEMMAP_E820_MAX_RECORDS 32 |
/* Free memory */ |
#define MEMMAP_MEMORY_AVAILABLE 1 |
/* Not available for OS */ |
#define MEMMAP_MEMORY_RESERVED 2 |
/* OS may use it after reading ACPI table */ |
#define MEMMAP_MEMORY_ACPI 3 |
/* Unusable, required to be saved and restored across an NVS sleep */ |
#define MEMMAP_MEMORY_NVS 4 |
/* Corrupted memory */ |
#define MEMMAP_MEMORY_UNUSABLE 5 |
/* Size of one entry */ |
#define MEMMAP_E820_RECORD_SIZE 20 |
/* Maximum entries */ |
#define MEMMAP_E820_MAX_RECORDS 32 |
#ifndef __ASM__ |
#include <arch/types.h> |
/branches/dd/kernel/arch/ia32/include/boot/boot.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
35,15 → 35,24 |
#ifndef KERN_ia32_BOOT_H_ |
#define KERN_ia32_BOOT_H_ |
#define BOOT_OFFSET 0x108000 |
#define AP_BOOT_OFFSET 0x8000 |
#define BOOT_STACK_SIZE 0x400 |
#define BOOT_OFFSET 0x108000 |
#define AP_BOOT_OFFSET 0x8000 |
#define BOOT_STACK_SIZE 0x400 |
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 |
#define MULTIBOOT_HEADER_FLAGS 0x00010003 |
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 |
#define MULTIBOOT_HEADER_FLAGS 0x00010003 |
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002 |
#ifndef __ASM__ |
#ifdef CONFIG_SMP |
/* This is only a symbol so the type is dummy. Obtain the value using &. */ |
extern int _hardcoded_unmapped_size; |
#endif /* CONFIG_SMP */ |
#endif /* __ASM__ */ |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/arch.h |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
35,6 → 35,10 |
#ifndef KERN_ia32_ARCH_H_ |
#define KERN_ia32_ARCH_H_ |
#include <genarch/multiboot/multiboot.h> |
extern void arch_pre_main(uint32_t, const multiboot_info_t *); |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/asm.h |
---|
27,7 → 27,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
38,6 → 38,7 |
#include <arch/pm.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <config.h> |
extern uint32_t interrupt_handler_size; |
56,6 → 57,7 |
/** Halt CPU |
* |
* Halt the current CPU until interrupt event. |
* |
*/ |
static inline void cpu_halt(void) |
{ |
68,16 → 70,22 |
} |
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \ |
{ \ |
unative_t res; \ |
asm volatile ("movl %%" #reg ", %0" : "=r" (res) ); \ |
return res; \ |
} |
{ \ |
unative_t res; \ |
asm volatile ( \ |
"movl %%" #reg ", %[res]" \ |
: [res] "=r" (res) \ |
); \ |
return res; \ |
} |
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \ |
{ \ |
asm volatile ("movl %0, %%" #reg : : "r" (regn)); \ |
} |
{ \ |
asm volatile ( \ |
"movl %[regn], %%" #reg \ |
:: [regn] "r" (regn) \ |
); \ |
} |
GEN_READ_REG(cr0) |
GEN_READ_REG(cr2) |
104,10 → 112,14 |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void outb(uint16_t port, uint8_t val) |
static inline void pio_write_8(ioport8_t *port, uint8_t val) |
{ |
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port) ); |
asm volatile ( |
"outb %b[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Word to port |
116,10 → 128,14 |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void outw(uint16_t port, uint16_t val) |
static inline void pio_write_16(ioport16_t *port, uint16_t val) |
{ |
asm volatile ("outw %w0, %w1\n" : : "a" (val), "d" (port) ); |
asm volatile ( |
"outw %w[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Double word to port |
128,10 → 144,14 |
* |
* @param port Port to write to |
* @param val Value to write |
* |
*/ |
static inline void outl(uint16_t port, uint32_t val) |
static inline void pio_write_32(ioport32_t *port, uint32_t val) |
{ |
asm volatile ("outl %l0, %w1\n" : : "a" (val), "d" (port) ); |
asm volatile ( |
"outl %[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
/** Byte from port |
140,12 → 160,18 |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint8_t inb(uint16_t port) |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uint8_t val; |
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port) ); |
asm volatile ( |
"inb %w[port], %b[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
155,12 → 181,18 |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint16_t inw(uint16_t port) |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uint16_t val; |
asm volatile ("inw %w1, %w0 \n" : "=a" (val) : "d" (port) ); |
asm volatile ( |
"inw %w[port], %w[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
170,12 → 202,18 |
* |
* @param port Port to read from |
* @return Value read |
* |
*/ |
static inline uint32_t inl(uint16_t port) |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uint32_t val; |
asm volatile ("inl %w1, %l0 \n" : "=a" (val) : "d" (port) ); |
asm volatile ( |
"inl %w[port], %[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
185,16 → 223,19 |
* value of EFLAGS. |
* |
* @return Old interrupt priority level. |
* |
*/ |
static inline ipl_t interrupts_enable(void) |
{ |
ipl_t v; |
asm volatile ( |
"pushf\n\t" |
"popl %0\n\t" |
"pushf\n" |
"popl %[v]\n" |
"sti\n" |
: "=r" (v) |
: [v] "=r" (v) |
); |
return v; |
} |
204,16 → 245,19 |
* value of EFLAGS. |
* |
* @return Old interrupt priority level. |
* |
*/ |
static inline ipl_t interrupts_disable(void) |
{ |
ipl_t v; |
asm volatile ( |
"pushf\n\t" |
"popl %0\n\t" |
"pushf\n" |
"popl %[v]\n" |
"cli\n" |
: "=r" (v) |
: [v] "=r" (v) |
); |
return v; |
} |
222,13 → 266,14 |
* Restore EFLAGS. |
* |
* @param ipl Saved interrupt priority level. |
* |
*/ |
static inline void interrupts_restore(ipl_t ipl) |
{ |
asm volatile ( |
"pushl %0\n\t" |
"pushl %[ipl]\n" |
"popf\n" |
: : "r" (ipl) |
:: [ipl] "r" (ipl) |
); |
} |
235,23 → 280,51 |
/** Return interrupt priority level. |
* |
* @return EFLAFS. |
* |
*/ |
static inline ipl_t interrupts_read(void) |
{ |
ipl_t v; |
asm volatile ( |
"pushf\n\t" |
"popl %0\n" |
: "=r" (v) |
"pushf\n" |
"popl %[v]\n" |
: [v] "=r" (v) |
); |
return v; |
} |
/** Write to MSR */ |
static inline void write_msr(uint32_t msr, uint64_t value) |
{ |
asm volatile ( |
"wrmsr" |
:: "c" (msr), "a" ((uint32_t) (value)), |
"d" ((uint32_t) (value >> 32)) |
); |
} |
static inline uint64_t read_msr(uint32_t msr) |
{ |
uint32_t ax, dx; |
asm volatile ( |
"rdmsr" |
: "=a" (ax), "=d" (dx) |
: "c" (msr) |
); |
return ((uint64_t) dx << 32) | ax; |
} |
/** Return base address of current stack |
* |
* Return the base address of the current stack. |
* The stack is assumed to be STACK_SIZE bytes long. |
* The stack must start on page boundary. |
* |
*/ |
static inline uintptr_t get_stack_base(void) |
{ |
258,8 → 331,8 |
uintptr_t v; |
asm volatile ( |
"andl %%esp, %0\n" |
: "=r" (v) |
"andl %%esp, %[v]\n" |
: [v] "=r" (v) |
: "0" (~(STACK_SIZE - 1)) |
); |
270,11 → 343,12 |
static inline uintptr_t * get_ip() |
{ |
uintptr_t *ip; |
asm volatile ( |
"mov %%eip, %0" |
: "=r" (ip) |
); |
"mov %%eip, %[ip]" |
: [ip] "=r" (ip) |
); |
return ip; |
} |
281,46 → 355,66 |
/** Invalidate TLB Entry. |
* |
* @param addr Address on a page whose TLB entry is to be invalidated. |
* |
*/ |
static inline void invlpg(uintptr_t addr) |
{ |
asm volatile ("invlpg %0\n" :: "m" (*(unative_t *)addr)); |
asm volatile ( |
"invlpg %[addr]\n" |
:: [addr] "m" (*(unative_t *) addr) |
); |
} |
/** Load GDTR register from memory. |
* |
* @param gdtr_reg Address of memory from where to load GDTR. |
* |
*/ |
static inline void gdtr_load(ptr_16_32_t *gdtr_reg) |
{ |
asm volatile ("lgdtl %0\n" : : "m" (*gdtr_reg)); |
asm volatile ( |
"lgdtl %[gdtr_reg]\n" |
:: [gdtr_reg] "m" (*gdtr_reg) |
); |
} |
/** Store GDTR register to memory. |
* |
* @param gdtr_reg Address of memory to where to load GDTR. |
* |
*/ |
static inline void gdtr_store(ptr_16_32_t *gdtr_reg) |
{ |
asm volatile ("sgdtl %0\n" : : "m" (*gdtr_reg)); |
asm volatile ( |
"sgdtl %[gdtr_reg]\n" |
:: [gdtr_reg] "m" (*gdtr_reg) |
); |
} |
/** Load IDTR register from memory. |
* |
* @param idtr_reg Address of memory from where to load IDTR. |
* |
*/ |
static inline void idtr_load(ptr_16_32_t *idtr_reg) |
{ |
asm volatile ("lidtl %0\n" : : "m" (*idtr_reg)); |
asm volatile ( |
"lidtl %[idtr_reg]\n" |
:: [idtr_reg] "m" (*idtr_reg) |
); |
} |
/** Load TR from descriptor table. |
* |
* @param sel Selector specifying descriptor of TSS segment. |
* |
*/ |
static inline void tr_load(uint16_t sel) |
{ |
asm volatile ("ltr %0" : : "r" (sel)); |
asm volatile ( |
"ltr %[sel]" |
:: [sel] "r" (sel) |
); |
} |
#endif |
/branches/dd/kernel/arch/ia32/include/mm/frame.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32mm |
/** @addtogroup ia32mm |
* @{ |
*/ |
/** @file |
35,8 → 35,8 |
#ifndef KERN_ia32_FRAME_H_ |
#define KERN_ia32_FRAME_H_ |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#define FRAME_WIDTH 12 /* 4K */ |
#define FRAME_SIZE (1 << FRAME_WIDTH) |
#ifdef KERNEL |
#ifndef __ASM__ |
/branches/dd/kernel/arch/ia32/include/mm/page.h |
---|
40,8 → 40,6 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#ifdef KERNEL |
#ifndef __ASM__ |
128,6 → 126,8 |
#include <mm/mm.h> |
#include <arch/interrupt.h> |
#include <arch/types.h> |
#include <typedefs.h> |
/* Page fault error codes. */ |
/branches/dd/kernel/arch/ia32/include/mm/tlb.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32mm |
/** @addtogroup ia32mm |
* @{ |
*/ |
/** @file |
35,9 → 35,6 |
#ifndef KERN_ia32_TLB_H_ |
#define KERN_ia32_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/mm/as.h |
---|
42,7 → 42,7 |
#define USER_ADDRESS_SPACE_START_ARCH ((unsigned long) 0x00000000) |
#define USER_ADDRESS_SPACE_END_ARCH ((unsigned long) 0x7fffffff) |
#define USTACK_ADDRESS_ARCH (USER_ADDRESS_SPACE_END_ARCH-(PAGE_SIZE-1)) |
#define USTACK_ADDRESS_ARCH (USER_ADDRESS_SPACE_END_ARCH - (PAGE_SIZE - 1)) |
typedef struct { |
} as_arch_t; |
/branches/dd/kernel/arch/ia32/include/barrier.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
46,8 → 46,8 |
* Provisions are made to prevent compiler from reordering instructions itself. |
*/ |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
#define CS_ENTER_BARRIER() asm volatile ("" ::: "memory") |
#define CS_LEAVE_BARRIER() asm volatile ("" ::: "memory") |
static inline void cpuid_serialization(void) |
{ |
58,32 → 58,41 |
); |
} |
#ifdef CONFIG_FENCES_P4 |
# define memory_barrier() asm volatile ("mfence\n" ::: "memory") |
# define read_barrier() asm volatile ("lfence\n" ::: "memory") |
# ifdef CONFIG_WEAK_MEMORY |
# define write_barrier() asm volatile ("sfence\n" ::: "memory") |
# else |
# define write_barrier() asm volatile( "" ::: "memory"); |
# endif |
#elif CONFIG_FENCES_P3 |
# define memory_barrier() cpuid_serialization() |
# define read_barrier() cpuid_serialization() |
# ifdef CONFIG_WEAK_MEMORY |
# define write_barrier() asm volatile ("sfence\n" ::: "memory") |
# else |
# define write_barrier() asm volatile( "" ::: "memory"); |
# endif |
#if defined(CONFIG_FENCES_P4) |
#define memory_barrier() asm volatile ("mfence\n" ::: "memory") |
#define read_barrier() asm volatile ("lfence\n" ::: "memory") |
#ifdef CONFIG_WEAK_MEMORY |
#define write_barrier() asm volatile ("sfence\n" ::: "memory") |
#else |
#define write_barrier() asm volatile ("" ::: "memory"); |
#endif |
#elif defined(CONFIG_FENCES_P3) |
#define memory_barrier() cpuid_serialization() |
#define read_barrier() cpuid_serialization() |
#ifdef CONFIG_WEAK_MEMORY |
#define write_barrier() asm volatile ("sfence\n" ::: "memory") |
#else |
#define write_barrier() asm volatile ("" ::: "memory"); |
#endif |
#else |
# define memory_barrier() cpuid_serialization() |
# define read_barrier() cpuid_serialization() |
# ifdef CONFIG_WEAK_MEMORY |
# define write_barrier() cpuid_serialization() |
# else |
# define write_barrier() asm volatile( "" ::: "memory"); |
# endif |
#define memory_barrier() cpuid_serialization() |
#define read_barrier() cpuid_serialization() |
#ifdef CONFIG_WEAK_MEMORY |
#define write_barrier() cpuid_serialization() |
#else |
#define write_barrier() asm volatile ("" ::: "memory"); |
#endif |
#endif |
/* |
* On ia32, the hardware takes care about instruction and data cache coherence, |
* even on SMP systems. We issue a write barrier to be sure that writes |
* queueing in the store buffer drain to the memory (even though it would be |
* sufficient for them to drain to the D-cache). |
*/ |
#define smc_coherence(a) write_barrier() |
#define smc_coherence_block(a, l) write_barrier() |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/cpu.h |
---|
35,25 → 35,33 |
#ifndef KERN_ia32_CPU_H_ |
#define KERN_ia32_CPU_H_ |
#define EFLAGS_IF (1 << 9) |
#define EFLAGS_RF (1 << 16) |
#define CR4_OSFXSR_MASK (1<<9) |
/* Support for SYSENTER and SYSEXIT */ |
#define IA32_MSR_SYSENTER_CS 0x174 |
#define IA32_MSR_SYSENTER_ESP 0x175 |
#define IA32_MSR_SYSENTER_EIP 0x176 |
#ifndef __ASM__ |
#include <arch/pm.h> |
#include <arch/asm.h> |
#define EFLAGS_IF (1 << 9) |
#define EFLAGS_RF (1 << 16) |
typedef struct { |
int vendor; |
int family; |
int model; |
int stepping; |
unsigned int vendor; |
unsigned int family; |
unsigned int model; |
unsigned int stepping; |
struct tss *tss; |
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */ |
} cpu_arch_t; |
#endif |
#define CR4_OSFXSR_MASK (1<<9) |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/include/drivers/i8042.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32/include/drivers/ega.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32/include/drivers/vesa.h |
---|
36,6 → 36,7 |
#define KERN_ia32_VESA_H_ |
extern int vesa_present(void); |
extern void vesa_redraw(void); |
extern void vesa_init(void); |
#endif |
/branches/dd/kernel/arch/ia32/include/drivers/i8259.h |
---|
38,10 → 38,10 |
#include <arch/types.h> |
#include <arch/interrupt.h> |
#define PIC_PIC0PORT1 0x20 |
#define PIC_PIC0PORT2 0x21 |
#define PIC_PIC1PORT1 0xa0 |
#define PIC_PIC1PORT2 0xa1 |
#define PIC_PIC0PORT1 ((ioport8_t *) 0x20) |
#define PIC_PIC0PORT2 ((ioport8_t *) 0x21) |
#define PIC_PIC1PORT1 ((ioport8_t *) 0xa0) |
#define PIC_PIC1PORT2 ((ioport8_t *) 0xa1) |
#define PIC_NEEDICW4 (1<<0) |
#define PIC_ICW1 (1<<4) |
/branches/dd/kernel/arch/ia32/include/drivers/kbd.h |
---|
0,0 → 1,41 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_ia32_KBD_H_ |
#define KERN_ia32_KBD_H_ |
#endif |
/** @} |
*/ |
/branches/dd/kernel/arch/ia32/Makefile.inc |
---|
33,9 → 33,9 |
BFD_ARCH = i386 |
BFD = binary |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/i686 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__ |
DEFS += -D__32_BITS__ |
CMN1 = -m32 |
GCC_CFLAGS += $(CMN1) |
45,110 → 45,61 |
## Accepted CPUs |
# |
ifeq ($(MACHINE),athlon-xp) |
CMN2 = -march=athlon-xp -mmmx -msse -m3dnow |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
ifeq ($(PROCESSOR),athlon_xp) |
CMN2 = -march=athlon-xp |
SUNCC_CFLAGS += -xarch=ssea |
DEFS += -DCONFIG_FENCES_P3 |
CONFIG_SMP = n |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),athlon-mp) |
CMN2 = -march=athlon-mp -mmmx -msse -m3dnow |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
ifeq ($(PROCESSOR),athlon_mp) |
CMN2 = -march=athlon-mp |
SUNCC_CFLAGS += xarch=ssea |
DEFS += -DCONFIG_FENCES_P3 |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),pentium3) |
CMN2 = -march=pentium3 -mmmx -msse |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
ifeq ($(PROCESSOR),pentium3) |
CMN2 = -march=pentium3 |
SUNCC_CFLAGS += -xarch=sse |
DEFS += -DCONFIG_FENCES_P3 |
CONFIG_HT = n |
endif |
ifeq ($(MACHINE),core) |
CMN2 = -march=prescott -mfpmath=sse -mmmx -msse -msse2 -msse3 |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
SUNCC_CFLAGS += -xarch=sse3 |
DEFS += -DCONFIG_FENCES_P4 |
endif |
ifeq ($(MACHINE),pentium4) |
GCC_CFLAGS += -march=pentium4 -mfpmath=sse -mmmx -msse -msse2 |
ICC_CFLAGS += -march=pentium4 |
ifeq ($(PROCESSOR),pentium4) |
CMN2 = -march=pentium4 |
SUNCC_CFLAGS += -xarch=sse2 |
DEFS += -DCONFIG_FENCES_P4 |
endif |
## Own configuration directives |
# |
CONFIG_ACPI = y |
## Compile with hierarchical page tables support. |
# |
CONFIG_PAGE_PT = y |
DEFS += -DCONFIG_PAGE_PT |
## Compile with i8042 controller support |
# |
CONFIG_I8042 = y |
DEFS += -DCONFIG_I8042 |
## Accepted configuration directives |
# |
ifeq ($(CONFIG_SMP),y) |
DEFS += -DCONFIG_SMP |
ifeq ($(PROCESSOR),core) |
CMN2 = -march=prescott |
SUNCC_CFLAGS += -xarch=sse3 |
endif |
ifeq ($(CONFIG_HT),y) |
DEFS += -DCONFIG_HT |
endif |
ifeq ($(CONFIG_SIMICS_FIX),y) |
DEFS += -DCONFIG_SIMICS_FIX |
endif |
## Compile with support for software integer division. |
# |
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow |
GCC_CFLAGS += $(CMN2) |
ICC_CFLAGS += $(CMN2) |
CONFIG_SOFTINT = y |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/context.S \ |
arch/$(ARCH)/src/debug/panic.s \ |
arch/$(ARCH)/src/delay.s \ |
arch/$(ARCH)/src/asm.S \ |
arch/$(ARCH)/src/proc/scheduler.c \ |
arch/$(ARCH)/src/proc/task.c \ |
arch/$(ARCH)/src/proc/thread.c \ |
arch/$(ARCH)/src/bios/bios.c \ |
arch/$(ARCH)/src/smp/ap.S \ |
arch/$(ARCH)/src/smp/apic.c \ |
arch/$(ARCH)/src/smp/mps.c \ |
arch/$(ARCH)/src/smp/smp.c \ |
arch/$(ARCH)/src/atomic.S \ |
arch/$(ARCH)/src/smp/ipi.c \ |
arch/$(ARCH)/src/ia32.c \ |
arch/$(ARCH)/src/interrupt.c \ |
arch/$(ARCH)/src/pm.c \ |
arch/$(ARCH)/src/userspace.c \ |
arch/$(ARCH)/src/cpu/cpu.c \ |
arch/$(ARCH)/src/mm/as.c \ |
arch/$(ARCH)/src/mm/frame.c \ |
arch/$(ARCH)/src/mm/page.c \ |
arch/$(ARCH)/src/mm/tlb.c \ |
arch/$(ARCH)/src/ddi/ddi.c \ |
arch/$(ARCH)/src/drivers/i8254.c \ |
arch/$(ARCH)/src/drivers/i8259.c \ |
arch/$(ARCH)/src/drivers/ega.c \ |
arch/$(ARCH)/src/drivers/vesa.c \ |
arch/$(ARCH)/src/boot/boot.S \ |
arch/$(ARCH)/src/boot/memmap.c \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/debugger.c |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/debug/panic.s \ |
arch/$(KARCH)/src/delay.s \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/proc/task.c \ |
arch/$(KARCH)/src/proc/thread.c \ |
arch/$(KARCH)/src/bios/bios.c \ |
arch/$(KARCH)/src/smp/ap.S \ |
arch/$(KARCH)/src/smp/apic.c \ |
arch/$(KARCH)/src/smp/mps.c \ |
arch/$(KARCH)/src/smp/smp.c \ |
arch/$(KARCH)/src/atomic.S \ |
arch/$(KARCH)/src/smp/ipi.c \ |
arch/$(KARCH)/src/ia32.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/pm.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
arch/$(KARCH)/src/mm/tlb.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/i8254.c \ |
arch/$(KARCH)/src/drivers/i8259.c \ |
arch/$(KARCH)/src/drivers/vesa.c \ |
arch/$(KARCH)/src/boot/boot.S \ |
arch/$(KARCH)/src/boot/memmap.c \ |
arch/$(KARCH)/src/fpu_context.c \ |
arch/$(KARCH)/src/debugger.c \ |
arch/$(KARCH)/src/syscall.c |
/branches/dd/kernel/arch/ia32/src/ia32.c |
---|
1,5 → 1,7 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2009 Jiri Svoboda |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
38,9 → 40,12 |
#include <arch/pm.h> |
#include <arch/drivers/ega.h> |
#include <genarch/multiboot/multiboot.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <genarch/drivers/ega/ega.h> |
#include <arch/drivers/vesa.h> |
#include <genarch/kbd/i8042.h> |
#include <genarch/drivers/i8042/i8042.h> |
#include <genarch/kbrd/kbrd.h> |
#include <arch/drivers/i8254.h> |
#include <arch/drivers/i8259.h> |
61,11 → 66,30 |
#include <syscall/syscall.h> |
#include <console/console.h> |
#include <ddi/device.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/boot/boot.h> |
#ifdef CONFIG_SMP |
#include <arch/smp/apic.h> |
#endif |
/** Perform ia32-specific initialization before main_bsp() is called. |
* |
* @param signature Should contain the multiboot signature. |
* @param mi Pointer to the multiboot information structure. |
*/ |
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi) |
{ |
/* Parse multiboot information obtained from the bootloader. */ |
multiboot_info_parse(signature, mi); |
#ifdef CONFIG_SMP |
/* Copy AP bootstrap routines below 1 MB. */ |
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, |
(size_t) &_hardcoded_unmapped_size); |
#endif |
} |
void arch_pre_mm_init(void) |
{ |
pm_init(); |
93,7 → 117,7 |
vesa_init(); |
else |
#endif |
ega_init(); /* video */ |
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */ |
/* Enable debugger */ |
debugger_init(); |
123,10 → 147,28 |
void arch_post_smp_init(void) |
{ |
devno_t kbd = device_assign_devno(); |
devno_t mouse = device_assign_devno(); |
/* keyboard controller */ |
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE); |
devno_t devno = device_assign_devno(); |
/* |
* Initialize the keyboard module and conect it to stdin. Then |
* initialize the i8042 controller and connect it to kbrdin. Enable |
* keyboard interrupts. |
*/ |
kbrd_init(stdin); |
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD, &kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
/* |
* This is the necessary evil until the userspace driver is entirely |
* self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
sysinfo_set_item_val("kbd.address.physical", NULL, |
(uintptr_t) I8042_BASE); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) I8042_BASE); |
} |
void calibrate_delay_loop(void) |
159,15 → 201,33 |
*/ |
void arch_grab_console(void) |
{ |
i8042_grab(); |
#ifdef CONFIG_FB |
vesa_redraw(); |
#else |
ega_redraw(); |
#endif |
} |
/** Return console to userspace |
* |
*/ |
void arch_release_console(void) |
{ |
i8042_release(); |
} |
/** Construct function pointer |
* |
* @param fptr function pointer structure |
* @param addr function address |
* @param caller calling function address |
* |
* @return address of the function pointer |
* |
*/ |
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller) |
{ |
return addr; |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia32/src/fpu_context.c |
---|
44,46 → 44,43 |
static void fpu_context_f_save(fpu_context_t *fctx) |
{ |
asm volatile ( |
"fnsave %0" |
: "=m"(*fctx) |
); |
"fnsave %[fctx]" |
: [fctx] "=m" (*fctx) |
); |
} |
static void fpu_context_f_restore(fpu_context_t *fctx) |
{ |
asm volatile ( |
"frstor %0" |
: "=m"(*fctx) |
); |
"frstor %[fctx]" |
: [fctx] "=m" (*fctx) |
); |
} |
static void fpu_context_fx_save(fpu_context_t *fctx) |
{ |
asm volatile ( |
"fxsave %0" |
: "=m"(*fctx) |
); |
"fxsave %[fctx]" |
: [fctx] "=m" (*fctx) |
); |
} |
static void fpu_context_fx_restore(fpu_context_t *fctx) |
{ |
asm volatile ( |
"fxrstor %0" |
: "=m"(*fctx) |
); |
"fxrstor %[fctx]" |
: [fctx] "=m" (*fctx) |
); |
} |
/* |
Setup using fxsr instruction |
*/ |
/* Setup using fxsr instruction */ |
void fpu_fxsr(void) |
{ |
fpu_save=fpu_context_fx_save; |
fpu_restore=fpu_context_fx_restore; |
} |
/* |
Setup using not fxsr instruction |
*/ |
/* Setup using not fxsr instruction */ |
void fpu_fsr(void) |
{ |
fpu_save = fpu_context_f_save; |
102,16 → 99,18 |
void fpu_init() |
{ |
uint32_t help0 = 0, help1 = 0; |
uint32_t help0 = 0; |
uint32_t help1 = 0; |
asm volatile ( |
"fninit;\n" |
"stmxcsr %0\n" |
"mov %0,%1;\n" |
"or %2,%1;\n" |
"mov %1,%0;\n" |
"ldmxcsr %0;\n" |
: "+m" (help0), "+r" (help1) |
: "i" (0x1f80) |
"fninit\n" |
"stmxcsr %[help0]\n" |
"mov %[help0], %[help1]\n" |
"or %[magic], %[help1]\n" |
"mov %[help1], %[help0]\n" |
"ldmxcsr %[help0]\n" |
: [help0] "+m" (help0), [help1] "+r" (help1) |
: [magic] "i" (0x1f80) |
); |
} |
/branches/dd/kernel/arch/ia32/src/asm.S |
---|
37,6 → 37,8 |
.global paging_on |
.global enable_l_apic_in_msr |
.global interrupt_handlers |
.global memsetb |
.global memsetw |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_from_uspace_failover_address |
44,6 → 46,15 |
.global memcpy_to_uspace_failover_address |
# Wrapper for generic memsetb |
memsetb: |
jmp _memsetb |
# Wrapper for generic memsetw |
memsetw: |
jmp _memsetw |
#define MEMCPY_DST 4 |
#define MEMCPY_SRC 8 |
#define MEMCPY_SIZE 12 |
60,7 → 71,7 |
* @param MEMCPY_SRC(%esp) Source address. |
* @param MEMCPY_SIZE(%esp) Size. |
* |
* @return MEMCPY_SRC(%esp) on success and 0 on failure. |
* @return MEMCPY_DST(%esp) on success and 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
85,7 → 96,7 |
0: |
movl %edx, %edi |
movl %eax, %esi |
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */ |
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ |
ret |
/* |
136,6 → 147,46 |
popfl |
.endm |
/* |
* The SYSENTER syscall mechanism can be used for syscalls with |
* four or fewer arguments. To pass these four arguments, we |
* use four registers: EDX, ECX, EBX, ESI. The syscall number |
* is passed in EAX. We use EDI to remember the return address |
* and EBP to remember the stack. The INT-based syscall mechanism |
* can actually handle six arguments plus the syscall number |
* entirely in registers. |
*/ |
.global sysenter_handler |
sysenter_handler: |
sti |
pushl %ebp # remember user stack |
pushl %edi # remember return user address |
pushl %gs # remember TLS |
pushl %eax # syscall number |
subl $8, %esp # unused sixth and fifth argument |
pushl %esi # fourth argument |
pushl %ebx # third argument |
pushl %ecx # second argument |
pushl %edx # first argument |
movw $16, %ax |
movw %ax, %ds |
movw %ax, %es |
cld |
call syscall_handler |
addl $28, %esp # remove arguments from stack |
pop %gs # restore TLS |
pop %edx # prepare return EIP for SYSEXIT |
pop %ecx # prepare userspace ESP for SYSEXIT |
sysexit # return to userspace |
## Declare interrupt handlers |
# |
# Declare interrupt handlers for n interrupt |
217,14 → 268,6 |
pushl %fs |
pushl %gs |
#ifdef CONFIG_DEBUG_ALLREGS |
pushl %ebx |
pushl %ebp |
pushl %edi |
pushl %esi |
#else |
subl $16, %esp |
#endif |
pushl %edx |
pushl %ecx |
pushl %eax |
246,14 → 289,6 |
popl %eax |
popl %ecx |
popl %edx |
#ifdef CONFIG_DEBUG_ALLREGS |
popl %esi |
popl %edi |
popl %ebp |
popl %ebx |
#else |
addl $16, %esp |
#endif |
popl %gs |
popl %fs |
/branches/dd/kernel/arch/ia32/src/debug/panic.s |
---|
30,5 → 30,5 |
.global panic_printf |
panic_printf: |
movl $halt,(%esp) # fake stack to make printf return to halt |
movl $halt, (%esp) # fake stack to make printf return to halt |
jmp printf |
/branches/dd/kernel/arch/ia32/src/cpu/cpu.c |
---|
42,22 → 42,23 |
#include <fpu_context.h> |
#include <arch/smp/apic.h> |
#include <arch/syscall.h> |
/* |
* Identification of CPUs. |
* Contains only non-MP-Specification specific SMP code. |
*/ |
#define AMD_CPUID_EBX 0x68747541 |
#define AMD_CPUID_ECX 0x444d4163 |
#define AMD_CPUID_EDX 0x69746e65 |
#define AMD_CPUID_EBX 0x68747541 |
#define AMD_CPUID_ECX 0x444d4163 |
#define AMD_CPUID_EDX 0x69746e65 |
#define INTEL_CPUID_EBX 0x756e6547 |
#define INTEL_CPUID_ECX 0x6c65746e |
#define INTEL_CPUID_EDX 0x49656e69 |
#define INTEL_CPUID_EBX 0x756e6547 |
#define INTEL_CPUID_ECX 0x6c65746e |
#define INTEL_CPUID_EDX 0x49656e69 |
enum vendor { |
VendorUnknown=0, |
VendorUnknown = 0, |
VendorAMD, |
VendorIntel |
}; |
64,19 → 65,17 |
static char *vendor_str[] = { |
"Unknown Vendor", |
"AuthenticAMD", |
"GenuineIntel" |
"AMD", |
"Intel" |
}; |
void fpu_disable(void) |
{ |
asm volatile ( |
"mov %%cr0,%%eax;" |
"or $8,%%eax;" |
"mov %%eax,%%cr0;" |
: |
: |
:"%eax" |
"mov %%cr0, %%eax\n" |
"or $8, %%eax\n" |
"mov %%eax, %%cr0\n" |
::: "%eax" |
); |
} |
83,13 → 82,11 |
void fpu_enable(void) |
{ |
asm volatile ( |
"mov %%cr0,%%eax;" |
"and $0xffFFffF7,%%eax;" |
"mov %%eax,%%cr0;" |
: |
: |
:"%eax" |
); |
"mov %%cr0, %%eax\n" |
"and $0xffFFffF7, %%eax\n" |
"mov %%eax,%%cr0\n" |
::: "%eax" |
); |
} |
void cpu_arch_init(void) |
101,11 → 98,11 |
CPU->arch.tss = tss_p; |
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss); |
CPU->fpu_owner = NULL; |
cpuid(1, &info); |
fi.word = info.cpuid_edx; |
efi.word = info.cpuid_ecx; |
112,17 → 109,20 |
if (fi.bits.fxsr) |
fpu_fxsr(); |
else |
fpu_fsr(); |
fpu_fsr(); |
if (fi.bits.sse) { |
asm volatile ( |
"mov %%cr4,%0\n" |
"or %1,%0\n" |
"mov %0,%%cr4\n" |
: "+r" (help) |
: "i" (CR4_OSFXSR_MASK|(1<<10)) |
"mov %%cr4, %[help]\n" |
"or %[mask], %[help]\n" |
"mov %[help], %%cr4\n" |
: [help] "+r" (help) |
: [mask] "i" (CR4_OSFXSR_MASK | (1 << 10)) |
); |
} |
/* Setup fast SYSENTER/SYSEXIT syscalls */ |
syscall_setup_cpu(); |
} |
void cpu_identify(void) |
136,29 → 136,31 |
/* |
* Check for AMD processor. |
*/ |
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) { |
if ((info.cpuid_ebx == AMD_CPUID_EBX) |
&& (info.cpuid_ecx == AMD_CPUID_ECX) |
&& (info.cpuid_edx == AMD_CPUID_EDX)) |
CPU->arch.vendor = VendorAMD; |
} |
/* |
* Check for Intel processor. |
*/ |
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) { |
if ((info.cpuid_ebx == INTEL_CPUID_EBX) |
&& (info.cpuid_ecx == INTEL_CPUID_ECX) |
&& (info.cpuid_edx == INTEL_CPUID_EDX)) |
CPU->arch.vendor = VendorIntel; |
} |
cpuid(1, &info); |
CPU->arch.family = (info.cpuid_eax>>8)&0xf; |
CPU->arch.model = (info.cpuid_eax>>4)&0xf; |
CPU->arch.stepping = (info.cpuid_eax>>0)&0xf; |
CPU->arch.family = (info.cpuid_eax >> 8) & 0x0f; |
CPU->arch.model = (info.cpuid_eax >> 4) & 0x0f; |
CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0f; |
} |
} |
void cpu_print_report(cpu_t* m) |
void cpu_print_report(cpu_t* cpu) |
{ |
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n", |
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping, |
m->frequency_mhz); |
printf("cpu%u: (%s family=%u model=%u stepping=%u) %" PRIu16 " MHz\n", |
cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family, |
cpu->arch.model, cpu->arch.stepping, cpu->frequency_mhz); |
} |
/** @} |
/branches/dd/kernel/arch/ia32/src/syscall.c |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/syscall.h> |
#include <arch/cpu.h> |
#include <arch/asm.h> |
#include <arch/types.h> |
#include <arch/pm.h> |
/** Enable & setup support for SYSENTER/SYSEXIT */ |
void syscall_setup_cpu(void) |
{ |
extern void sysenter_handler(void); |
/* set kernel mode CS selector */ |
write_msr(IA32_MSR_SYSENTER_CS, selector(KTEXT_DES)); |
/* set kernel mode entry point */ |
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler); |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia32/src/pm.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
112,7 → 112,7 |
void tss_initialize(tss_t *t) |
{ |
memsetb((uintptr_t) t, sizeof(struct tss), 0); |
memsetb(t, sizeof(struct tss), 0); |
} |
/* |
154,7 → 154,7 |
"and $0xffff8fff, %%eax\n" |
"push %%eax\n" |
"popfl\n" |
: : : "eax" |
::: "eax" |
); |
} |
165,7 → 165,7 |
"mov %%cr0, %%eax\n" |
"and $0xfffbffff, %%eax\n" |
"mov %%eax, %%cr0\n" |
: : : "eax" |
::: "eax" |
); |
} |
198,7 → 198,7 |
else { |
tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC); |
if (!tss_p) |
panic("could not allocate TSS\n"); |
panic("Cannot allocate TSS."); |
} |
tss_initialize(tss_p); |
240,7 → 240,7 |
preemption_disable(); |
ipl_t ipl = interrupts_disable(); |
memsetb((uintptr_t) idt, sizeof(idt), 0); |
memsetb(idt, sizeof(idt), 0); |
ptr_16_32_t idtr; |
idtr.limit = sizeof(idt); |
/branches/dd/kernel/arch/ia32/src/smp/smp.c |
---|
75,12 → 75,12 |
l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, |
FRAME_ATOMIC | FRAME_KA); |
if (!l_apic_address) |
panic("cannot allocate address for l_apic\n"); |
panic("Cannot allocate address for l_apic."); |
io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, |
FRAME_ATOMIC | FRAME_KA); |
if (!io_apic_address) |
panic("cannot allocate address for io_apic\n"); |
panic("Cannot allocate address for io_apic."); |
if (config.cpu_count > 1) { |
page_mapping_insert(AS_KERNEL, l_apic_address, |
122,8 → 122,8 |
* Save 0xa to address 0xf of the CMOS RAM. |
* BIOS will not do the POST after the INIT signal. |
*/ |
outb(0x70, 0xf); |
outb(0x71, 0xa); |
pio_write_8((ioport8_t *)0x70, 0xf); |
pio_write_8((ioport8_t *)0x71, 0xa); |
pic_disable_irqs(0xffff); |
apic_init(); |
154,14 → 154,18 |
/* |
* Prepare new GDT for CPU in question. |
*/ |
/* XXX Flag FRAME_LOW_4_GiB was removed temporarily, |
* it needs to be replaced by a generic fuctionality of |
* the memory subsystem |
*/ |
gdt_new = (struct descriptor *) malloc(GDT_ITEMS * |
sizeof(struct descriptor), FRAME_ATOMIC); |
if (!gdt_new) |
panic("couldn't allocate memory for GDT\n"); |
panic("Cannot allocate memory for GDT."); |
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor)); |
memsetb((uintptr_t)(&gdt_new[TSS_DES]), |
sizeof(struct descriptor), 0); |
memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0); |
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor); |
protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new); |
gdtr.base = (uintptr_t) gdt_new; |
/branches/dd/kernel/arch/ia32/src/smp/ap.S |
---|
45,7 → 45,7 |
KTEXT=8 |
KDATA=16 |
# This piece of code is real-mode and is meant to be alligned at 4K boundary. |
# This piece of code is real-mode and is meant to be aligned at 4K boundary. |
# The requirement for such an alignment comes from MP Specification's STARTUP IPI |
# requirements. |
/branches/dd/kernel/arch/ia32/src/smp/apic.c |
---|
132,12 → 132,12 |
#endif |
} |
static irq_ownership_t l_apic_timer_claim(void) |
static irq_ownership_t l_apic_timer_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
static void l_apic_timer_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...) |
static void l_apic_timer_irq_handler(irq_t *irq) |
{ |
/* |
* Holding a spinlock could prevent clock() from preempting |
/branches/dd/kernel/arch/ia32/src/boot/vga323.pal |
---|
1,256 → 1,256 |
.byte 0x3f, 0x3f, 0x3f, 0x00 |
.byte 0x36, 0x3f, 0x3f, 0x00 |
.byte 0x2d, 0x3f, 0x3f, 0x00 |
.byte 0x24, 0x3f, 0x3f, 0x00 |
.byte 0x1b, 0x3f, 0x3f, 0x00 |
.byte 0x12, 0x3f, 0x3f, 0x00 |
.byte 0x09, 0x3f, 0x3f, 0x00 |
.byte 0x00, 0x3f, 0x3f, 0x00 |
.byte 0x3f, 0x2a, 0x3f, 0x00 |
.byte 0x36, 0x2a, 0x3f, 0x00 |
.byte 0x2d, 0x2a, 0x3f, 0x00 |
.byte 0x24, 0x2a, 0x3f, 0x00 |
.byte 0x1b, 0x2a, 0x3f, 0x00 |
.byte 0x12, 0x2a, 0x3f, 0x00 |
.byte 0x09, 0x2a, 0x3f, 0x00 |
.byte 0x00, 0x2a, 0x3f, 0x00 |
.byte 0x3f, 0x15, 0x3f, 0x00 |
.byte 0x36, 0x15, 0x3f, 0x00 |
.byte 0x2d, 0x15, 0x3f, 0x00 |
.byte 0x24, 0x15, 0x3f, 0x00 |
.byte 0x1b, 0x15, 0x3f, 0x00 |
.byte 0x12, 0x15, 0x3f, 0x00 |
.byte 0x09, 0x15, 0x3f, 0x00 |
.byte 0x00, 0x15, 0x3f, 0x00 |
.byte 0x3f, 0x00, 0x3f, 0x00 |
.byte 0x36, 0x00, 0x3f, 0x00 |
.byte 0x2d, 0x00, 0x3f, 0x00 |
.byte 0x24, 0x00, 0x3f, 0x00 |
.byte 0x1b, 0x00, 0x3f, 0x00 |
.byte 0x12, 0x00, 0x3f, 0x00 |
.byte 0x09, 0x00, 0x3f, 0x00 |
.byte 0x00, 0x00, 0x3f, 0x00 |
.byte 0x3f, 0x3f, 0x36, 0x00 |
.byte 0x36, 0x3f, 0x36, 0x00 |
.byte 0x2d, 0x3f, 0x36, 0x00 |
.byte 0x24, 0x3f, 0x36, 0x00 |
.byte 0x1b, 0x3f, 0x36, 0x00 |
.byte 0x12, 0x3f, 0x36, 0x00 |
.byte 0x09, 0x3f, 0x36, 0x00 |
.byte 0x00, 0x3f, 0x36, 0x00 |
.byte 0x3f, 0x2a, 0x36, 0x00 |
.byte 0x36, 0x2a, 0x36, 0x00 |
.byte 0x2d, 0x2a, 0x36, 0x00 |
.byte 0x24, 0x2a, 0x36, 0x00 |
.byte 0x1b, 0x2a, 0x36, 0x00 |
.byte 0x12, 0x2a, 0x36, 0x00 |
.byte 0x09, 0x2a, 0x36, 0x00 |
.byte 0x00, 0x2a, 0x36, 0x00 |
.byte 0x3f, 0x15, 0x36, 0x00 |
.byte 0x36, 0x15, 0x36, 0x00 |
.byte 0x2d, 0x15, 0x36, 0x00 |
.byte 0x24, 0x15, 0x36, 0x00 |
.byte 0x1b, 0x15, 0x36, 0x00 |
.byte 0x12, 0x15, 0x36, 0x00 |
.byte 0x09, 0x15, 0x36, 0x00 |
.byte 0x00, 0x15, 0x36, 0x00 |
.byte 0x3f, 0x00, 0x36, 0x00 |
.byte 0x36, 0x00, 0x36, 0x00 |
.byte 0x2d, 0x00, 0x36, 0x00 |
.byte 0x24, 0x00, 0x36, 0x00 |
.byte 0x1b, 0x00, 0x36, 0x00 |
.byte 0x12, 0x00, 0x36, 0x00 |
.byte 0x09, 0x00, 0x36, 0x00 |
.byte 0x00, 0x00, 0x36, 0x00 |
.byte 0x3f, 0x3f, 0x2d, 0x00 |
.byte 0x36, 0x3f, 0x2d, 0x00 |
.byte 0x2d, 0x3f, 0x2d, 0x00 |
.byte 0x24, 0x3f, 0x2d, 0x00 |
.byte 0x1b, 0x3f, 0x2d, 0x00 |
.byte 0x12, 0x3f, 0x2d, 0x00 |
.byte 0x09, 0x3f, 0x2d, 0x00 |
.byte 0x00, 0x3f, 0x2d, 0x00 |
.byte 0x3f, 0x2a, 0x2d, 0x00 |
.byte 0x36, 0x2a, 0x2d, 0x00 |
.byte 0x2d, 0x2a, 0x2d, 0x00 |
.byte 0x24, 0x2a, 0x2d, 0x00 |
.byte 0x1b, 0x2a, 0x2d, 0x00 |
.byte 0x12, 0x2a, 0x2d, 0x00 |
.byte 0x09, 0x2a, 0x2d, 0x00 |
.byte 0x00, 0x2a, 0x2d, 0x00 |
.byte 0x3f, 0x15, 0x2d, 0x00 |
.byte 0x36, 0x15, 0x2d, 0x00 |
.byte 0x2d, 0x15, 0x2d, 0x00 |
.byte 0x24, 0x15, 0x2d, 0x00 |
.byte 0x1b, 0x15, 0x2d, 0x00 |
.byte 0x12, 0x15, 0x2d, 0x00 |
.byte 0x09, 0x15, 0x2d, 0x00 |
.byte 0x00, 0x15, 0x2d, 0x00 |
.byte 0x3f, 0x00, 0x2d, 0x00 |
.byte 0x36, 0x00, 0x2d, 0x00 |
.byte 0x2d, 0x00, 0x2d, 0x00 |
.byte 0x24, 0x00, 0x2d, 0x00 |
.byte 0x1b, 0x00, 0x2d, 0x00 |
.byte 0x12, 0x00, 0x2d, 0x00 |
.byte 0x09, 0x00, 0x2d, 0x00 |
.byte 0x00, 0x00, 0x2d, 0x00 |
.byte 0x3f, 0x3f, 0x24, 0x00 |
.byte 0x36, 0x3f, 0x24, 0x00 |
.byte 0x2d, 0x3f, 0x24, 0x00 |
.byte 0x24, 0x3f, 0x24, 0x00 |
.byte 0x1b, 0x3f, 0x24, 0x00 |
.byte 0x12, 0x3f, 0x24, 0x00 |
.byte 0x09, 0x3f, 0x24, 0x00 |
.byte 0x00, 0x3f, 0x24, 0x00 |
.byte 0x3f, 0x2a, 0x24, 0x00 |
.byte 0x36, 0x2a, 0x24, 0x00 |
.byte 0x2d, 0x2a, 0x24, 0x00 |
.byte 0x24, 0x2a, 0x24, 0x00 |
.byte 0x1b, 0x2a, 0x24, 0x00 |
.byte 0x12, 0x2a, 0x24, 0x00 |
.byte 0x09, 0x2a, 0x24, 0x00 |
.byte 0x00, 0x2a, 0x24, 0x00 |
.byte 0x3f, 0x15, 0x24, 0x00 |
.byte 0x36, 0x15, 0x24, 0x00 |
.byte 0x2d, 0x15, 0x24, 0x00 |
.byte 0x24, 0x15, 0x24, 0x00 |
.byte 0x1b, 0x15, 0x24, 0x00 |
.byte 0x12, 0x15, 0x24, 0x00 |
.byte 0x09, 0x15, 0x24, 0x00 |
.byte 0x00, 0x15, 0x24, 0x00 |
.byte 0x3f, 0x00, 0x24, 0x00 |
.byte 0x36, 0x00, 0x24, 0x00 |
.byte 0x2d, 0x00, 0x24, 0x00 |
.byte 0x24, 0x00, 0x24, 0x00 |
.byte 0x1b, 0x00, 0x24, 0x00 |
.byte 0x12, 0x00, 0x24, 0x00 |
.byte 0x09, 0x00, 0x24, 0x00 |
.byte 0x00, 0x00, 0x24, 0x00 |
.byte 0x3f, 0x3f, 0x1b, 0x00 |
.byte 0x36, 0x3f, 0x1b, 0x00 |
.byte 0x2d, 0x3f, 0x1b, 0x00 |
.byte 0x24, 0x3f, 0x1b, 0x00 |
.byte 0x1b, 0x3f, 0x1b, 0x00 |
.byte 0x12, 0x3f, 0x1b, 0x00 |
.byte 0x09, 0x3f, 0x1b, 0x00 |
.byte 0x00, 0x3f, 0x1b, 0x00 |
.byte 0x3f, 0x2a, 0x1b, 0x00 |
.byte 0x36, 0x2a, 0x1b, 0x00 |
.byte 0x2d, 0x2a, 0x1b, 0x00 |
.byte 0x24, 0x2a, 0x1b, 0x00 |
.byte 0x1b, 0x2a, 0x1b, 0x00 |
.byte 0x12, 0x2a, 0x1b, 0x00 |
.byte 0x09, 0x2a, 0x1b, 0x00 |
.byte 0x00, 0x2a, 0x1b, 0x00 |
.byte 0x3f, 0x15, 0x1b, 0x00 |
.byte 0x36, 0x15, 0x1b, 0x00 |
.byte 0x2d, 0x15, 0x1b, 0x00 |
.byte 0x24, 0x15, 0x1b, 0x00 |
.byte 0x1b, 0x15, 0x1b, 0x00 |
.byte 0x12, 0x15, 0x1b, 0x00 |
.byte 0x09, 0x15, 0x1b, 0x00 |
.byte 0x00, 0x15, 0x1b, 0x00 |
.byte 0x3f, 0x00, 0x1b, 0x00 |
.byte 0x36, 0x00, 0x1b, 0x00 |
.byte 0x2d, 0x00, 0x1b, 0x00 |
.byte 0x24, 0x00, 0x1b, 0x00 |
.byte 0x1b, 0x00, 0x1b, 0x00 |
.byte 0x12, 0x00, 0x1b, 0x00 |
.byte 0x09, 0x00, 0x1b, 0x00 |
.byte 0x00, 0x00, 0x1b, 0x00 |
.byte 0x3f, 0x3f, 0x12, 0x00 |
.byte 0x36, 0x3f, 0x12, 0x00 |
.byte 0x2d, 0x3f, 0x12, 0x00 |
.byte 0x24, 0x3f, 0x12, 0x00 |
.byte 0x1b, 0x3f, 0x12, 0x00 |
.byte 0x12, 0x3f, 0x12, 0x00 |
.byte 0x09, 0x3f, 0x12, 0x00 |
.byte 0x00, 0x3f, 0x12, 0x00 |
.byte 0x3f, 0x2a, 0x12, 0x00 |
.byte 0x36, 0x2a, 0x12, 0x00 |
.byte 0x2d, 0x2a, 0x12, 0x00 |
.byte 0x24, 0x2a, 0x12, 0x00 |
.byte 0x1b, 0x2a, 0x12, 0x00 |
.byte 0x12, 0x2a, 0x12, 0x00 |
.byte 0x09, 0x2a, 0x12, 0x00 |
.byte 0x00, 0x2a, 0x12, 0x00 |
.byte 0x3f, 0x15, 0x12, 0x00 |
.byte 0x36, 0x15, 0x12, 0x00 |
.byte 0x2d, 0x15, 0x12, 0x00 |
.byte 0x24, 0x15, 0x12, 0x00 |
.byte 0x1b, 0x15, 0x12, 0x00 |
.byte 0x12, 0x15, 0x12, 0x00 |
.byte 0x09, 0x15, 0x12, 0x00 |
.byte 0x00, 0x15, 0x12, 0x00 |
.byte 0x3f, 0x00, 0x12, 0x00 |
.byte 0x36, 0x00, 0x12, 0x00 |
.byte 0x2d, 0x00, 0x12, 0x00 |
.byte 0x24, 0x00, 0x12, 0x00 |
.byte 0x1b, 0x00, 0x12, 0x00 |
.byte 0x12, 0x00, 0x12, 0x00 |
.byte 0x09, 0x00, 0x12, 0x00 |
.byte 0x00, 0x00, 0x12, 0x00 |
.byte 0x3f, 0x3f, 0x09, 0x00 |
.byte 0x36, 0x3f, 0x09, 0x00 |
.byte 0x2d, 0x3f, 0x09, 0x00 |
.byte 0x24, 0x3f, 0x09, 0x00 |
.byte 0x1b, 0x3f, 0x09, 0x00 |
.byte 0x12, 0x3f, 0x09, 0x00 |
.byte 0x09, 0x3f, 0x09, 0x00 |
.byte 0x00, 0x3f, 0x09, 0x00 |
.byte 0x3f, 0x2a, 0x09, 0x00 |
.byte 0x36, 0x2a, 0x09, 0x00 |
.byte 0x2d, 0x2a, 0x09, 0x00 |
.byte 0x24, 0x2a, 0x09, 0x00 |
.byte 0x1b, 0x2a, 0x09, 0x00 |
.byte 0x12, 0x2a, 0x09, 0x00 |
.byte 0x09, 0x2a, 0x09, 0x00 |
.byte 0x00, 0x2a, 0x09, 0x00 |
.byte 0x3f, 0x15, 0x09, 0x00 |
.byte 0x36, 0x15, 0x09, 0x00 |
.byte 0x2d, 0x15, 0x09, 0x00 |
.byte 0x24, 0x15, 0x09, 0x00 |
.byte 0x1b, 0x15, 0x09, 0x00 |
.byte 0x12, 0x15, 0x09, 0x00 |
.byte 0x09, 0x15, 0x09, 0x00 |
.byte 0x00, 0x15, 0x09, 0x00 |
.byte 0x3f, 0x00, 0x09, 0x00 |
.byte 0x36, 0x00, 0x09, 0x00 |
.byte 0x2d, 0x00, 0x09, 0x00 |
.byte 0x24, 0x00, 0x09, 0x00 |
.byte 0x1b, 0x00, 0x09, 0x00 |
.byte 0x12, 0x00, 0x09, 0x00 |
.byte 0x09, 0x00, 0x09, 0x00 |
.byte 0x00, 0x00, 0x09, 0x00 |
.byte 0x3f, 0x3f, 0x00, 0x00 |
.byte 0x36, 0x3f, 0x00, 0x00 |
.byte 0x2d, 0x3f, 0x00, 0x00 |
.byte 0x24, 0x3f, 0x00, 0x00 |
.byte 0x1b, 0x3f, 0x00, 0x00 |
.byte 0x12, 0x3f, 0x00, 0x00 |
.byte 0x09, 0x3f, 0x00, 0x00 |
.byte 0x00, 0x3f, 0x00, 0x00 |
.byte 0x3f, 0x2a, 0x00, 0x00 |
.byte 0x36, 0x2a, 0x00, 0x00 |
.byte 0x2d, 0x2a, 0x00, 0x00 |
.byte 0x24, 0x2a, 0x00, 0x00 |
.byte 0x1b, 0x2a, 0x00, 0x00 |
.byte 0x12, 0x2a, 0x00, 0x00 |
.byte 0x09, 0x2a, 0x00, 0x00 |
.byte 0x00, 0x2a, 0x00, 0x00 |
.byte 0x3f, 0x15, 0x00, 0x00 |
.byte 0x36, 0x15, 0x00, 0x00 |
.byte 0x2d, 0x15, 0x00, 0x00 |
.byte 0x24, 0x15, 0x00, 0x00 |
.byte 0x1b, 0x15, 0x00, 0x00 |
.byte 0x12, 0x15, 0x00, 0x00 |
.byte 0x09, 0x15, 0x00, 0x00 |
.byte 0x00, 0x15, 0x00, 0x00 |
.byte 0x3f, 0x00, 0x00, 0x00 |
.byte 0x36, 0x00, 0x00, 0x00 |
.byte 0x2d, 0x00, 0x00, 0x00 |
.byte 0x24, 0x00, 0x00, 0x00 |
.byte 0x1b, 0x00, 0x00, 0x00 |
.byte 0x12, 0x00, 0x00, 0x00 |
.byte 0x09, 0x00, 0x00, 0x00 |
.byte 0x00, 0x00, 0x00, 0x00 |
.byte 0x09, 0x00, 0x00, 0x00 |
.byte 0x12, 0x00, 0x00, 0x00 |
.byte 0x1b, 0x00, 0x00, 0x00 |
.byte 0x24, 0x00, 0x00, 0x00 |
.byte 0x2d, 0x00, 0x00, 0x00 |
.byte 0x36, 0x00, 0x00, 0x00 |
.byte 0x3f, 0x00, 0x00, 0x00 |
.byte 0x00, 0x15, 0x00, 0x00 |
.byte 0x09, 0x15, 0x00, 0x00 |
.byte 0x12, 0x15, 0x00, 0x00 |
.byte 0x1b, 0x15, 0x00, 0x00 |
.byte 0x24, 0x15, 0x00, 0x00 |
.byte 0x2d, 0x15, 0x00, 0x00 |
.byte 0x36, 0x15, 0x00, 0x00 |
.byte 0x3f, 0x15, 0x00, 0x00 |
.byte 0x00, 0x2a, 0x00, 0x00 |
.byte 0x09, 0x2a, 0x00, 0x00 |
.byte 0x12, 0x2a, 0x00, 0x00 |
.byte 0x1b, 0x2a, 0x00, 0x00 |
.byte 0x24, 0x2a, 0x00, 0x00 |
.byte 0x2d, 0x2a, 0x00, 0x00 |
.byte 0x36, 0x2a, 0x00, 0x00 |
.byte 0x3f, 0x2a, 0x00, 0x00 |
.byte 0x00, 0x3f, 0x00, 0x00 |
.byte 0x09, 0x3f, 0x00, 0x00 |
.byte 0x12, 0x3f, 0x00, 0x00 |
.byte 0x1b, 0x3f, 0x00, 0x00 |
.byte 0x24, 0x3f, 0x00, 0x00 |
.byte 0x2d, 0x3f, 0x00, 0x00 |
.byte 0x36, 0x3f, 0x00, 0x00 |
.byte 0x3f, 0x3f, 0x00, 0x00 |
.byte 0x00, 0x00, 0x09, 0x00 |
.byte 0x09, 0x00, 0x09, 0x00 |
.byte 0x12, 0x00, 0x09, 0x00 |
.byte 0x1b, 0x00, 0x09, 0x00 |
.byte 0x24, 0x00, 0x09, 0x00 |
.byte 0x2d, 0x00, 0x09, 0x00 |
.byte 0x36, 0x00, 0x09, 0x00 |
.byte 0x3f, 0x00, 0x09, 0x00 |
.byte 0x00, 0x15, 0x09, 0x00 |
.byte 0x09, 0x15, 0x09, 0x00 |
.byte 0x12, 0x15, 0x09, 0x00 |
.byte 0x1b, 0x15, 0x09, 0x00 |
.byte 0x24, 0x15, 0x09, 0x00 |
.byte 0x2d, 0x15, 0x09, 0x00 |
.byte 0x36, 0x15, 0x09, 0x00 |
.byte 0x3f, 0x15, 0x09, 0x00 |
.byte 0x00, 0x2a, 0x09, 0x00 |
.byte 0x09, 0x2a, 0x09, 0x00 |
.byte 0x12, 0x2a, 0x09, 0x00 |
.byte 0x1b, 0x2a, 0x09, 0x00 |
.byte 0x24, 0x2a, 0x09, 0x00 |
.byte 0x2d, 0x2a, 0x09, 0x00 |
.byte 0x36, 0x2a, 0x09, 0x00 |
.byte 0x3f, 0x2a, 0x09, 0x00 |
.byte 0x00, 0x3f, 0x09, 0x00 |
.byte 0x09, 0x3f, 0x09, 0x00 |
.byte 0x12, 0x3f, 0x09, 0x00 |
.byte 0x1b, 0x3f, 0x09, 0x00 |
.byte 0x24, 0x3f, 0x09, 0x00 |
.byte 0x2d, 0x3f, 0x09, 0x00 |
.byte 0x36, 0x3f, 0x09, 0x00 |
.byte 0x3f, 0x3f, 0x09, 0x00 |
.byte 0x00, 0x00, 0x12, 0x00 |
.byte 0x09, 0x00, 0x12, 0x00 |
.byte 0x12, 0x00, 0x12, 0x00 |
.byte 0x1b, 0x00, 0x12, 0x00 |
.byte 0x24, 0x00, 0x12, 0x00 |
.byte 0x2d, 0x00, 0x12, 0x00 |
.byte 0x36, 0x00, 0x12, 0x00 |
.byte 0x3f, 0x00, 0x12, 0x00 |
.byte 0x00, 0x15, 0x12, 0x00 |
.byte 0x09, 0x15, 0x12, 0x00 |
.byte 0x12, 0x15, 0x12, 0x00 |
.byte 0x1b, 0x15, 0x12, 0x00 |
.byte 0x24, 0x15, 0x12, 0x00 |
.byte 0x2d, 0x15, 0x12, 0x00 |
.byte 0x36, 0x15, 0x12, 0x00 |
.byte 0x3f, 0x15, 0x12, 0x00 |
.byte 0x00, 0x2a, 0x12, 0x00 |
.byte 0x09, 0x2a, 0x12, 0x00 |
.byte 0x12, 0x2a, 0x12, 0x00 |
.byte 0x1b, 0x2a, 0x12, 0x00 |
.byte 0x24, 0x2a, 0x12, 0x00 |
.byte 0x2d, 0x2a, 0x12, 0x00 |
.byte 0x36, 0x2a, 0x12, 0x00 |
.byte 0x3f, 0x2a, 0x12, 0x00 |
.byte 0x00, 0x3f, 0x12, 0x00 |
.byte 0x09, 0x3f, 0x12, 0x00 |
.byte 0x12, 0x3f, 0x12, 0x00 |
.byte 0x1b, 0x3f, 0x12, 0x00 |
.byte 0x24, 0x3f, 0x12, 0x00 |
.byte 0x2d, 0x3f, 0x12, 0x00 |
.byte 0x36, 0x3f, 0x12, 0x00 |
.byte 0x3f, 0x3f, 0x12, 0x00 |
.byte 0x00, 0x00, 0x1b, 0x00 |
.byte 0x09, 0x00, 0x1b, 0x00 |
.byte 0x12, 0x00, 0x1b, 0x00 |
.byte 0x1b, 0x00, 0x1b, 0x00 |
.byte 0x24, 0x00, 0x1b, 0x00 |
.byte 0x2d, 0x00, 0x1b, 0x00 |
.byte 0x36, 0x00, 0x1b, 0x00 |
.byte 0x3f, 0x00, 0x1b, 0x00 |
.byte 0x00, 0x15, 0x1b, 0x00 |
.byte 0x09, 0x15, 0x1b, 0x00 |
.byte 0x12, 0x15, 0x1b, 0x00 |
.byte 0x1b, 0x15, 0x1b, 0x00 |
.byte 0x24, 0x15, 0x1b, 0x00 |
.byte 0x2d, 0x15, 0x1b, 0x00 |
.byte 0x36, 0x15, 0x1b, 0x00 |
.byte 0x3f, 0x15, 0x1b, 0x00 |
.byte 0x00, 0x2a, 0x1b, 0x00 |
.byte 0x09, 0x2a, 0x1b, 0x00 |
.byte 0x12, 0x2a, 0x1b, 0x00 |
.byte 0x1b, 0x2a, 0x1b, 0x00 |
.byte 0x24, 0x2a, 0x1b, 0x00 |
.byte 0x2d, 0x2a, 0x1b, 0x00 |
.byte 0x36, 0x2a, 0x1b, 0x00 |
.byte 0x3f, 0x2a, 0x1b, 0x00 |
.byte 0x00, 0x3f, 0x1b, 0x00 |
.byte 0x09, 0x3f, 0x1b, 0x00 |
.byte 0x12, 0x3f, 0x1b, 0x00 |
.byte 0x1b, 0x3f, 0x1b, 0x00 |
.byte 0x24, 0x3f, 0x1b, 0x00 |
.byte 0x2d, 0x3f, 0x1b, 0x00 |
.byte 0x36, 0x3f, 0x1b, 0x00 |
.byte 0x3f, 0x3f, 0x1b, 0x00 |
.byte 0x00, 0x00, 0x24, 0x00 |
.byte 0x09, 0x00, 0x24, 0x00 |
.byte 0x12, 0x00, 0x24, 0x00 |
.byte 0x1b, 0x00, 0x24, 0x00 |
.byte 0x24, 0x00, 0x24, 0x00 |
.byte 0x2d, 0x00, 0x24, 0x00 |
.byte 0x36, 0x00, 0x24, 0x00 |
.byte 0x3f, 0x00, 0x24, 0x00 |
.byte 0x00, 0x15, 0x24, 0x00 |
.byte 0x09, 0x15, 0x24, 0x00 |
.byte 0x12, 0x15, 0x24, 0x00 |
.byte 0x1b, 0x15, 0x24, 0x00 |
.byte 0x24, 0x15, 0x24, 0x00 |
.byte 0x2d, 0x15, 0x24, 0x00 |
.byte 0x36, 0x15, 0x24, 0x00 |
.byte 0x3f, 0x15, 0x24, 0x00 |
.byte 0x00, 0x2a, 0x24, 0x00 |
.byte 0x09, 0x2a, 0x24, 0x00 |
.byte 0x12, 0x2a, 0x24, 0x00 |
.byte 0x1b, 0x2a, 0x24, 0x00 |
.byte 0x24, 0x2a, 0x24, 0x00 |
.byte 0x2d, 0x2a, 0x24, 0x00 |
.byte 0x36, 0x2a, 0x24, 0x00 |
.byte 0x3f, 0x2a, 0x24, 0x00 |
.byte 0x00, 0x3f, 0x24, 0x00 |
.byte 0x09, 0x3f, 0x24, 0x00 |
.byte 0x12, 0x3f, 0x24, 0x00 |
.byte 0x1b, 0x3f, 0x24, 0x00 |
.byte 0x24, 0x3f, 0x24, 0x00 |
.byte 0x2d, 0x3f, 0x24, 0x00 |
.byte 0x36, 0x3f, 0x24, 0x00 |
.byte 0x3f, 0x3f, 0x24, 0x00 |
.byte 0x00, 0x00, 0x2d, 0x00 |
.byte 0x09, 0x00, 0x2d, 0x00 |
.byte 0x12, 0x00, 0x2d, 0x00 |
.byte 0x1b, 0x00, 0x2d, 0x00 |
.byte 0x24, 0x00, 0x2d, 0x00 |
.byte 0x2d, 0x00, 0x2d, 0x00 |
.byte 0x36, 0x00, 0x2d, 0x00 |
.byte 0x3f, 0x00, 0x2d, 0x00 |
.byte 0x00, 0x15, 0x2d, 0x00 |
.byte 0x09, 0x15, 0x2d, 0x00 |
.byte 0x12, 0x15, 0x2d, 0x00 |
.byte 0x1b, 0x15, 0x2d, 0x00 |
.byte 0x24, 0x15, 0x2d, 0x00 |
.byte 0x2d, 0x15, 0x2d, 0x00 |
.byte 0x36, 0x15, 0x2d, 0x00 |
.byte 0x3f, 0x15, 0x2d, 0x00 |
.byte 0x00, 0x2a, 0x2d, 0x00 |
.byte 0x09, 0x2a, 0x2d, 0x00 |
.byte 0x12, 0x2a, 0x2d, 0x00 |
.byte 0x1b, 0x2a, 0x2d, 0x00 |
.byte 0x24, 0x2a, 0x2d, 0x00 |
.byte 0x2d, 0x2a, 0x2d, 0x00 |
.byte 0x36, 0x2a, 0x2d, 0x00 |
.byte 0x3f, 0x2a, 0x2d, 0x00 |
.byte 0x00, 0x3f, 0x2d, 0x00 |
.byte 0x09, 0x3f, 0x2d, 0x00 |
.byte 0x12, 0x3f, 0x2d, 0x00 |
.byte 0x1b, 0x3f, 0x2d, 0x00 |
.byte 0x24, 0x3f, 0x2d, 0x00 |
.byte 0x2d, 0x3f, 0x2d, 0x00 |
.byte 0x36, 0x3f, 0x2d, 0x00 |
.byte 0x3f, 0x3f, 0x2d, 0x00 |
.byte 0x00, 0x00, 0x36, 0x00 |
.byte 0x09, 0x00, 0x36, 0x00 |
.byte 0x12, 0x00, 0x36, 0x00 |
.byte 0x1b, 0x00, 0x36, 0x00 |
.byte 0x24, 0x00, 0x36, 0x00 |
.byte 0x2d, 0x00, 0x36, 0x00 |
.byte 0x36, 0x00, 0x36, 0x00 |
.byte 0x3f, 0x00, 0x36, 0x00 |
.byte 0x00, 0x15, 0x36, 0x00 |
.byte 0x09, 0x15, 0x36, 0x00 |
.byte 0x12, 0x15, 0x36, 0x00 |
.byte 0x1b, 0x15, 0x36, 0x00 |
.byte 0x24, 0x15, 0x36, 0x00 |
.byte 0x2d, 0x15, 0x36, 0x00 |
.byte 0x36, 0x15, 0x36, 0x00 |
.byte 0x3f, 0x15, 0x36, 0x00 |
.byte 0x00, 0x2a, 0x36, 0x00 |
.byte 0x09, 0x2a, 0x36, 0x00 |
.byte 0x12, 0x2a, 0x36, 0x00 |
.byte 0x1b, 0x2a, 0x36, 0x00 |
.byte 0x24, 0x2a, 0x36, 0x00 |
.byte 0x2d, 0x2a, 0x36, 0x00 |
.byte 0x36, 0x2a, 0x36, 0x00 |
.byte 0x3f, 0x2a, 0x36, 0x00 |
.byte 0x00, 0x3f, 0x36, 0x00 |
.byte 0x09, 0x3f, 0x36, 0x00 |
.byte 0x12, 0x3f, 0x36, 0x00 |
.byte 0x1b, 0x3f, 0x36, 0x00 |
.byte 0x24, 0x3f, 0x36, 0x00 |
.byte 0x2d, 0x3f, 0x36, 0x00 |
.byte 0x36, 0x3f, 0x36, 0x00 |
.byte 0x3f, 0x3f, 0x36, 0x00 |
.byte 0x00, 0x00, 0x3f, 0x00 |
.byte 0x09, 0x00, 0x3f, 0x00 |
.byte 0x12, 0x00, 0x3f, 0x00 |
.byte 0x1b, 0x00, 0x3f, 0x00 |
.byte 0x24, 0x00, 0x3f, 0x00 |
.byte 0x2d, 0x00, 0x3f, 0x00 |
.byte 0x36, 0x00, 0x3f, 0x00 |
.byte 0x3f, 0x00, 0x3f, 0x00 |
.byte 0x00, 0x15, 0x3f, 0x00 |
.byte 0x09, 0x15, 0x3f, 0x00 |
.byte 0x12, 0x15, 0x3f, 0x00 |
.byte 0x1b, 0x15, 0x3f, 0x00 |
.byte 0x24, 0x15, 0x3f, 0x00 |
.byte 0x2d, 0x15, 0x3f, 0x00 |
.byte 0x36, 0x15, 0x3f, 0x00 |
.byte 0x3f, 0x15, 0x3f, 0x00 |
.byte 0x00, 0x2a, 0x3f, 0x00 |
.byte 0x09, 0x2a, 0x3f, 0x00 |
.byte 0x12, 0x2a, 0x3f, 0x00 |
.byte 0x1b, 0x2a, 0x3f, 0x00 |
.byte 0x24, 0x2a, 0x3f, 0x00 |
.byte 0x2d, 0x2a, 0x3f, 0x00 |
.byte 0x36, 0x2a, 0x3f, 0x00 |
.byte 0x3f, 0x2a, 0x3f, 0x00 |
.byte 0x00, 0x3f, 0x3f, 0x00 |
.byte 0x09, 0x3f, 0x3f, 0x00 |
.byte 0x12, 0x3f, 0x3f, 0x00 |
.byte 0x1b, 0x3f, 0x3f, 0x00 |
.byte 0x24, 0x3f, 0x3f, 0x00 |
.byte 0x2d, 0x3f, 0x3f, 0x00 |
.byte 0x36, 0x3f, 0x3f, 0x00 |
.byte 0x3f, 0x3f, 0x3f, 0x00 |
/branches/dd/kernel/arch/ia32/src/boot/boot.S |
---|
101,117 → 101,18 |
shr $16, %ebx |
mov %bx, KA2PA(vesa_bpp) |
#endif |
call map_kernel # map kernel and turn paging on |
# arch_pre_main(grub_eax, grub_ebx) |
pushl grub_ebx |
pushl grub_eax |
call arch_pre_main |
movl grub_eax, %eax |
movl grub_ebx, %ebx |
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature |
je valid_boot |
xorl %ecx, %ecx # no memory map available |
movl %ecx, e820counter |
jmp invalid_boot |
valid_boot: |
movl (%ebx), %eax # ebx = physical address of struct multiboot_info |
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid) |
jc mods_valid |
xorl %ecx, %ecx |
movl %ecx, init |
jmp mods_end |
mods_valid: |
movl 20(%ebx), %ecx # mbi->mods_count |
movl %ecx, init |
cmpl $0, %ecx |
je mods_end |
movl 24(%ebx), %esi # mbi->mods_addr |
movl $init, %edi |
mods_loop: |
movl 0(%esi), %edx # mods->mod_start |
addl $0x80000000, %edx |
movl %edx, 4(%edi) |
movl 4(%esi), %edx |
subl 0(%esi), %edx # mods->mod_end - mods->mod_start |
movl %edx, 8(%edi) |
addl $16, %esi |
addl $8 , %edi |
loop mods_loop |
mods_end: |
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid) |
jc mmap_valid |
xorl %edx, %edx |
jmp mmap_invalid |
mmap_valid: |
movl 44(%ebx), %ecx # mbi->mmap_length |
movl 48(%ebx), %esi # mbi->mmap_addr |
movl $e820table, %edi |
xorl %edx, %edx |
mmap_loop: |
cmpl $0, %ecx |
jle mmap_end |
movl 4(%esi), %eax # mmap->base_addr_low |
movl %eax, (%edi) |
movl 8(%esi), %eax # mmap->base_addr_high |
movl %eax, 4(%edi) |
movl 12(%esi), %eax # mmap->length_low |
movl %eax, 8(%edi) |
movl 16(%esi), %eax # mmap->length_high |
movl %eax, 12(%edi) |
movl 20(%esi), %eax # mmap->type |
movl %eax, 16(%edi) |
movl (%esi), %eax # mmap->size |
addl $0x4, %eax |
addl %eax, %esi |
subl %eax, %ecx |
addl $MEMMAP_E820_RECORD_SIZE, %edi |
incl %edx |
jmp mmap_loop |
mmap_end: |
mmap_invalid: |
movl %edx, e820counter |
invalid_boot: |
call main_bsp |
#ifdef CONFIG_SMP |
# Not reached. |
# copy AP bootstrap routines below 1 MB |
movl $BOOT_OFFSET, %esi |
movl $AP_BOOT_OFFSET, %edi |
movl $_hardcoded_unmapped_size, %ecx |
rep movsb |
#endif |
call main_bsp # never returns |
cli |
hlt |
442,7 → 343,8 |
xor %dx, %dx |
int $0x10 |
jmp vga_not_compat |
cmp $0x00, %ah |
je vga_not_compat |
vga_compat: |
/branches/dd/kernel/arch/ia32/src/proc/scheduler.c |
---|
38,7 → 38,6 |
#include <proc/thread.h> |
#include <arch.h> |
#include <arch/context.h> /* SP_DELTA */ |
#include <arch/debugger.h> |
#include <arch/pm.h> |
#include <arch/asm.h> |
#include <arch/ddi/ddi.h> |
58,21 → 57,18 |
*/ |
void before_thread_runs_arch(void) |
{ |
CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
SP_DELTA]; |
/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */ |
write_msr(IA32_MSR_SYSENTER_ESP, kstk); |
/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */ |
CPU->arch.tss->esp0 = kstk; |
CPU->arch.tss->ss0 = selector(KDATA_DES); |
/* Set up TLS in GS register */ |
set_tls_desc(THREAD->arch.tls); |
#ifdef CONFIG_DEBUG_AS_WATCHPOINT |
/* Set watchpoint on AS to ensure that nobody sets it to zero */ |
if (CPU->id < BKPOINTS_MAX) { |
the_t *the = THE; |
breakpoint_add(&((the_t *) the->thread->kstack)->as, |
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, the->cpu->id); |
} |
#endif |
} |
void after_thread_ran_arch(void) |
/branches/dd/kernel/arch/ia32/src/mm/tlb.c |
---|
67,5 → 67,13 |
invlpg(page + i * PAGE_SIZE); |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia32/src/mm/as.c |
---|
39,9 → 39,7 |
/** Architecture dependent address space init. */ |
void as_arch_init(void) |
{ |
#ifndef __OBJC__ |
as_operations = &as_pt_operations; |
#endif |
} |
/** @} |
/branches/dd/kernel/arch/ia32/src/mm/frame.c |
---|
54,26 → 54,57 |
static void init_e820_memory(pfn_t minconf) |
{ |
unsigned int i; |
pfn_t start, conf; |
size_t size; |
for (i = 0; i < e820counter; i++) { |
uint64_t base = e820table[i].base_address; |
uint64_t size = e820table[i].size; |
#ifdef __32_BITS__ |
/* Ignore physical memory above 4 GB */ |
if ((base >> 32) != 0) |
continue; |
/* Clip regions above 4 GB */ |
if (((base + size) >> 32) != 0) |
size = 0xffffffff - base; |
#endif |
pfn_t pfn; |
count_t count; |
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) { |
start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE)); |
size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE)); |
/* To be safe, make available zone possibly smaller */ |
pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE)); |
count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)); |
if ((minconf < start) || (minconf >= start + size)) |
conf = start; |
pfn_t conf; |
if ((minconf < pfn) || (minconf >= pfn + count)) |
conf = pfn; |
else |
conf = minconf; |
zone_create(start, size, conf, 0); |
zone_create(pfn, count, conf, ZONE_AVAILABLE); |
if (last_frame < ALIGN_UP(e820table[i].base_address + |
e820table[i].size, FRAME_SIZE)) |
last_frame = |
ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE); |
} |
// XXX this has to be removed |
if (last_frame < ALIGN_UP(base + size, FRAME_SIZE)) |
last_frame = ALIGN_UP(base + size, FRAME_SIZE); |
} |
if (e820table[i].type == MEMMAP_MEMORY_RESERVED) { |
/* To be safe, make reserved zone possibly larger */ |
pfn = ADDR2PFN(ALIGN_DOWN(base, FRAME_SIZE)); |
count = SIZE2FRAMES(ALIGN_UP(size, FRAME_SIZE)); |
zone_create(pfn, count, 0, ZONE_RESERVED); |
} |
if (e820table[i].type == MEMMAP_MEMORY_ACPI) { |
/* To be safe, make firmware zone possibly larger */ |
pfn = ADDR2PFN(ALIGN_DOWN(base, (uintptr_t) FRAME_SIZE)); |
count = SIZE2FRAMES(ALIGN_UP(size, (uintptr_t) FRAME_SIZE)); |
zone_create(pfn, count, 0, ZONE_FIRMWARE); |
} |
} |
} |
113,16 → 144,14 |
if (config.cpu_active == 1) { |
minconf = 1; |
#ifdef CONFIG_SMP |
minconf = max(minconf, |
ADDR2PFN(AP_BOOT_OFFSET + hardcoded_unmapped_ktext_size + |
hardcoded_unmapped_kdata_size)); |
#endif |
#ifdef CONFIG_SIMICS_FIX |
minconf = max(minconf, ADDR2PFN(0x10000)); |
#endif |
init_e820_memory(minconf); |
/* Reserve frame 0 (BIOS data) */ |
frame_mark_unavailable(0, 1); |
131,12 → 160,7 |
frame_mark_unavailable(AP_BOOT_OFFSET >> FRAME_WIDTH, |
(hardcoded_unmapped_ktext_size + |
hardcoded_unmapped_kdata_size) >> FRAME_WIDTH); |
#ifdef CONFIG_SIMICS_FIX |
/* Don't know why, but these addresses help */ |
frame_mark_unavailable(0xd000 >> FRAME_WIDTH, 3); |
#endif |
#endif |
} |
} |
/branches/dd/kernel/arch/ia32/src/mm/page.c |
---|
53,7 → 53,7 |
{ |
uintptr_t cur; |
int flags; |
if (config.cpu_active == 1) { |
page_mapping_operations = &pt_mapping_operations; |
66,12 → 66,12 |
flags |= PAGE_GLOBAL; |
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); |
} |
exc_register(14, "page_fault", (iroutine) page_fault); |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
} else |
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); |
paging_on(); |
} |
79,7 → 79,7 |
uintptr_t hw_map(uintptr_t physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
panic("Unable to map physical memory %p (%d bytes).", physaddr, size) |
uintptr_t virtaddr = PA2KA(last_frame); |
pfn_t i; |
101,8 → 101,8 |
page = read_cr2(); |
if (istate->error_word & PFERR_CODE_RSVD) |
panic("Reserved bit set in page directory.\n"); |
panic("Reserved bit set in page directory."); |
if (istate->error_word & PFERR_CODE_RW) |
access = PF_ACCESS_WRITE; |
else |
109,11 → 109,11 |
access = PF_ACCESS_READ; |
if (as_page_fault(page, access, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate, "Page fault: %#x", page); |
fault_if_from_uspace(istate, "Page fault: %#x.", page); |
decode_istate(istate); |
printf("page fault address: %#lx\n", page); |
panic("page fault\n"); |
panic("Page fault."); |
} |
} |
/branches/dd/kernel/arch/ia32/src/userspace.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia32 |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
47,10 → 47,8 |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
ipl_t ipl; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
asm volatile ( |
/* |
* Clear nested task flag. |
60,31 → 58,33 |
"and $0xffffbfff, %%eax\n" |
"push %%eax\n" |
"popfl\n" |
/* Set up GS register (TLS) */ |
"movl %6, %%gs\n" |
"pushl %0\n" |
"pushl %1\n" |
"pushl %2\n" |
"pushl %3\n" |
"pushl %4\n" |
"movl %5, %%eax\n" |
"movl %[tls_des], %%gs\n" |
"pushl %[udata_des]\n" |
"pushl %[stack_size]\n" |
"pushl %[ipl]\n" |
"pushl %[utext_des]\n" |
"pushl %[entry]\n" |
"movl %[uarg], %%eax\n" |
/* %ebx is defined to hold pcb_ptr - set it to 0 */ |
"xorl %%ebx, %%ebx\n" |
"iret\n" |
: |
: "i" (selector(UDATA_DES) | PL_USER), |
"r" ((uint8_t *) kernel_uarg->uspace_stack + |
THREAD_STACK_SIZE), |
"r" (ipl), |
"i" (selector(UTEXT_DES) | PL_USER), |
"r" (kernel_uarg->uspace_entry), |
"r" (kernel_uarg->uspace_uarg), |
"r" (selector(TLS_DES)) |
: |
: [udata_des] "i" (selector(UDATA_DES) | PL_USER), |
[stack_size] "r" ((uint8_t *) kernel_uarg->uspace_stack + THREAD_STACK_SIZE), |
[ipl] "r" (ipl), |
[utext_des] "i" (selector(UTEXT_DES) | PL_USER), |
[entry] "r" (kernel_uarg->uspace_entry), |
[uarg] "r" (kernel_uarg->uspace_uarg), |
[tls_des] "r" (selector(TLS_DES)) |
: "eax"); |
/* Unreachable */ |
for(;;) |
; |
while (1); |
} |
/** @} |
/branches/dd/kernel/arch/ia32/src/interrupt.c |
---|
77,9 → 77,6 |
printf("ERROR_WORD=%#lx\n", istate->error_word); |
printf("%%cs=%#lx,flags=%#lx\n", istate->cs, istate->eflags); |
printf("%%eax=%#lx, %%ecx=%#lx, %%edx=%#lx, %%esp=%p\n", istate->eax, istate->ecx, istate->edx, &istate->stack[0]); |
#ifdef CONFIG_DEBUG_ALLREGS |
printf("%%esi=%#lx, %%edi=%#lx, %%ebp=%#lx, %%ebx=%#lx\n", istate->esi, istate->edi, istate->ebp, istate->ebx); |
#endif |
printf("stack: %#lx, %#lx, %#lx, %#lx\n", istate->stack[0], istate->stack[1], istate->stack[2], istate->stack[3]); |
printf(" %#lx, %#lx, %#lx, %#lx\n", istate->stack[4], istate->stack[5], istate->stack[6], istate->stack[7]); |
} |
89,16 → 86,16 |
if (eoi_function) |
eoi_function(); |
else |
panic("no eoi_function\n"); |
panic("No eoi_function."); |
} |
static void null_interrupt(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "unserviced interrupt: %d", n); |
fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n); |
decode_istate(istate); |
panic("unserviced interrupt: %d\n", n); |
panic("Unserviced interrupt: %d.", n); |
} |
/** General Protection Fault. */ |
122,19 → 119,19 |
io_perm_bitmap_install(); |
return; |
} |
fault_if_from_uspace(istate, "general protection fault"); |
fault_if_from_uspace(istate, "General protection fault."); |
} |
decode_istate(istate); |
panic("general protection fault\n"); |
panic("General protection fault."); |
} |
static void ss_fault(int n __attribute__((unused)), istate_t *istate) |
{ |
fault_if_from_uspace(istate, "stack fault"); |
fault_if_from_uspace(istate, "Stack fault."); |
decode_istate(istate); |
panic("stack fault\n"); |
panic("Stack fault."); |
} |
static void simd_fp_exception(int n __attribute__((unused)), istate_t *istate) |
141,15 → 138,15 |
{ |
uint32_t mxcsr; |
asm ( |
"stmxcsr %0;\n" |
: "=m" (mxcsr) |
"stmxcsr %[mxcsr]\n" |
: [mxcsr] "=m" (mxcsr) |
); |
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx", |
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx.", |
(unative_t) mxcsr); |
decode_istate(istate); |
printf("MXCSR: %#lx\n", mxcsr); |
panic("SIMD FP exception(19)\n"); |
panic("SIMD FP exception(19)."); |
} |
static void nm_fault(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) |
157,8 → 154,8 |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#else |
fault_if_from_uspace(istate, "fpu fault"); |
panic("fpu fault"); |
fault_if_from_uspace(istate, "FPU fault."); |
panic("FPU fault."); |
#endif |
} |
191,7 → 188,7 |
trap_virtual_eoi(); |
ack = true; |
} |
irq->handler(irq, irq->arg); |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* |
233,7 → 230,7 |
if (enable_irqs_function) |
enable_irqs_function(irqmask); |
else |
panic("no enable_irqs_function\n"); |
panic("No enable_irqs_function."); |
} |
void trap_virtual_disable_irqs(uint16_t irqmask) |
241,7 → 238,7 |
if (disable_irqs_function) |
disable_irqs_function(irqmask); |
else |
panic("no disable_irqs_function\n"); |
panic("No disable_irqs_function."); |
} |
/** @} |
/branches/dd/kernel/arch/ia32/src/drivers/ega.c |
---|
File deleted |
/branches/dd/kernel/arch/ia32/src/drivers/vesa.c |
---|
83,12 → 83,25 |
visual = VISUAL_RGB_0_8_8_8; |
break; |
default: |
panic("Unsupported bits per pixel"); |
panic("Unsupported bits per pixel."); |
} |
fb_init(vesa_ph_addr, vesa_width, vesa_height, vesa_scanline, visual); |
fb_properties_t vesa_props = { |
.addr = vesa_ph_addr, |
.offset = 0, |
.x = vesa_width, |
.y = vesa_height, |
.scan = vesa_scanline, |
.visual = visual, |
}; |
fb_init(&vesa_props); |
} |
void vesa_redraw(void) |
{ |
fb_redraw(); |
} |
#endif |
/** @} |
/branches/dd/kernel/arch/ia32/src/drivers/i8259.c |
---|
49,28 → 49,28 |
void i8259_init(void) |
{ |
/* ICW1: this is ICW1, ICW4 to follow */ |
outb(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4); |
pio_write_8(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4); |
/* ICW2: IRQ 0 maps to INT IRQBASE */ |
outb(PIC_PIC0PORT2, IVT_IRQBASE); |
pio_write_8(PIC_PIC0PORT2, IVT_IRQBASE); |
/* ICW3: pic1 using IRQ IRQ_PIC1 */ |
outb(PIC_PIC0PORT2, 1 << IRQ_PIC1); |
pio_write_8(PIC_PIC0PORT2, 1 << IRQ_PIC1); |
/* ICW4: i8086 mode */ |
outb(PIC_PIC0PORT2, 1); |
pio_write_8(PIC_PIC0PORT2, 1); |
/* ICW1: ICW1, ICW4 to follow */ |
outb(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4); |
pio_write_8(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4); |
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */ |
outb(PIC_PIC1PORT2, IVT_IRQBASE + 8); |
pio_write_8(PIC_PIC1PORT2, IVT_IRQBASE + 8); |
/* ICW3: pic1 is known as IRQ_PIC1 */ |
outb(PIC_PIC1PORT2, IRQ_PIC1); |
pio_write_8(PIC_PIC1PORT2, IRQ_PIC1); |
/* ICW4: i8086 mode */ |
outb(PIC_PIC1PORT2, 1); |
pio_write_8(PIC_PIC1PORT2, 1); |
/* |
* Register interrupt handler for the PIC spurious interrupt. |
94,12 → 94,12 |
uint8_t x; |
if (irqmask & 0xff) { |
x = inb(PIC_PIC0PORT2); |
outb(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff)))); |
x = pio_read_8(PIC_PIC0PORT2); |
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff)))); |
} |
if (irqmask >> 8) { |
x = inb(PIC_PIC1PORT2); |
outb(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8)))); |
x = pio_read_8(PIC_PIC1PORT2); |
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8)))); |
} |
} |
108,19 → 108,19 |
uint8_t x; |
if (irqmask & 0xff) { |
x = inb(PIC_PIC0PORT2); |
outb(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff))); |
x = pio_read_8(PIC_PIC0PORT2); |
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff))); |
} |
if (irqmask >> 8) { |
x = inb(PIC_PIC1PORT2); |
outb(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8))); |
x = pio_read_8(PIC_PIC1PORT2); |
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8))); |
} |
} |
void pic_eoi(void) |
{ |
outb(0x20, 0x20); |
outb(0xa0, 0x20); |
pio_write_8((ioport8_t *)0x20, 0x20); |
pio_write_8((ioport8_t *)0xa0, 0x20); |
} |
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) |
/branches/dd/kernel/arch/ia32/src/drivers/i8254.c |
---|
53,8 → 53,8 |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#define CLK_PORT1 0x40 |
#define CLK_PORT4 0x43 |
#define CLK_PORT1 ((ioport8_t *)0x40) |
#define CLK_PORT4 ((ioport8_t *)0x43) |
#define CLK_CONST 1193180 |
#define MAGIC_NUMBER 1194 |
61,12 → 61,12 |
static irq_t i8254_irq; |
static irq_ownership_t i8254_claim(void) |
static irq_ownership_t i8254_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
} |
static void i8254_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...) |
static void i8254_irq_handler(irq_t *irq) |
{ |
/* |
* This IRQ is responsible for kernel preemption. |
94,10 → 94,10 |
void i8254_normal_operation(void) |
{ |
outb(CLK_PORT4, 0x36); |
pio_write_8(CLK_PORT4, 0x36); |
pic_disable_irqs(1 << IRQ_CLK); |
outb(CLK_PORT1, (CLK_CONST / HZ) & 0xf); |
outb(CLK_PORT1, (CLK_CONST / HZ) >> 8); |
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) & 0xf); |
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) >> 8); |
pic_enable_irqs(1 << IRQ_CLK); |
} |
114,36 → 114,36 |
* One-shot timer. Count-down from 0xffff at 1193180Hz |
* MAGIC_NUMBER is the magic value for 1ms. |
*/ |
outb(CLK_PORT4, 0x30); |
outb(CLK_PORT1, 0xff); |
outb(CLK_PORT1, 0xff); |
pio_write_8(CLK_PORT4, 0x30); |
pio_write_8(CLK_PORT1, 0xff); |
pio_write_8(CLK_PORT1, 0xff); |
do { |
/* will read both status and count */ |
outb(CLK_PORT4, 0xc2); |
not_ok = (uint8_t) ((inb(CLK_PORT1) >> 6) & 1); |
t1 = inb(CLK_PORT1); |
t1 |= inb(CLK_PORT1) << 8; |
pio_write_8(CLK_PORT4, 0xc2); |
not_ok = (uint8_t) ((pio_read_8(CLK_PORT1) >> 6) & 1); |
t1 = pio_read_8(CLK_PORT1); |
t1 |= pio_read_8(CLK_PORT1) << 8; |
} while (not_ok); |
asm_delay_loop(LOOPS); |
outb(CLK_PORT4, 0xd2); |
t2 = inb(CLK_PORT1); |
t2 |= inb(CLK_PORT1) << 8; |
pio_write_8(CLK_PORT4, 0xd2); |
t2 = pio_read_8(CLK_PORT1); |
t2 |= pio_read_8(CLK_PORT1) << 8; |
/* |
* We want to determine the overhead of the calibrating mechanism. |
*/ |
outb(CLK_PORT4, 0xd2); |
o1 = inb(CLK_PORT1); |
o1 |= inb(CLK_PORT1) << 8; |
pio_write_8(CLK_PORT4, 0xd2); |
o1 = pio_read_8(CLK_PORT1); |
o1 |= pio_read_8(CLK_PORT1) << 8; |
asm_fake_loop(LOOPS); |
outb(CLK_PORT4, 0xd2); |
o2 = inb(CLK_PORT1); |
o2 |= inb(CLK_PORT1) << 8; |
pio_write_8(CLK_PORT4, 0xd2); |
o2 = pio_read_8(CLK_PORT1); |
o2 |= pio_read_8(CLK_PORT1) << 8; |
CPU->delay_loop_const = |
((MAGIC_NUMBER * LOOPS) / 1000) / ((t1 - t2) - (o1 - o2)) + |
/branches/dd/tools/xtui.py |
---|
0,0 → 1,260 |
# |
# Copyright (c) 2009 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
Text User Interface wrapper |
""" |
import sys |
import os |
def call_dlg(dlgcmd, *args, **kw): |
"Wrapper for calling 'dialog' program" |
indesc, outdesc = os.pipe() |
pid = os.fork() |
if (not pid): |
os.close(2) |
os.dup(outdesc) |
os.close(indesc) |
dlgargs = [dlgcmd] |
for key, val in kw.items(): |
dlgargs.append('--' + key) |
dlgargs.append(val) |
dlgargs += args |
os.execlp(dlgcmd, *dlgargs) |
os.close(outdesc) |
try: |
errout = os.fdopen(indesc, 'r') |
data = errout.read() |
errout.close() |
pid, status = os.wait() |
except: |
# Reset terminal |
os.system('reset') |
raise |
if (not os.WIFEXITED(status)): |
# Reset terminal |
os.system('reset') |
raise EOFError |
status = os.WEXITSTATUS(status) |
if (status == 255): |
raise EOFError |
return (status, data) |
try: |
import snack |
newt = True |
dialog = False |
except ImportError: |
newt = False |
dlgcmd = os.environ.get('DIALOG', 'dialog') |
if (call_dlg(dlgcmd, '--print-maxsize')[0] != 0): |
dialog = False |
else: |
dialog = True |
width_extra = 13 |
height_extra = 11 |
def width_fix(screen, width): |
"Correct width to screen size" |
if (width + width_extra > screen.width): |
width = screen.width - width_extra |
if (width <= 0): |
width = screen.width |
return width |
def height_fix(screen, height): |
"Correct height to screen size" |
if (height + height_extra > screen.height): |
height = screen.height - height_extra |
if (height <= 0): |
height = screen.height |
return height |
def screen_init(): |
"Initialize the screen" |
if (newt): |
return snack.SnackScreen() |
return None |
def screen_done(screen): |
"Cleanup the screen" |
if (newt): |
screen.finish() |
def choice_window(screen, title, text, options, position): |
"Create options menu" |
maxopt = 0 |
for option in options: |
length = len(option) |
if (length > maxopt): |
maxopt = length |
width = maxopt |
height = len(options) |
if (newt): |
width = width_fix(screen, width + width_extra) |
height = height_fix(screen, height) |
if (height > 3): |
large = True |
else: |
large = False |
buttonbar = snack.ButtonBar(screen, ('Done', 'Cancel')) |
textbox = snack.TextboxReflowed(width, text) |
listbox = snack.Listbox(height, scroll = large, returnExit = 1) |
cnt = 0 |
for option in options: |
listbox.append(option, cnt) |
cnt += 1 |
if (position != None): |
listbox.setCurrent(position) |
grid = snack.GridForm(screen, title, 1, 3) |
grid.add(textbox, 0, 0) |
grid.add(listbox, 0, 1, padding = (0, 1, 0, 1)) |
grid.add(buttonbar, 0, 2, growx = 1) |
retval = grid.runOnce() |
return (buttonbar.buttonPressed(retval), listbox.current()) |
elif (dialog): |
if (width < 35): |
width = 35 |
args = [] |
cnt = 0 |
for option in options: |
args.append(str(cnt + 1)) |
args.append(option) |
cnt += 1 |
kw = {} |
if (position != None): |
kw['default-item'] = str(position + 1) |
status, data = call_dlg(dlgcmd, '--title', title, '--extra-button', '--extra-label', 'Done', '--menu', text, str(height + height_extra), str(width + width_extra), str(cnt), *args, **kw) |
if (status == 1): |
return ('cancel', None) |
try: |
choice = int(data) - 1 |
except ValueError: |
return ('cancel', None) |
if (status == 0): |
return (None, choice) |
return ('done', choice) |
sys.stdout.write("\n *** %s *** \n%s\n\n" % (title, text)) |
maxcnt = len(str(len(options))) |
cnt = 0 |
for option in options: |
sys.stdout.write("%*s. %s\n" % (maxcnt, cnt + 1, option)) |
cnt += 1 |
sys.stdout.write("\n%*s. Done\n" % (maxcnt, '0')) |
sys.stdout.write("%*s. Quit\n\n" % (maxcnt, 'q')) |
while True: |
if (position != None): |
sys.stdout.write("Selection[%s]: " % str(position + 1)) |
else: |
sys.stdout.write("Selection: ") |
inp = sys.stdin.readline() |
if (not inp): |
raise EOFError |
if (not inp.strip()): |
if (position != None): |
return (None, position) |
continue |
if (inp.strip() == 'q'): |
return ('cancel', None) |
try: |
choice = int(inp.strip()) |
except ValueError: |
continue |
if (choice == 0): |
return ('done', 0) |
if (choice < 1) or (choice > len(options)): |
continue |
return (None, choice - 1) |
def error_dialog(screen, title, msg): |
"Print error dialog" |
width = len(msg) |
if (newt): |
width = width_fix(screen, width) |
buttonbar = snack.ButtonBar(screen, ['Ok']) |
textbox = snack.TextboxReflowed(width, msg) |
grid = snack.GridForm(screen, title, 1, 2) |
grid.add(textbox, 0, 0, padding = (0, 0, 0, 1)) |
grid.add(buttonbar, 0, 1, growx = 1) |
grid.runOnce() |
elif (dialog): |
call_dlg(dlgcmd, '--title', title, '--msgbox', msg, '6', str(width + width_extra)) |
else: |
sys.stdout.write("\n%s: %s\n" % (title, msg)) |
/branches/dd/tools/xstruct.py |
---|
0,0 → 1,110 |
# |
# Copyright (c) 2008 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
Convert descriptive structure definitions to structure object |
""" |
import struct |
class Struct: |
def size(self): |
return struct.calcsize(self._format_) |
def pack(self): |
args = [] |
for variable in self._args_: |
if (isinstance(self.__dict__[variable], list)): |
for item in self.__dict__[variable]: |
args.append(item) |
else: |
args.append(self.__dict__[variable]) |
return struct.pack(self._format_, *args) |
def create(definition): |
"Create structure object" |
tokens = definition.split(None) |
# Initial byte order tag |
format = { |
"little:": lambda: "<", |
"big:": lambda: ">", |
"network:": lambda: "!" |
}[tokens[0]]() |
inst = Struct() |
args = [] |
# Member tags |
comment = False |
variable = None |
for token in tokens[1:]: |
if (comment): |
if (token == "*/"): |
comment = False |
continue |
if (token == "/*"): |
comment = True |
continue |
if (variable != None): |
subtokens = token.split("[") |
if (len(subtokens) > 1): |
format += "%d" % int(subtokens[1].split("]")[0]) |
format += variable |
inst.__dict__[subtokens[0]] = None |
args.append(subtokens[0]) |
variable = None |
continue |
if (token[0:8] == "padding["): |
size = token[8:].split("]")[0] |
format += "%dx" % int(size) |
continue |
variable = { |
"char": lambda: "s", |
"uint8_t": lambda: "B", |
"uint16_t": lambda: "H", |
"uint32_t": lambda: "L", |
"uint64_t": lambda: "Q", |
"int8_t": lambda: "b", |
"int16_t": lambda: "h", |
"int32_t": lambda: "l", |
"int64_t": lambda: "q" |
}[token]() |
inst.__dict__['_format_'] = format |
inst.__dict__['_args_'] = args |
return inst |
/branches/dd/tools/fix_symlinks.sh |
---|
1,3 → 1,5 |
#!/bin/bash |
# by Alf |
# This script solves malfunction of symlinks in cygwin |
# |
6,17 → 8,17 |
if uname | grep 'CYGWIN' > /dev/null; then |
echo "Good ... you have cygwin" |
echo "Good ... you have cygwin" |
else |
echo "Wrong. This script is only for cygwin" |
exit |
echo "Wrong. This script is only for cygwin" |
exit |
fi |
for linkName in `find . ! -iwholename '.*svn*' ! -type d -print`; do |
if head -n 1 $linkName | grep '^link' > /dev/null; then |
linkTarget=`head -n 1 $linkName | sed 's/^link //'` |
echo $linkName " -->" $linkTarget |
rm $linkName |
ln -s "$linkTarget" "$linkName" |
fi |
if head -n 1 $linkName | grep '^link' > /dev/null; then |
linkTarget=`head -n 1 $linkName | sed 's/^link //'` |
echo $linkName " -> " $linkTarget |
rm $linkName |
ln -s "$linkTarget" "$linkName" |
fi |
done |
/branches/dd/tools/mktmpfs.py |
---|
32,69 → 32,107 |
import sys |
import os |
import struct |
import xstruct |
def align_up(size, alignment): |
return (((size) + ((alignment) - 1)) & ~((alignment) - 1)) |
exclude_names = set(['.svn']) |
HEADER = """little: |
char tag[5] /* 'TMPFS' */ |
""" |
DENTRY_NONE = """little: |
uint8_t kind /* NONE */ |
uint32_t fname_len /* 0 */ |
""" |
DENTRY_FILE = """little: |
uint8_t kind /* FILE */ |
uint32_t fname_len /* filename length */ |
char fname[%d] /* filename */ |
uint32_t flen /* file length */ |
""" |
DENTRY_DIRECTORY = """little: |
uint8_t kind /* DIRECTORY */ |
uint32_t fname_len /* filename length */ |
char fname[%d] /* filename */ |
""" |
TMPFS_NONE = 0 |
TMPFS_FILE = 1 |
TMPFS_DIRECTORY = 2 |
def usage(prname): |
"Print usage syntax" |
print prname + " <ALIGNMENT> <PATH> <IMAGE>" |
print prname + " <PATH> <IMAGE>" |
def main(): |
if (len(sys.argv) < 4): |
usage(sys.argv[0]) |
return |
def recursion(root, outf): |
"Recursive directory walk" |
if (not sys.argv[1].isdigit()): |
print "<ALIGNMENT> must be a number" |
return |
align = int(sys.argv[1], 0) |
path = os.path.abspath(sys.argv[2]) |
if (not os.path.isdir(path)): |
print "<PATH> must be a directory" |
return |
header_size = align_up(18, align) |
payload_size = 0 |
outf = file(sys.argv[3], "w") |
outf.write(struct.pack("<" + ("%d" % header_size) + "x")) |
for root, dirs, files in os.walk(path): |
relpath = root[len(path):len(root)] |
for name in files: |
canon = os.path.join(relpath, name) |
outf.write(struct.pack("<BL" + ("%d" % len(canon)) + "s", 1, len(canon), canon)) |
payload_size += 5 + len(canon) |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
size = os.path.getsize(canon) |
fn = os.path.join(root, name) |
size = os.path.getsize(fn) |
dentry = xstruct.create(DENTRY_FILE % len(name)) |
dentry.kind = TMPFS_FILE |
dentry.fname_len = len(name) |
dentry.fname = name |
dentry.flen = size |
outf.write(dentry.pack()) |
inf = file(canon, "r") |
rd = 0; |
outf.write(struct.pack("<L", size)) |
payload_size += 4 |
inf = file(fn, "r") |
while (rd < size): |
data = inf.read(4096); |
outf.write(data) |
payload_size += len(data) |
rd += len(data) |
inf.close() |
for name in dirs: |
canon = os.path.join(relpath, name) |
outf.write(struct.pack("<BL" + ("%d" % len(canon)) + "s", 2, len(canon), canon)) |
payload_size += 5 + len(canon) |
if (os.path.isdir(canon) and (not name in exclude_names)): |
dentry = xstruct.create(DENTRY_DIRECTORY % len(name)) |
dentry.kind = TMPFS_DIRECTORY |
dentry.fname_len = len(name) |
dentry.fname = name |
outf.write(dentry.pack()) |
recursion(canon, outf) |
dentry = xstruct.create(DENTRY_NONE) |
dentry.kind = TMPFS_NONE |
dentry.fname_len = 0 |
outf.write(dentry.pack()) |
def main(): |
if (len(sys.argv) < 3): |
usage(sys.argv[0]) |
return |
aligned_size = align_up(payload_size, align) |
path = os.path.abspath(sys.argv[1]) |
if (not os.path.isdir(path)): |
print "<PATH> must be a directory" |
return |
if (aligned_size - payload_size > 0): |
outf.write(struct.pack("<" + ("%d" % (aligned_size - payload_size)) + "x")) |
outf = file(sys.argv[2], "w") |
outf.seek(0) |
outf.write(struct.pack("<4sBBLQ", "HORD", 1, 1, header_size, aligned_size)) |
header = xstruct.create(HEADER) |
header.tag = "TMPFS" |
outf.write(header.pack()) |
recursion(path, outf) |
dentry = xstruct.create(DENTRY_NONE) |
dentry.kind = TMPFS_NONE |
dentry.fname_len = 0 |
outf.write(dentry.pack()) |
outf.close() |
if __name__ == '__main__': |
main() |
/branches/dd/tools/mkfat.py |
---|
0,0 → 1,450 |
#!/usr/bin/env python |
# |
# Copyright (c) 2008 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
FAT creator |
""" |
import sys |
import os |
import random |
import xstruct |
import array |
exclude_names = set(['.svn']) |
def align_up(size, alignment): |
"Return size aligned up to alignment" |
if (size % alignment == 0): |
return size |
return (((size / alignment) + 1) * alignment) |
def subtree_size(root, cluster_size, dirent_size): |
"Recursive directory walk and calculate size" |
size = 0 |
files = 2 |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
size += align_up(os.path.getsize(canon), cluster_size) |
files += 1 |
if (os.path.isdir(canon) and (not name in exclude_names)): |
size += subtree_size(canon, cluster_size, dirent_size) |
files += 1 |
return size + align_up(files * dirent_size, cluster_size) |
def root_entries(root): |
"Return number of root directory entries" |
return len(os.listdir(root)) |
def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters): |
"Store the contents of a file" |
size = os.path.getsize(path) |
prev = -1 |
first = 0 |
inf = file(path, "r") |
rd = 0; |
while (rd < size): |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
if (prev != -1): |
fat[prev] = empty_cluster |
else: |
first = empty_cluster |
prev = empty_cluster |
data = inf.read(cluster_size); |
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) |
outf.write(data) |
rd += len(data) |
inf.close() |
return first, size |
def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster): |
"Store the contents of a directory" |
length = len(directory) |
size = length * dirent_size |
prev = -1 |
first = 0 |
i = 0 |
rd = 0; |
while (rd < size): |
if (prev != -1): |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
fat[prev] = empty_cluster |
else: |
first = empty_cluster |
prev = empty_cluster |
data = '' |
data_len = 0 |
while ((i < length) and (data_len < cluster_size)): |
if (i == 0): |
directory[i].cluster = empty_cluster |
data += directory[i].pack() |
data_len += dirent_size |
i += 1 |
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size) |
outf.write(data) |
rd += len(data) |
return first, size |
DIR_ENTRY = """little: |
char name[8] /* file name */ |
char ext[3] /* file extension */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
DOT_DIR_ENTRY = """little: |
uint8_t signature /* 0x2e signature */ |
char name[7] /* empty */ |
char ext[3] /* empty */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
DOTDOT_DIR_ENTRY = """little: |
uint8_t signature[2] /* 0x2e signature */ |
char name[6] /* empty */ |
char ext[3] /* empty */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
uint16_t adate /* access date */ |
padding[2] /* EA-index */ |
uint16_t mtime /* modification time */ |
uint16_t mdate /* modification date */ |
uint16_t cluster /* first cluster */ |
uint32_t size /* file size */ |
""" |
def mangle_fname(name): |
# FIXME: filter illegal characters |
parts = name.split('.') |
if (len(parts) > 0): |
fname = parts[0] |
else: |
fname = '' |
return (fname + ' ').upper()[0:8] |
def mangle_ext(name): |
# FIXME: filter illegal characters |
parts = name.split('.') |
if (len(parts) > 1): |
ext = parts[1] |
else: |
ext = '' |
return (ext + ' ').upper()[0:3] |
def create_dirent(name, directory, cluster, size): |
dir_entry = xstruct.create(DIR_ENTRY) |
dir_entry.name = mangle_fname(name) |
dir_entry.ext = mangle_ext(name) |
if (directory): |
dir_entry.attr = 0x30 |
else: |
dir_entry.attr = 0x20 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = cluster |
if (directory): |
dir_entry.size = 0 |
else: |
dir_entry.size = size |
return dir_entry |
def create_dot_dirent(empty_cluster): |
dir_entry = xstruct.create(DOT_DIR_ENTRY) |
dir_entry.signature = 0x2e |
dir_entry.name = ' ' |
dir_entry.ext = ' ' |
dir_entry.attr = 0x10 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = empty_cluster |
dir_entry.size = 0 |
return dir_entry |
def create_dotdot_dirent(parent_cluster): |
dir_entry = xstruct.create(DOTDOT_DIR_ENTRY) |
dir_entry.signature = [0x2e, 0x2e] |
dir_entry.name = ' ' |
dir_entry.ext = ' ' |
dir_entry.attr = 0x10 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
dir_entry.adate = 0 # FIXME |
dir_entry.mtime = 0 # FIXME |
dir_entry.mdate = 0 # FIXME |
dir_entry.cluster = parent_cluster |
dir_entry.size = 0 |
return dir_entry |
def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster): |
"Recursive directory walk" |
directory = [] |
if (not head): |
# Directory cluster preallocation |
empty_cluster = fat.index(0) |
fat[empty_cluster] = 0xffff |
directory.append(create_dot_dirent(empty_cluster)) |
directory.append(create_dotdot_dirent(parent_cluster)) |
else: |
empty_cluster = 0 |
for name in os.listdir(root): |
canon = os.path.join(root, name) |
if (os.path.isfile(canon) and (not name in exclude_names)): |
rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters) |
directory.append(create_dirent(name, False, rv[0], rv[1])) |
if (os.path.isdir(canon) and (not name in exclude_names)): |
rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster) |
directory.append(create_dirent(name, True, rv[0], rv[1])) |
if (head): |
outf.seek(root_start) |
for dir_entry in directory: |
outf.write(dir_entry.pack()) |
else: |
return write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster) |
BOOT_SECTOR = """little: |
uint8_t jmp[3] /* jump instruction */ |
char oem[8] /* OEM string */ |
uint16_t sector /* bytes per sector */ |
uint8_t cluster /* sectors per cluster */ |
uint16_t reserved /* reserved sectors */ |
uint8_t fats /* number of FATs */ |
uint16_t rootdir /* root directory entries */ |
uint16_t sectors /* total number of sectors */ |
uint8_t descriptor /* media descriptor */ |
uint16_t fat_sectors /* sectors per single FAT */ |
uint16_t track_sectors /* sectors per track */ |
uint16_t heads /* number of heads */ |
uint32_t hidden /* hidden sectors */ |
uint32_t sectors_big /* total number of sectors (if sectors == 0) */ |
/* Extended BIOS Parameter Block */ |
uint8_t drive /* physical drive number */ |
padding[1] /* reserved (current head) */ |
uint8_t extboot_signature /* extended boot signature */ |
uint32_t serial /* serial number */ |
char label[11] /* volume label */ |
char fstype[8] /* filesystem type */ |
padding[448] /* boot code */ |
uint8_t boot_signature[2] /* boot signature */ |
""" |
EMPTY_SECTOR = """little: |
padding[512] /* empty sector data */ |
""" |
FAT_ENTRY = """little: |
uint16_t next /* FAT16 entry */ |
""" |
def usage(prname): |
"Print usage syntax" |
print prname + " <PATH> <IMAGE>" |
def main(): |
if (len(sys.argv) < 3): |
usage(sys.argv[0]) |
return |
path = os.path.abspath(sys.argv[1]) |
if (not os.path.isdir(path)): |
print "<PATH> must be a directory" |
return |
fat16_clusters = 4096 |
sector_size = 512 |
cluster_size = 4096 |
dirent_size = 32 |
fatent_size = 2 |
fat_count = 2 |
reserved_clusters = 2 |
# Make sure the filesystem is large enought for FAT16 |
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size |
while (size / cluster_size < fat16_clusters): |
if (cluster_size > sector_size): |
cluster_size /= 2 |
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size |
else: |
size = fat16_clusters * cluster_size + reserved_clusters * cluster_size |
root_size = align_up(root_entries(path) * dirent_size, cluster_size) |
fat_size = align_up(align_up(size, cluster_size) / cluster_size * fatent_size, sector_size) |
sectors = (cluster_size + fat_count * fat_size + root_size + size) / sector_size |
root_start = cluster_size + fat_count * fat_size |
data_start = root_start + root_size |
outf = file(sys.argv[2], "w") |
boot_sector = xstruct.create(BOOT_SECTOR) |
boot_sector.jmp = [0xEB, 0x3C, 0x90] |
boot_sector.oem = "MSDOS5.0" |
boot_sector.sector = sector_size |
boot_sector.cluster = cluster_size / sector_size |
boot_sector.reserved = cluster_size / sector_size |
boot_sector.fats = fat_count |
boot_sector.rootdir = root_size / dirent_size |
if (sectors <= 65535): |
boot_sector.sectors = sectors |
else: |
boot_sector.sectors = 0 |
boot_sector.descriptor = 0xF8 |
boot_sector.fat_sectors = fat_size / sector_size |
boot_sector.track_sectors = 63 |
boot_sector.heads = 6 |
boot_sector.hidden = 0 |
if (sectors > 65535): |
boot_sector.sectors_big = sectors |
else: |
boot_sector.sectors_big = 0 |
boot_sector.drive = 0x80 |
boot_sector.extboot_signature = 0x29 |
boot_sector.serial = random.randint(0, 0x7fffffff) |
boot_sector.label = "HELENOS" |
boot_sector.fstype = "FAT16 " |
boot_sector.boot_signature = [0x55, 0xAA] |
outf.write(boot_sector.pack()) |
empty_sector = xstruct.create(EMPTY_SECTOR) |
# Reserved sectors |
for i in range(1, cluster_size / sector_size): |
outf.write(empty_sector.pack()) |
# FAT tables |
for i in range(0, fat_count): |
for j in range(0, fat_size / sector_size): |
outf.write(empty_sector.pack()) |
# Root directory |
for i in range(0, root_size / sector_size): |
outf.write(empty_sector.pack()) |
# Data |
for i in range(0, size / sector_size): |
outf.write(empty_sector.pack()) |
fat = array.array('L', [0] * (fat_size / fatent_size)) |
fat[0] = 0xfff8 |
fat[1] = 0xffff |
recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) |
# Store FAT |
fat_entry = xstruct.create(FAT_ENTRY) |
for i in range(0, fat_count): |
outf.seek(cluster_size + i * fat_size) |
for j in range(0, fat_size / fatent_size): |
fat_entry.next = fat[j] |
outf.write(fat_entry.pack()) |
outf.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/tools/mkhord.py |
---|
0,0 → 1,104 |
#!/usr/bin/env python |
# |
# Copyright (c) 2008 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
HORD encapsulator |
""" |
import sys |
import os |
import xstruct |
HEADER = """little: |
char tag[4] /* 'HORD' */ |
uint8_t version /* version */ |
uint8_t encoding /* encoding */ |
uint32_t header_size /* header size */ |
uint64_t payload_size /* payload size */ |
""" |
HORD_LSB = 1 |
def align_up(size, alignment): |
"Align upwards to a given alignment" |
return (((size) + ((alignment) - 1)) & ~((alignment) - 1)) |
def usage(prname): |
"Print usage syntax" |
print prname + " <ALIGNMENT> <FS_IMAGE> <HORD_IMAGE>" |
def main(): |
if (len(sys.argv) < 4): |
usage(sys.argv[0]) |
return |
if (not sys.argv[1].isdigit()): |
print "<ALIGNMENT> must be a number" |
return |
align = int(sys.argv[1], 0) |
if (align <= 0): |
print "<ALIGNMENT> must be positive" |
return |
fs_image = os.path.abspath(sys.argv[2]) |
if (not os.path.isfile(fs_image)): |
print "<FS_IMAGE> must be a file" |
return |
inf = file(fs_image, "rb") |
outf = file(sys.argv[3], "wb") |
header = xstruct.create(HEADER) |
header_size = header.size() |
payload_size = os.path.getsize(fs_image) |
header_size_aligned = align_up(header_size, align) |
payload_size_aligned = align_up(payload_size, align) |
header.tag = "HORD" |
header.version = 1 |
header.encoding = HORD_LSB |
header.header_size = header_size_aligned |
header.payload_size = payload_size_aligned |
outf.write(header.pack()) |
outf.write(xstruct.create("little: padding[%d]" % (header_size_aligned - header_size)).pack()) |
outf.write(inf.read()) |
padding = payload_size_aligned - payload_size |
if (padding > 0): |
outf.write(xstruct.create("little: padding[%d]" % padding).pack()) |
inf.close() |
outf.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/tools/config.py |
---|
1,6 → 1,7 |
#!/usr/bin/env python |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# Copyright (c) 2009 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
27,512 → 28,373 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
HelenOS configuration script |
HelenOS configuration system |
""" |
import sys |
import os |
import re |
import commands |
import xtui |
INPUT = sys.argv[1] |
OUTPUT = 'Makefile.config' |
TMPOUTPUT = 'Makefile.config.tmp' |
MAKEFILE = 'Makefile.config' |
MACROS = 'config.h' |
DEFS = 'config.defs' |
class DefaultDialog: |
"Wrapper dialog that tries to return default values" |
def __init__(self, dlg): |
self.dlg = dlg |
def read_defaults(fname, defaults): |
"Read saved values from last configuration run" |
inf = file(fname, 'r') |
for line in inf: |
res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line) |
if (res): |
defaults[res.group(1)] = res.group(2) |
inf.close() |
def set_title(self,text): |
self.dlg.set_title(text) |
def yesno(self, text, default=None): |
if default is not None: |
return default |
return self.dlg.yesno(text, default) |
def noyes(self, text, default=None): |
if default is not None: |
return default |
return self.dlg.noyes(text, default) |
def choice(self, text, choices, defopt=None): |
if defopt is not None: |
return choices[defopt][0] |
return self.dlg.choice(text, choices, defopt) |
def check_condition(text, defaults, ask_names): |
"Check that the condition specified on input line is True (only CNF and DNF is supported)" |
ctype = 'cnf' |
if ((')|' in text) or ('|(' in text)): |
ctype = 'dnf' |
if (ctype == 'cnf'): |
conds = text.split('&') |
else: |
conds = text.split('|') |
for cond in conds: |
if (cond.startswith('(')) and (cond.endswith(')')): |
cond = cond[1:-1] |
inside = check_inside(cond, defaults, ctype) |
if (ctype == 'cnf') and (not inside): |
return False |
if (ctype == 'dnf') and (inside): |
return True |
if (ctype == 'cnf'): |
return True |
return False |
class NoDialog: |
def __init__(self): |
self.printed = None |
self.title = 'HelenOS Configuration' |
def check_inside(text, defaults, ctype): |
"Check for condition" |
if (ctype == 'cnf'): |
conds = text.split('|') |
else: |
conds = text.split('&') |
for cond in conds: |
res = re.match(r'^(.*?)(!?=)(.*)$', cond) |
if (not res): |
raise RuntimeError("Invalid condition: %s" % cond) |
condname = res.group(1) |
oper = res.group(2) |
condval = res.group(3) |
if (not defaults.has_key(condname)): |
varval = '' |
else: |
varval = defaults[condname] |
if (varval == '*'): |
varval = 'y' |
if (ctype == 'cnf'): |
if (oper == '=') and (condval == varval): |
return True |
if (oper == '!=') and (condval != varval): |
return True |
else: |
if (oper == '=') and (condval != varval): |
return False |
if (oper == '!=') and (condval == varval): |
return False |
if (ctype == 'cnf'): |
return False |
return True |
def print_title(self): |
if not self.printed: |
sys.stdout.write("\n*** %s ***\n" % self.title) |
self.printed = True |
def parse_config(fname, ask_names): |
"Parse configuration file" |
inf = file(fname, 'r') |
name = '' |
choices = [] |
for line in inf: |
if (line.startswith('!')): |
# Ask a question |
res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line) |
if (not res): |
raise RuntimeError("Weird line: %s" % line) |
cond = res.group(1) |
varname = res.group(2) |
vartype = res.group(3) |
ask_names.append((varname, vartype, name, choices, cond)) |
name = '' |
choices = [] |
continue |
if (line.startswith('@')): |
# Add new line into the 'choices' array |
res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line) |
if not res: |
raise RuntimeError("Bad line: %s" % line) |
choices.append((res.group(2), res.group(3))) |
continue |
if (line.startswith('%')): |
# Name of the option |
name = line[1:].strip() |
continue |
if ((line.startswith('#')) or (line == '\n')): |
# Comment or empty line |
continue |
raise RuntimeError("Unknown syntax: %s" % line) |
inf.close() |
def set_title(self, text): |
self.title = text |
self.printed = False |
def noyes(self, text, default=None): |
if not default: |
default = 'n' |
return self.yesno(text, default) |
def yesno(self, text, default=None): |
self.print_title() |
if default != 'n': |
default = 'y' |
while 1: |
sys.stdout.write("%s (y/n)[%s]: " % (text,default)) |
inp = sys.stdin.readline() |
if not inp: |
raise EOFError |
inp = inp.strip().lower() |
if not inp: |
return default |
if inp == 'y': |
return 'y' |
elif inp == 'n': |
return 'n' |
def yes_no(default): |
"Return '*' if yes, ' ' if no" |
if (default == 'y'): |
return '*' |
return ' ' |
def _print_choice(self, text, choices, defopt): |
sys.stdout.write('%s:\n' % text) |
for i,(text,descr) in enumerate(choices): |
if descr is '': |
sys.stdout.write('\t%2d. %s\n' % (i, text)) |
else: |
sys.stdout.write('\t%2d. %s\n' % (i, descr)) |
if defopt is not None: |
sys.stdout.write('Enter choice number[%d]: ' % defopt) |
else: |
sys.stdout.write('Enter choice number: ') |
def subchoice(screen, name, choices, default): |
"Return choice of choices" |
maxkey = 0 |
for key, val in choices: |
length = len(key) |
if (length > maxkey): |
maxkey = length |
options = [] |
position = None |
cnt = 0 |
for key, val in choices: |
if ((default) and (key == default)): |
position = cnt |
options.append(" %-*s %s " % (maxkey, key, val)) |
cnt += 1 |
(button, value) = xtui.choice_window(screen, name, 'Choose value', options, position) |
if (button == 'cancel'): |
return None |
return choices[value][0] |
def menu(self, text, choices, button, defopt=None): |
self.title = 'Main menu' |
menu = [] |
for key, descr in choices: |
txt = key + (45-len(key))*' ' + ': ' + descr |
menu.append((key, txt)) |
return self.choice(text, [button] + menu) |
def choice(self, text, choices, defopt=None): |
self.print_title() |
while 1: |
self._print_choice(text, choices, defopt) |
inp = sys.stdin.readline() |
if not inp: |
raise EOFError |
if not inp.strip(): |
if defopt is not None: |
return choices[defopt][0] |
continue |
try: |
number = int(inp.strip()) |
except ValueError: |
continue |
if number < 0 or number >= len(choices): |
continue |
return choices[number][0] |
def check_choices(defaults, ask_names): |
"Check whether all accessible variables have a default" |
for varname, vartype, name, choices, cond in ask_names: |
if ((cond) and (not check_condition(cond, defaults, ask_names))): |
continue |
if (not defaults.has_key(varname)): |
return False |
return True |
def create_output(mkname, mcname, dfname, defaults, ask_names): |
"Create output configuration" |
revision = commands.getoutput('svnversion . 2> /dev/null') |
timestamp = commands.getoutput('date "+%Y-%m-%d %H:%M:%S"') |
outmk = file(mkname, 'w') |
outmc = file(mcname, 'w') |
outdf = file(dfname, 'w') |
outmk.write('#########################################\n') |
outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n') |
outmk.write('#########################################\n\n') |
outmc.write('/***************************************\n') |
outmc.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n') |
outmc.write(' ***************************************/\n\n') |
outdf.write('#########################################\n') |
outdf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n') |
outdf.write('#########################################\n\n') |
outdf.write('CONFIG_DEFS =') |
for varname, vartype, name, choices, cond in ask_names: |
if ((cond) and (not check_condition(cond, defaults, ask_names))): |
continue |
if (not defaults.has_key(varname)): |
default = '' |
else: |
default = defaults[varname] |
if (default == '*'): |
default = 'y' |
outmk.write('# %s\n%s = %s\n\n' % (name, varname, default)) |
if ((vartype == "y") or (vartype == "y/n") or (vartype == "n/y")): |
if (default == "y"): |
outmc.write('/* %s */\n#define %s\n\n' % (name, varname)) |
outdf.write(' -D%s' % varname) |
else: |
outmc.write('/* %s */\n#define %s %s\n#define %s_%s\n\n' % (name, varname, default, varname, default)) |
outdf.write(' -D%s=%s -D%s_%s' % (varname, default, varname, default)) |
outmk.write('REVISION = %s\n' % revision) |
outmk.write('TIMESTAMP = %s\n' % timestamp) |
outmc.write('#define REVISION %s\n' % revision) |
outmc.write('#define TIMESTAMP %s\n' % timestamp) |
outdf.write(' "-DREVISION=%s" "-DTIMESTAMP=%s"\n' % (revision, timestamp)) |
outmk.close() |
outmc.close() |
outdf.close() |
def eof_checker(fnc): |
def wrapper(self, *args, **kw): |
try: |
return fnc(self, *args, **kw) |
except EOFError: |
return getattr(self.bckdialog,fnc.func_name)(*args, **kw) |
return wrapper |
class Dialog(NoDialog): |
def __init__(self): |
NoDialog.__init__(self) |
self.dlgcmd = os.environ.get('DIALOG','dialog') |
self.title = '' |
self.backtitle = 'HelenOS Configuration' |
if os.system('%s --print-maxsize >/dev/null 2>&1' % self.dlgcmd) != 0: |
raise NotImplementedError |
self.bckdialog = NoDialog() |
def set_title(self,text): |
self.title = text |
self.bckdialog.set_title(text) |
def calldlg(self,*args,**kw): |
"Wrapper for calling 'dialog' program" |
indesc, outdesc = os.pipe() |
pid = os.fork() |
if not pid: |
os.close(2) |
os.dup(outdesc) |
os.close(indesc) |
dlgargs = [self.dlgcmd,'--title',self.title, |
'--backtitle', self.backtitle] |
for key,val in kw.items(): |
dlgargs.append('--'+key) |
dlgargs.append(val) |
dlgargs += args |
os.execlp(self.dlgcmd,*dlgargs) |
os.close(outdesc) |
try: |
errout = os.fdopen(indesc,'r') |
data = errout.read() |
errout.close() |
pid,status = os.wait() |
except: |
os.system('reset') # Reset terminal |
raise |
if not os.WIFEXITED(status): |
os.system('reset') # Reset terminal |
raise EOFError |
status = os.WEXITSTATUS(status) |
if status == 255: |
raise EOFError |
return status,data |
def yesno(self, text, default=None): |
if text[-1] not in ('?',':'): |
text = text + ':' |
width = '50' |
height = '5' |
if len(text) < 48: |
text = ' '*int(((48-len(text))/2)) + text |
else: |
width = '0' |
height = '0' |
if default == 'n': |
res,data = self.calldlg('--defaultno','--yesno',text,height,width) |
else: |
res,data = self.calldlg('--yesno',text,height,width) |
if res == 0: |
return 'y' |
return 'n' |
yesno = eof_checker(yesno) |
def menu(self, text, choices, button, defopt=None): |
self.title = 'Main menu' |
text = text + ':' |
width = '70' |
height = str(8 + len(choices)) |
args = [] |
for key,val in choices: |
args.append(key) |
args.append(val) |
kw = {} |
if defopt: |
kw['default-item'] = choices[defopt][0] |
res,data = self.calldlg('--ok-label','Change', |
'--extra-label',button[1], |
'--extra-button', |
'--menu',text,height,width, |
str(len(choices)),*args,**kw) |
if res == 3: |
return button[0] |
if res == 1: # Cancel |
sys.exit(1) |
elif res: |
print data |
raise EOFError |
return data |
menu = eof_checker(menu) |
def choice(self, text, choices, defopt=None): |
text = text + ':' |
width = '50' |
height = str(8 + len(choices)) |
args = [] |
for key,val in choices: |
args.append(key) |
args.append(val) |
kw = {} |
if defopt: |
kw['default-item'] = choices[defopt][0] |
res,data = self.calldlg('--nocancel','--menu',text,height,width, |
str(len(choices)),*args, **kw) |
if res: |
print data |
raise EOFError |
return data |
choice = eof_checker(choice) |
def read_defaults(fname,defaults): |
"Read saved values from last configuration run" |
f = file(fname,'r') |
for line in f: |
res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line) |
if res: |
defaults[res.group(1)] = res.group(2) |
f.close() |
def check_condition(text, defaults, asked_names): |
seen_vars = [ x[0] for x in asked_names ] |
ctype = 'cnf' |
if ')|' in text or '|(' in text: |
ctype = 'dnf' |
if ctype == 'cnf': |
conds = text.split('&') |
else: |
conds = text.split('|') |
for cond in conds: |
if cond.startswith('(') and cond.endswith(')'): |
cond = cond[1:-1] |
inside = check_inside(cond, defaults, ctype, seen_vars) |
if ctype == 'cnf' and not inside: |
return False |
if ctype == 'dnf' and inside: |
return True |
if ctype == 'cnf': |
return True |
return False |
def check_inside(text, defaults, ctype, seen_vars): |
""" |
Check that the condition specified on input line is True |
only CNF is supported |
""" |
if ctype == 'cnf': |
conds = text.split('|') |
else: |
conds = text.split('&') |
for cond in conds: |
res = re.match(r'^(.*?)(!?=)(.*)$', cond) |
if not res: |
raise RuntimeError("Invalid condition: %s" % cond) |
condname = res.group(1) |
oper = res.group(2) |
condval = res.group(3) |
if condname not in seen_vars: |
varval = '' |
## raise RuntimeError("Variable %s not defined before being asked." %\ |
## condname) |
elif not defaults.has_key(condname): |
raise RuntimeError("Condition var %s does not exist: %s" % \ |
(condname,text)) |
else: |
varval = defaults[condname] |
if ctype == 'cnf': |
if oper == '=' and condval == varval: |
return True |
if oper == '!=' and condval != varval: |
return True |
else: |
if oper== '=' and condval != varval: |
return False |
if oper== '!=' and condval == varval: |
return False |
if ctype=='cnf': |
return False |
return True |
def parse_config(input, output, dlg, defaults={}, askonly=None): |
"Parse configuration file and create Makefile.config on the fly" |
def ask_the_question(dialog): |
"Ask question based on the type of variables to ask" |
# This is quite a hack, this thingy is written just to |
# have access to local variables.. |
if vartype == 'y/n': |
return dialog.yesno(comment, default) |
elif vartype == 'n/y': |
return dialog.noyes(comment, default) |
elif vartype == 'choice': |
defopt = None |
if default is not None: |
for i,(key,val) in enumerate(choices): |
if key == default: |
defopt = i |
break |
return dialog.choice(comment, choices, defopt) |
else: |
raise RuntimeError("Bad method: %s" % vartype) |
f = file(input, 'r') |
outf = file(output, 'w') |
outf.write('#########################################\n') |
outf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n') |
outf.write('#########################################\n\n') |
asked_names = [] |
comment = '' |
default = None |
choices = [] |
for line in f: |
if line.startswith('%'): |
res = re.match(r'^%\s*(?:\[(.*?)\])?\s*(.*)$', line) |
if not res: |
raise RuntimeError('Invalid command: %s' % line) |
if res.group(1): |
if not check_condition(res.group(1), defaults, |
asked_names): |
continue |
args = res.group(2).strip().split(' ') |
cmd = args[0].lower() |
args = args[1:] |
if cmd == 'saveas': |
outf.write('%s = %s\n' % (args[1],defaults[args[0]])) |
elif cmd == 'shellcmd': |
varname = args[0] |
args = args[1:] |
for i,arg in enumerate(args): |
if arg.startswith('$'): |
args[i] = defaults[arg[1:]] |
data,status = commands.getstatusoutput(' '.join(args)) |
if status: |
raise RuntimeError('Error running: %s' % ' '.join(args)) |
outf.write('%s = %s\n' % (varname,data.strip())) |
continue |
if line.startswith('!'): |
# Ask a question |
res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line) |
if not res: |
raise RuntimeError("Weird line: %s" % line) |
varname = res.group(2) |
vartype = res.group(3) |
default = defaults.get(varname,None) |
if res.group(1): |
if not check_condition(res.group(1), defaults, |
asked_names): |
if default is not None: |
outf.write('#!# %s = %s\n' % (varname, default)) |
# Clear cumulated values |
comment = '' |
default = None |
choices = [] |
continue |
asked_names.append((varname,comment)) |
if default is None or not askonly or askonly == varname: |
default = ask_the_question(dlg) |
else: |
default = ask_the_question(DefaultDialog(dlg)) |
outf.write('%s = %s\n' % (varname, default)) |
# Remeber the selected value |
defaults[varname] = default |
# Clear cumulated values |
comment = '' |
default = None |
choices = [] |
continue |
if line.startswith('@'): |
# Add new line into the 'choice array' |
res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line) |
if not res: |
raise RuntimeError("Bad line: %s" % line) |
if res.group(1): |
if not check_condition(res.group(1),defaults, |
asked_names): |
continue |
choices.append((res.group(2), res.group(3))) |
continue |
# All other things print to output file |
outf.write(line) |
if re.match(r'^#[^#]', line): |
# Last comment before question will be displayed to the user |
comment = line[1:].strip() |
elif line.startswith('## '): |
# Set title of the dialog window |
dlg.set_title(line[2:].strip()) |
outf.write('\n') |
outf.write('REVISION = %s\n' % commands.getoutput('svnversion . 2> /dev/null')) |
outf.write('TIMESTAMP = %s\n' % commands.getoutput('date "+%Y-%m-%d %H:%M:%S"')) |
outf.close() |
f.close() |
return asked_names |
def main(): |
defaults = {} |
try: |
dlg = Dialog() |
except NotImplementedError: |
dlg = NoDialog() |
if len(sys.argv) >= 3 and sys.argv[2]=='default': |
defmode = True |
else: |
defmode = False |
# Default run will update the configuration file |
# with newest options |
if os.path.exists(OUTPUT): |
read_defaults(OUTPUT, defaults) |
# Get ARCH from command line if specified |
if len(sys.argv) >= 4: |
defaults['ARCH'] = sys.argv[3] |
defaults['PLATFORM'] = sys.argv[3] |
defaults = {} |
ask_names = [] |
# Get COMPILER from command line if specified |
if len(sys.argv) >= 5: |
defaults['COMPILER'] = sys.argv[4] |
# Parse configuration file |
parse_config(INPUT, ask_names) |
# Get CONFIG_DEBUG from command line if specified |
if len(sys.argv) >= 6: |
defaults['CONFIG_DEBUG'] = sys.argv[5] |
# Read defaults from previous run |
if os.path.exists(MAKEFILE): |
read_defaults(MAKEFILE, defaults) |
# Get MACHINE/IMAGE from command line if specified |
if len(sys.argv) >= 7: |
defaults['MACHINE'] = sys.argv[6] |
defaults['IMAGE'] = sys.argv[6] |
# Default mode: only check defaults and regenerate configuration |
if ((len(sys.argv) >= 3) and (sys.argv[2] == 'default')): |
if (check_choices(defaults, ask_names)): |
create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names) |
return 0 |
# Check mode: only check defaults |
if ((len(sys.argv) >= 3) and (sys.argv[2] == 'check')): |
if (check_choices(defaults, ask_names)): |
return 0 |
return 1 |
screen = xtui.screen_init() |
try: |
selname = None |
while True: |
# Cancel out all defaults which have to be deduced |
for varname, vartype, name, choices, cond in ask_names: |
if ((vartype == 'y') and (defaults.has_key(varname)) and (defaults[varname] == '*')): |
defaults[varname] = None |
options = [] |
opt2row = {} |
position = None |
cnt = 0 |
for varname, vartype, name, choices, cond in ask_names: |
if ((cond) and (not check_condition(cond, defaults, ask_names))): |
continue |
if (varname == selname): |
position = cnt |
if (not defaults.has_key(varname)): |
default = None |
else: |
default = defaults[varname] |
if (vartype == 'choice'): |
# Check if the default is an acceptable value |
if ((default) and (not default in [choice[0] for choice in choices])): |
default = None |
defaults.pop(varname) |
# If there is just one option, use it |
if (len(choices) == 1): |
defaults[varname] = choices[0][0] |
continue |
if (default == None): |
options.append("? %s --> " % name) |
else: |
options.append(" %s [%s] --> " % (name, default)) |
elif (vartype == 'y'): |
defaults[varname] = '*' |
continue |
elif (vartype == 'y/n'): |
if (default == None): |
default = 'y' |
defaults[varname] = default |
options.append(" <%s> %s " % (yes_no(default), name)) |
elif (vartype == 'n/y'): |
if (default == None): |
default = 'n' |
defaults[varname] = default |
options.append(" <%s> %s " % (yes_no(default), name)) |
else: |
raise RuntimeError("Unknown variable type: %s" % vartype) |
opt2row[cnt] = (varname, vartype, name, choices) |
cnt += 1 |
(button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position) |
if (button == 'cancel'): |
return 'Configuration canceled' |
if (not opt2row.has_key(value)): |
raise RuntimeError("Error selecting value: %s" % value) |
(selname, seltype, name, choices) = opt2row[value] |
if (not defaults.has_key(selname)): |
default = None |
else: |
default = defaults[selname] |
if (button == 'done'): |
if (check_choices(defaults, ask_names)): |
break |
else: |
xtui.error_dialog(screen, 'Error', 'Some options have still undefined values. These options are marked with the "?" sign.') |
continue |
if (seltype == 'choice'): |
defaults[selname] = subchoice(screen, name, choices, default) |
elif ((seltype == 'y/n') or (seltype == 'n/y')): |
if (defaults[selname] == 'y'): |
defaults[selname] = 'n' |
else: |
defaults[selname] = 'y' |
finally: |
xtui.screen_done(screen) |
create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names) |
return 0 |
# Dry run only with defaults |
varnames = parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults) |
# If not in default mode, present selection of all possibilities |
if not defmode: |
defopt = 0 |
while 1: |
# varnames contains variable names that were in the |
# last question set |
choices = [ (x[1],defaults[x[0]]) for x in varnames ] |
res = dlg.menu('Configuration',choices,('save','Save'),defopt) |
if res == 'save': |
parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults) |
break |
# transfer description back to varname |
for i,(vname,descr) in enumerate(varnames): |
if res == descr: |
defopt = i |
break |
# Ask the user a simple question, produce output |
# as if the user answered all the other questions |
# with default answer |
varnames = parse_config(INPUT, TMPOUTPUT, dlg, defaults, |
askonly=varnames[i][0]) |
if os.path.exists(OUTPUT): |
os.unlink(OUTPUT) |
os.rename(TMPOUTPUT, OUTPUT) |
if not defmode and dlg.yesno('Rebuild everything?') == 'y': |
os.execlp('make','make','clean','build') |
if __name__ == '__main__': |
main() |
sys.exit(main()) |
/branches/dd/uspace/uspace.config |
---|
File deleted |
/branches/dd/uspace/app/ash/input.c |
---|
File deleted |
/branches/dd/uspace/app/ash/output.c |
---|
File deleted |
/branches/dd/uspace/app/ash/mkbuiltins |
---|
File deleted |
/branches/dd/uspace/app/ash/parser.h |
---|
File deleted |
/branches/dd/uspace/app/ash/input.h |
---|
File deleted |
/branches/dd/uspace/app/ash/redir.c |
---|
File deleted |
/branches/dd/uspace/app/ash/output.h |
---|
File deleted |
/branches/dd/uspace/app/ash/builtins.def |
---|
File deleted |
/branches/dd/uspace/app/ash/machdep.h |
---|
File deleted |
/branches/dd/uspace/app/ash/fake.c |
---|
File deleted |
/branches/dd/uspace/app/ash/arith.c |
---|
File deleted |
/branches/dd/uspace/app/ash/init.h |
---|
File deleted |
/branches/dd/uspace/app/ash/redir.h |
---|
File deleted |
/branches/dd/uspace/app/ash/fake.h |
---|
File deleted |
/branches/dd/uspace/app/ash/arith.h |
---|
File deleted |
/branches/dd/uspace/app/ash/tags |
---|
File deleted |
/branches/dd/uspace/app/ash/miscbltin.c |
---|
File deleted |
/branches/dd/uspace/app/ash/bltin/times.c |
---|
File deleted |
/branches/dd/uspace/app/ash/bltin/echo.1 |
---|
File deleted |
/branches/dd/uspace/app/ash/bltin/bltin.h |
---|
File deleted |
/branches/dd/uspace/app/ash/bltin/echo.c |
---|
File deleted |
/branches/dd/uspace/app/ash/bltin/test.c |
---|
File deleted |
/branches/dd/uspace/app/ash/myhistedit.h |
---|
File deleted |
/branches/dd/uspace/app/ash/miscbltin.h |
---|
File deleted |
/branches/dd/uspace/app/ash/arith.y |
---|
File deleted |
/branches/dd/uspace/app/ash/expand.c |
---|
File deleted |
/branches/dd/uspace/app/ash/expand.h |
---|
File deleted |
/branches/dd/uspace/app/ash/exec.c |
---|
File deleted |
/branches/dd/uspace/app/ash/error.c |
---|
File deleted |
/branches/dd/uspace/app/ash/memalloc.c |
---|
File deleted |
/branches/dd/uspace/app/ash/exec.h |
---|
File deleted |
/branches/dd/uspace/app/ash/jobs.c |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/suspend |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/dirs |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/popd |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/newgrp |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/pushd |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/cmv |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/login |
---|
File deleted |
/branches/dd/uspace/app/ash/funcs/kill |
---|
File deleted |
/branches/dd/uspace/app/ash/memalloc.h |
---|
File deleted |
/branches/dd/uspace/app/ash/error.h |
---|
File deleted |
/branches/dd/uspace/app/ash/jobs.h |
---|
File deleted |
/branches/dd/uspace/app/ash/hetio.c |
---|
File deleted |
/branches/dd/uspace/app/ash/mystring.c |
---|
File deleted |
/branches/dd/uspace/app/ash/shell.h |
---|
File deleted |
/branches/dd/uspace/app/ash/hetio.h |
---|
File deleted |
/branches/dd/uspace/app/ash/histedit.c |
---|
File deleted |
/branches/dd/uspace/app/ash/show.c |
---|
File deleted |
/branches/dd/uspace/app/ash/mystring.h |
---|
File deleted |
/branches/dd/uspace/app/ash/show.h |
---|
File deleted |
/branches/dd/uspace/app/ash/var.c |
---|
File deleted |
/branches/dd/uspace/app/ash/lex.yy.c |
---|
File deleted |
/branches/dd/uspace/app/ash/sh.1 |
---|
File deleted |
/branches/dd/uspace/app/ash/alias.c |
---|
File deleted |
/branches/dd/uspace/app/ash/options.c |
---|
File deleted |
/branches/dd/uspace/app/ash/nodes.c.pat |
---|
File deleted |
/branches/dd/uspace/app/ash/Makefile |
---|
File deleted |
/branches/dd/uspace/app/ash/var.h |
---|
File deleted |
/branches/dd/uspace/app/ash/alias.h |
---|
File deleted |
/branches/dd/uspace/app/ash/setmode.c |
---|
File deleted |
/branches/dd/uspace/app/ash/options.h |
---|
File deleted |
/branches/dd/uspace/app/ash/trap.c |
---|
File deleted |
/branches/dd/uspace/app/ash/TOUR |
---|
File deleted |
/branches/dd/uspace/app/ash/mktokens |
---|
File deleted |
/branches/dd/uspace/app/ash/trap.h |
---|
File deleted |
/branches/dd/uspace/app/ash/tools/mkinit.c |
---|
File deleted |
/branches/dd/uspace/app/ash/tools/Makefile |
---|
File deleted |
/branches/dd/uspace/app/ash/tools/mksyntax.c |
---|
File deleted |
/branches/dd/uspace/app/ash/tools/mksignames.c |
---|
File deleted |
/branches/dd/uspace/app/ash/tools/mknodes.c |
---|
File deleted |
/branches/dd/uspace/app/ash/mail.c |
---|
File deleted |
/branches/dd/uspace/app/ash/main.c |
---|
File deleted |
/branches/dd/uspace/app/ash/cd.c |
---|
File deleted |
/branches/dd/uspace/app/ash/mail.h |
---|
File deleted |
/branches/dd/uspace/app/ash/eval.c |
---|
File deleted |
/branches/dd/uspace/app/ash/arith_lex.l |
---|
File deleted |
/branches/dd/uspace/app/ash/nodetypes |
---|
File deleted |
/branches/dd/uspace/app/ash/main.h |
---|
File deleted |
/branches/dd/uspace/app/ash/cd.h |
---|
File deleted |
/branches/dd/uspace/app/ash/parser.c |
---|
File deleted |
/branches/dd/uspace/app/ash/eval.h |
---|
File deleted |
/branches/dd/uspace/app/bdsh/input.c |
---|
0,0 → 1,146 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* Copyright (c) 2008, Jiri Svoboda - All Rights Reserved |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <io/stream.h> |
#include <console.h> |
#include "config.h" |
#include "util.h" |
#include "scli.h" |
#include "input.h" |
#include "errors.h" |
#include "exec.h" |
static void read_line(char *, int); |
/* Tokenizes input from console, sees if the first word is a built-in, if so |
* invokes the built-in entry point (a[0]) passing all arguments in a[] to |
* the handler */ |
int tok_input(cliuser_t *usr) |
{ |
char *cmd[WORD_MAX]; |
int n = 0, i = 0; |
int rc = 0; |
char *tmp; |
if (NULL == usr->line) |
return CL_EFAIL; |
tmp = strdup(usr->line); |
cmd[n] = strtok(tmp, " "); |
while (cmd[n] && n < WORD_MAX) { |
cmd[++n] = strtok(NULL, " "); |
} |
/* We have rubbish */ |
if (NULL == cmd[0]) { |
rc = CL_ENOENT; |
goto finit; |
} |
/* Its a builtin command ? */ |
if ((i = (is_builtin(cmd[0]))) > -1) { |
rc = run_builtin(i, cmd, usr); |
goto finit; |
/* Its a module ? */ |
} else if ((i = (is_module(cmd[0]))) > -1) { |
rc = run_module(i, cmd); |
goto finit; |
} |
/* See what try_exec thinks of it */ |
rc = try_exec(cmd[0], cmd); |
finit: |
if (NULL != usr->line) { |
free(usr->line); |
usr->line = (char *) NULL; |
} |
if (NULL != tmp) |
free(tmp); |
return rc; |
} |
static void read_line(char *buffer, int n) |
{ |
char c; |
int chars; |
chars = 0; |
while (chars < n - 1) { |
c = getchar(); |
if (c < 0) |
return; |
if (c == '\n') |
break; |
if (c == '\b') { |
if (chars > 0) { |
putchar('\b'); |
--chars; |
} |
continue; |
} |
if (c >= ' ') { |
putchar(c); |
buffer[chars++] = c; |
} |
} |
putchar('\n'); |
buffer[chars] = '\0'; |
} |
/* TODO: |
* Implement something like editline() / readline(), if even |
* just for command history and making arrows work. */ |
void get_input(cliuser_t *usr) |
{ |
char line[INPUT_MAX]; |
size_t len = 0; |
console_set_style(STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
console_set_style(STYLE_NORMAL); |
read_line(line, INPUT_MAX); |
len = strlen(line); |
/* Make sure we don't have rubbish or a C/R happy user */ |
if (len == 0 || line[0] == '\n') |
return; |
usr->line = strdup(line); |
return; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
0,0 → 1,214 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* NOTE: |
* This is a bit of an ugly hack, working around the absence of fstat / etc. |
* As more stuff is completed and exposed in libc, this will improve */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <string.h> |
#include "errors.h" |
#include "config.h" |
#include "util.h" |
#include "entry.h" |
#include "ls.h" |
#include "cmds.h" |
static char *cmdname = "ls"; |
static inline off_t flen(const char *f) |
{ |
int fd; |
off_t size; |
fd = open(f, O_RDONLY); |
if (fd == -1) |
return 0; |
size = lseek(fd, 0, SEEK_END); |
close(fd); |
if (size < 0) |
size = 0; |
return size; |
} |
static unsigned int ls_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return LS_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return LS_FILE; |
} |
return LS_BOGUS; |
} |
static void ls_scan_dir(const char *d, DIR *dirp) |
{ |
struct dirent *dp; |
unsigned int scope; |
char *buff; |
if (! dirp) |
return; |
buff = (char *)malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "ls: failed to scan %s", d); |
return; |
} |
while ((dp = readdir(dirp))) { |
memset(buff, 0, sizeof(buff)); |
/* Don't worry if inserting a double slash, this will be fixed by |
* absolutize() later with subsequent calls to open() or readdir() */ |
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_DIR: |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name, buff); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
* it and the time that it was scoped */ |
printf("ls: skipping bogus node %s\n", dp->d_name); |
break; |
} |
} |
free(buff); |
return; |
} |
/* ls_print_* currently does nothing more than print the entry. |
* in the future, we will likely pass the absolute path, and |
* some sort of ls_options structure that controls how each |
* entry is printed and what is printed about it. |
* |
* Now we just print basic DOS style lists */ |
static void ls_print_dir(const char *d) |
{ |
printf("%-40s\t<dir>\n", d); |
return; |
} |
static void ls_print_file(const char *name, const char *pathname) |
{ |
printf("%-40s\t%llu\n", name, (long long) flen(pathname)); |
return; |
} |
void help_cmd_ls(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' lists files and directories.\n", cmdname); |
} else { |
help_cmd_ls(HELP_SHORT); |
printf(" `%s' [path], if no path is given the current " |
"working directory is used.\n", cmdname); |
} |
return; |
} |
int cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
char *buff; |
DIR *dirp; |
argc = cli_count_args(argv); |
buff = (char *) malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "%s: ", cmdname); |
return CMD_FAILURE; |
} |
memset(buff, 0, sizeof(buff)); |
if (argc == 1) |
getcwd(buff, PATH_MAX); |
else |
strncpy(buff, argv[1], PATH_MAX); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_BOGUS: |
cli_error(CL_ENOENT, buff); |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff, buff); |
break; |
case LS_DIR: |
dirp = opendir(buff); |
if (! dirp) { |
/* May have been deleted between scoping it and opening it */ |
cli_error(CL_EFAIL, "Could not stat %s", buff); |
free(buff); |
return CMD_FAILURE; |
} |
ls_scan_dir(buff, dirp); |
closedir(dirp); |
break; |
} |
free(buff); |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
0,0 → 1,16 |
#ifndef LS_H |
#define LS_H |
/* Various values that can be returned by ls_scope() */ |
#define LS_BOGUS 0 |
#define LS_FILE 1 |
#define LS_DIR 2 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *, const char *); |
#endif /* LS_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls_def.h |
---|
0,0 → 1,6 |
{ |
"ls", |
"List files and directories", |
&cmd_ls, |
&help_cmd_ls, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/entry.h |
---|
0,0 → 1,9 |
#ifndef LS_ENTRY_H |
#define LS_ENTRY_H |
/* Entry points for the ls command */ |
extern int cmd_ls(char **); |
extern void help_cmd_ls(unsigned int); |
#endif /* LS_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/cp/cp.c |
---|
0,0 → 1,231 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <getopt.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cp.h" |
#include "cmds.h" |
#define CP_VERSION "0.0.1" |
#define CP_DEFAULT_BUFLEN 1024 |
static const char *cmdname = "cp"; |
static struct option const long_options[] = { |
{ "buffer", required_argument, 0, 'b' }, |
{ "force", no_argument, 0, 'f' }, |
{ "recursive", no_argument, 0, 'r' }, |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "verbose", no_argument, 0, 'V' }, |
{ 0, 0, 0, 0 } |
}; |
static int strtoint(const char *s1) |
{ |
long t1; |
if (-1 == (t1 = strtol(s1, (char **) NULL, 10))) |
return -1; |
if (t1 <= 0) |
return -1; |
return (int) t1; |
} |
static int64_t copy_file(const char *src, const char *dest, |
size_t blen, int vb) |
{ |
int fd1, fd2, bytes = 0; |
off_t total = 0; |
int64_t copied = 0; |
char *buff = NULL; |
if (vb) |
printf("Copying %s to %s\n", src, dest); |
if (-1 == (fd1 = open(src, O_RDONLY))) { |
printf("Unable to open source file %s\n", src); |
return -1; |
} |
if (-1 == (fd2 = open(dest, O_CREAT))) { |
printf("Unable to open destination file %s\n", dest); |
close(fd1); |
return -1; |
} |
total = lseek(fd1, 0, SEEK_END); |
if (vb) |
printf("%d bytes to copy\n", total); |
lseek(fd1, 0, SEEK_SET); |
if (NULL == (buff = (char *) malloc(blen))) { |
printf("Unable to allocate enough memory to read %s\n", |
src); |
copied = -1; |
goto out; |
} |
for (;;) { |
ssize_t res; |
bytes = read(fd1, buff, blen); |
if (bytes <= 0) |
break; |
copied += bytes; |
res = bytes; |
do { |
/* |
* Theoretically, it may not be enough to call write() |
* only once. Also the previous read() may have |
* returned less data than requested. |
*/ |
bytes = write(fd2, buff, res); |
if (bytes < 0) |
goto err; |
res -= bytes; |
} while (res > 0); |
/* TODO: re-insert assert() once this is stand alone, |
* removed as abort() exits the entire shell |
*/ |
if (res != 0) { |
printf("\n%d more bytes than actually exist were copied\n", res); |
goto err; |
} |
} |
if (bytes < 0) { |
err: |
printf("\nError copying %s, (%d)\n", src, bytes); |
copied = bytes; |
} |
out: |
close(fd1); |
close(fd2); |
if (buff) |
free(buff); |
return copied; |
} |
void help_cmd_cp(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s [options] <source> <dest>\n" |
"Options: (* indicates not yet implemented)\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
"* -V, --verbose Be annoyingly noisy about what's being done\n" |
"* -f, --force Do not complain when <dest> exists\n" |
"* -r, --recursive Copy entire directories\n" |
" -b, --buffer ## Set the read buffer size to ##\n" |
"Currently, %s is under development, some options may not work.\n"; |
if (level == HELP_SHORT) { |
printf("`%s' copies files and directories\n", cmdname); |
} else { |
help_cmd_cp(HELP_SHORT); |
printf(helpfmt, cmdname, cmdname); |
} |
return; |
} |
int cmd_cp(char **argv) |
{ |
unsigned int argc, buffer = 0, verbose = 0; |
int c, opt_ind; |
int64_t ret; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_cp(1); |
return CMD_SUCCESS; |
case 'v': |
printf("%d\n", CP_VERSION); |
return CMD_SUCCESS; |
case 'V': |
verbose = 1; |
break; |
case 'f': |
break; |
case 'r': |
break; |
case 'b': |
if (-1 == (buffer = strtoint(optarg))) { |
printf("%s: Invalid buffer specification, " |
"(should be a number greater than zero)\n", |
cmdname); |
return CMD_FAILURE; |
} |
if (verbose) |
printf("Buffer = %d\n", buffer); |
break; |
} |
} |
if (buffer == 0) |
buffer = CP_DEFAULT_BUFLEN; |
argc -= optind; |
if (argc != 2) { |
printf("%s: invalid number of arguments. Try %s --help\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose); |
if (verbose) |
printf("%d bytes copied\n", ret); |
if (ret >= 0) |
return CMD_SUCCESS; |
else |
return CMD_FAILURE; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/cp/cp_def.h |
---|
0,0 → 1,7 |
{ |
"cp", |
"Copy files and directories", |
&cmd_cp, |
&help_cmd_cp, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/cp/entry.h |
---|
0,0 → 1,9 |
#ifndef CP_ENTRY_H |
#define CP_ENTRY_H |
/* Entry points for the cp command */ |
extern int cmd_cp(char **); |
extern void help_cmd_cp(unsigned int); |
#endif /* CP_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/cp/cp.h |
---|
0,0 → 1,8 |
#ifndef CP_H |
#define CP_H |
/* Prototypes for the cp command, excluding entry points */ |
#endif /* CP_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
0,0 → 1,257 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <getopt.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "rm.h" |
#include "cmds.h" |
static char *cmdname = "rm"; |
#define RM_VERSION "0.0.1" |
static rm_job_t rm; |
static struct option const long_options[] = { |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "recursive", no_argument, 0, 'r' }, |
{ "force", no_argument, 0, 'f' }, |
{ "safe", no_argument, 0, 's' }, |
{ 0, 0, 0, 0 } |
}; |
static unsigned int rm_start(rm_job_t *rm) |
{ |
rm->recursive = 0; |
rm->force = 0; |
rm->safe = 0; |
/* Make sure we can allocate enough memory to store |
* what is needed in the job structure */ |
if (NULL == (rm->nwd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->nwd, 0, sizeof(rm->nwd)); |
if (NULL == (rm->owd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->owd, 0, sizeof(rm->owd)); |
if (NULL == (rm->cwd = (char *) malloc(PATH_MAX))) |
return 0; |
memset(rm->cwd, 0, sizeof(rm->cwd)); |
chdir("."); |
if (NULL == (getcwd(rm->owd, PATH_MAX))) |
return 0; |
return 1; |
} |
static void rm_end(rm_job_t *rm) |
{ |
if (NULL != rm->nwd) |
free(rm->nwd); |
if (NULL != rm->owd) |
free(rm->owd); |
if (NULL != rm->cwd) |
free(rm->cwd); |
return; |
} |
static unsigned int rm_recursive(const char *path) |
{ |
int rc; |
/* First see if it will just go away */ |
rc = rmdir(path); |
if (rc == 0) |
return 0; |
/* Its not empty, recursively scan it */ |
cli_error(CL_ENOTSUP, |
"Can not remove %s, directory not empty", path); |
return 1; |
} |
static unsigned int rm_single(const char *path) |
{ |
if (unlink(path)) { |
cli_error(CL_EFAIL, "rm: could not remove file %s", path); |
return 1; |
} |
return 0; |
} |
static unsigned int rm_scope(const char *path) |
{ |
int fd; |
DIR *dirp; |
dirp = opendir(path); |
if (dirp) { |
closedir(dirp); |
return RM_DIR; |
} |
fd = open(path, O_RDONLY); |
if (fd > 0) { |
close(fd); |
return RM_FILE; |
} |
return RM_BOGUS; |
} |
/* Dispays help for rm in various levels */ |
void help_cmd_rm(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' removes files and directories.\n", cmdname); |
} else { |
help_cmd_rm(HELP_SHORT); |
printf( |
"Usage: %s [options] <path>\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
" -r, --recursive Recursively remove sub directories\n" |
" -f, --force Do not prompt prior to removing files\n" |
" -s, --safe Stop if directories change during removal\n\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return; |
} |
/* Main entry point for rm, accepts an array of arguments */ |
int cmd_rm(char **argv) |
{ |
unsigned int argc; |
unsigned int i, scope, ret = 0; |
int c, opt_ind; |
size_t len; |
char *buff = NULL; |
argc = cli_count_args(argv); |
if (argc < 2) { |
cli_error(CL_EFAIL, |
"%s: insufficient arguments. Try %s --help", cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (!rm_start(&rm)) { |
cli_error(CL_ENOMEM, "%s: could not initialize", cmdname); |
rm_end(&rm); |
return CMD_FAILURE; |
} |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_rm(HELP_LONG); |
return CMD_SUCCESS; |
case 'v': |
printf("%s\n", RM_VERSION); |
return CMD_SUCCESS; |
case 'r': |
rm.recursive = 1; |
break; |
case 'f': |
rm.force = 1; |
break; |
case 's': |
rm.safe = 1; |
break; |
} |
} |
if (optind == argc) { |
cli_error(CL_EFAIL, |
"%s: insufficient arguments. Try %s --help", cmdname, cmdname); |
rm_end(&rm); |
return CMD_FAILURE; |
} |
i = optind; |
while (NULL != argv[i]) { |
len = strlen(argv[i]) + 2; |
buff = (char *) realloc(buff, len); |
if (buff == NULL) { |
printf("rm: out of memory\n"); |
ret = 1; |
break; |
} |
memset(buff, 0, sizeof(buff)); |
snprintf(buff, len, argv[i]); |
scope = rm_scope(buff); |
switch (scope) { |
case RM_BOGUS: /* FIXME */ |
case RM_FILE: |
ret += rm_single(buff); |
break; |
case RM_DIR: |
if (! rm.recursive) { |
printf("%s is a directory, use -r to remove it.\n", buff); |
ret ++; |
} else { |
ret += rm_recursive(buff); |
} |
break; |
} |
i++; |
} |
if (NULL != buff) |
free(buff); |
rm_end(&rm); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/rm/rm_def.h |
---|
0,0 → 1,7 |
{ |
"rm", |
"Remove files and directories", |
&cmd_rm, |
&help_cmd_rm, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/rm/entry.h |
---|
0,0 → 1,9 |
#ifndef RM_ENTRY_H |
#define RM_ENTRY_H |
/* Entry points for the rm command */ |
extern int cmd_rm(char **); |
extern void help_cmd_rm(unsigned int); |
#endif /* RM_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/rm/rm.h |
---|
0,0 → 1,43 |
#ifndef RM_H |
#define RM_H |
/* Return values for rm_scope() */ |
#define RM_BOGUS 0 |
#define RM_FILE 1 |
#define RM_DIR 2 |
/* Flags for rm_update() */ |
#define _RM_ENTRY 0 |
#define _RM_ADVANCE 1 |
#define _RM_REWIND 2 |
#define _RM_EXIT 3 |
/* A simple job structure */ |
typedef struct { |
/* Options set at run time */ |
unsigned int force; /* -f option */ |
unsigned int recursive; /* -r option */ |
unsigned int safe; /* -s option */ |
/* Keeps track of the job in progress */ |
int advance; /* How far deep we've gone since entering */ |
DIR *entry; /* Entry point to the tree being removed */ |
char *owd; /* Where we were when we invoked rm */ |
char *cwd; /* Current directory being transversed */ |
char *nwd; /* Next directory to be transversed */ |
/* Counters */ |
int f_removed; /* Number of files unlinked */ |
int d_removed; /* Number of directories unlinked */ |
} rm_job_t; |
/* Prototypes for the rm command, excluding entry points */ |
static unsigned int rm_start(rm_job_t *); |
static void rm_end(rm_job_t *rm); |
static unsigned int rm_recursive(const char *); |
static unsigned int rm_single(const char *); |
static unsigned int rm_scope(const char *); |
#endif /* RM_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/touch/touch.c |
---|
0,0 → 1,108 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* TODO: Options that people would expect, such as not creating the file if |
* it doesn't exist, specifying the access time, etc */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <sys/types.h> |
#include <string.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "touch.h" |
#include "cmds.h" |
static char *cmdname = "touch"; |
/* Dispays help for touch in various levels */ |
void help_cmd_touch(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' updates access times for files\n", cmdname); |
} else { |
help_cmd_touch(HELP_SHORT); |
printf(" `%s' <file>, if the file does not exist it will be " |
"created\n", cmdname); |
} |
return; |
} |
/* Main entry point for touch, accepts an array of arguments */ |
int cmd_touch(char **argv) |
{ |
unsigned int argc, i = 0, ret = 0; |
int fd; |
char *buff = NULL; |
DIR *dirp; |
argc = cli_count_args(argv); |
if (argc == 1) { |
printf("%s - incorrect number of arguments. Try `help %s extended'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
for (i = 1; i < argc; i ++) { |
buff = strdup(argv[i]); |
dirp = opendir(buff); |
if (dirp) { |
cli_error(CL_ENOTSUP, "%s is a directory", buff); |
closedir(dirp); |
ret ++; |
continue; |
} |
fd = open(buff, O_RDWR | O_CREAT); |
if (fd < 0) { |
cli_error(CL_EFAIL, "Could not update / create %s ", buff); |
ret ++; |
continue; |
} else |
close(fd); |
free(buff); |
} |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/touch/touch_def.h |
---|
0,0 → 1,7 |
{ |
"touch", |
"Create files or update access times", |
&cmd_touch, |
&help_cmd_touch, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/touch/entry.h |
---|
0,0 → 1,9 |
#ifndef TOUCH_ENTRY_H |
#define TOUCH_ENTRY_H |
/* Entry points for the touch command */ |
extern int cmd_touch(char **); |
extern void help_cmd_touch(unsigned int); |
#endif /* TOUCH_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/touch/touch.h |
---|
0,0 → 1,8 |
#ifndef TOUCH_H |
#define TOUCH_H |
/* Prototypes for the touch command, excluding entry points */ |
#endif /* TOUCH_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c |
---|
0,0 → 1,251 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <getopt.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
#include "entry.h" |
#include "mkdir.h" |
#include "cmds.h" |
#define MKDIR_VERSION "0.0.1" |
static char *cmdname = "mkdir"; |
static struct option const long_options[] = { |
{"parents", no_argument, 0, 'p'}, |
{"verbose", no_argument, 0, 'v'}, |
{"mode", required_argument, 0, 'm'}, |
{"help", no_argument, 0, 'h'}, |
{"version", no_argument, 0, 'V'}, |
{"follow", no_argument, 0, 'f'}, |
{0, 0, 0, 0} |
}; |
void help_cmd_mkdir(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' creates a new directory\n", cmdname); |
} else { |
help_cmd_mkdir(HELP_SHORT); |
printf( |
"Usage: %s [options] <path>\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -V, --version Print version information and exit\n" |
" -p, --parents Create needed parents for <path>\n" |
" -m, --mode Set permissions to [mode] (UNUSED)\n" |
" -v, --verbose Be extremely noisy about what is happening\n" |
" -f, --follow Go to the new directory once created\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return; |
} |
/* This is kind of clunky, but effective for now */ |
static unsigned int |
create_directory(const char *path, unsigned int p) |
{ |
DIR *dirp; |
char *tmp = NULL, *buff = NULL, *wdp = NULL; |
char *dirs[255]; |
unsigned int absolute = 0, i = 0, ret = 0; |
/* Its a good idea to allocate path, plus we (may) need a copy of |
* path to tokenize if parents are specified */ |
if (NULL == (tmp = strdup(path))) { |
cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
return 1; |
} |
if (NULL == (wdp = (char *) malloc(PATH_MAX))) { |
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname); |
free(tmp); |
return 1; |
} |
/* The only reason for wdp is to be (optionally) verbose */ |
getcwd(wdp, PATH_MAX); |
/* Typical use without specifying the creation of parents */ |
if (p == 0) { |
dirp = opendir(tmp); |
if (dirp) { |
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path); |
closedir(dirp); |
goto finit; |
} |
if (-1 == (mkdir(tmp, 0))) { |
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path); |
goto finit; |
} |
} |
/* Parents need to be created, path has to be broken up */ |
/* See if path[0] is a slash, if so we have to remember to append it */ |
if (tmp[0] == '/') |
absolute = 1; |
/* TODO: Canonify the path prior to tokenizing it, see below */ |
dirs[i] = strtok(tmp, "/"); |
while (dirs[i] && i < 255) |
dirs[++i] = strtok(NULL, "/"); |
if (NULL == dirs[0]) |
return 1; |
if (absolute == 1) { |
asprintf(&buff, "/%s", dirs[0]); |
mkdir(buff, 0); |
chdir(buff); |
free(buff); |
getcwd(wdp, PATH_MAX); |
i = 1; |
} else { |
i = 0; |
} |
while (dirs[i] != NULL) { |
/* Sometimes make or scripts conjoin odd paths. Account for something |
* like this: ../../foo/bar/../foo/foofoo/./bar */ |
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) { |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: impossible path: %s", |
cmdname, path); |
ret ++; |
goto finit; |
} |
getcwd(wdp, PATH_MAX); |
} else { |
if (-1 == (mkdir(dirs[i], 0))) { |
cli_error(CL_EFAIL, |
"%s: failed at %s/%s", wdp, dirs[i]); |
ret ++; |
goto finit; |
} |
if (0 != (chdir(dirs[i]))) { |
cli_error(CL_EFAIL, "%s: failed creating %s\n", |
cmdname, dirs[i]); |
ret ++; |
break; |
} |
} |
i++; |
} |
goto finit; |
finit: |
free(wdp); |
free(tmp); |
return ret; |
} |
int cmd_mkdir(char **argv) |
{ |
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0; |
unsigned int verbose = 0; |
int c, opt_ind; |
char *cwd; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind); |
switch (c) { |
case 'p': |
create_parents = 1; |
break; |
case 'v': |
verbose = 1; |
break; |
case 'h': |
help_cmd_mkdir(HELP_LONG); |
return CMD_SUCCESS; |
case 'V': |
printf("%s\n", MKDIR_VERSION); |
return CMD_SUCCESS; |
case 'f': |
follow = 1; |
break; |
case 'm': |
printf("%s: [W] Ignoring mode %s\n", cmdname, optarg); |
break; |
} |
} |
argc -= optind; |
if (argc < 1) { |
printf("%s - incorrect number of arguments. Try `%s --help'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (NULL == (cwd = (char *) malloc(PATH_MAX))) { |
cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname); |
return CMD_FAILURE; |
} |
memset(cwd, 0, sizeof(cwd)); |
getcwd(cwd, PATH_MAX); |
for (i = optind; argv[i] != NULL; i++) { |
if (verbose == 1) |
printf("%s: creating %s%s\n", |
cmdname, argv[i], |
create_parents ? " (and all parents)" : ""); |
ret += create_directory(argv[i], create_parents); |
} |
if (follow == 0) |
chdir(cwd); |
free(cwd); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h |
---|
0,0 → 1,8 |
{ |
"mkdir", |
"Create new directories", |
&cmd_mkdir, |
&help_cmd_mkdir, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/mkdir/entry.h |
---|
0,0 → 1,9 |
#ifndef MKDIR_ENTRY_H |
#define MKDIR_ENTRY_H |
/* Entry points for the mkdir command */ |
extern int cmd_mkdir(char **); |
extern void help_cmd_mkdir(unsigned int); |
#endif /* MKDIR_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/mkdir/mkdir.h |
---|
0,0 → 1,8 |
#ifndef MKDIR_H |
#define MKDIR_H |
/* Prototypes for the mkdir command, excluding entry points */ |
static unsigned int create_directory(const char *, unsigned int); |
#endif /* MKDIR_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/modules.h |
---|
0,0 → 1,47 |
#ifndef MODULES_H |
#define MODULES_H |
/* Each built in function has two files, one being an entry.h file which |
* prototypes the run/help entry functions, the other being a .def file |
* which fills the modules[] array according to the cmd_t structure |
* defined in cmds.h. |
* |
* To add or remove a module, just make a new directory in cmds/modules |
* for it and copy the 'show' example for basics, then include it here. |
* (or reverse the process to remove one) |
* |
* NOTE: See module_ aliases.h as well, this is where aliases (commands that |
* share an entry point with others) are indexed */ |
#include "config.h" |
/* Prototypes for each module's entry (help/exec) points */ |
#include "help/entry.h" |
#include "mkdir/entry.h" |
#include "rm/entry.h" |
#include "cat/entry.h" |
#include "touch/entry.h" |
#include "ls/entry.h" |
#include "pwd/entry.h" |
#include "sleep/entry.h" |
#include "cp/entry.h" |
/* Each .def function fills the module_t struct with the individual name, entry |
* point, help entry point, etc. You can use config.h to control what modules |
* are loaded based on what libraries exist on the system. */ |
module_t modules[] = { |
#include "help/help_def.h" |
#include "mkdir/mkdir_def.h" |
#include "rm/rm_def.h" |
#include "cat/cat_def.h" |
#include "touch/touch_def.h" |
#include "ls/ls_def.h" |
#include "pwd/pwd_def.h" |
#include "sleep/sleep_def.h" |
#include "cp/cp_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat_def.h |
---|
0,0 → 1,7 |
{ |
"cat", |
"Show the contents of a file", |
&cmd_cat, |
&help_cmd_cat, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
0,0 → 1,178 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <getopt.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cat.h" |
#include "cmds.h" |
static char *cmdname = "cat"; |
#define CAT_VERSION "0.0.1" |
#define CAT_DEFAULT_BUFLEN 1024 |
static char *cat_oops = "That option is not yet supported\n"; |
static struct option const long_options[] = { |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "head", required_argument, 0, 'H' }, |
{ "tail", required_argument, 0, 't' }, |
{ "buffer", required_argument, 0, 'b' }, |
{ "more", no_argument, 0, 'm' }, |
{ 0, 0, 0, 0 } |
}; |
/* Dispays help for cat in various levels */ |
void help_cmd_cat(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' shows the contents of files\n", cmdname); |
} else { |
help_cmd_cat(HELP_SHORT); |
printf( |
"Usage: %s [options] <file1> [file2] [...]\n" |
"Options:\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
" -H, --head ## Print only the first ## bytes\n" |
" -t, --tail ## Print only the last ## bytes\n" |
" -b, --buffer ## Set the read buffer size to ##\n" |
" -m, --more Pause after each screen full\n" |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return; |
} |
static unsigned int cat_file(const char *fname, size_t blen) |
{ |
int fd, bytes = 0, count = 0, reads = 0; |
off_t total = 0; |
char *buff = NULL; |
if (-1 == (fd = open(fname, O_RDONLY))) { |
printf("Unable to open %s\n", fname); |
return 1; |
} |
total = lseek(fd, 0, SEEK_END); |
lseek(fd, 0, SEEK_SET); |
if (NULL == (buff = (char *) malloc(blen + 1))) { |
close(fd); |
printf("Unable to allocate enough memory to read %s\n", |
fname); |
return 1; |
} |
do { |
bytes = read(fd, buff, blen); |
if (bytes > 0) { |
count += bytes; |
buff[bytes] = '\0'; |
printf("%s", buff); |
reads++; |
} |
} while (bytes > 0); |
close(fd); |
if (bytes == -1) { |
printf("Error reading %s\n", fname); |
free(buff); |
return 1; |
} |
free(buff); |
return 0; |
} |
/* Main entry point for cat, accepts an array of arguments */ |
int cmd_cat(char **argv) |
{ |
unsigned int argc, i, ret = 0, buffer = 0; |
int c, opt_ind; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_cat(HELP_LONG); |
return CMD_SUCCESS; |
case 'v': |
printf("%s\n", CAT_VERSION); |
return CMD_SUCCESS; |
case 'H': |
printf(cat_oops); |
return CMD_FAILURE; |
case 't': |
printf(cat_oops); |
return CMD_FAILURE; |
case 'b': |
printf(cat_oops); |
break; |
case 'm': |
printf(cat_oops); |
return CMD_FAILURE; |
} |
} |
argc -= optind; |
if (argc < 1) { |
printf("%s - incorrect number of arguments. Try `%s --help'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
if (buffer <= 0) |
buffer = CAT_DEFAULT_BUFLEN; |
for (i = optind; argv[i] != NULL; i++) |
ret += cat_file(argv[i], buffer); |
if (ret) |
return CMD_FAILURE; |
else |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/cat/entry.h |
---|
0,0 → 1,9 |
#ifndef CAT_ENTRY_H |
#define CAT_ENTRY_H |
/* Entry points for the cat command */ |
extern int cmd_cat(char **); |
extern void help_cmd_cat(unsigned int); |
#endif /* CAT_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat.h |
---|
0,0 → 1,9 |
#ifndef CAT_H |
#define CAT_H |
/* Prototypes for the cat command, excluding entry points */ |
static unsigned int cat_file(const char *, size_t); |
#endif /* CAT_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/help/help.c |
---|
0,0 → 1,158 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "config.h" |
#include "entry.h" |
#include "help.h" |
#include "cmds.h" |
#include "modules.h" |
#include "builtins.h" |
#include "errors.h" |
#include "util.h" |
static char *cmdname = "help"; |
extern const char *progname; |
#define HELP_IS_MODULE 1 |
#define HELP_IS_BUILTIN 0 |
#define HELP_IS_RUBBISH -1 |
volatile int mod_switch = -1; |
/* Just use a pointer here, no need for mod_switch */ |
static int is_mod_or_builtin(char *cmd) |
{ |
int rc = HELP_IS_RUBBISH; |
rc = is_builtin(cmd); |
if (rc > -1) { |
mod_switch = rc; |
return HELP_IS_BUILTIN; |
} |
rc = is_module(cmd); |
if (rc > -1) { |
mod_switch = rc; |
return HELP_IS_MODULE; |
} |
return HELP_IS_RUBBISH; |
} |
void help_cmd_help(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf( |
"\n %s [command] <extended>\n" |
" Use help [command] extended for detailed help on [command] " |
", even `help'\n\n", cmdname); |
} else { |
printf( |
"\n `%s' - shows help for commands\n" |
" Examples:\n" |
" %s [command] Show help for [command]\n" |
" %s [command] extended Show extended help for [command]\n" |
"\n If no argument is given to %s, a list of commands are shown\n\n", |
cmdname, cmdname, cmdname, cmdname); |
} |
return; |
} |
int cmd_help(char *argv[]) |
{ |
module_t *mod; |
builtin_t *cmd; |
unsigned int i = 0; |
int rc = 0; |
int argc; |
int level = HELP_SHORT; |
argc = cli_count_args(argv); |
if (argc > 3) { |
printf("\nToo many arguments to `%s', try:\n", cmdname); |
help_cmd_help(HELP_SHORT); |
return CMD_FAILURE; |
} |
if (argc == 3) { |
if (!strcmp("extended", argv[2])) |
level = HELP_LONG; |
else |
level = HELP_SHORT; |
} |
if (argc > 1) { |
rc = is_mod_or_builtin(argv[1]); |
switch (rc) { |
case HELP_IS_RUBBISH: |
printf("Invalid command %s\n", argv[1]); |
return CMD_FAILURE; |
case HELP_IS_MODULE: |
help_module(mod_switch, level); |
return CMD_SUCCESS; |
case HELP_IS_BUILTIN: |
help_builtin(mod_switch, level); |
return CMD_SUCCESS; |
} |
} |
printf("\n Available commands are:\n"); |
printf(" ------------------------------------------------------------\n"); |
/* First, show a list of built in commands that are available in this mode */ |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (is_builtin_alias(cmd->name)) |
printf(" %-16s\tAlias for `%s'\n", cmd->name, |
alias_for_builtin(cmd->name)); |
else |
printf(" %-16s\t%s\n", cmd->name, cmd->desc); |
} |
i = 0; |
/* Now, show a list of module commands that are available in this mode */ |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (is_module_alias(mod->name)) |
printf(" %-16s\tAlias for `%s'\n", mod->name, |
alias_for_module(mod->name)); |
else |
printf(" %-16s\t%s\n", mod->name, mod->desc); |
} |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
cmdname, cmdname, cmdname); |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/help/help_def.h |
---|
0,0 → 1,6 |
{ |
"help", |
"Show help for commands", |
&cmd_help, |
&help_cmd_help, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/help/entry.h |
---|
0,0 → 1,8 |
#ifndef HELP_ENTRY_H_ |
#define HELP_ENTRY_H_ |
/* Entry points for the help command */ |
extern void help_cmd_help(unsigned int); |
extern int cmd_help(char *[]); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/help/help.h |
---|
0,0 → 1,7 |
#ifndef HELP_H |
#define HELP_H |
/* Prototypes for the help command (excluding entry points) */ |
static int is_mod_or_builtin(char *); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h |
---|
0,0 → 1,7 |
{ |
"sleep", |
"Pause for given time interval (in seconds)", |
&cmd_sleep, |
&help_cmd_sleep, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/entry.h |
---|
0,0 → 1,9 |
#ifndef SLEEP_ENTRY_H |
#define SLEEP_ENTRY_H |
/* Entry points for the sleep command */ |
extern int cmd_sleep(char **); |
extern void help_cmd_sleep(unsigned int); |
#endif /* SLEEP_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/sleep.c |
---|
0,0 → 1,73 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "sleep.h" |
#include "cmds.h" |
static char *cmdname = "sleep"; |
/* Dispays help for sleep in various levels */ |
void help_cmd_sleep(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
return; |
} |
/* Main entry point for sleep, accepts an array of arguments */ |
int cmd_sleep(char **argv) |
{ |
unsigned int argc; |
unsigned int i; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
printf("%s %s\n", TEST_ANNOUNCE, cmdname); |
printf("%d arguments passed to %s", argc - 1, cmdname); |
if (argc < 2) { |
printf("\n"); |
return CMD_SUCCESS; |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/sleep.h |
---|
0,0 → 1,8 |
#ifndef SLEEP_H |
#define SLEEP_H |
/* Prototypes for the sleep command, excluding entry points */ |
#endif /* SLEEP_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h |
---|
0,0 → 1,6 |
{ |
"pwd", |
"Prints the current working directory", |
&cmd_pwd, |
&help_cmd_pwd, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/entry.h |
---|
0,0 → 1,12 |
#ifndef PWD_ENTRY_H |
#define PWD_ENTRY_H |
#include "scli.h" |
/* Entry points for the pwd command */ |
extern void help_cmd_pwd(unsigned int); |
extern int cmd_pwd(char **); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/pwd.c |
---|
0,0 → 1,71 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "errors.h" |
#include "entry.h" |
#include "cmds.h" |
#include "pwd.h" |
static char * cmdname = "pwd"; |
void help_cmd_pwd(unsigned int level) |
{ |
printf("`%s' prints your current working directory.\n", cmdname); |
return; |
} |
int cmd_pwd(char *argv[]) |
{ |
char *buff; |
buff = (char *) malloc(PATH_MAX); |
if (NULL == buff) { |
cli_error(CL_ENOMEM, "%s:", cmdname); |
return CMD_FAILURE; |
} |
memset(buff, 0, sizeof(buff)); |
getcwd(buff, PATH_MAX); |
if (! buff) { |
cli_error(CL_EFAIL, |
"Unable to determine the current working directory"); |
free(buff); |
return CMD_FAILURE; |
} else { |
printf("%s\n", buff); |
free(buff); |
return CMD_SUCCESS; |
} |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/pwd.h |
---|
0,0 → 1,6 |
#ifndef PWD_H_ |
#define PWD_H_ |
/* Prototypes for the pwd command (excluding entry points) */ |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/module_aliases.h |
---|
0,0 → 1,18 |
#ifndef MODULE_ALIASES_H |
#define MODULE_ALIASES_H |
/* Modules that declare multiple names for themselves but use the |
* same entry functions are aliases. This array helps to determine if |
* a module is an alias, as such it can be invoked differently. |
* format is alias , real_name */ |
/* So far, this is only used in the help display but could be used to |
* handle a module differently even prior to reaching its entry code. |
* For instance, 'exit' could behave differently than 'quit', prior to |
* the entry point being reached. */ |
char *mod_aliases[] = { |
NULL, NULL |
}; |
#endif |
/branches/dd/uspace/app/bdsh/cmds/modules/README |
---|
0,0 → 1,15 |
Modules are commands or full programs (anything can be made into a module |
that can return int type) should go here. Note, modules do not (can not) |
update or read cliuser_t. |
Stuff that needs to write to the user structures contained in scli.h should |
be made as built-in commands, not modules, but there are very few times when |
you would want to do that. |
See the README file in the bdsh root directory for a quick overview of how to |
write a new command, or convert an existig stand-alone program into a module |
for BDSH. |
/branches/dd/uspace/app/bdsh/cmds/builtins/builtins.h |
---|
0,0 → 1,15 |
#ifndef BUILTINS_H |
#define BUILTINS_H |
#include "config.h" |
#include "cd/entry.h" |
#include "exit/entry.h" |
builtin_t builtins[] = { |
#include "cd/cd_def.h" |
#include "exit/exit_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit.h |
---|
0,0 → 1,6 |
#ifndef EXIT_H |
#define EXIT_H |
/* Prototypes for the quit command (excluding entry points) */ |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/entry.h |
---|
0,0 → 1,12 |
#ifndef EXIT_ENTRY_H_ |
#define EXIT_ENTRY_H_ |
#include "scli.h" |
/* Entry points for the quit command */ |
extern void help_cmd_exit(unsigned int); |
extern int cmd_exit(char *[], cliuser_t *); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit.c |
---|
0,0 → 1,55 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "entry.h" |
#include "exit.h" |
#include "cmds.h" |
static const char *cmdname = "exit"; |
extern volatile unsigned int cli_quit; |
extern const char *progname; |
void help_cmd_exit(unsigned int level) |
{ |
printf("Type `%s' to exit %s\n", cmdname, progname); |
return; |
} |
/* Quits the program and returns the status of whatever command |
* came before invoking 'quit' */ |
int cmd_exit(char *argv[], cliuser_t *usr) |
{ |
/* Inform that we're outta here */ |
cli_quit = 1; |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit_def.h |
---|
0,0 → 1,6 |
{ |
"exit", |
"Exit the shell", |
&cmd_exit, |
&help_cmd_exit, |
}, |
/branches/dd/uspace/app/bdsh/cmds/builtins/cd/cd_def.h |
---|
0,0 → 1,6 |
{ |
"cd", |
"Change the current working directory", |
&cmd_cd, |
&help_cmd_cd, |
}, |
/branches/dd/uspace/app/bdsh/cmds/builtins/cd/cd.c |
---|
0,0 → 1,106 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <string.h> |
#include <errno.h> |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cmds.h" |
#include "cd.h" |
static char * cmdname = "cd"; |
void help_cmd_cd(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' changes the current working directory.\n", cmdname); |
} else { |
printf( |
" %s <directory>\n" |
" Change directory to <directory>, e.g `%s /sbin'\n", |
cmdname, cmdname); |
} |
return; |
} |
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */ |
int cmd_cd(char **argv, cliuser_t *usr) |
{ |
int argc, rc = 0; |
argc = cli_count_args(argv); |
/* We don't yet play nice with whitespace, a getopt implementation should |
* protect "quoted\ destination" as a single argument. Its not our job to |
* look for && || or redirection as the tokenizer should have done that |
* (currently, it does not) */ |
if (argc > 2) { |
cli_error(CL_EFAIL, "Too many arguments to `%s'", cmdname); |
return CMD_FAILURE; |
} |
if (argc < 2) { |
printf("%s - no directory specified. Try `help %s extended'\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
/* We have the correct # of arguments |
* TODO: handle tidle (~) expansion? */ |
rc = chdir(argv[1]); |
if (rc == 0) { |
cli_set_prompt(usr); |
return CMD_SUCCESS; |
} else { |
switch (rc) { |
case ENOMEM: |
cli_error(CL_EFAIL, "Destination path too long"); |
break; |
case ENOENT: |
cli_error(CL_ENOENT, "Invalid directory `%s'", argv[1]); |
break; |
default: |
cli_error(CL_EFAIL, "Unable to change to `%s'", argv[1]); |
break; |
} |
} |
return CMD_FAILURE; |
} |
/branches/dd/uspace/app/bdsh/cmds/builtins/cd/entry.h |
---|
0,0 → 1,12 |
#ifndef CD_ENTRY_H_ |
#define CD_ENTRY_H_ |
#include "scli.h" |
/* Entry points for the cd command */ |
extern void help_cmd_cd(unsigned int); |
extern int cmd_cd(char **, cliuser_t *); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/cd/cd.h |
---|
0,0 → 1,7 |
#ifndef CD_H |
#define CD_H |
/* Prototypes for the cd command (excluding entry points) */ |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/builtin_aliases.h |
---|
0,0 → 1,10 |
#ifndef BUILTIN_ALIASES_H |
#define BUILTIN_ALIASES_H |
/* See modules/module_aliases.h for an explanation of this file */ |
char *builtin_aliases[] = { |
NULL, NULL |
}; |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtins/README |
---|
0,0 → 1,21 |
Commands that need to modify the running user structure defined in scli.h |
should reside here. They (will) have a slightly different prototype that |
allows passing the user structure to them for ease of modifications. |
Examples of what should be a built-in and not a module would be: |
cd (cliuser_t->cwd needs to be updated) |
In the future, more user preferences will be set via built-in commands, |
such as the formatting of the prompt string (HelenOS doesn't yet have |
an environment, much less PS*, even if it did we'd likely do it a little |
differently). |
.... etc. |
Anything that does _not_ need to use this structure should be included |
as a module, not a built in. If you want to include a new command, there |
is a 99% chance that you want it to be a module. |
/branches/dd/uspace/app/bdsh/cmds/mknewcmd |
---|
0,0 → 1,314 |
#!/bin/sh |
# Copyright (C) 2008 Tim Post - All Rights Reserved |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions are met: |
# |
# Redistributions of source code must retain the above copyright notice, this |
# list of conditions and the following disclaimer. |
# |
# Redistributions in binary form must reproduce the above copyright notice, |
# this list of conditions and the following disclaimer in the documentation |
# and/or other materials provided with the distribution. |
# |
# Neither the name of the original program's authors nor the names of its |
# contributors may be used to endorse or promote products derived from this |
# software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
# POSSIBILITY OF SUCH DAMAGE. |
# Script to generate skeletal files for a new command |
# Uses `getopt', not quite a bash-ism but might be |
# lacking on some legacy systems. |
# If your shell does not support eval, shift (x) or |
# here-now documents, sorry :) |
usage() |
{ |
def="$DEFAULT_COMMAND" |
cat << EOF |
\`$PROGNAME' generates skeletal command files to simplify adding commands |
Usage: $PROGNAME [options] <location> |
Options: |
-n, --name Name of the command (default: ${def}) |
-d, --desc Short (20 30 chars) description of the command |
(def: "The $def command") |
-e, --entry Entry function of the command (def: cmd_${def}) |
-h, --help-entry Entry function for command help (def: help_cmd_${def}) |
-a, --alias Alias (nickname) for this command (def: none) |
-t, --type Type of command (module or builtin) (def: module) |
-H, --help This help summary |
-V, --version Print $PROGNAME version and exit normally |
Notes: |
You must supply at least the name of the command. |
If you do not specify a location (i.e. modules/foo), the command will be |
created in modules/command_name or builtins/command_name depending on your |
selection. |
This script will only create skeletal files and inform you what headers |
need to be modified to incorporate the command. You will also have to |
manually update the main Makefile. |
This script is intended only to be a convenience for developers. Example use: |
$PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo |
The example would generate a modular command named 'foo', which is also |
reached by typing 'bar'. |
Skeletal files do *not* depend on the autoconf generated "config.h" unless you |
include it. This may or may not be desirable depending on your use. |
Report bugs to $PROGMAINT |
EOF |
} |
# Convert a string to all uppercase |
toupper() |
{ |
local str="$1" |
echo "${str}" | tr 'a-z' 'A-Z' |
} |
# Template stored `here-now' style, this generates all files needed |
# for a new command according to arguments passed. |
generate_code() |
{ |
echo "Creating ${OUTDIR}/${CMDNAME}_def.h ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}_def.h |
{ |
"${CMDNAME}", |
"${CMDDESC}", |
&${CMDENTRY}, |
&${HELPENTRY}, |
}, |
EOF |
[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h |
{ |
"${CMDALIAS}", |
NULL, |
&${CMDENTRY}, |
&${HELPENTRY}, |
}, |
EOF |
local defname=$(toupper "${CMDNAME}") |
echo "Creating ${OUTDIR}/entry.h ..." |
cat << EOF > ${OUTDIR}/entry.h |
#ifndef ${defname}_ENTRY_H |
#define ${defname}_ENTRY_H |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h |
/* Entry points for the ${CMDNAME} command */ |
extern int ${CMDENTRY}(char **); |
extern void ${HELPENTRY}(unsigned int); |
#endif /* ${defname}_ENTRY_H */ |
EOF |
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/entry.h |
/* Pick up cliuser_t */ |
#include "scli.h" |
/* Entry points for the ${CMDNAME} command */ |
extern int * ${CMDENTRY}(char **, cliuser_t *); |
extern void * ${HELPENTRY}(unsigned int); |
#endif /* ${defname}_ENTRY_H */ |
EOF |
echo "Creating ${OUTDIR}/${CMDNAME}.h ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}.h |
#ifndef ${defname}_H |
#define ${defname}_H |
/* Prototypes for the ${CMDNAME} command, excluding entry points */ |
#endif /* ${defname}_H */ |
EOF |
echo "Creating ${OUTDIR}/${CMDNAME}.c ..." |
cat << EOF > ${OUTDIR}/${CMDNAME}.c |
/* Automatically generated by ${PROGNAME} on ${TIMESTAMP} |
* This is machine generated output. The author of ${PROGNAME} claims no |
* copyright over the contents of this file. Where legally permitted, the |
* contents herein are donated to the public domain. |
* |
* You should apply any license and copyright that you wish to this file, |
* replacing this header in its entirety. */ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "${CMDNAME}.h" |
#include "cmds.h" |
static const char *cmdname = "${CMDNAME}"; |
/* Dispays help for ${CMDNAME} in various levels */ |
void ${HELPENTRY}(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
return; |
} |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments */ |
int ${CMDENTRY}(char **argv) |
EOF |
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a |
* pointer to the cliuser_t structure */ |
int ${CMDENTRY}(char **argv, cliuser_t *usr) |
EOF |
cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
{ |
unsigned int argc; |
unsigned int i; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
printf("%s %s\n", TEST_ANNOUNCE, cmdname); |
printf("%d arguments passed to %s", argc - 1, cmdname); |
if (argc < 2) { |
printf("\n"); |
return CMD_SUCCESS; |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
return CMD_SUCCESS; |
} |
EOF |
printf "Done.\n\nYou should now modify %ss/%ss.h and ../Makefile" \ |
"${CMDTYPE}" "${CMDTYPE}" |
printf " to include your new command.\n" |
[ -n "$CMDALIAS" ] && { |
printf "\nYou should also modify %ss/%s_aliases.h and " \ |
"${CMDTYPE}" "${CMDTYPE}" |
printf "add %s as an alias for %s\n" \ |
"${CMDALIAS}" "${CMDNAME}" |
} |
printf "\nOnce completed, re-run make\n\n" |
} |
# Main program |
TIMESTAMP="$(date)" |
PROGNAME=$(basename $0) |
PROGVER="0.0.1" |
PROGMAINT="Tim Post <echo@echoreply.us>" |
DEFAULT_COMMAND="cmdname" |
# We need at least one |
[ $# = 0 ] && usage && exit 1; |
TEMP=$(getopt -o n:d:e:h:a:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,type:,help,version \ |
-- "$@") || { |
echo "Try $PROGNAME --help for help" |
} |
eval set -- "$TEMP" |
while true; do |
case "$1" in |
-n | --name) |
CMDNAME="$2" |
shift 2 |
continue |
;; |
-d | --desc) |
CMDDESC="$2" |
shift 2 |
continue |
;; |
-e | --entry) |
CMDENTRY="$2" |
shift 2 |
continue |
;; |
-h | --help-entry) |
HELPENTRY="$2" |
shift 2 |
continue |
;; |
-a | --alias) |
CMDALIAS="$2" |
shift 2 |
continue |
;; |
-t | --type) |
CMDTYPE="$2" |
shift 2 |
continue |
;; |
-H | --help) |
usage |
exit 0 |
;; |
-V | --version) |
echo "$PROGVER" |
exit 0 |
;; |
--) |
break |
;; |
esac |
done |
# Pick up a location if one was specified |
eval set -- "$*" |
[ -n "$2" ] && OUTDIR="$2" |
# Fill in defaults for whatever was not specified |
[ -n "$CMDNAME" ] || CMDNAME="$DEFAULT_COMMAND" |
[ -n "$CMDDESC" ] || CMDDESC="The $CMDNAME command" |
[ -n "$CMDENTRY" ] || CMDENTRY="cmd_${CMDNAME}" |
[ -n "$HELPENTRY" ] || HELPENTRY="help_cmd_${CMDNAME}" |
[ -n "$CMDTYPE" ] || CMDTYPE="module" |
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}" |
# Do a little sanity |
[ -d $OUTDIR ] && { |
echo "$OUTDIR already exists, remove it to proceed." |
exit 1 |
} |
mkdir -p ${OUTDIR} >/dev/null 2>&1 || { |
echo "Could not create ${OUTDIR}, aborting!" |
exit 1 |
} |
# Generate the files and inform on how to include them based on options |
generate_code |
exit 0 |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/uspace/app/bdsh/cmds/mod_cmds.c |
---|
0,0 → 1,136 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* NOTES: |
* module_* functions are pretty much identical to builtin_* functions at this |
* point. On the surface, it would appear that making each function dual purpose |
* would be economical. |
* |
* These are kept separate because the structures (module_t and builtin_t) may |
* grow apart and become rather different, even though they're identical at this |
* point. |
* |
* To keep things easy to hack, everything is separated. In reality this only adds |
* 6 - 8 extra functions, but keeps each function very easy to read and modify. */ |
/* TODO: |
* Many of these could be unsigned, provided the modules and builtins themselves |
* can follow suit. Long term goal. */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "errors.h" |
#include "cmds.h" |
#include "module_aliases.h" |
extern volatile unsigned int cli_interactive; |
/* Checks if an entry function matching command exists in modules[], if so |
* its position in the array is returned */ |
int is_module(const char *command) |
{ |
module_t *mod; |
unsigned int i = 0; |
if (NULL == command) |
return -2; |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!strcmp(mod->name, command)) |
return i; |
} |
return -1; |
} |
/* Checks if a module is an alias (sharing an entry point with another |
* module). Returns 1 if so */ |
int is_module_alias(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return -1; |
for(i=0; mod_aliases[i] != NULL; i+=2) { |
if (!strcmp(mod_aliases[i], command)) |
return 1; |
} |
return 0; |
} |
/* Returns the name of the module that an alias points to */ |
char *alias_for_module(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return (char *)NULL; |
for(i=0; mod_aliases[i] != NULL; i++) { |
if (!strcmp(mod_aliases[i], command)) |
return (char *)mod_aliases[++i]; |
i++; |
} |
return (char *)NULL; |
} |
/* Invokes the 'help' entry function for the module at position (int) module, |
* which wants an unsigned int to determine brief or extended display. */ |
int help_module(int module, unsigned int extended) |
{ |
module_t *mod = modules; |
mod += module; |
if (NULL != mod->help) { |
mod->help(extended); |
return CL_EOK; |
} else |
return CL_ENOENT; |
} |
/* Invokes the module entry point modules[module], passing argv[] as an argument |
* stack. */ |
int run_module(int module, char *argv[]) |
{ |
module_t *mod = modules; |
mod += module; |
if (NULL != mod->entry) |
return ((int)mod->entry(argv)); |
return CL_ENOENT; |
} |
/branches/dd/uspace/app/bdsh/cmds/cmds.h |
---|
0,0 → 1,71 |
#ifndef CMDS_H |
#define CMDS_H |
#include "config.h" |
#include "scli.h" |
/* Temporary to store strings */ |
#define EXT_HELP "extended" |
#define SHORT_HELP "short" |
#define TEST_ANNOUNCE "Hello, this is :" |
/* Simple levels of help displays */ |
#define HELP_SHORT 0 |
#define HELP_LONG 1 |
/* Acceptable buffer sizes (for strn functions) */ |
/* TODO: Move me, other files duplicate these needlessly */ |
#define BUFF_LARGE 1024 |
#define BUFF_SMALL 255 |
/* Return macros for int type entry points */ |
#define CMD_FAILURE 1 |
#define CMD_SUCCESS 0 |
/* Types for module command entry and help */ |
typedef int (* mod_entry_t)(char **); |
typedef void (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int (* builtin_entry_t)(char **, cliuser_t *); |
typedef void (* builtin_help_t)(unsigned int); |
/* Module structure */ |
typedef struct { |
char *name; /* Name of the command */ |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
} module_t; |
/* Builtin structure, same as modules except different types of entry points */ |
typedef struct { |
char *name; |
char *desc; |
builtin_entry_t entry; |
builtin_help_t help; |
int restricted; |
} builtin_t; |
/* Declared in cmds/modules/modules.h and cmds/builtins/builtins.h |
* respectively */ |
extern module_t modules[]; |
extern builtin_t builtins[]; |
/* Prototypes for module launchers */ |
extern int module_is_restricted(int); |
extern int is_module(const char *); |
extern int is_module_alias(const char *); |
extern char * alias_for_module(const char *); |
extern int help_module(int, unsigned int); |
extern int run_module(int, char *[]); |
/* Prototypes for builtin launchers */ |
extern int builtin_is_restricted(int); |
extern int is_builtin(const char *); |
extern int is_builtin_alias(const char *); |
extern char * alias_for_builtin(const char *); |
extern int help_builtin(int, unsigned int); |
extern int run_builtin(int, char *[], cliuser_t *); |
#endif |
/branches/dd/uspace/app/bdsh/cmds/builtin_cmds.c |
---|
0,0 → 1,113 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* Almost identical (for now) to mod_cmds.c , however this will not be the case |
* soon as builtin_t is going to grow way beyond module_t */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "errors.h" |
#include "cmds.h" |
#include "builtin_aliases.h" |
extern volatile unsigned int cli_interactive; |
int is_builtin(const char *command) |
{ |
builtin_t *cmd; |
unsigned int i = 0; |
if (NULL == command) |
return -2; |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!strcmp(cmd->name, command)) |
return i; |
} |
return -1; |
} |
int is_builtin_alias(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return -1; |
for(i=0; builtin_aliases[i] != NULL; i+=2) { |
if (!strcmp(builtin_aliases[i], command)) |
return 1; |
} |
return 0; |
} |
char *alias_for_builtin(const char *command) |
{ |
unsigned int i = 0; |
if (NULL == command) |
return (char *)NULL; |
for(i=0; builtin_aliases[i] != NULL; i++) { |
if (!strcmp(builtin_aliases[i], command)) |
return (char *)builtin_aliases[++i]; |
i++; |
} |
return (char *)NULL; |
} |
int help_builtin(int builtin, unsigned int extended) |
{ |
builtin_t *cmd = builtins; |
cmd += builtin; |
if (NULL != cmd->help) { |
cmd->help(extended); |
return CL_EOK; |
} else |
return CL_ENOENT; |
} |
int run_builtin(int builtin, char *argv[], cliuser_t *usr) |
{ |
builtin_t *cmd = builtins; |
cmd += builtin; |
if (NULL != cmd->entry) |
return((int)cmd->entry(argv, usr)); |
return CL_ENOENT; |
} |
/branches/dd/uspace/app/bdsh/Makefile |
---|
0,0 → 1,130 |
# Copyright (c) 2005, Martin Decky |
# All rights reserved. |
# Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions are met: |
# |
# Redistributions of source code must retain the above copyright notice, this |
# list of conditions and the following disclaimer. |
# |
# Redistributions in binary form must reproduce the above copyright notice, |
# this list of conditions and the following disclaimer in the documentation |
# and/or other materials provided with the distribution. |
# |
# Neither the name of the original program's authors nor the names of its |
# contributors may be used to endorse or promote products derived from this |
# software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
# POSSIBILITY OF SUCH DAMAGE. |
include ../../../version |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=$(RELEASE) |
PROGRAM = bdsh |
# Any directory that cleaning targets should know about |
SUBDIRS = \ |
./ \ |
cmds/ \ |
cmds/modules/ \ |
cmds/modules/help/ \ |
cmds/modules/mkdir/ \ |
cmds/modules/rm/ \ |
cmds/modules/cat/ \ |
cmds/modules/touch/ \ |
cmds/modules/ls/ \ |
cmds/modules/pwd/ \ |
cmds/modules/sleep/ \ |
cmds/modules/cp/ \ |
cmds/builtins/ \ |
cmds/builtins/exit/\ |
cmds/builtins/cd/ |
SOURCES = \ |
cmds/modules/help/help.c \ |
cmds/modules/mkdir/mkdir.c \ |
cmds/modules/rm/rm.c \ |
cmds/modules/cat/cat.c \ |
cmds/modules/touch/touch.c \ |
cmds/modules/ls/ls.c \ |
cmds/modules/pwd/pwd.c \ |
cmds/modules/sleep/sleep.c \ |
cmds/modules/cp/cp.c \ |
cmds/builtins/exit/exit.c \ |
cmds/builtins/cd/cd.c \ |
cmds/mod_cmds.c \ |
cmds/builtin_cmds.c \ |
errors.c \ |
input.c \ |
util.c \ |
exec.c \ |
scli.c |
CFLAGS += -I. -Icmds/ -Icmds/builtins -Icmds/modules |
OBJECTS = $(SOURCES:.c=.o) |
# For easy cleaning, *.o is already handled |
CLEANDIRS := $(addsuffix *~,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.bak,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.tmp,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.out,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.d,$(SUBDIRS)) |
CLEANDIRS += $(addsuffix *.gch,$(SUBDIRS) ) |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(CFLAGS) $(INC) -c $< -o $@ |
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d |
$(PROGRAM): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
# Everything else is a phony target |
.PHONY: all clean distclean depend disasm |
all: $(PROGRAM) disasm |
clean: |
@-rm -f $(OBJECTS) |
@-rm -f $(PROGRAM) |
@-rm -f $(PROGRAM).map |
@-rm -f $(PROGRAM).disasm |
@-rm -f $(CLEANDIRS) |
depend: |
@echo '' |
disasm: |
$(OBJDUMP) -d $(PROGRAM) >$(PROGRAM).disasm |
distclean: clean |
# Do not delete - dependencies |
-include $(OBJECTS:.o=.d) |
/branches/dd/uspace/app/bdsh/AUTHORS |
---|
0,0 → 1,14 |
Written by Tim Post <echo@echoreply.us> to serve as a primitive shell |
for HelenOS, or as a template to make a command line interface that |
offers shell like creature comforts. |
This program was mostly written from scratch, some existing code was |
used from other various free software projects: |
* Based on the HelenOS testing sub-system written by Martin Decky |
* read_line() (input.c) was written by Jiri Svoboda |
Individual author copyrights are listed in the headers of each file. |
/branches/dd/uspace/app/bdsh/util.c |
---|
0,0 → 1,82 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> - All rights reserved |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdarg.h> |
#include <stdlib.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "util.h" |
extern volatile int cli_errno; |
/* Count and return the # of elements in an array */ |
unsigned int cli_count_args(char **args) |
{ |
unsigned int i; |
for (i=0; args[i] != NULL; i++); |
return i; |
} |
/* (re)allocates memory to store the current working directory, gets |
* and updates the current working directory, formats the prompt |
* string */ |
unsigned int cli_set_prompt(cliuser_t *usr) |
{ |
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX); |
if (NULL == usr->prompt) { |
cli_error(CL_ENOMEM, "Can not allocate prompt"); |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->prompt, 0, sizeof(usr->prompt)); |
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX); |
if (NULL == usr->cwd) { |
cli_error(CL_ENOMEM, "Can not allocate cwd"); |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->cwd, 0, sizeof(usr->cwd)); |
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1); |
if (NULL == usr->cwd) |
snprintf(usr->cwd, PATH_MAX, "(unknown)"); |
asprintf(&usr->prompt, "%s # ", usr->cwd); |
return 0; |
} |
/branches/dd/uspace/app/bdsh/util.h |
---|
0,0 → 1,10 |
#ifndef UTIL_H |
#define UTIL_H |
#include "scli.h" |
/* Utility functions */ |
extern unsigned int cli_count_args(char **); |
extern unsigned int cli_set_prompt(cliuser_t *usr); |
#endif |
/branches/dd/uspace/app/bdsh/exec.c |
---|
0,0 → 1,129 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* The VERY basics of execute in place support. These are buggy, leaky |
* and not nearly done. Only here for beta testing!! You were warned!! |
* TODO: |
* Hash command lookups to save time |
* Create a running pointer to **path and advance/rewind it as we go */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "exec.h" |
#include "errors.h" |
/* FIXME: Just have find_command() return an allocated string */ |
static char *found; |
static char *find_command(char *); |
static int try_access(const char *); |
/* work-around for access() */ |
static int try_access(const char *f) |
{ |
int fd; |
fd = open(f, O_RDONLY); |
if (fd > -1) { |
close(fd); |
return 0; |
} else |
return -1; |
} |
/* Returns the full path of "cmd" if cmd is found, else just hand back |
* cmd as it was presented */ |
static char *find_command(char *cmd) |
{ |
char *path_tok; |
char *path[PATH_MAX]; |
int n = 0, i = 0; |
size_t x = strlen(cmd) + 2; |
found = (char *)malloc(PATH_MAX); |
/* The user has specified a full or relative path, just give it back. */ |
if (-1 != try_access(cmd)) { |
return (char *) cmd; |
} |
path_tok = strdup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
if ((strlen(path[n]) + x ) > PATH_MAX) { |
cli_error(CL_ENOTSUP, |
"Segment %d of path is too large, search ends at segment %d", |
n, n-1); |
break; |
} |
path[++n] = strtok(NULL, PATH_DELIM); |
} |
/* We now have n places to look for the command */ |
for (i=0; path[i]; i++) { |
memset(found, 0, sizeof(found)); |
snprintf(found, PATH_MAX, "%s/%s", path[i], cmd); |
if (-1 != try_access(found)) { |
free(path_tok); |
return (char *) found; |
} |
} |
/* We didn't find it, just give it back as-is. */ |
free(path_tok); |
return (char *) cmd; |
} |
unsigned int try_exec(char *cmd, char **argv) |
{ |
task_id_t tid; |
char *tmp; |
tmp = strdup(find_command(cmd)); |
free(found); |
tid = task_spawn((const char *)tmp, argv); |
free(tmp); |
if (tid == 0) { |
cli_error(CL_EEXEC, "Can not spawn %s", cmd); |
return 1; |
} else { |
return 0; |
} |
} |
/branches/dd/uspace/app/bdsh/scli.c |
---|
0,0 → 1,105 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include "config.h" |
#include "scli.h" |
#include "input.h" |
#include "util.h" |
#include "errors.h" |
#include "cmds/cmds.h" |
/* See scli.h */ |
static cliuser_t usr; |
/* Globals that are modified during start-up that modules/builtins |
* should be aware of. */ |
volatile unsigned int cli_quit = 0; |
volatile unsigned int cli_verbocity = 1; |
/* The official name of this program |
* (change to your liking in configure.ac and re-run autoconf) */ |
const char *progname = PACKAGE_NAME; |
/* These are not exposed, even to builtins */ |
static int cli_init(cliuser_t *); |
static void cli_finit(cliuser_t *); |
/* Constructor */ |
static int cli_init(cliuser_t *usr) |
{ |
usr->line = (char *) NULL; |
usr->name = "root"; |
usr->home = "/"; |
usr->cwd = (char *) NULL; |
usr->prompt = (char *) NULL; |
chdir(usr->home); |
usr->lasterr = 0; |
return (int) cli_set_prompt(usr); |
} |
/* Destructor */ |
static void cli_finit(cliuser_t *usr) |
{ |
if (NULL != usr->line) |
free(usr->line); |
if (NULL != usr->prompt) |
free(usr->prompt); |
if (NULL != usr->cwd) |
free(usr->cwd); |
} |
int main(int argc, char *argv[]) |
{ |
int ret = 0; |
if (cli_init(&usr)) |
exit(EXIT_FAILURE); |
printf("Welcome to %s - %s\nType `help' at any time for usage information.\n", |
progname, PACKAGE_STRING); |
while (!cli_quit) { |
get_input(&usr); |
if (NULL != usr.line) { |
ret = tok_input(&usr); |
cli_set_prompt(&usr); |
usr.lasterr = ret; |
} |
} |
goto finit; |
finit: |
cli_finit(&usr); |
return ret; |
} |
/branches/dd/uspace/app/bdsh/config.h |
---|
0,0 → 1,36 |
/* Various things that are used in many places including a few |
* tidbits left over from autoconf prior to the HelenOS port */ |
/* Specific port work-arounds : */ |
#ifndef PATH_MAX |
#define PATH_MAX 255 |
#endif |
#ifndef EXIT_SUCCESS |
#define EXIT_SUCCESS 0 |
#define EXIT_FAILURE 1 |
#endif |
/* Work around for getenv() */ |
#define PATH "/srv:/app" |
#define PATH_DELIM ":" |
/* Used in many places */ |
#define SMALL_BUFLEN 256 |
#define LARGE_BUFLEN 1024 |
/* How many words (arguments) are permitted, how big can a whole |
* sentence be? Similar to ARG_MAX */ |
#define WORD_MAX 255 |
#define INPUT_MAX 1024 |
/* Leftovers from Autoconf */ |
#define PACKAGE_MAINTAINER "Tim Post" |
#define PACKAGE_BUGREPORT "echo@echoreply.us" |
#define PACKAGE_NAME "bdsh" |
#define PACKAGE_STRING "The brain dead shell" |
#define PACKAGE_TARNAME "bdsh" |
#define PACKAGE_VERSION "0.0.1" |
/branches/dd/uspace/app/bdsh/README |
---|
0,0 → 1,252 |
BDSH - The Brain Dead Shell | Design Documentation |
-------------------------------------------------- |
Overview: |
========= |
BDSH was written as a drop in command line interface for HelenOS to permit |
interactive access to persistent file systems in development. BDSH was |
written from scratch with a very limited userspace standard C library in |
mind. Much like the popular Busybox program, BDSH provides a very limited |
shell with limited common UNIX creature comforts built in. |
Porting Busybox (and by extension ASH) would have taken much longer to |
complete, much less make stable due to stark differences between Linux and |
Spartan with regards to IPC, term I/O and process creation. BDSH was written |
and made stable within the space of less than 30 days. |
BDSH will eventually evolve and be refined into the HelenOS equivalent |
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and |
use of strictly lower level functions makes it extremely easy to port. |
Design: |
======= |
BDSH is made up of three basic components: |
1. Main i/o, error handling and task management |
2. The builtin sub system |
3. The module sub system |
The main part handles user input, reports errors, spawns external tasks and |
provides a convenient entry point for built-in and modular commands. A simple |
structure, cliuser_t keeps track of the user's vitals, such as their current |
working directory (and eventually uid, home directory, etc if they apply). |
This part defines and exposes all functions that are not intrinsic to a |
certain built in or modular command. For instance: string handlers, |
module/builtin search and launch functions, error handlers and other things |
can be found here. |
Builtin commands are commands that must have access to cliuser_t, which is |
not exposed to modular commands. For instance, the 'cd' command must update |
the current working directory, which is stored in cliuser_t. As such, the |
entry types for builtin commands are slightly different. |
Modular commands do not need anything more than the basic functions that are |
exposed by default. They do not need to modify cliuser_t, they are just self |
contained. A modular command could very easily be made into a stand alone |
program, likewise any stand alone program could easily become a modular |
command. |
Both modular and builtin commands share two things in common. Both must have |
two entry points, one to invoke the command and one to invoke a help display |
for the command. Exec (main()) entry points are int * and are expected to |
return a value. Help entry points are void *, no return value is expected. |
They are typed as such (from cmds.h): |
/* Types for module command entry and help */ |
typedef int (* mod_entry_t)(char **); |
typedef void (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int (* builtin_entry_t)(char **, cliuser_t *); |
typedef void (* builtin_help_t)(unsigned int); |
As you can see, both modular and builtin commands expect an array of |
arguments, however bulitins also expect to be pointed to cliuser_t. |
Both are defined with the same simple structure: |
/* Module structure */ |
typedef struct { |
char *name; /* Name of the command */ |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
int restricted; /* Restricts to interactive/non-interactive only */ |
} module_t; |
NOTE: Builtin commands may grow in this respect, that is why they are |
defined separately. |
Builtins, of course, would use the builtin_entry_t type. The name of the |
command is used to associate user input to a possible entry point. The |
description is a short (40 - 60 chars) summary of what the command does. Both |
entry points are then defined, and the restrict value is used to determine a |
commands availability. |
Restriction levels are easy, a command is either available exclusively within |
interactive mode, exclusively within non-interactive mode or both. If you are |
looking at a prompt, you are in interactive mode. If you issue a command like |
this: |
/sbin/bdsh command [arg1] [arg2] |
... you are in non interactive mode. This is done when you need to force the |
parent shell to be the one who actually handles the command, or ensure that |
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode. |
The values are: |
0 : Unrestricted |
-1 : Interactive only |
1 : Non-interactive only |
A script to generate skeletal files for a new command is included, it can be |
found in cmds/mknewcmd. To generate a new modular command named 'foo', which |
should also be reachable by typing 'f00', you would issue this command: |
./mknewcmd -n foo -a f00 -t module |
This generates all needed files and instructs you on how to include your new |
command in the build and make it accessible. By default, the command will be |
unrestricted. Builtin commands can be created by changing 'module' to |
'builtin' |
There are more options to mknewcmd, which allow you to specify the |
description, entry point, help entry point, or restriction. By default, names |
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command', |
etc. If you want to see the options and explanations in detail, use |
./mknewcmd --help. |
When working with commands, keep in mind that only the main and help entry |
points need to be exposed. If commands share the same functions, put them |
where they are exposed to all commands, without the potential oops of those |
functions going away if the command is eliminated in favor of a stand alone |
external program. |
The util.c file is a great place to put those types of functions. |
Also, be careful with globals, option structures, etc. The compiler will |
generally tell you if you've made a mistake, however declaring: |
volatile int foo |
... in a command will allow for anything else to pick it up. Sometimes |
this could be desirable .. other times not. When communicating between |
builtins and the main system, try to use cliuser_t. The one exception |
for this is the cli_quit global, since everything may at some point |
need to check it. Modules should only communicate their return value. |
Symbolic constants that everything needs should go in the config.h file, |
however this is not the place to define shared macros. |
Making a program into a module |
============================== |
If you have some neat program that would be useful as a modular command, |
converting it is not very hard. The following steps should get you through |
the process easily (assuming your program is named 'foo'): |
1: Use mknewcmd to generate the skeletal files. |
2: Change your "usage()" command as shown: |
-- void usage(...) |
++ void help_cmd_foo(unsigned int level) |
'level' is either 0 or 1, indicating the level of help requested. |
If the help / usage function currently exits based on how it is |
called, you'll need to change it. |
3: Change the programs "main()" as shown: |
-- int main(int argc, char **argv) |
++ int cmd_foo(char **argv) |
-- return 1; |
++ return CMD_FAILURE; |
-- return 0; |
++ return CMD_SUCCESS; |
NOTE: If main is void, you'll need to change it and ensure that its |
expecting an array of arguments, even if they'll never be read or |
used. I.e.: |
-- void main(void) |
++ int cmd_foo(char **argv) |
4: Don't expose more than the entry and help points: |
-- void my_function(int n) |
++ static void my_function(int n) |
5: Copy/paste to the stub generated by mknewcmd then add your files to the |
Makefile. Be sure to add any directories that you made to the SUBDIRS so |
that a 'make clean' will clean them. |
Provided that all functions that your calling are available in the |
userspace C library, your program should compile just fine and appear |
as a modular command. |
Overcoming userspace libc obstacles |
=================================== |
A quick glance through the util.c file will reveal functions like |
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions |
that were missing from userspace libc when BDSH was born. Later, after |
porting what was needed from FBSD/NBSD, the real functions appeared in |
the userspace libc after being tested in their cli_* implementations. |
Those functions remain because they guarantee that bdsh will work even |
on systems that lack them. Additionally, more BDSH specific stuff can |
go into them, such as error handling and reporting when malloc() fails. |
You will also notice that FILE, fopen() (and all friends), ato*() and |
other common things might be missing. The HelenOS userspace C library is |
still very young, you are sure to run into something that you want/need |
which is missing. |
When that happens, you have three options: |
1 - Implement it internally in util.c , when its tested and stable send a |
patch to HelenOS asking for your function to be included in libc. This is |
the best option, as you not only improve BDSH .. but HelenOS as a whole. |
2 - Work around it. Not everyone can implement / port fopen() and all of |
its friends. Make open(), read(), write() (etc) work if at all possible. |
3 - Send an e-mail to the HelenOS development mailing list. Explain why you |
need the function and what its absence is holding up. |
If what you need is part of a library that is typically a shared object, try |
to implement a 'mini' version of it. Currently, all userspace applications |
are statically linked. Giving up creature comforts for size while avoiding |
temporary 'band aids' is never frowned upon. |
Most of all, don't get discouraged .. ask for some help prior to giving up |
if you just can't accomplish something with the limited means provided. |
Contributing |
============ |
I will take any well written patch that sanely improves or expands BDSH. Send |
me a patch against the trunk revision, or, if you like a Mercurial repository |
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with |
the trunk. |
Please be sure to follow the simple coding standards outlined at |
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your |
changes and make sure your patch applies cleanly against the latest revision. |
All patches submitted must be your original code, or a derivative work of |
something licensed under the same 3 clause BSD license as BDSH. See LICENSE |
for more information. |
When sending patches, you agree that your work will be published under the |
same 3 clause BSD license as BDSH itself. Failure to ensure that anything |
you used is not under the same or less restrictive license could cause major |
issues for BDSH in the future .. please be sure. Also, please don't forget |
to add yourself in the AUTHORS file, as I am horrible about keeping such |
things up to date. |
/branches/dd/uspace/app/bdsh/scli.h |
---|
0,0 → 1,16 |
#ifndef SCLI_H |
#define SCLI_H |
#include "config.h" |
#include <stdint.h> |
typedef struct { |
char *name; |
char *home; |
char *line; |
char *cwd; |
char *prompt; |
int lasterr; |
} cliuser_t; |
#endif |
/branches/dd/uspace/app/bdsh/input.h |
---|
0,0 → 1,11 |
#ifndef INPUT_H |
#define INPUT_H |
#include "cmds/cmds.h" |
/* prototypes */ |
extern void get_input(cliuser_t *); |
extern int tok_input(cliuser_t *); |
#endif |
/branches/dd/uspace/app/bdsh/exec.h |
---|
0,0 → 1,7 |
#ifndef EXEC_H |
#define EXEC_H |
#include <task.h> |
extern unsigned int try_exec(char *, char **); |
#endif |
/branches/dd/uspace/app/bdsh/errors.c |
---|
0,0 → 1,87 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <stdarg.h> |
#include "config.h" |
#include "errors.h" |
#include "errstr.h" |
volatile int cli_errno = CL_EOK; |
extern volatile unsigned int cli_quit; |
/* Error printing, translation and handling functions */ |
/* Look up errno in cl_errors and return the corresponding string. |
* Return NULL if not found */ |
static char *err2str(int err) |
{ |
if (NULL != cl_errors[err]) |
return cl_errors[err]; |
return (char *)NULL; |
} |
/* Print an error report signifying errno, which is translated to |
* its corresponding human readable string. If errno > 0, raise the |
* cli_quit int that tells the main program loop to exit immediately */ |
void cli_error(int err, const char *fmt, ...) |
{ |
va_list vargs; |
va_start(vargs, fmt); |
vprintf(fmt, vargs); |
va_end(vargs); |
if (NULL != err2str(err)) |
printf(" (%s)\n", err2str(err)); |
else |
printf(" (Unknown Error %d)\n", err); |
/* If fatal, raise cli_quit so that we try to exit |
* gracefully. This will break the main loop and |
* invoke the destructor */ |
if (err == CL_EFATAL) |
cli_quit = 1; |
return; |
} |
/branches/dd/uspace/app/bdsh/errors.h |
---|
0,0 → 1,22 |
#ifndef ERRORS_H |
#define ERRORS_H |
/* Various error levels */ |
#define CL_EFATAL -1 |
#define CL_EOK 0 |
#define CL_EFAIL 1 |
#define CL_EBUSY 2 |
#define CL_ENOENT 3 |
#define CL_ENOMEM 4 |
#define CL_EPERM 5 |
#define CL_ENOTSUP 6 |
#define CL_EEXEC 7 |
#define CL_EEXISTS 8 |
#define CL_ETOOBIG 9 |
/* Just like 'errno' */ |
extern volatile int cli_errno; |
extern void cli_error(int, const char *, ...); |
#endif |
/branches/dd/uspace/app/bdsh/errstr.h |
---|
0,0 → 1,23 |
#ifndef ERRSTR_H |
#define ERRSTR_H |
/* Simple array to translate error codes to meaningful strings */ |
static char *cl_errors[] = { |
"Success", |
"Failure", |
"Busy", |
"No Such Entry", |
"Not Enough Memory", |
"Permission Denied", |
"Method Not Supported", |
"Bad command or file name", |
"Entry already exists", |
"Object too large", |
NULL |
}; |
static char *err2str(int); |
#endif |
/branches/dd/uspace/app/bdsh/TODO |
---|
0,0 → 1,57 |
This is a very brain dead shell. It needs some love, coffee or perhaps beer. |
Currently, you can't even really call it a shell, its more of a CLI that |
offers some shell like creature comforts. |
This was written in a hurry to provide some means of testing persistent file |
systems in HelenOS. It does its job, its nowhere near complete but it is |
actively developed. If your reading this, its likely that you're looking for |
some functionality that is not yet present. Prior to filing a bug report, |
please make sure that what you want is not on the list below. |
A list of things to do: |
----------------------- |
* rm: add support for recursively removing directories and files therein |
* Port an editor (vim?) |
* Finish cat / cp |
* Support basic redirection (i.e ls > foo.txt) |
* Expand wildcards (i.e. *.txt), don't worry about variables for now |
* Basic scripting |
* Hash previously found commands |
* Improve input, add history / etc (port libedit?) |
* Add wrappers for signal, sigaction to make ports to modules easier |
* Add 'echo' and 'printf' modules. |
Regarding POSIX: |
---------------- |
POSIX is a standard for Unix-like operating systems. HelenOS is (mostly) just |
a kernel at this point with a few userspace programs that facilitate testing |
of the kernel and file systems. |
HelenOS is not a Unix-like operating system. HelenOS is its own thing, a modern |
microkernel OS and many directions are not yet set. |
Please do not e-mail me to point out that modular implementations that resemble |
typical core utilities do not conform to some POSIX standard, these are temporary |
and serve the useful purpose of testing persistent file systems. |
Contributing: |
------------- |
If you feel like doing any of the above to-do items, I am echo@echoreply.us. Please |
e-mail me and let me know your working on something so that I do not unwittingly |
duplicate your efforts. You can also e-mail the HelenOS list directly: |
HelenOS development mailing list <helenos-devel@lists.modry.cz> |
Subscribe here if you like: http://lists.modry.cz/cgi-bin/listinfo/helenos-devel |
Cheers and happy hacking! |
--Tim |
/branches/dd/uspace/app/bdsh/LICENSE |
---|
0,0 → 1,28 |
Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
Redistributions of source code must retain the above copyright notice, this |
list of conditions and the following disclaimer. |
Redistributions in binary form must reproduce the above copyright notice, |
this list of conditions and the following disclaimer in the documentation |
and/or other materials provided with the distribution. |
Neither the name of the original program's authors nor the names of its |
contributors may be used to endorse or promote products derived from this |
software without specific prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
/branches/dd/uspace/app/init/init.c |
---|
27,37 → 27,93 |
*/ |
/** @addtogroup init Init |
* @brief Init process for testing purposes. |
* @brief Init process for user space environment configuration. |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
#include <stdio.h> |
#include <unistd.h> |
#include <ipc/ipc.h> |
#include <vfs/vfs.h> |
#include <bool.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <task.h> |
#include <malloc.h> |
#include <macros.h> |
#include "init.h" |
#include "version.h" |
#include <stdio.h> |
static void test_console(void) |
static bool mount_fs(const char *fstype) |
{ |
int c; |
int rc = -1; |
while (rc < 0) { |
rc = mount(fstype, "/", "initrd", IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
printf(NAME ": Root filesystem mounted\n"); |
break; |
case EBUSY: |
printf(NAME ": Root filesystem already mounted\n"); |
break; |
case ELIMIT: |
printf(NAME ": Unable to mount root filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (%s)\n", fstype); |
return false; |
} |
} |
return true; |
} |
while ((c = getchar()) != EOF) |
putchar(c); |
static void spawn(char *fname) |
{ |
char *argv[2]; |
printf(NAME ": Spawning %s\n", fname); |
argv[0] = fname; |
argv[1] = NULL; |
if (task_spawn(fname, argv)) |
/* Add reasonable delay to avoid |
intermixed klog output */ |
usleep(10000); |
else |
printf(NAME ": Error spawning %s\n", fname); |
} |
int main(int argc, char *argv[]) |
{ |
info_print(); |
if (!mount_fs(STRING(RDFMT))) { |
printf(NAME ": Exiting\n"); |
return -1; |
} |
// FIXME: spawn("/srv/pci"); |
spawn("/srv/fb"); |
spawn("/srv/kbd"); |
spawn("/srv/console"); |
spawn("/srv/fhc"); |
spawn("/srv/obio"); |
console_wait(); |
version_print(); |
printf("This is init\n"); |
test_console(); |
printf("\nBye.\n"); |
spawn("/app/klog"); |
spawn("/app/bdsh"); |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/app/init/version.c |
---|
35,22 → 35,29 |
#include <unistd.h> |
#include <stdio.h> |
#include <macros.h> |
#include "init.h" |
#include "version.h" |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
void info_print(void) |
{ |
printf(NAME ": HelenOS init\n"); |
} |
/** Print version information. */ |
void version_print(void) |
{ |
/branches/dd/uspace/app/init/init.h |
---|
36,7 → 36,7 |
#ifndef __INIT_H__ |
#define __INIT_H__ |
#include "version.h" |
#define NAME "init" |
#endif |
/branches/dd/uspace/app/init/version.h |
---|
36,6 → 36,7 |
#ifndef __VERSION_H__ |
#define __VERSION_H__ |
extern void info_print(void); |
extern void version_print(void); |
#endif |
/branches/dd/uspace/app/init/Makefile |
---|
27,7 → 27,6 |
# |
include ../../../version |
include ../../Makefile.config |
## Setup toolchain |
# |
34,21 → 33,14 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
DEFS += -DRELEASE=$(RELEASE) |
ifdef REVISION |
DEFS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
## Sources |
# |
61,22 → 53,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/tester/console/console1.c |
---|
0,0 → 1,109 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <io/stream.h> |
#include <async.h> |
#include "../tester.h" |
#include <console.h> |
const char *color_name[] = { |
[COLOR_BLACK] = "black", |
[COLOR_BLUE] = "blue", |
[COLOR_GREEN] = "green", |
[COLOR_CYAN] = "cyan", |
[COLOR_RED] = "red", |
[COLOR_MAGENTA] = "magenta", |
[COLOR_YELLOW] = "yellow", |
[COLOR_WHITE] = "white" |
}; |
char * test_console1(bool quiet) |
{ |
int i, j; |
printf("Style test: "); |
console_set_style(STYLE_NORMAL); |
printf("normal "); |
console_set_style(STYLE_EMPHASIS); |
printf("emphasized"); |
console_set_style(STYLE_NORMAL); |
printf(".\n"); |
printf("Foreground color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
console_set_color(i, COLOR_WHITE, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
printf("Background color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
console_set_color(COLOR_WHITE, i, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
} |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
} |
printf("Now let's test RGB colors:\n"); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(0xffffff, i << 16); |
putchar('X'); |
} |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(0xffffff, i << 8); |
putchar('X'); |
} |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(0xffffff, i); |
putchar('X'); |
} |
console_set_color(COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
printf("[press a key]\n"); |
getchar(); |
return NULL; |
} |
/branches/dd/uspace/app/tester/console/console1.def |
---|
0,0 → 1,6 |
{ |
"console1", |
"Console color test", |
&test_console1, |
true |
}, |
/branches/dd/uspace/app/tester/stdio/stdio1.def |
---|
0,0 → 1,6 |
{ |
"stdio1", |
"ANSI C streams reading test", |
&test_stdio1, |
true |
}, |
/branches/dd/uspace/app/tester/stdio/stdio2.def |
---|
0,0 → 1,6 |
{ |
"stdio2", |
"ANSI C streams writing test", |
&test_stdio2, |
true |
}, |
/branches/dd/uspace/app/tester/stdio/stdio2.c |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <errno.h> |
#include "../tester.h" |
char * test_stdio2(bool quiet) |
{ |
FILE *f; |
char *file_name = "/test"; |
size_t n; |
int c; |
printf("Open file '%s' for writing\n", file_name); |
errno = 0; |
f = fopen(file_name, "wt"); |
if (f == NULL) |
return "Failed opening file."; |
fprintf(f, "Integer: %d, string: '%s'\n", 42, "Hello!"); |
if (fclose(f) != 0) |
return "Failed closing file."; |
printf("Open file '%s' for reading\n", file_name); |
f = fopen(file_name, "rt"); |
if (f == NULL) |
return "Failed opening file."; |
printf("File contains:\n"); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
putchar(c); |
} |
if (fclose(f) != 0) |
return "Failed closing file."; |
return NULL; |
} |
/branches/dd/uspace/app/tester/stdio/stdio1.c |
---|
0,0 → 1,85 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <errno.h> |
#include "../tester.h" |
#define BUF_SIZE 32 |
static char buf[BUF_SIZE + 1]; |
char * test_stdio1(bool quiet) |
{ |
FILE *f; |
char *file_name = "/readme"; |
size_t n; |
int c; |
printf("Open file '%s'\n", file_name); |
errno = 0; |
f = fopen(file_name, "rt"); |
if (f == NULL) printf("errno = %d\n", errno); |
if (f == NULL) |
return "Failed opening file."; |
n = fread(buf, 1, BUF_SIZE, f); |
if (ferror(f)) { |
fclose(f); |
return "Failed reading file."; |
} |
printf("Read %d bytes.\n", n); |
buf[n] = '\0'; |
printf("Read string '%s'.\n", buf); |
printf("Seek to beginning.\n"); |
if (fseek(f, 0, SEEK_SET) != 0) { |
fclose(f); |
return "Failed seeking."; |
} |
printf("Read using fgetc().\n"); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
printf("'%c'", c); |
} |
printf("[EOF]\n"); |
printf("Closing.\n"); |
if (fclose(f) != 0) |
return "Failed closing."; |
return NULL; |
} |
/branches/dd/uspace/app/tester/tester.c |
---|
56,7 → 56,11 |
#include "ipc/answer.def" |
#include "ipc/hangup.def" |
#include "devmap/devmap1.def" |
#include "loop/loop1.def" |
#include "vfs/vfs1.def" |
#include "console/console1.def" |
#include "stdio/stdio1.def" |
#include "stdio/stdio2.def" |
{NULL, NULL, NULL} |
}; |
107,8 → 111,17 |
printf("*\t\t\tRun all safe tests\n"); |
} |
int main(void) |
int main(int argc, char **argv) |
{ |
printf("Number of arguments: %d\n", argc); |
if (argv) { |
printf("Arguments:"); |
while (*argv) { |
printf(" '%s'", *argv++); |
} |
printf("\n"); |
} |
while (1) { |
char c; |
test_t *test; |
124,15 → 137,22 |
if (c == 'a') |
break; |
if (c > 'a') |
if (test->name == NULL) |
printf("Unknown test\n\n"); |
else |
run_test(test); |
} else if (c == '*') |
} else if (c == '*') { |
run_safe_tests(); |
else |
} else if (c < 0) { |
/* got EOF */ |
break; |
} else { |
printf("Invalid test\n\n"); |
} |
} |
return 0; |
} |
/** @} |
/branches/dd/uspace/app/tester/loop/loop1.def |
---|
0,0 → 1,6 |
{ |
"loop1", |
"Endless loop", |
&test_loop1, |
false |
}, |
/branches/dd/uspace/app/tester/loop/loop1.c |
---|
0,0 → 1,41 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "../tester.h" |
char *test_loop1(bool quiet) |
{ |
printf("Looping...\n"); |
while (1); |
printf("Survived endless loop?!!\n"); |
return NULL; |
} |
/branches/dd/uspace/app/tester/ipc/send_sync.c |
---|
35,7 → 35,6 |
{ |
int phoneid; |
int res; |
static int msgid = 1; |
char c; |
printf("Select phoneid to send msg: 2-9 (q to skip)\n"); |
/branches/dd/uspace/app/tester/devmap/devmap1.c |
---|
32,7 → 32,7 |
#include <ipc/services.h> |
#include <async.h> |
#include <errno.h> |
#include <../../../srv/devmap/devmap.h> |
#include <ipc/devmap.h> |
#include "../tester.h" |
#include <time.h> |
132,12 → 132,10 |
int phone; |
ipcarg_t callback_phonehash; |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
while (phone < 0) { |
usleep(100000); |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_DRIVER, 0); |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
if (phone < 0) { |
printf("Failed to connect to device mapper\n"); |
return -1; |
} |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
/branches/dd/uspace/app/tester/tester.h |
---|
69,7 → 69,11 |
extern char * test_answer(bool quiet); |
extern char * test_hangup(bool quiet); |
extern char * test_devmap1(bool quiet); |
extern char * test_loop1(bool quiet); |
extern char * test_vfs1(bool quiet); |
extern char * test_console1(bool quiet); |
extern char * test_stdio1(bool quiet); |
extern char * test_stdio2(bool quiet); |
extern test_t tests[]; |
/branches/dd/uspace/app/tester/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
52,7 → 53,11 |
ipc/send_sync.c \ |
ipc/answer.c \ |
ipc/hangup.c \ |
loop/loop1.c \ |
devmap/devmap1.c \ |
console/console1.c \ |
stdio/stdio1.c \ |
stdio/stdio2.c \ |
vfs/vfs1.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
59,22 → 64,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/tester/vfs/vfs1.c |
---|
45,7 → 45,7 |
{ |
int rc; |
rc = mount("tmpfs", "/", "nulldev0"); |
rc = mount("tmpfs", "/", "nulldev0", 0); |
switch (rc) { |
case EOK: |
if (!quiet) |
/branches/dd/uspace/app/tetris/scores.c |
---|
52,7 → 52,7 |
/* #include <err.h> */ |
/* #include <fcntl.h> */ |
/* #include <pwd.h> */ |
#include <stdio.h> |
#include <stdio.h> |
/* #include <stdlib.h> */ |
#include <string.h> |
/* #include <time.h> */ |
/branches/dd/uspace/app/tetris/input.c |
---|
57,7 → 57,8 |
#include "tetris.h" |
#include <async.h> |
#include "../../srv/console/console.h" |
#include <ipc/console.h> |
#include <kbd/kbd.h> |
/* return true iff the given timeval is positive */ |
#define TV_POS(tv) \ |
96,6 → 97,7 |
struct timeval starttv, endtv, *s; |
static ipc_call_t charcall; |
ipcarg_t rc; |
int cons_phone; |
/* |
* Someday, select() will do this for us. |
110,8 → 112,12 |
s = NULL; |
if (!lastchar) { |
if (!getchar_inprog) |
getchar_inprog = async_send_2(1,CONSOLE_GETCHAR,0,0,&charcall); |
again: |
if (!getchar_inprog) { |
cons_phone = get_console_phone(); |
getchar_inprog = async_send_2(cons_phone, |
CONSOLE_GETKEY, 0, 0, &charcall); |
} |
if (!s) |
async_wait_for(getchar_inprog, &rc); |
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) { |
123,7 → 129,10 |
if (rc) { |
stop("end of file, help"); |
} |
lastchar = IPC_GET_ARG1(charcall); |
if (IPC_GET_ARG1(charcall) == KE_RELEASE) |
goto again; |
lastchar = IPC_GET_ARG4(charcall); |
} |
if (tvp) { |
/* since there is input, we may not have timed out */ |
/branches/dd/uspace/app/tetris/screen.c |
---|
50,13 → 50,12 |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <io/stream.h> |
#include <console.h> |
#include <async.h> |
#include "screen.h" |
#include "tetris.h" |
#include "../../srv/console/console.h" |
#include <ipc/console.h> |
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ |
static int curscore; |
73,29 → 72,19 |
putchar(*(s++)); |
} |
static int con_phone; |
static void set_style(int fgcolor, int bgcolor) |
{ |
async_msg_2(con_phone, CONSOLE_SET_STYLE, fgcolor, bgcolor); |
} |
static void start_standout(void) |
{ |
set_style(0xf0f0f0, 0); |
console_set_rgb_color(0xf0f0f0, 0); |
} |
static void resume_normal(void) |
{ |
set_style(0, 0xf0f0f0); |
console_set_rgb_color(0, 0xf0f0f0); |
} |
void clear_screen(void) |
{ |
async_msg_0(con_phone, CONSOLE_CLEAR); |
console_clear(); |
moveto(0, 0); |
} |
107,7 → 96,7 |
{ |
resume_normal(); |
async_msg_0(con_phone, CONSOLE_CLEAR); |
console_clear(); |
curscore = -1; |
memset((char *)curscreen, 0, sizeof(curscreen)); |
} |
118,8 → 107,7 |
void |
scr_init(void) |
{ |
con_phone = get_cons_phone(); |
async_msg_1(con_phone, CONSOLE_CURSOR_VISIBILITY, 0); |
console_cursor_visibility(0); |
resume_normal(); |
scr_clear(); |
} |
126,12 → 114,12 |
void moveto(int r, int c) |
{ |
async_msg_2(con_phone, CONSOLE_GOTO, r, c); |
console_goto(r, c); |
} |
static void fflush(void) |
{ |
async_msg_0(con_phone, CONSOLE_FLUSH); |
console_flush(); |
} |
winsize_t winsize; |
138,8 → 126,7 |
static int get_display_size(winsize_t *ws) |
{ |
return async_req_0_2(con_phone, CONSOLE_GETSIZE, &ws->ws_row, |
&ws->ws_col); |
return console_get_size(&ws->ws_row, &ws->ws_col); |
} |
/* |
/branches/dd/uspace/app/tetris/screen.h |
---|
49,8 → 49,8 |
#include <async.h> |
typedef struct { |
ipcarg_t ws_row; |
ipcarg_t ws_col; |
int ws_row; |
int ws_col; |
} winsize_t; |
extern winsize_t winsize; |
/branches/dd/uspace/app/tetris/Makefile |
---|
1,5 → 1,6 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
10,7 → 11,7 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
18,13 → 19,16 |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/klog/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
47,22 → 48,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/klog/klog.c |
---|
27,9 → 27,9 |
*/ |
/** @addtogroup klog KLog |
* @brief HelenOS KLog |
* @brief HelenOS KLog |
* @{ |
*/ |
*/ |
/** |
* @file |
*/ |
40,46 → 40,56 |
#include <ipc/services.h> |
#include <as.h> |
#include <sysinfo.h> |
#include <io/stream.h> |
#include <errno.h> |
#define NAME "klog" |
#define KLOG_SIZE PAGE_SIZE |
/* Pointer to klog area */ |
static char *klog; |
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
int i; |
async_serialize_start(); |
async_serialize_start(); |
for (i=0; klog[i + IPC_GET_ARG1(*call)] && i < IPC_GET_ARG2(*call); i++) |
putchar(klog[i + IPC_GET_ARG1(*call)]); |
putchar('\n'); |
size_t klog_start = (size_t) IPC_GET_ARG1(*call); |
size_t klog_len = (size_t) IPC_GET_ARG2(*call); |
size_t klog_stored = (size_t) IPC_GET_ARG3(*call); |
size_t i; |
for (i = klog_len - klog_stored; i < klog_len; i++) |
putchar(klog[(klog_start + i) % KLOG_SIZE]); |
async_serialize_end(); |
} |
int main(int argc, char *argv[]) |
{ |
int res; |
void *mapping; |
printf("Kernel console output.\n"); |
console_wait(); |
mapping = as_get_mappable_page(PAGE_SIZE); |
res = ipc_share_in_start_1_0(PHONE_NS, mapping, PAGE_SIZE, |
klog = (char *) as_get_mappable_page(KLOG_SIZE); |
if (klog == NULL) { |
printf(NAME ": Error allocating memory area\n"); |
return -1; |
} |
int res = ipc_share_in_start_1_0(PHONE_NS, (void *) klog, KLOG_SIZE, |
SERVICE_MEM_KLOG); |
if (res) { |
printf("Failed to initialize klog memarea\n"); |
_exit(1); |
if (res != EOK) { |
printf(NAME ": Error initializing memory area\n"); |
return -1; |
} |
klog = mapping; |
int devno = sysinfo_value("klog.devno"); |
int inr = sysinfo_value("klog.inr"); |
int devno = sysinfo_value("klog.devno"); |
if (ipc_register_irq(inr, devno, 0, NULL)) { |
printf("Error registering for klog service.\n"); |
return 0; |
if (ipc_register_irq(inr, devno, 0, NULL) != EOK) { |
printf(NAME ": Error registering klog notifications\n"); |
return -1; |
} |
async_set_interrupt_received(interrupt_received); |
klog_update(); |
async_manager(); |
return 0; |
/branches/dd/uspace/app/trace/trace.c |
---|
0,0 → 1,831 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <ipc/ipc.h> |
#include <fibril.h> |
#include <errno.h> |
#include <udebug.h> |
#include <async.h> |
#include <task.h> |
#include <loader/loader.h> |
#include <libc.h> |
// Temporary: service and method names |
#include "proto.h" |
#include <ipc/services.h> |
#include "../../srv/vfs/vfs.h" |
#include <ipc/console.h> |
#include "syscalls.h" |
#include "ipcp.h" |
#include "errors.h" |
#include "trace.h" |
#define THBUF_SIZE 64 |
uintptr_t thread_hash_buf[THBUF_SIZE]; |
int n_threads; |
int next_thread_id; |
int phoneid; |
int abort_trace; |
uintptr_t thash; |
volatile int paused; |
void thread_trace_start(uintptr_t thread_hash); |
static proto_t *proto_console; |
static task_id_t task_id; |
static loader_t *task_ldr; |
/** Combination of events/data to print. */ |
display_mask_t display_mask; |
static int program_run_fibril(void *arg); |
static void program_run(void) |
{ |
fid_t fid; |
fid = fibril_create(program_run_fibril, NULL); |
if (fid == 0) { |
printf("Error creating fibril\n"); |
exit(1); |
} |
fibril_add_ready(fid); |
} |
static int program_run_fibril(void *arg) |
{ |
int rc; |
/* |
* This must be done in background as it will block until |
* we let the task reply to this call. |
*/ |
rc = loader_run(task_ldr); |
if (rc != 0) { |
printf("Error running program\n"); |
exit(1); |
} |
free(task_ldr); |
task_ldr = NULL; |
printf("program_run_fibril exiting\n"); |
return 0; |
} |
static int connect_task(task_id_t task_id) |
{ |
int rc; |
rc = ipc_connect_kbox(task_id); |
if (rc == ENOTSUP) { |
printf("You do not have userspace debugging support " |
"compiled in the kernel.\n"); |
printf("Compile kernel with 'Support for userspace debuggers' " |
"(CONFIG_UDEBUG) enabled.\n"); |
return rc; |
} |
if (rc < 0) { |
printf("Error connecting\n"); |
printf("ipc_connect_task(%lld) -> %d ", task_id, rc); |
return rc; |
} |
phoneid = rc; |
rc = udebug_begin(phoneid); |
if (rc < 0) { |
printf("udebug_begin() -> %d\n", rc); |
return rc; |
} |
rc = udebug_set_evmask(phoneid, UDEBUG_EM_ALL); |
if (rc < 0) { |
printf("udebug_set_evmask(0x%x) -> %d\n ", UDEBUG_EM_ALL, rc); |
return rc; |
} |
return 0; |
} |
static int get_thread_list(void) |
{ |
int rc; |
size_t tb_copied; |
size_t tb_needed; |
int i; |
rc = udebug_thread_read(phoneid, thread_hash_buf, |
THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed); |
if (rc < 0) { |
printf("udebug_thread_read() -> %d\n", rc); |
return rc; |
} |
n_threads = tb_copied / sizeof(uintptr_t); |
printf("Threads:"); |
for (i = 0; i < n_threads; i++) { |
printf(" [%d] (hash 0x%lx)", 1+i, thread_hash_buf[i]); |
} |
printf("\ntotal of %u threads\n", tb_needed / sizeof(uintptr_t)); |
return 0; |
} |
void val_print(sysarg_t val, val_type_t v_type) |
{ |
switch (v_type) { |
case V_VOID: |
printf("<void>"); |
break; |
case V_INTEGER: |
printf("%ld", val); |
break; |
case V_HASH: |
case V_PTR: |
printf("0x%08lx", val); |
break; |
case V_ERRNO: |
if (val >= -15 && val <= 0) { |
printf("%ld %s (%s)", val, |
err_desc[-val].name, |
err_desc[-val].desc); |
} else { |
printf("%ld", val); |
} |
break; |
case V_INT_ERRNO: |
if (val >= -15 && val < 0) { |
printf("%ld %s (%s)", val, |
err_desc[-val].name, |
err_desc[-val].desc); |
} else { |
printf("%ld", val); |
} |
break; |
case V_CHAR: |
if (val >= 0x20 && val < 0x7f) { |
printf("'%c'", val); |
} else { |
switch (val) { |
case '\a': printf("'\\a'"); break; |
case '\b': printf("'\\b'"); break; |
case '\n': printf("'\\n'"); break; |
case '\r': printf("'\\r'"); break; |
case '\t': printf("'\\t'"); break; |
case '\\': printf("'\\\\'"); break; |
default: printf("'\\x%02lX'", val); break; |
} |
} |
break; |
} |
} |
static void print_sc_retval(sysarg_t retval, val_type_t val_type) |
{ |
printf(" -> "); |
val_print(retval, val_type); |
putchar('\n'); |
} |
static void print_sc_args(sysarg_t *sc_args, int n) |
{ |
int i; |
putchar('('); |
if (n > 0) printf("%ld", sc_args[0]); |
for (i = 1; i < n; i++) { |
printf(", %ld", sc_args[i]); |
} |
putchar(')'); |
} |
static void sc_ipc_call_async_fast(sysarg_t *sc_args, sysarg_t sc_rc) |
{ |
ipc_call_t call; |
ipcarg_t phoneid; |
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY) |
return; |
phoneid = sc_args[0]; |
IPC_SET_METHOD(call, sc_args[1]); |
IPC_SET_ARG1(call, sc_args[2]); |
IPC_SET_ARG2(call, sc_args[3]); |
IPC_SET_ARG3(call, sc_args[4]); |
IPC_SET_ARG4(call, sc_args[5]); |
IPC_SET_ARG5(call, 0); |
ipcp_call_out(phoneid, &call, sc_rc); |
} |
static void sc_ipc_call_async_slow(sysarg_t *sc_args, sysarg_t sc_rc) |
{ |
ipc_call_t call; |
int rc; |
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY) |
return; |
memset(&call, 0, sizeof(call)); |
rc = udebug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args)); |
if (rc >= 0) { |
ipcp_call_out(sc_args[0], &call, sc_rc); |
} |
} |
static void sc_ipc_call_sync_fast(sysarg_t *sc_args) |
{ |
ipc_call_t question, reply; |
int rc; |
int phoneidx; |
// printf("sc_ipc_call_sync_fast()\n"); |
phoneidx = sc_args[0]; |
IPC_SET_METHOD(question, sc_args[1]); |
IPC_SET_ARG1(question, sc_args[2]); |
IPC_SET_ARG2(question, sc_args[3]); |
IPC_SET_ARG3(question, sc_args[4]); |
IPC_SET_ARG4(question, 0); |
IPC_SET_ARG5(question, 0); |
// printf("memset\n"); |
memset(&reply, 0, sizeof(reply)); |
// printf("udebug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n", |
// phoneid, &reply.args, sc_args[5], sizeof(reply.args)); |
rc = udebug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args)); |
// printf("dmr->%d\n", rc); |
if (rc < 0) return; |
// printf("call ipc_call_sync\n"); |
ipcp_call_sync(phoneidx, &question, &reply); |
} |
static void sc_ipc_call_sync_slow(sysarg_t *sc_args) |
{ |
ipc_call_t question, reply; |
int rc; |
memset(&question, 0, sizeof(question)); |
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args)); |
printf("dmr->%d\n", rc); |
if (rc < 0) return; |
memset(&reply, 0, sizeof(reply)); |
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args)); |
printf("dmr->%d\n", rc); |
if (rc < 0) return; |
ipcp_call_sync(sc_args[0], &question, &reply); |
} |
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc) |
{ |
ipc_call_t call; |
int rc; |
if (sc_rc == 0) return; |
memset(&call, 0, sizeof(call)); |
rc = udebug_mem_read(phoneid, &call, sc_args[0], sizeof(call)); |
// printf("udebug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n", |
// phoneid, (int)&call, sc_args[0], sizeof(call), rc); |
if (rc >= 0) { |
ipcp_call_in(&call, sc_rc); |
} |
} |
static void event_syscall_b(unsigned thread_id, uintptr_t thread_hash, |
unsigned sc_id, sysarg_t sc_rc) |
{ |
sysarg_t sc_args[6]; |
int rc; |
/* Read syscall arguments */ |
rc = udebug_args_read(phoneid, thread_hash, sc_args); |
async_serialize_start(); |
// printf("[%d] ", thread_id); |
if (rc < 0) { |
printf("error\n"); |
async_serialize_end(); |
return; |
} |
if ((display_mask & DM_SYSCALL) != 0) { |
/* Print syscall name and arguments */ |
printf("%s", syscall_desc[sc_id].name); |
print_sc_args(sc_args, syscall_desc[sc_id].n_args); |
} |
async_serialize_end(); |
} |
static void event_syscall_e(unsigned thread_id, uintptr_t thread_hash, |
unsigned sc_id, sysarg_t sc_rc) |
{ |
sysarg_t sc_args[6]; |
int rv_type; |
int rc; |
/* Read syscall arguments */ |
rc = udebug_args_read(phoneid, thread_hash, sc_args); |
async_serialize_start(); |
// printf("[%d] ", thread_id); |
if (rc < 0) { |
printf("error\n"); |
async_serialize_end(); |
return; |
} |
if ((display_mask & DM_SYSCALL) != 0) { |
/* Print syscall return value */ |
rv_type = syscall_desc[sc_id].rv_type; |
print_sc_retval(sc_rc, rv_type); |
} |
switch (sc_id) { |
case SYS_IPC_CALL_ASYNC_FAST: |
sc_ipc_call_async_fast(sc_args, sc_rc); |
break; |
case SYS_IPC_CALL_ASYNC_SLOW: |
sc_ipc_call_async_slow(sc_args, sc_rc); |
break; |
case SYS_IPC_CALL_SYNC_FAST: |
sc_ipc_call_sync_fast(sc_args); |
break; |
case SYS_IPC_CALL_SYNC_SLOW: |
sc_ipc_call_sync_slow(sc_args); |
break; |
case SYS_IPC_WAIT: |
sc_ipc_wait(sc_args, sc_rc); |
break; |
default: |
break; |
} |
async_serialize_end(); |
} |
static void event_thread_b(uintptr_t hash) |
{ |
async_serialize_start(); |
printf("New thread, hash 0x%lx\n", hash); |
async_serialize_end(); |
thread_trace_start(hash); |
} |
static int trace_loop(void *thread_hash_arg) |
{ |
int rc; |
unsigned ev_type; |
uintptr_t thread_hash; |
unsigned thread_id; |
sysarg_t val0, val1; |
thread_hash = (uintptr_t)thread_hash_arg; |
thread_id = next_thread_id++; |
printf("Start tracing thread [%d] (hash 0x%lx).\n", thread_id, thread_hash); |
while (!abort_trace) { |
if (paused) { |
printf("Press R to resume (and be patient).\n"); |
while (paused) { |
usleep(1000000); |
fibril_yield(); |
printf("."); |
} |
printf("Resumed\n"); |
} |
/* Run thread until an event occurs */ |
rc = udebug_go(phoneid, thread_hash, |
&ev_type, &val0, &val1); |
// printf("rc = %d, ev_type=%d\n", rc, ev_type); |
if (ev_type == UDEBUG_EVENT_FINISHED) { |
/* Done tracing this thread */ |
break; |
} |
if (rc >= 0) { |
switch (ev_type) { |
case UDEBUG_EVENT_SYSCALL_B: |
event_syscall_b(thread_id, thread_hash, val0, (int)val1); |
break; |
case UDEBUG_EVENT_SYSCALL_E: |
event_syscall_e(thread_id, thread_hash, val0, (int)val1); |
break; |
case UDEBUG_EVENT_STOP: |
printf("Stop event\n"); |
break; |
case UDEBUG_EVENT_THREAD_B: |
event_thread_b(val0); |
break; |
case UDEBUG_EVENT_THREAD_E: |
printf("Thread 0x%lx exited.\n", val0); |
abort_trace = 1; |
break; |
default: |
printf("Unknown event type %d.\n", ev_type); |
break; |
} |
} |
} |
printf("Finished tracing thread [%d].\n", thread_id); |
return 0; |
} |
void thread_trace_start(uintptr_t thread_hash) |
{ |
fid_t fid; |
thash = thread_hash; |
fid = fibril_create(trace_loop, (void *)thread_hash); |
if (fid == 0) { |
printf("Warning: Failed creating fibril\n"); |
} |
fibril_add_ready(fid); |
} |
static loader_t *preload_task(const char *path, char *const argv[], |
task_id_t *task_id) |
{ |
loader_t *ldr; |
int rc; |
/* Spawn a program loader */ |
ldr = loader_connect(); |
if (ldr == NULL) |
return 0; |
/* Get task ID. */ |
rc = loader_get_task_id(ldr, task_id); |
if (rc != EOK) |
goto error; |
/* Send program pathname */ |
rc = loader_set_pathname(ldr, path); |
if (rc != EOK) |
goto error; |
/* Send arguments */ |
rc = loader_set_args(ldr, argv); |
if (rc != EOK) |
goto error; |
/* Load the program. */ |
rc = loader_load_program(ldr); |
if (rc != EOK) |
goto error; |
/* Success */ |
return ldr; |
/* Error exit */ |
error: |
loader_abort(ldr); |
free(ldr); |
return NULL; |
} |
static void trace_task(task_id_t task_id) |
{ |
int i; |
int rc; |
int c; |
ipcp_init(); |
/* |
* User apps now typically have console on phone 3. |
* (Phones 1 and 2 are used by the loader). |
*/ |
ipcp_connection_set(3, 0, proto_console); |
rc = get_thread_list(); |
if (rc < 0) { |
printf("Failed to get thread list (error %d)\n", rc); |
return; |
} |
abort_trace = 0; |
for (i = 0; i < n_threads; i++) { |
thread_trace_start(thread_hash_buf[i]); |
} |
while(1) { |
c = getchar(); |
if (c == 'q') break; |
if (c == 'p') { |
printf("Pause...\n"); |
paused = 1; |
rc = udebug_stop(phoneid, thash); |
printf("stop -> %d\n", rc); |
} |
if (c == 'r') { |
paused = 0; |
printf("Resume...\n"); |
} |
} |
printf("\nTerminate debugging session...\n"); |
abort_trace = 1; |
udebug_end(phoneid); |
ipc_hangup(phoneid); |
ipcp_cleanup(); |
printf("Done\n"); |
return; |
} |
static void main_init(void) |
{ |
proto_t *p; |
oper_t *o; |
val_type_t arg_def[OPER_MAX_ARGS] = { |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER |
}; |
val_type_t resp_def[OPER_MAX_ARGS] = { |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER |
}; |
next_thread_id = 1; |
paused = 0; |
proto_init(); |
p = proto_new("vfs"); |
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_READ, o); |
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_WRITE, o); |
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_TRUNCATE, o); |
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MOUNT, o); |
/* o = oper_new("unmount", 0, arg_def); |
proto_add_oper(p, VFS_UNMOUNT, o);*/ |
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_OPEN, o); |
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_CLOSE, o); |
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_SEEK, o); |
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MKDIR, o); |
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_UNLINK, o); |
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_RENAME, o); |
proto_register(SERVICE_VFS, p); |
p = proto_new("console"); |
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER; |
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR; |
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def); |
proto_add_oper(p, CONSOLE_GETKEY, o); |
arg_def[0] = V_CHAR; |
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_PUTCHAR, o); |
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CLEAR, o); |
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER; |
o = oper_new("goto", 2, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_GOTO, o); |
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER; |
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def); |
proto_add_oper(p, CONSOLE_GETSIZE, o); |
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_FLUSH, o); |
arg_def[0] = V_INTEGER; |
o = oper_new("set_style", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_STYLE, o); |
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER; arg_def[2] = V_INTEGER; |
o = oper_new("set_color", 3, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_COLOR, o); |
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER; |
o = oper_new("set_rgb_color", 2, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_SET_RGB_COLOR, o); |
o = oper_new("cursor_visibility", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CURSOR_VISIBILITY, o); |
proto_console = p; |
proto_register(SERVICE_CONSOLE, p); |
} |
static void print_syntax() |
{ |
printf("Syntax:\n"); |
printf("\ttrace [+<events>] <executable> [<arg1> [...]]\n"); |
printf("or\ttrace [+<events>] -t <task_id>\n"); |
printf("Events: (default is +tp)\n"); |
printf("\n"); |
printf("\tt ... Thread creation and termination\n"); |
printf("\ts ... System calls\n"); |
printf("\ti ... Low-level IPC\n"); |
printf("\tp ... Protocol level\n"); |
printf("\n"); |
printf("Examples:\n"); |
printf("\ttrace +s /app/tetris\n"); |
printf("\ttrace +tsip -t 12\n"); |
} |
static display_mask_t parse_display_mask(char *text) |
{ |
display_mask_t dm; |
char *c; |
c = text; |
while (*c) { |
switch (*c) { |
case 't': dm = dm | DM_THREAD; break; |
case 's': dm = dm | DM_SYSCALL; break; |
case 'i': dm = dm | DM_IPC; break; |
case 'p': dm = dm | DM_SYSTEM | DM_USER; break; |
default: |
printf("Unexpected event type '%c'.\n", *c); |
exit(1); |
} |
++c; |
} |
return dm; |
} |
static int parse_args(int argc, char *argv[]) |
{ |
char *arg; |
char *err_p; |
task_id = 0; |
--argc; ++argv; |
while (argc > 0) { |
arg = *argv; |
if (arg[0] == '+') { |
display_mask = parse_display_mask(&arg[1]); |
} else if (arg[0] == '-') { |
if (arg[1] == 't') { |
/* Trace an already running task */ |
--argc; ++argv; |
task_id = strtol(*argv, &err_p, 10); |
task_ldr = NULL; |
if (*err_p) { |
printf("Task ID syntax error\n"); |
print_syntax(); |
return -1; |
} |
} else { |
printf("Uknown option '%s'\n", arg[0]); |
print_syntax(); |
return -1; |
} |
} else { |
break; |
} |
--argc; ++argv; |
} |
if (task_id != 0) { |
if (argc == 0) return 0; |
printf("Extra arguments\n"); |
print_syntax(); |
return -1; |
} |
if (argc < 1) { |
printf("Missing argument\n"); |
print_syntax(); |
return -1; |
} |
/* Preload the specified program file. */ |
printf("Spawning '%s' with arguments:\n", *argv); |
{ |
char **cp = argv; |
while (*cp) printf("'%s'\n", *cp++); |
} |
task_ldr = preload_task(*argv, argv, &task_id); |
return 0; |
} |
int main(int argc, char *argv[]) |
{ |
int rc; |
printf("System Call / IPC Tracer\n"); |
printf("Controls: Q - Quit, P - Pause, R - Resume\n"); |
display_mask = DM_THREAD | DM_SYSTEM | DM_USER; |
if (parse_args(argc, argv) < 0) |
return 1; |
main_init(); |
rc = connect_task(task_id); |
if (rc < 0) { |
printf("Failed connecting to task %lld.\n", task_id); |
return 1; |
} |
printf("Connected to task %lld.\n", task_id); |
if (task_ldr != NULL) { |
program_run(); |
} |
trace_task(task_id); |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/app/trace/Makefile |
---|
0,0 → 1,79 |
# |
# Copyright (c) 2005 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = trace |
SOURCES = trace.c \ |
syscalls.c \ |
ipcp.c \ |
ipc_desc.c \ |
proto.c \ |
errors.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/app/trace/syscalls.c |
---|
0,0 → 1,81 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <kernel/syscall/syscall.h> |
#include "syscalls.h" |
#include "trace.h" |
const sc_desc_t syscall_desc[] = { |
[SYS_KLOG] ={ "klog", 3, V_INT_ERRNO }, |
[SYS_TLS_SET] = { "tls_set", 1, V_ERRNO }, |
[SYS_THREAD_CREATE] = { "thread_create", 3, V_ERRNO }, |
[SYS_THREAD_EXIT] = { "thread_exit", 1, V_ERRNO }, |
[SYS_THREAD_GET_ID] = { "thread_get_id", 1, V_ERRNO }, |
[SYS_TASK_GET_ID] = { "task_get_id", 1, V_ERRNO }, |
[SYS_FUTEX_SLEEP] = { "futex_sleep_timeout", 3, V_ERRNO }, |
[SYS_FUTEX_WAKEUP] = { "futex_wakeup", 1, V_ERRNO }, |
[SYS_AS_AREA_CREATE] = { "as_area_create", 3, V_ERRNO }, |
[SYS_AS_AREA_RESIZE] = { "as_area_resize", 3, V_ERRNO }, |
[SYS_AS_AREA_DESTROY] = { "as_area_destroy", 1, V_ERRNO }, |
[SYS_IPC_CALL_SYNC_FAST] = { "ipc_call_sync_fast", 6, V_ERRNO }, |
[SYS_IPC_CALL_SYNC_SLOW] = { "ipc_call_sync_slow", 3, V_ERRNO }, |
[SYS_IPC_CALL_ASYNC_FAST] = { "ipc_call_async_fast", 6, V_HASH }, |
[SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 2, V_HASH }, |
[SYS_IPC_ANSWER_FAST] = { "ipc_answer_fast", 6, V_ERRNO }, |
[SYS_IPC_ANSWER_SLOW] = { "ipc_answer_slow", 2, V_ERRNO }, |
[SYS_IPC_FORWARD_FAST] = { "ipc_forward_fast", 6, V_ERRNO }, |
[SYS_IPC_FORWARD_SLOW] = { "ipc_forward_slow", 3, V_ERRNO }, |
[SYS_IPC_WAIT] = { "ipc_wait_for_call", 3, V_HASH }, |
[SYS_IPC_HANGUP] = { "ipc_hangup", 1, V_ERRNO }, |
[SYS_IPC_REGISTER_IRQ] = { "ipc_register_irq", 4, V_ERRNO }, |
[SYS_IPC_UNREGISTER_IRQ] = { "ipc_unregister_irq", 2, V_ERRNO }, |
[SYS_CAP_GRANT] = { "cap_grant", 2, V_ERRNO }, |
[SYS_CAP_REVOKE] = { "cap_revoke", 2, V_ERRNO }, |
[SYS_PHYSMEM_MAP] = { "physmem_map", 4, V_ERRNO }, |
[SYS_IOSPACE_ENABLE] = { "iospace_enable", 1, V_ERRNO }, |
[SYS_PREEMPT_CONTROL] = { "preempt_control", 1, V_ERRNO }, |
[SYS_SYSINFO_VALID] = { "sysinfo_valid", 2, V_HASH }, |
[SYS_SYSINFO_VALUE] = { "sysinfo_value", 2, V_HASH }, |
[SYS_DEBUG_ENABLE_CONSOLE] = { "debug_enable_console", 0, V_ERRNO }, |
[SYS_IPC_CONNECT_KBOX] = { "ipc_connect_kbox", 1, V_ERRNO } |
}; |
/** @} |
*/ |
/branches/dd/uspace/app/trace/ipcp.c |
---|
0,0 → 1,375 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <libadt/hash_table.h> |
#include "ipc_desc.h" |
#include "proto.h" |
#include "trace.h" |
#include "ipcp.h" |
#define IPCP_CALLID_SYNC 0 |
typedef struct { |
ipcarg_t phone_hash; |
ipc_call_t question; |
oper_t *oper; |
ipc_callid_t call_hash; |
link_t link; |
} pending_call_t; |
typedef struct { |
int server; |
proto_t *proto; |
} connection_t; |
#define MAX_PHONE 64 |
connection_t connections[MAX_PHONE]; |
int have_conn[MAX_PHONE]; |
#define PCALL_TABLE_CHAINS 32 |
hash_table_t pending_calls; |
/* |
* Pseudo-protocols |
*/ |
proto_t *proto_system; /**< Protocol describing system IPC methods. */ |
proto_t *proto_unknown; /**< Protocol with no known methods. */ |
static hash_index_t pending_call_hash(unsigned long key[]); |
static int pending_call_compare(unsigned long key[], hash_count_t keys, |
link_t *item); |
static void pending_call_remove_callback(link_t *item); |
hash_table_operations_t pending_call_ops = { |
.hash = pending_call_hash, |
.compare = pending_call_compare, |
.remove_callback = pending_call_remove_callback |
}; |
static hash_index_t pending_call_hash(unsigned long key[]) |
{ |
// printf("pending_call_hash\n"); |
return key[0] % PCALL_TABLE_CHAINS; |
} |
static int pending_call_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
pending_call_t *hs; |
// printf("pending_call_compare\n"); |
hs = hash_table_get_instance(item, pending_call_t, link); |
// FIXME: this will fail if sizeof(long) < sizeof(void *). |
return key[0] == hs->call_hash; |
} |
static void pending_call_remove_callback(link_t *item) |
{ |
// printf("pending_call_remove_callback\n"); |
} |
void ipcp_connection_set(int phone, int server, proto_t *proto) |
{ |
if (phone <0 || phone >= MAX_PHONE) return; |
connections[phone].server = server; |
connections[phone].proto = proto; |
have_conn[phone] = 1; |
} |
void ipcp_connection_clear(int phone) |
{ |
have_conn[phone] = 0; |
connections[phone].server = 0; |
connections[phone].proto = NULL; |
} |
static void ipc_m_print(proto_t *proto, ipcarg_t method) |
{ |
oper_t *oper; |
/* Try system methods first */ |
oper = proto_get_oper(proto_system, method); |
if (oper == NULL && proto != NULL) { |
/* Not a system method, try the user protocol. */ |
oper = proto_get_oper(proto, method); |
} |
if (oper != NULL) { |
printf("%s (%ld)", oper->name, method); |
return; |
} |
printf("%ld", method); |
} |
void ipcp_init(void) |
{ |
ipc_m_desc_t *desc; |
oper_t *oper; |
val_type_t arg_def[OPER_MAX_ARGS] = { |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER, |
V_INTEGER |
}; |
/* |
* Create a pseudo-protocol 'unknown' that has no known methods. |
*/ |
proto_unknown = proto_new("unknown"); |
/* |
* Create a pseudo-protocol 'system' defining names of system IPC |
* methods. |
*/ |
proto_system = proto_new("system"); |
desc = ipc_methods; |
while (desc->number != 0) { |
oper = oper_new(desc->name, OPER_MAX_ARGS, arg_def, V_INTEGER, |
OPER_MAX_ARGS, arg_def); |
proto_add_oper(proto_system, desc->number, oper); |
++desc; |
} |
hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops); |
} |
void ipcp_cleanup(void) |
{ |
proto_delete(proto_system); |
hash_table_destroy(&pending_calls); |
} |
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash) |
{ |
pending_call_t *pcall; |
proto_t *proto; |
unsigned long key[1]; |
oper_t *oper; |
ipcarg_t *args; |
int i; |
if (have_conn[phone]) proto = connections[phone].proto; |
else proto = NULL; |
args = call->args; |
if ((display_mask & DM_IPC) != 0) { |
printf("Call ID: 0x%lx, phone: %d, proto: %s, method: ", hash, |
phone, (proto ? proto->name : "n/a")); |
ipc_m_print(proto, IPC_GET_METHOD(*call)); |
printf(" args: (%lu, %lu, %lu, %lu, %lu)\n", args[1], args[2], |
args[3], args[4], args[5]); |
} |
if ((display_mask & DM_USER) != 0) { |
if (proto != NULL) { |
oper = proto_get_oper(proto, IPC_GET_METHOD(*call)); |
} else { |
oper = NULL; |
} |
if (oper != NULL) { |
printf("%s(%d).%s", (proto ? proto->name : "n/a"), |
phone, (oper ? oper->name : "unknown")); |
putchar('('); |
for (i = 1; i <= oper->argc; ++i) { |
if (i > 1) printf(", "); |
val_print(args[i], oper->arg_type[i - 1]); |
} |
putchar(')'); |
if (oper->rv_type == V_VOID && oper->respc == 0) { |
/* |
* No response data (typically the task will |
* not be interested in the response). |
* We will not display response. |
*/ |
putchar('.'); |
} |
putchar('\n'); |
} |
} else { |
oper = NULL; |
} |
/* Store call in hash table for response matching */ |
pcall = malloc(sizeof(pending_call_t)); |
pcall->phone_hash = phone; |
pcall->question = *call; |
pcall->call_hash = hash; |
pcall->oper = oper; |
key[0] = hash; |
hash_table_insert(&pending_calls, key, &pcall->link); |
} |
static void parse_answer(ipc_callid_t hash, pending_call_t *pcall, |
ipc_call_t *answer) |
{ |
ipcarg_t phone; |
ipcarg_t method; |
ipcarg_t service; |
ipcarg_t retval; |
proto_t *proto; |
int cphone; |
ipcarg_t *resp; |
oper_t *oper; |
int i; |
// printf("parse_answer\n"); |
phone = pcall->phone_hash; |
method = IPC_GET_METHOD(pcall->question); |
retval = IPC_GET_RETVAL(*answer); |
resp = answer->args; |
if ((display_mask & DM_IPC) != 0) { |
printf("Response to 0x%lx: retval=%ld, args = (%lu, %lu, %lu, %lu, %lu)\n", |
hash, retval, IPC_GET_ARG1(*answer), |
IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer), |
IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer)); |
} |
if ((display_mask & DM_USER) != 0) { |
oper = pcall->oper; |
if (oper != NULL && (oper->rv_type != V_VOID || oper->respc > 0)) { |
printf("->"); |
if (oper->rv_type != V_VOID) { |
putchar(' '); |
val_print(retval, oper->rv_type); |
} |
if (oper->respc > 0) { |
putchar(' '); |
putchar('('); |
for (i = 1; i <= oper->respc; ++i) { |
if (i > 1) printf(", "); |
val_print(resp[i], oper->resp_type[i - 1]); |
} |
putchar(')'); |
} |
putchar('\n'); |
} |
} |
if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) { |
/* Connected to a service (through NS) */ |
service = IPC_GET_ARG1(pcall->question); |
proto = proto_get_by_srv(service); |
if (proto == NULL) proto = proto_unknown; |
cphone = IPC_GET_ARG5(*answer); |
if ((display_mask & DM_SYSTEM) != 0) { |
printf("Registering connection (phone %d, protocol: %s)\n", cphone, |
proto->name); |
} |
ipcp_connection_set(cphone, 0, proto); |
} |
} |
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash) |
{ |
link_t *item; |
pending_call_t *pcall; |
unsigned long key[1]; |
// printf("ipcp_call_in()\n"); |
if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) { |
/* Not a response */ |
if ((display_mask & DM_IPC) != 0) { |
printf("Not a response (hash 0x%lx)\n", hash); |
} |
return; |
} |
hash = hash & ~IPC_CALLID_ANSWERED; |
key[0] = hash; |
item = hash_table_find(&pending_calls, key); |
if (item == NULL) return; // No matching question found |
/* |
* Response matched to question. |
*/ |
pcall = hash_table_get_instance(item, pending_call_t, link); |
hash_table_remove(&pending_calls, key, 1); |
parse_answer(hash, pcall, call); |
free(pcall); |
} |
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer) |
{ |
ipcp_call_out(phone, call, IPCP_CALLID_SYNC); |
ipcp_call_in(answer, IPCP_CALLID_SYNC); |
} |
void ipcp_hangup(int phone, int rc) |
{ |
if ((display_mask & DM_SYSTEM) != 0) { |
printf("Hang phone %d up -> %d\n", phone, rc); |
ipcp_connection_clear(phone); |
} |
} |
/** @} |
*/ |
/branches/dd/uspace/app/trace/trace.h |
---|
0,0 → 1,71 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef TRACE_H_ |
#define TRACE_H_ |
#include <sys/types.h> |
/** |
* Classes of events that can be displayed. Can be or-ed together. |
*/ |
typedef enum { |
DM_THREAD = 1, /**< Thread creation and termination events */ |
DM_SYSCALL = 2, /**< System calls */ |
DM_IPC = 4, /**< Low-level IPC */ |
DM_SYSTEM = 8, /**< Sysipc protocol */ |
DM_USER = 16 /**< User IPC protocols */ |
} display_mask_t; |
typedef enum { |
V_VOID, |
V_INTEGER, |
V_PTR, |
V_HASH, |
V_ERRNO, |
V_INT_ERRNO, |
V_CHAR |
} val_type_t; |
/** Combination of events to print. */ |
extern display_mask_t display_mask; |
void val_print(sysarg_t val, val_type_t v_type); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/syscalls.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef SYSCALLS_H_ |
#define SYSCALLS_H_ |
#include "trace.h" |
typedef struct { |
char *name; |
int n_args; |
val_type_t rv_type; |
} sc_desc_t; |
extern const sc_desc_t syscall_desc[]; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/proto.c |
---|
0,0 → 1,236 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <ipc/ipc.h> |
#include <libadt/hash_table.h> |
#include "trace.h" |
#include "proto.h" |
#define SRV_PROTO_TABLE_CHAINS 32 |
#define METHOD_OPER_TABLE_CHAINS 32 |
hash_table_t srv_proto; |
typedef struct { |
int srv; |
proto_t *proto; |
link_t link; |
} srv_proto_t; |
typedef struct { |
ipcarg_t method; |
oper_t *oper; |
link_t link; |
} method_oper_t; |
static hash_index_t srv_proto_hash(unsigned long key[]); |
static int srv_proto_compare(unsigned long key[], hash_count_t keys, |
link_t *item); |
static void srv_proto_remove_callback(link_t *item); |
hash_table_operations_t srv_proto_ops = { |
.hash = srv_proto_hash, |
.compare = srv_proto_compare, |
.remove_callback = srv_proto_remove_callback |
}; |
static hash_index_t method_oper_hash(unsigned long key[]); |
static int method_oper_compare(unsigned long key[], hash_count_t keys, |
link_t *item); |
static void method_oper_remove_callback(link_t *item); |
hash_table_operations_t method_oper_ops = { |
.hash = method_oper_hash, |
.compare = method_oper_compare, |
.remove_callback = method_oper_remove_callback |
}; |
static hash_index_t srv_proto_hash(unsigned long key[]) |
{ |
return key[0] % SRV_PROTO_TABLE_CHAINS; |
} |
static int srv_proto_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
srv_proto_t *sp; |
sp = hash_table_get_instance(item, srv_proto_t, link); |
return key[0] == sp->srv; |
} |
static void srv_proto_remove_callback(link_t *item) |
{ |
} |
static hash_index_t method_oper_hash(unsigned long key[]) |
{ |
return key[0] % METHOD_OPER_TABLE_CHAINS; |
} |
static int method_oper_compare(unsigned long key[], hash_count_t keys, |
link_t *item) |
{ |
method_oper_t *mo; |
mo = hash_table_get_instance(item, method_oper_t, link); |
return key[0] == mo->method; |
} |
static void method_oper_remove_callback(link_t *item) |
{ |
} |
void proto_init(void) |
{ |
hash_table_create(&srv_proto, SRV_PROTO_TABLE_CHAINS, 1, |
&srv_proto_ops); |
} |
void proto_cleanup(void) |
{ |
hash_table_destroy(&srv_proto); |
} |
void proto_register(int srv, proto_t *proto) |
{ |
srv_proto_t *sp; |
unsigned long key; |
sp = malloc(sizeof(srv_proto_t)); |
sp->srv = srv; |
sp->proto = proto; |
key = srv; |
hash_table_insert(&srv_proto, &key, &sp->link); |
} |
proto_t *proto_get_by_srv(int srv) |
{ |
unsigned long key; |
link_t *item; |
srv_proto_t *sp; |
key = srv; |
item = hash_table_find(&srv_proto, &key); |
if (item == NULL) return NULL; |
sp = hash_table_get_instance(item, srv_proto_t, link); |
return sp->proto; |
} |
static void proto_struct_init(proto_t *proto, char *name) |
{ |
proto->name = name; |
hash_table_create(&proto->method_oper, SRV_PROTO_TABLE_CHAINS, 1, |
&method_oper_ops); |
} |
proto_t *proto_new(char *name) |
{ |
proto_t *p; |
p = malloc(sizeof(proto_t)); |
proto_struct_init(p, name); |
return p; |
} |
void proto_delete(proto_t *proto) |
{ |
free(proto); |
} |
void proto_add_oper(proto_t *proto, int method, oper_t *oper) |
{ |
method_oper_t *mo; |
unsigned long key; |
mo = malloc(sizeof(method_oper_t)); |
mo->method = method; |
mo->oper = oper; |
key = method; |
hash_table_insert(&proto->method_oper, &key, &mo->link); |
} |
oper_t *proto_get_oper(proto_t *proto, int method) |
{ |
unsigned long key; |
link_t *item; |
method_oper_t *mo; |
key = method; |
item = hash_table_find(&proto->method_oper, &key); |
if (item == NULL) return NULL; |
mo = hash_table_get_instance(item, method_oper_t, link); |
return mo->oper; |
} |
static void oper_struct_init(oper_t *oper, char *name) |
{ |
oper->name = name; |
} |
oper_t *oper_new(char *name, int argc, val_type_t *arg_types, |
val_type_t rv_type, int respc, val_type_t *resp_types) |
{ |
oper_t *o; |
int i; |
o = malloc(sizeof(oper_t)); |
oper_struct_init(o, name); |
o->argc = argc; |
for (i = 0; i < argc; i++) |
o->arg_type[i] = arg_types[i]; |
o->rv_type = rv_type; |
o->respc = respc; |
for (i = 0; i < respc; i++) |
o->resp_type[i] = resp_types[i]; |
return o; |
} |
/** @} |
*/ |
/branches/dd/uspace/app/trace/proto.h |
---|
0,0 → 1,85 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef PROTO_H_ |
#define PROTO_H_ |
#include <libadt/hash_table.h> |
#include <ipc/ipc.h> |
#include "trace.h" |
#define OPER_MAX_ARGS (IPC_CALL_LEN - 1) |
typedef struct { |
char *name; |
int argc; |
val_type_t arg_type[OPER_MAX_ARGS]; |
val_type_t rv_type; |
int respc; |
val_type_t resp_type[OPER_MAX_ARGS]; |
} oper_t; |
typedef struct { |
/** Protocol name */ |
char *name; |
/** Maps method number to operation */ |
hash_table_t method_oper; |
} proto_t; |
/* Maps service number to protocol */ |
extern hash_table_t srv_proto; |
void proto_init(void); |
void proto_cleanup(void); |
void proto_register(int srv, proto_t *proto); |
proto_t *proto_get_by_srv(int srv); |
proto_t *proto_new(char *name); |
void proto_delete(proto_t *proto); |
void proto_add_oper(proto_t *proto, int method, oper_t *oper); |
oper_t *proto_get_oper(proto_t *proto, int method); |
oper_t *oper_new(char *name, int argc, val_type_t *arg_types, |
val_type_t rv_type, int respc, val_type_t *resp_types); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/ipc_desc.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef IPC_DESC_H_ |
#define IPC_DESC_H_ |
typedef struct { |
int number; |
char *name; |
} ipc_m_desc_t; |
extern ipc_m_desc_t ipc_methods[]; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/ipcp.h |
---|
0,0 → 1,55 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef IPCP_H_ |
#define IPCP_H_ |
#include <ipc/ipc.h> |
#include "proto.h" |
void ipcp_init(void); |
void ipcp_cleanup(void); |
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash); |
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer); |
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash); |
void ipcp_hangup(int phone, int rc); |
void ipcp_connection_set(int phone, int server, proto_t *proto); |
void ipcp_connection_clear(int phone); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/errors.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#ifndef ERRORS_H_ |
#define ERRORS_H_ |
typedef struct { |
char *name; /**< Error value name (Exx) */ |
char *desc; /**< Error description */ |
} err_desc_t; |
extern const err_desc_t err_desc[]; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/app/trace/ipc_desc.c |
---|
0,0 → 1,58 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <stdlib.h> |
#include <ipc/ipc.h> |
#include "ipc_desc.h" |
ipc_m_desc_t ipc_methods[] = { |
/* System methods */ |
{ IPC_M_CONNECT_TO_ME, "CONNECT_TO_ME" }, |
{ IPC_M_CONNECT_ME_TO, "CONNECT_ME_TO" }, |
{ IPC_M_PHONE_HUNGUP, "PHONE_HUNGUP" }, |
{ IPC_M_SHARE_OUT, "SHARE_OUT" }, |
{ IPC_M_SHARE_IN, "SHARE_IN" }, |
{ IPC_M_DATA_WRITE, "DATA_WRITE" }, |
{ IPC_M_DATA_READ, "DATA_READ" }, |
{ IPC_M_DEBUG_ALL, "DEBUG_ALL" }, |
/* Well-known methods */ |
{ IPC_M_PING, "PING" }, |
/* Terminating entry */ |
{ 0, NULL } |
}; |
/** @} |
*/ |
/branches/dd/uspace/app/trace/errors.c |
---|
0,0 → 1,61 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup trace |
* @{ |
*/ |
/** @file |
*/ |
#include <errno.h> |
#include "errors.h" |
const err_desc_t err_desc[] = { |
[-EOK] = { "EOK", "No error" }, |
[-ENOENT] = { "ENOENT", "No such entry" }, |
[-ENOMEM] = { "ENOMEM", "Not enough memory" }, |
[-ELIMIT] = { "ELIMIT", "Limit exceeded" }, |
[-EREFUSED] = { "EREFUSED", "Connection refused" }, |
[-EFORWARD] = { "EFORWARD", "Forward error" }, |
[-EPERM] = { "EPERM", "Permission denied" }, |
[-EHANGUP] = { "EHANGUP", "Answerbox closed connection" }, |
[-EEXISTS] = { "EEXISTS", "Entry already exists" }, |
[-EBADMEM] = { "EBADMEM", "Bad memory pointer" }, |
[-ENOTSUP] = { "ENOTSUP", "Not supported" }, |
[-EADDRNOTAVAIL] = { "EADDRNOTAVAIL", "Address not available." }, |
[-ETIMEOUT] = { "ETIMEOUT", "Timeout expired" }, |
[-EINVAL] = { "EINVAL", "Invalid value" }, |
[-EBUSY] = { "EBUSY", "Resource is busy" }, |
[-EOVERFLOW] = { "EOVERFLOW", "The result does not fit its size." } |
}; |
/** @} |
*/ |
/branches/dd/uspace/dist/readme |
---|
0,0 → 1,0 |
Lorem ipsum. |
/branches/dd/uspace/lib/libfs/libfs.c |
---|
160,7 → 160,7 |
len = 0; |
while ((next <= last) && (ops->plb_get_char(next) != '/')) { |
if (len + 1 == NAME_MAX) { |
/* comopnent length overflow */ |
/* component length overflow */ |
ipc_answer_0(rid, ENAMETOOLONG); |
goto out; |
} |
191,17 → 191,20 |
} |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
nodep = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, |
index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
int rc; |
rc = ops->link(cur, nodep, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) { |
(void)ops->destroy( |
nodep); |
} |
ipc_answer_0(rid, ENOSPC); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
262,14 → 265,17 |
void *nodep; |
if (lflag & L_CREATE) |
nodep = ops->create(lflag); |
nodep = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
if (!ops->link(cur, nodep, component)) { |
int rc; |
rc = ops->link(cur, nodep, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) |
(void)ops->destroy(nodep); |
ipc_answer_0(rid, ENOSPC); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
/branches/dd/uspace/lib/libfs/libfs.h |
---|
45,9 → 45,9 |
void * (* match)(void *, const char *); |
void * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(void *); |
void * (* create)(int); |
void * (* create)(dev_handle_t, int); |
int (* destroy)(void *); |
bool (* link)(void *, void *, const char *); |
int (* link)(void *, void *, const char *); |
int (* unlink)(void *, void *); |
fs_index_t (* index_get)(void *); |
size_t (* size_get)(void *); |
/branches/dd/uspace/lib/libfs/Makefile |
---|
31,6 → 31,7 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
57,7 → 58,7 |
find . -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
libfs.a: depend $(OBJECTS) |
$(AR) rc libfs.a $(OBJECTS) |
/branches/dd/uspace/lib/softfloat/Makefile |
---|
30,25 → 30,26 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS +=-Iinclude -Iarch/$(ARCH)/include/ |
CFLAGS +=-Iinclude -Iarch/$(UARCH)/include/ |
## Sources |
# |
GENERIC_SOURCES = \ |
generic/add.c \ |
generic/common.c \ |
generic/comparison.c \ |
generic/conversion.c \ |
generic/div.c \ |
generic/mul.c \ |
generic/other.c \ |
generic/softfloat.c \ |
GENERIC_SOURCES = \ |
generic/add.c \ |
generic/common.c \ |
generic/comparison.c \ |
generic/conversion.c \ |
generic/div.c \ |
generic/mul.c \ |
generic/other.c \ |
generic/softfloat.c \ |
generic/sub.c |
ARCH_SOURCES = |
66,7 → 67,7 |
find generic/ -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libsoftfloat.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libsoftfloat.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
/branches/dd/uspace/lib/softfloat/arch/ppc64/include/functions.h |
---|
File deleted |
/branches/dd/uspace/lib/libblock/libblock.c |
---|
0,0 → 1,494 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libblock |
* @{ |
*/ |
/** |
* @file |
* @brief |
*/ |
#include "libblock.h" |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/rd/rd.h" |
#include <ipc/devmap.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <sys/mman.h> |
#include <async.h> |
#include <ipc/ipc.h> |
#include <as.h> |
#include <assert.h> |
#include <futex.h> |
#include <libadt/list.h> |
#include <libadt/hash_table.h> |
/** Lock protecting the device connection list */ |
static futex_t dcl_lock = FUTEX_INITIALIZER; |
/** Device connection list head. */ |
static LIST_INITIALIZE(dcl_head); |
#define CACHE_BUCKETS_LOG2 10 |
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) |
typedef struct { |
futex_t lock; |
size_t block_size; /**< Block size. */ |
unsigned block_count; /**< Total number of blocks. */ |
hash_table_t block_hash; |
link_t free_head; |
} cache_t; |
typedef struct { |
link_t link; |
int dev_handle; |
int dev_phone; |
void *com_area; |
size_t com_size; |
void *bb_buf; |
off_t bb_off; |
size_t bb_size; |
cache_t *cache; |
} devcon_t; |
static devcon_t *devcon_search(dev_handle_t dev_handle) |
{ |
link_t *cur; |
futex_down(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *devcon = list_get_instance(cur, devcon_t, link); |
if (devcon->dev_handle == dev_handle) { |
futex_up(&dcl_lock); |
return devcon; |
} |
} |
futex_up(&dcl_lock); |
return NULL; |
} |
static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area, |
size_t com_size) |
{ |
link_t *cur; |
devcon_t *devcon; |
devcon = malloc(sizeof(devcon_t)); |
if (!devcon) |
return ENOMEM; |
link_initialize(&devcon->link); |
devcon->dev_handle = dev_handle; |
devcon->dev_phone = dev_phone; |
devcon->com_area = com_area; |
devcon->com_size = com_size; |
devcon->bb_buf = NULL; |
devcon->bb_off = 0; |
devcon->bb_size = 0; |
devcon->cache = NULL; |
futex_down(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *d = list_get_instance(cur, devcon_t, link); |
if (d->dev_handle == dev_handle) { |
futex_up(&dcl_lock); |
free(devcon); |
return EEXIST; |
} |
} |
list_append(&devcon->link, &dcl_head); |
futex_up(&dcl_lock); |
return EOK; |
} |
static void devcon_remove(devcon_t *devcon) |
{ |
futex_down(&dcl_lock); |
list_remove(&devcon->link); |
futex_up(&dcl_lock); |
} |
int block_init(dev_handle_t dev_handle, size_t com_size) |
{ |
int rc; |
int dev_phone; |
void *com_area; |
com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE, |
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!com_area) { |
return ENOMEM; |
} |
dev_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
if (dev_phone < 0) { |
munmap(com_area, com_size); |
return dev_phone; |
} |
rc = ipc_share_out_start(dev_phone, com_area, |
AS_AREA_READ | AS_AREA_WRITE); |
if (rc != EOK) { |
munmap(com_area, com_size); |
ipc_hangup(dev_phone); |
return rc; |
} |
rc = devcon_add(dev_handle, dev_phone, com_area, com_size); |
if (rc != EOK) { |
munmap(com_area, com_size); |
ipc_hangup(dev_phone); |
return rc; |
} |
return EOK; |
} |
void block_fini(dev_handle_t dev_handle) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
devcon_remove(devcon); |
if (devcon->bb_buf) |
free(devcon->bb_buf); |
if (devcon->cache) { |
hash_table_destroy(&devcon->cache->block_hash); |
free(devcon->cache); |
} |
munmap(devcon->com_area, devcon->com_size); |
ipc_hangup(devcon->dev_phone); |
free(devcon); |
} |
int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size) |
{ |
void *bb_buf; |
int rc; |
devcon_t *devcon = devcon_search(dev_handle); |
if (!devcon) |
return ENOENT; |
if (devcon->bb_buf) |
return EEXIST; |
bb_buf = malloc(size); |
if (!bb_buf) |
return ENOMEM; |
off_t bufpos = 0; |
size_t buflen = 0; |
rc = block_read(dev_handle, &bufpos, &buflen, &off, |
bb_buf, size, size); |
if (rc != EOK) { |
free(bb_buf); |
return rc; |
} |
devcon->bb_buf = bb_buf; |
devcon->bb_off = off; |
devcon->bb_size = size; |
return EOK; |
} |
void *block_bb_get(dev_handle_t dev_handle) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
return devcon->bb_buf; |
} |
static hash_index_t cache_hash(unsigned long *key) |
{ |
return *key & (CACHE_BUCKETS - 1); |
} |
static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) |
{ |
block_t *b = hash_table_get_instance(item, block_t, hash_link); |
return b->boff == *key; |
} |
static void cache_remove_callback(link_t *item) |
{ |
} |
static hash_table_operations_t cache_ops = { |
.hash = cache_hash, |
.compare = cache_compare, |
.remove_callback = cache_remove_callback |
}; |
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
cache_t *cache; |
if (!devcon) |
return ENOENT; |
if (devcon->cache) |
return EEXIST; |
cache = malloc(sizeof(cache_t)); |
if (!cache) |
return ENOMEM; |
futex_initialize(&cache->lock, 1); |
list_initialize(&cache->free_head); |
cache->block_size = size; |
cache->block_count = blocks; |
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, |
&cache_ops)) { |
free(cache); |
return ENOMEM; |
} |
devcon->cache = cache; |
return EOK; |
} |
static bool cache_can_grow(cache_t *cache) |
{ |
return true; |
} |
static void block_initialize(block_t *b) |
{ |
futex_initialize(&b->lock, 1); |
b->refcnt = 1; |
b->dirty = false; |
rwlock_initialize(&b->contents_lock); |
link_initialize(&b->free_link); |
link_initialize(&b->hash_link); |
} |
/** Instantiate a block in memory and get a reference to it. |
* |
* @param dev_handle Device handle of the block device. |
* @param boff Block offset. |
* @param flags If BLOCK_FLAGS_NOREAD is specified, block_get() |
* will not read the contents of the block from the |
* device. |
* |
* @return Block structure. |
*/ |
block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags) |
{ |
devcon_t *devcon; |
cache_t *cache; |
block_t *b; |
link_t *l; |
unsigned long key = boff; |
devcon = devcon_search(dev_handle); |
assert(devcon); |
assert(devcon->cache); |
cache = devcon->cache; |
futex_down(&cache->lock); |
l = hash_table_find(&cache->block_hash, &key); |
if (l) { |
/* |
* We found the block in the cache. |
*/ |
b = hash_table_get_instance(l, block_t, hash_link); |
futex_down(&b->lock); |
if (b->refcnt++ == 0) |
list_remove(&b->free_link); |
futex_up(&b->lock); |
futex_up(&cache->lock); |
} else { |
/* |
* The block was not found in the cache. |
*/ |
int rc; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = boff * cache->block_size; |
bool sync = false; |
if (cache_can_grow(cache)) { |
/* |
* We can grow the cache by allocating new blocks. |
* Should the allocation fail, we fail over and try to |
* recycle a block from the cache. |
*/ |
b = malloc(sizeof(block_t)); |
if (!b) |
goto recycle; |
b->data = malloc(cache->block_size); |
if (!b->data) { |
free(b); |
goto recycle; |
} |
} else { |
/* |
* Try to recycle a block from the free list. |
*/ |
unsigned long temp_key; |
recycle: |
assert(!list_empty(&cache->free_head)); |
l = cache->free_head.next; |
list_remove(l); |
b = hash_table_get_instance(l, block_t, hash_link); |
sync = b->dirty; |
temp_key = b->boff; |
hash_table_remove(&cache->block_hash, &temp_key, 1); |
} |
block_initialize(b); |
b->dev_handle = dev_handle; |
b->size = cache->block_size; |
b->boff = boff; |
hash_table_insert(&cache->block_hash, &key, &b->hash_link); |
/* |
* Lock the block before releasing the cache lock. Thus we don't |
* kill concurent operations on the cache while doing I/O on the |
* block. |
*/ |
futex_down(&b->lock); |
futex_up(&cache->lock); |
if (sync) { |
/* |
* The block is dirty and needs to be written back to |
* the device before we can read in the new contents. |
*/ |
abort(); /* TODO: block_write() */ |
} |
if (!(flags & BLOCK_FLAGS_NOREAD)) { |
/* |
* The block contains old or no data. We need to read |
* the new contents from the device. |
*/ |
rc = block_read(dev_handle, &bufpos, &buflen, &pos, |
b->data, cache->block_size, cache->block_size); |
assert(rc == EOK); |
} |
futex_up(&b->lock); |
} |
return b; |
} |
/** Release a reference to a block. |
* |
* If the last reference is dropped, the block is put on the free list. |
* |
* @param block Block of which a reference is to be released. |
*/ |
void block_put(block_t *block) |
{ |
devcon_t *devcon = devcon_search(block->dev_handle); |
cache_t *cache; |
assert(devcon); |
assert(devcon->cache); |
cache = devcon->cache; |
futex_down(&cache->lock); |
futex_down(&block->lock); |
if (!--block->refcnt) { |
/* |
* Last reference to the block was dropped, put the block on the |
* free list. |
*/ |
list_append(&block->free_link, &cache->free_head); |
} |
futex_up(&block->lock); |
futex_up(&cache->lock); |
} |
/** Read data from a block device. |
* |
* @param dev_handle Device handle of the block device. |
* @param bufpos Pointer to the first unread valid offset within the |
* communication buffer. |
* @param buflen Pointer to the number of unread bytes that are ready in |
* the communication buffer. |
* @param pos Device position to be read. |
* @param dst Destination buffer. |
* @param size Size of the destination buffer. |
* @param block_size Block size to be used for the transfer. |
* |
* @return EOK on success or a negative return code on failure. |
*/ |
int |
block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst, |
size_t size, size_t block_size) |
{ |
off_t offset = 0; |
size_t left = size; |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
while (left > 0) { |
size_t rd; |
if (*bufpos + left < *buflen) |
rd = left; |
else |
rd = *buflen - *bufpos; |
if (rd > 0) { |
/* |
* Copy the contents of the communication buffer to the |
* destination buffer. |
*/ |
memcpy(dst + offset, devcon->com_area + *bufpos, rd); |
offset += rd; |
*bufpos += rd; |
*pos += rd; |
left -= rd; |
} |
if (*bufpos == *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : retval); |
*bufpos = 0; |
*buflen = block_size; |
} |
} |
return EOK; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libblock/Makefile |
---|
0,0 → 1,67 |
# |
# Copyright (c) 2005 Martin Decky |
# Copyright (c) 2007 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Common compiler flags |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -Iinclude |
## Sources |
# |
SOURCES = \ |
libblock.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend |
all: libblock.a |
-include Makefile.depend |
clean: |
-rm -f libblock.a Makefile.depend |
find . -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
libblock.a: depend $(OBJECTS) |
$(AR) rc libblock.a $(OBJECTS) |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/lib/libblock/libblock.h |
---|
0,0 → 1,105 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libblock |
* @{ |
*/ |
/** |
* @file |
*/ |
#ifndef LIBBLOCK_LIBBLOCK_H_ |
#define LIBBLOCK_LIBBLOCK_H_ |
#include <stdint.h> |
#include "../../srv/vfs/vfs.h" |
#include <futex.h> |
#include <rwlock.h> |
#include <libadt/hash_table.h> |
#include <libadt/list.h> |
/* |
* Flags that can be used with block_get(). |
*/ |
/** |
* This macro is a symbolic value for situations where no special flags are |
* needed. |
*/ |
#define BLOCK_FLAGS_NONE 0 |
/** |
* When the client of block_get() intends to overwrite the current contents of |
* the block, this flag is used to avoid the unnecessary read. |
*/ |
#define BLOCK_FLAGS_NOREAD 1 |
typedef unsigned bn_t; /**< Block number type. */ |
typedef struct block { |
/** Futex protecting the reference count. */ |
futex_t lock; |
/** Number of references to the block_t structure. */ |
unsigned refcnt; |
/** If true, the block needs to be written back to the block device. */ |
bool dirty; |
/** Readers / Writer lock protecting the contents of the block. */ |
rwlock_t contents_lock; |
/** Handle of the device where the block resides. */ |
dev_handle_t dev_handle; |
/** Block offset on the block device. Counted in 'size'-byte blocks. */ |
bn_t boff; |
/** Size of the block. */ |
size_t size; |
/** Link for placing the block into the free block list. */ |
link_t free_link; |
/** Link for placing the block into the block hash table. */ |
link_t hash_link; |
/** Buffer with the block data. */ |
void *data; |
} block_t; |
extern int block_init(dev_handle_t, size_t); |
extern void block_fini(dev_handle_t); |
extern int block_bb_read(dev_handle_t, off_t, size_t); |
extern void *block_bb_get(dev_handle_t); |
extern int block_cache_init(dev_handle_t, size_t, unsigned); |
extern block_t *block_get(dev_handle_t, bn_t, int flags); |
extern void block_put(block_t *); |
extern int block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/softint/Makefile |
---|
30,6 → 30,7 |
# |
LIBC_PREFIX = ../libc |
## Setup toolchain |
# |
58,7 → 59,7 |
find generic/ -name '*.o' -follow -exec rm \{\} \; |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEMD_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libsoftint.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libsoftint.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
/branches/dd/uspace/lib/libc/include/align.h |
---|
35,21 → 35,28 |
#ifndef LIBC_ALIGN_H_ |
#define LIBC_ALIGN_H_ |
/** Align to the nearest lower address. |
/** Align to the nearest lower address which is a power of two. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1)) |
/** Align to the nearest higher address. |
/** Align to the nearest higher address which is a power of two. |
* |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
* @param s Address or size to be aligned. |
* @param a Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(s, a) ((long)((s) + ((a) - 1)) & ~((long) (a) - 1)) |
/** Round up to the nearest higher boundary. |
* |
* @param n Number to be aligned. |
* @param b Boundary, arbitrary unsigned number. |
*/ |
#define ROUND_UP(n, b) (((n) / (b) + ((n) % (b) != 0)) * (b)) |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/byteorder.h |
---|
52,6 → 52,14 |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
62,6 → 70,14 |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n) |
#endif |
static inline uint64_t uint64_t_byteorder_swap(uint64_t n) |
/branches/dd/uspace/lib/libc/include/ddi.h |
---|
37,9 → 37,10 |
#include <task.h> |
extern int physmem_map(void *pf, void *vp, unsigned long pages, int flags); |
extern int iospace_enable(task_id_t id, void *ioaddr, unsigned long size); |
extern int preemption_control(int enable); |
extern int physmem_map(void *, void *, unsigned long, int); |
extern int iospace_enable(task_id_t, void *, unsigned long); |
extern int preemption_control(int); |
extern int pio_enable(void *, size_t, void **); |
#endif |
/branches/dd/uspace/lib/libc/include/console.h |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_CONSOLE_H_ |
#define LIBC_CONSOLE_H_ |
#include <console/style.h> |
#include <console/color.h> |
extern void console_clear(void); |
extern void console_goto(int, int); |
extern void console_flush(void); |
extern int console_get_size(int *, int *); |
extern void console_set_style(int); |
extern void console_set_color(int, int, int); |
extern void console_set_rgb_color(int, int); |
extern void console_cursor_visibility(int); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/getopt.h |
---|
0,0 → 1,71 |
/* $NetBSD: getopt.h,v 1.10.6.1 2008/05/18 12:30:09 yamt Exp $ */ |
/*- |
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
* All rights reserved. |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* by Dieter Baron and Thomas Klausner. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */ |
#ifndef _GETOPT_H_ |
#define _GETOPT_H_ |
#include <unistd.h> |
/* |
* Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions |
*/ |
#define no_argument 0 |
#define required_argument 1 |
#define optional_argument 2 |
struct option { |
/* name of long option */ |
const char *name; |
/* |
* one of no_argument, required_argument, and optional_argument: |
* whether option takes an argument |
*/ |
int has_arg; |
/* if not NULL, set *flag to val when option found */ |
int *flag; |
/* if flag not NULL, value to set *flag to; else return value */ |
int val; |
}; |
/* HelenOS Port - These need to be exposed for legacy getopt() */ |
extern char *optarg; |
extern int optind, opterr, optopt; |
extern int optreset; |
int getopt_long(int, char * const *, const char *, |
const struct option *, int *); |
/* HelenOS Port : Expose legacy getopt() */ |
int getopt(int, char * const [], const char *); |
#endif /* !_GETOPT_H_ */ |
/branches/dd/uspace/lib/libc/include/as.h |
---|
42,6 → 42,7 |
extern void *as_area_create(void *address, size_t size, int flags); |
extern int as_area_resize(void *address, size_t size, int flags); |
extern int as_area_change_flags(void *address, int flags); |
extern int as_area_destroy(void *address); |
extern void *set_maxheapsize(size_t mhs); |
extern void * as_get_mappable_page(size_t sz); |
/branches/dd/uspace/lib/libc/include/string.h |
---|
35,18 → 35,12 |
#ifndef LIBC_STRING_H_ |
#define LIBC_STRING_H_ |
#include <mem.h> |
#include <sys/types.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
extern int bcmp(const char *, const char *, size_t); |
extern int strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
extern char *strcpy(char *, const char *); |
extern char *strncpy(char *, const char *, size_t); |
55,6 → 49,8 |
extern size_t strlen(const char *); |
extern char *strdup(const char *); |
extern char *strchr(const char *, int); |
extern char *strrchr(const char *, int); |
61,6 → 57,9 |
extern long int strtol(const char *, char **, int); |
extern unsigned long strtoul(const char *, char **, int); |
extern char * strtok_r(char *, const char *, char **); |
extern char * strtok(char *, const char *); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/vfs/vfs.h |
---|
35,8 → 35,13 |
#ifndef LIBC_VFS_H_ |
#define LIBC_VFS_H_ |
extern int mount(const char *, const char *, const char *); |
#include <sys/types.h> |
extern char *absolutize(const char *, size_t *); |
extern int mount(const char *, const char *, const char *, |
const unsigned int flags); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/syscall.h |
---|
32,15 → 32,28 |
/** |
* @file |
* @brief Syscall function declaration for architectures that don't |
* inline syscalls. |
* inline syscalls or architectures that handle syscalls |
* according to the number of arguments. |
*/ |
#ifndef LIBC_SYSCALL_H_ |
#define LIBC_SYSCALL_H_ |
#ifndef LIBARCH_SYSCALL_GENERIC |
#error "You can't include this file directly." |
#endif |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall |
#define __syscall1 __syscall |
#define __syscall2 __syscall |
#define __syscall3 __syscall |
#define __syscall4 __syscall |
#define __syscall5 __syscall |
#define __syscall6 __syscall |
extern sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2, |
const sysarg_t p3, const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, |
const syscall_t id); |
/branches/dd/uspace/lib/libc/include/async.h |
---|
76,7 → 76,7 |
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \ |
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), (dataptr)) |
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr); |
extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
86,8 → 86,8 |
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, |
suseconds_t timeout); |
fid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid, |
ipc_call_t *call, void (*cthread)(ipc_callid_t,ipc_call_t *)); |
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *)); |
void async_usleep(suseconds_t timeout); |
void async_create_manager(void); |
void async_destroy_manager(void); |
118,7 → 118,7 |
/* |
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros |
* are in the form async_req_m_n(), where m is the number of payload arguments |
* and n is the number of return arguments. The macros decidce between the fast |
* and n is the number of return arguments. The macros decide between the fast |
* and slow verion based on m. |
*/ |
#define async_req_0_0(phoneid, method) \ |
/branches/dd/uspace/lib/libc/include/stdio.h |
---|
49,27 → 49,65 |
int n; \ |
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \ |
if (n > 0) \ |
(void) __SYSCALL3(SYS_IO, 1, (sysarg_t) buf, strlen(buf)); \ |
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, strlen(buf)); \ |
} |
typedef struct { |
/** Underlying file descriptor. */ |
int fd; |
/** Error indicator. */ |
int error; |
/** End-of-file indicator. */ |
int eof; |
} FILE; |
extern FILE *stdin, *stdout, *stderr; |
extern int getchar(void); |
extern int puts(const char * str); |
extern int putchar(int c); |
extern int puts(const char *); |
extern int putchar(int); |
extern int printf(const char *fmt, ...); |
extern int sprintf(char *str, const char *fmt, ...); |
extern int snprintf(char *str, size_t size, const char *fmt, ...); |
extern int printf(const char *, ...); |
extern int asprintf(char **, const char *, ...); |
extern int sprintf(char *, const char *, ...); |
extern int snprintf(char *, size_t , const char *, ...); |
extern int vprintf(const char *fmt, va_list ap); |
extern int vsprintf(char *str, const char *fmt, va_list ap); |
extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); |
extern int vprintf(const char *, va_list); |
extern int vsprintf(char *, const char *, va_list); |
extern int vsnprintf(char *, size_t, const char *, va_list); |
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__) |
extern int rename(const char *, const char *); |
extern FILE *fopen(const char *, const char *); |
extern int fclose(FILE *); |
extern size_t fread(void *, size_t, size_t, FILE *); |
extern size_t fwrite(const void *, size_t, size_t, FILE *); |
extern int feof(FILE *); |
extern int ferror(FILE *); |
extern void clearerr(FILE *); |
extern int fgetc(FILE *); |
extern int fputc(int, FILE *); |
extern int fputs(const char *, FILE *); |
extern int fprintf(FILE *, const char *, ...); |
extern int vfprintf(FILE *, const char *, va_list); |
#define getc fgetc |
#define putc fputc |
extern int fseek(FILE *, long, int); |
#ifndef SEEK_SET |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#endif |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/task.h |
---|
40,6 → 40,8 |
typedef uint64_t task_id_t; |
extern task_id_t task_get_id(void); |
extern int task_set_name(const char *name); |
extern task_id_t task_spawn(const char *path, char *const argv[]); |
#endif |
/branches/dd/uspace/lib/libc/include/unistd.h |
---|
44,9 → 44,11 |
#define getpagesize() (PAGE_SIZE) |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#ifndef SEEK_SET |
#define SEEK_SET 0 |
#define SEEK_CUR 1 |
#define SEEK_END 2 |
#endif |
extern ssize_t write(int, const void *, size_t); |
extern ssize_t read(int, void *, size_t); |
/branches/dd/uspace/lib/libc/include/libc.h |
---|
39,17 → 39,22 |
#include <kernel/syscall/syscall.h> |
#include <libarch/syscall.h> |
#define __SYSCALL0(id) __syscall(0, 0, 0, 0, 0, 0, id) |
#define __SYSCALL1(id, p1) __syscall(p1, 0, 0, 0, 0, 0, id) |
#define __SYSCALL2(id, p1, p2) __syscall(p1, p2, 0, 0, 0, 0, id) |
#define __SYSCALL3(id, p1, p2, p3) __syscall(p1, p2, p3, 0, 0, 0, id) |
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall(p1, p2, p3, p4, 0, 0, id) |
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall(p1, p2, p3, p4, p5, 0, id) |
#define __SYSCALL0(id) \ |
__syscall0(0, 0, 0, 0, 0, 0, id) |
#define __SYSCALL1(id, p1) \ |
__syscall1(p1, 0, 0, 0, 0, 0, id) |
#define __SYSCALL2(id, p1, p2) \ |
__syscall2(p1, p2, 0, 0, 0, 0, id) |
#define __SYSCALL3(id, p1, p2, p3) \ |
__syscall3(p1, p2, p3, 0, 0, 0, id) |
#define __SYSCALL4(id, p1, p2, p3, p4) \ |
__syscall4(p1, p2, p3, p4, 0, 0, id) |
#define __SYSCALL5(id, p1, p2, p3, p4, p5) \ |
__syscall5(p1, p2, p3, p4, p5, 0, id) |
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \ |
__syscall(p1, p2, p3, p4, p5, p6,id) |
__syscall6(p1, p2, p3, p4, p5, p6, id) |
extern void __main(void); |
extern void __io_init(void); |
extern void __main(void *pcb_ptr); |
extern void __exit(void); |
#endif |
/branches/dd/uspace/lib/libc/include/kbd/keycode.h |
---|
0,0 → 1,220 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_KBD_KEYCODE_H_ |
#define LIBC_KBD_KEYCODE_H_ |
/** Keycode definitions. |
* |
* A keycode identifies a key by its position on the keyboard, rather |
* than by its label. For human readability, key positions are noted |
* with the key label on a keyboard with US layout. This label has |
* nothing to do with the character, that the key produces |
* -- this is determined by the keymap. |
* |
* The keyboard model reflects a standard PC keyboard layout. |
* Non-standard keyboards need to be mapped to this model in some |
* logical way. Scancodes are mapped to keycodes with a scanmap. |
* |
* For easier mapping to the model and to emphasize the nature of keycodes, |
* they really are organized here by position, rather than by label. |
*/ |
enum keycode { |
/* Main block row 1 */ |
KC_BACKTICK = 1, |
KC_1, |
KC_2, |
KC_3, |
KC_4, |
KC_5, |
KC_6, |
KC_7, |
KC_8, |
KC_9, |
KC_0, |
KC_MINUS, |
KC_EQUALS, |
KC_BACKSPACE, |
/* Main block row 2 */ |
KC_TAB, |
KC_Q, |
KC_W, |
KC_E, |
KC_R, |
KC_T, |
KC_Y, |
KC_U, |
KC_I, |
KC_O, |
KC_P, |
KC_LBRACKET, |
KC_RBRACKET, |
/* Main block row 3 */ |
KC_CAPS_LOCK, |
KC_A, |
KC_S, |
KC_D, |
KC_F, |
KC_G, |
KC_H, |
KC_J, |
KC_K, |
KC_L, |
KC_SEMICOLON, |
KC_QUOTE, |
KC_BACKSLASH, |
KC_ENTER, |
/* Main block row 4 */ |
KC_LSHIFT, |
KC_Z, |
KC_X, |
KC_C, |
KC_V, |
KC_B, |
KC_N, |
KC_M, |
KC_COMMA, |
KC_PERIOD, |
KC_SLASH, |
KC_RSHIFT, |
/* Main block row 5 */ |
KC_LCTRL, |
KC_LALT, |
KC_SPACE, |
KC_RALT, |
KC_RCTRL, |
/* Function keys block */ |
KC_ESCAPE, |
KC_F1, |
KC_F2, |
KC_F3, |
KC_F4, |
KC_F5, |
KC_F6, |
KC_F7, |
KC_F8, |
KC_F9, |
KC_F10, |
KC_F11, |
KC_F12, |
KC_PRTSCR, |
KC_SCROLL_LOCK, |
KC_PAUSE, |
/* Cursor keys block */ |
KC_INSERT, |
KC_HOME, |
KC_PAGE_UP, |
KC_DELETE, |
KC_END, |
KC_PAGE_DOWN, |
KC_UP, |
KC_LEFT, |
KC_DOWN, |
KC_RIGHT, |
/* Numeric block */ |
KC_NUM_LOCK, |
KC_NSLASH, |
KC_NTIMES, |
KC_NMINUS, |
KC_NPLUS, |
KC_NENTER, |
KC_N7, |
KC_N8, |
KC_N9, |
KC_N4, |
KC_N5, |
KC_N6, |
KC_N1, |
KC_N2, |
KC_N3, |
KC_N0, |
KC_NPERIOD |
} keycode_t; |
enum keymod { |
KM_LSHIFT = 0x001, |
KM_RSHIFT = 0x002, |
KM_LCTRL = 0x004, |
KM_RCTRL = 0x008, |
KM_LALT = 0x010, |
KM_RALT = 0x020, |
KM_CAPS_LOCK = 0x040, |
KM_NUM_LOCK = 0x080, |
KM_SCROLL_LOCK = 0x100, |
KM_SHIFT = KM_LSHIFT | KM_RSHIFT, |
KM_CTRL = KM_LCTRL | KM_RCTRL, |
KM_ALT = KM_LALT | KM_RALT |
} keymod_t; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/kbd/kbd.h |
---|
0,0 → 1,63 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_KBD_H_ |
#define LIBC_KBD_H_ |
typedef enum kbd_ev_type { |
KE_PRESS, |
KE_RELEASE |
} kbd_ev_type_t; |
/** Keyboard event structure. */ |
typedef struct { |
/** Press or release event. */ |
kbd_ev_type_t type; |
/** Keycode of the key that was pressed or released. */ |
unsigned int key; |
/** Bitmask of modifiers held. */ |
unsigned int mods; |
/** The character that was generated or '\0' for none. */ |
char c; |
} kbd_event_t; |
extern int kbd_get_event(kbd_event_t *); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/udebug.h |
---|
0,0 → 1,58 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_UDEBUG_H_ |
#define LIBC_UDEBUG_H_ |
#include <kernel/udebug/udebug.h> |
#include <sys/types.h> |
#include <libarch/types.h> |
typedef sysarg_t thash_t; |
int udebug_begin(int phoneid); |
int udebug_end(int phoneid); |
int udebug_set_evmask(int phoneid, udebug_evmask_t mask); |
int udebug_thread_read(int phoneid, void *buffer, size_t n, |
size_t *copied, size_t *needed); |
int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n); |
int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer); |
int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type, |
sysarg_t *val0, sysarg_t *val1); |
int udebug_stop(int phoneid, thash_t tid); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/console/color.h |
---|
0,0 → 1,55 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_CONSOLE_COLOR_H_ |
#define LIBC_CONSOLE_COLOR_H_ |
enum console_color { |
COLOR_BLACK = 0, |
COLOR_BLUE = 1, |
COLOR_GREEN = 2, |
COLOR_CYAN = 3, |
COLOR_RED = 4, |
COLOR_MAGENTA = 5, |
COLOR_YELLOW = 6, |
COLOR_WHITE = 7, |
CATTR_BRIGHT = 8, |
CATTR_BLINK = 8 |
}; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/console/style.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_CONSOLE_STYLE_H_ |
#define LIBC_CONSOLE_STYLE_H_ |
enum console_style { |
STYLE_NORMAL = 0, |
STYLE_EMPHASIS = 1 |
}; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/mem.h |
---|
0,0 → 1,51 |
/* |
* Copyright (c) 2005 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_MEM_H_ |
#define LIBC_MEM_H_ |
#include <sys/types.h> |
#define bzero(ptr, len) memset((ptr), 0, (len)) |
extern void * memset(void *, int, size_t); |
extern void * memcpy(void *, const void *, size_t); |
extern void * memmove(void *, const void *, size_t); |
extern int bcmp(const char *, const char *, size_t); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/lib/libc/include/loader/loader.h |
---|
0,0 → 1,60 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** @file |
* @brief Program loader interface. |
*/ |
#ifndef LIBC_LOADER_H_ |
#define LIBC_LOADER_H_ |
#include <task.h> |
/** Abstraction of a loader connection */ |
typedef struct { |
/** ID of the phone connected to the loader. */ |
int phone_id; |
} loader_t; |
extern int loader_spawn(const char *); |
extern loader_t *loader_connect(void); |
extern int loader_get_task_id(loader_t *, task_id_t *); |
extern int loader_set_pathname(loader_t *, const char *); |
extern int loader_set_args(loader_t *, char *const []); |
extern int loader_load_program(loader_t *); |
extern int loader_run(loader_t *); |
extern void loader_abort(loader_t *); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/lib/libc/include/loader/pcb.h |
---|
0,0 → 1,75 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** @file |
* @brief Program Control Block interface. |
*/ |
#ifndef LIBC_PCB_H_ |
#define LIBC_PCB_H_ |
#include <sys/types.h> |
typedef void (*entry_point_t)(void); |
/** Program Control Block. |
* |
* Holds pointers to data passed from the program loader to the program |
* and/or to the dynamic linker. This includes the program entry point, |
* arguments, environment variables etc. |
*/ |
typedef struct { |
/** Program entry point. */ |
entry_point_t entry; |
/** Number of command-line arguments. */ |
int argc; |
/** Command-line arguments. */ |
char **argv; |
/* |
* ELF-specific data. |
*/ |
/** Pointer to ELF dynamic section of the program. */ |
void *dynamic; |
} pcb_t; |
/** |
* A pointer to the program control block. Having received the PCB pointer, |
* the C library startup code stores it here for later use. |
*/ |
extern pcb_t *__pcb; |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/lib/libc/include/io/stream.h |
---|
39,14 → 39,16 |
#define EMFILE -17 |
extern void open_stdin(void); |
extern void open_stdout(void); |
extern void open_console(void); |
extern void close_console(void); |
extern void klog_update(void); |
extern ssize_t read_stdin(void *, size_t); |
extern ssize_t write_stdout(const void *, size_t); |
extern ssize_t write_stderr(const void *, size_t); |
extern int get_cons_phone(void); |
extern int get_console_phone(void); |
extern void console_wait(void); |
#endif |
/branches/dd/uspace/lib/libc/include/smc.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_SMC_H_ |
#define LIBC_SMC_H_ |
#include <sys/types.h> |
extern int smc_coherence(void *address, size_t size); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/ctype.h |
---|
76,6 → 76,22 |
} |
} |
static inline int tolower(int c) |
{ |
if (isupper(c)) |
return (c + ('a' - 'A')); |
else |
return c; |
} |
static inline int toupper(int c) |
{ |
if (islower(c)) |
return (c + ('A' - 'a')); |
else |
return c; |
} |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/macros.h |
---|
0,0 → 1,50 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_MACROS_H_ |
#define LIBC_MACROS_H_ |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
#define KB2SIZE(kb) ((kb) << 10) |
#define MB2SIZE(mb) ((mb) << 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/ipc/bus.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_BUS_H_ |
#define LIBC_BUS_H_ |
#include <ipc/ipc.h> |
typedef enum { |
BUS_CLEAR_INTERRUPT = IPC_FIRST_USER_METHOD |
} bus_request_t; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/ipc/ipc.h |
---|
47,8 → 47,7 |
} ipc_call_t; |
typedef sysarg_t ipc_callid_t; |
typedef void (* ipc_async_callback_t)(void *private, int retval, |
ipc_call_t *data); |
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *); |
/* |
* User-friendly wrappers for ipc_call_sync_fast() and ipc_call_sync_slow(). |
173,22 → 172,20 |
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (arg5), (res1), (res2), (res3), (res4), (res5)) |
extern int ipc_call_sync_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, |
ipcarg_t *result3, ipcarg_t *result4, ipcarg_t *result5); |
extern int ipc_call_sync_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *); |
extern int ipc_call_sync_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3, ipcarg_t *result4, |
ipcarg_t *result5); |
extern int ipc_call_sync_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *, |
ipcarg_t *); |
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags); |
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec); |
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int); |
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t); |
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data) |
{ |
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT); |
} |
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data); |
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *); |
/* |
* User-friendly wrappers for ipc_answer_fast() and ipc_answer_slow(). |
209,10 → 206,10 |
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \ |
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5)) |
extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4); |
extern ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5); |
extern ipcarg_t ipc_answer_fast(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t); |
extern ipcarg_t ipc_answer_slow(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t); |
/* |
* User-friendly wrappers for ipc_call_async_fast() and ipc_call_async_slow(). |
220,8 → 217,7 |
* arguments. The macros decide between the fast and the slow version according |
* to m. |
*/ |
#define ipc_call_async_0(phoneid, method, private, callback, \ |
can_preempt) \ |
#define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \ |
ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \ |
(callback), (can_preempt)) |
#define ipc_call_async_1(phoneid, method, arg1, private, callback, \ |
245,23 → 241,24 |
ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \ |
(arg4), (arg5), (private), (callback), (can_preempt)) |
extern void ipc_call_async_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, void *private, |
ipc_async_callback_t callback, int can_preempt); |
extern void ipc_call_async_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, void *private, |
ipc_async_callback_t callback, int can_preempt); |
extern void ipc_call_async_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, void *, ipc_async_callback_t, int); |
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int); |
extern int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, |
ipcarg_t *phone); |
extern int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3); |
extern int ipc_hangup(int phoneid); |
extern int ipc_register_irq(int inr, int devno, int method, irq_code_t *code); |
extern int ipc_unregister_irq(int inr, int devno); |
extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, |
ipcarg_t arg1, ipcarg_t arg2, int mode); |
#define IPC_FLAG_BLOCKING 0x01 |
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *); |
extern int ipc_connect_me_to(int, int, int, int); |
extern int ipc_connect_me_to_blocking(int, int, int, int); |
extern int ipc_hangup(int); |
extern int ipc_register_irq(int, int, int, irq_code_t *); |
extern int ipc_unregister_irq(int, int); |
extern int ipc_forward_fast(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, int); |
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, |
ipcarg_t, ipcarg_t, ipcarg_t, int); |
/* |
* User-friendly wrappers for ipc_share_in_start(). |
*/ |
274,20 → 271,23 |
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \ |
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags)) |
extern int ipc_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg, |
int *flags); |
extern int ipc_share_in_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags); |
extern int ipc_share_out_start(int phoneid, void *src, int flags); |
extern int ipc_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags); |
extern int ipc_share_out_finalize(ipc_callid_t callid, void *dst); |
extern int ipc_data_read_start(int phoneid, void *dst, size_t size); |
extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size); |
extern int ipc_data_write_start(int phoneid, void *src, size_t size); |
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size); |
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *); |
extern int ipc_share_in_receive(ipc_callid_t *, size_t *); |
extern int ipc_share_in_finalize(ipc_callid_t, void *, int ); |
extern int ipc_share_out_start(int, void *, int); |
extern int ipc_share_out_receive(ipc_callid_t *, size_t *, int *); |
extern int ipc_share_out_finalize(ipc_callid_t, void *); |
extern int ipc_data_read_start(int, void *, size_t); |
extern int ipc_data_read_receive(ipc_callid_t *, size_t *); |
extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t); |
extern int ipc_data_write_start(int, const void *, size_t); |
extern int ipc_data_write_receive(ipc_callid_t *, size_t *); |
extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t); |
#include <task.h> |
extern int ipc_connect_kbox(task_id_t); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/ipc/devmap.h |
---|
0,0 → 1,99 |
/* |
* Copyright (c) 2007 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup devmap |
* @{ |
*/ |
#ifndef DEVMAP_DEVMAP_H_ |
#define DEVMAP_DEVMAP_H_ |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#define DEVMAP_NAME_MAXLEN 512 |
typedef enum { |
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD, |
DEVMAP_DRIVER_UNREGISTER, |
DEVMAP_DEVICE_REGISTER, |
DEVMAP_DEVICE_UNREGISTER, |
DEVMAP_DEVICE_GET_NAME, |
DEVMAP_DEVICE_GET_HANDLE |
} devmap_request_t; |
/** Representation of device driver. |
* Each driver is responsible for a set of devices. |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by |
* this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
int handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Interface provided by devmap. |
* Every process that connects to devmap must ask one of following |
* interfaces otherwise connection will be refused. |
*/ |
typedef enum { |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
DEVMAP_CLIENT, |
/** Create new connection to instance of device that |
* is specified by second argument of call. */ |
DEVMAP_CONNECT_TO_DEVICE |
} devmap_interface_t; |
#endif |
/branches/dd/uspace/lib/libc/include/ipc/console.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2006 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_CONSOLE_H_ |
#define LIBC_IPC_CONSOLE_H_ |
#include <ipc/ipc.h> |
typedef enum { |
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD, |
CONSOLE_PUTCHAR, |
CONSOLE_CLEAR, |
CONSOLE_GOTO, |
CONSOLE_GETSIZE, |
CONSOLE_FLUSH, |
CONSOLE_SET_STYLE, |
CONSOLE_SET_COLOR, |
CONSOLE_SET_RGB_COLOR, |
CONSOLE_CURSOR_VISIBILITY |
} console_request_t; |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/lib/libc/include/ipc/services.h |
---|
30,8 → 30,8 |
* @{ |
*/ |
/** |
* @file services.h |
* @brief List of all known services and their codes. |
* @file services.h |
* @brief List of all known services and their codes. |
*/ |
#ifndef LIBIPC_SERVICES_H_ |
38,13 → 38,15 |
#define LIBIPC_SERVICES_H_ |
typedef enum { |
SERVICE_PCI = 1, |
SERVICE_LOAD = 1, |
SERVICE_PCI, |
SERVICE_KEYBOARD, |
SERVICE_VIDEO, |
SERVICE_CONSOLE, |
SERVICE_RD, |
SERVICE_VFS, |
SERVICE_DEVMAP |
SERVICE_DEVMAP, |
SERVICE_FHC, |
SERVICE_OBIO |
} services_t; |
/* Memory area to be received from NS */ |
/branches/dd/uspace/lib/libc/include/ipc/loader.h |
---|
0,0 → 1,52 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_LOADER_H_ |
#define LIBC_IPC_LOADER_H_ |
#include <ipc/ipc.h> |
typedef enum { |
LOADER_HELLO = IPC_FIRST_USER_METHOD, |
LOADER_GET_TASKID, |
LOADER_SET_PATHNAME, |
LOADER_SET_ARGS, |
LOADER_LOAD, |
LOADER_RUN |
} loader_request_t; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/ipc/fb.h |
---|
48,10 → 48,11 |
FB_VIEWPORT_CREATE, |
FB_VIEWPORT_DELETE, |
FB_SET_STYLE, |
FB_SET_COLOR, |
FB_SET_RGB_COLOR, |
FB_GET_RESOLUTION, |
FB_DRAW_TEXT_DATA, |
FB_FLUSH, |
FB_VIEWPORT_DB, |
FB_DRAW_PPM, |
FB_PREPARE_SHM, |
FB_DROP_SHM, |
59,7 → 60,6 |
FB_VP_DRAW_PIXMAP, |
FB_VP2PIXMAP, |
FB_DROP_PIXMAP, |
FB_TRANS_PUTCHAR, |
FB_ANIM_CREATE, |
FB_ANIM_DROP, |
FB_ANIM_ADDPIXMAP, |
69,7 → 69,6 |
FB_POINTER_MOVE |
} fb_request_t; |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/errno.h |
---|
35,6 → 35,10 |
#ifndef LIBC_ERRNO_H_ |
#define LIBC_ERRNO_H_ |
/* TODO: support threads/fibrils */ |
extern int _errno; |
#define errno _errno |
#include <kernel/errno.h> |
#define ENAMETOOLONG (-256) |
46,6 → 50,8 |
#define EBADF (-262) |
#define ERANGE (-263) |
#define EXDEV (-264) |
#define EIO (-265) |
#define EMLINK (-266) |
#endif |
/branches/dd/uspace/lib/libc/include/sys/types.h |
---|
42,6 → 42,10 |
typedef long off_t; |
typedef int mode_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/Makefile.toolchain |
---|
26,16 → 26,23 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
DEFS = -DARCH=$(ARCH) |
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include |
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -imacros $(LIBC_PREFIX)/../../../config.h -I$(LIBC_PREFIX)/include -pipe -g |
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS = |
#-Werror |
## Cross-toolchain prefix |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
## Setup platform configuration |
# |
include $(LIBC_PREFIX)/arch/$(ARCH)/Makefile.inc |
-include $(LIBC_PREFIX)/../../../Makefile.config |
-include $(LIBC_PREFIX)/../../../config.defs |
-include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc |
## Simple detection of the host system |
# |
59,6 → 66,7 |
AR = $(BINUTILS_PREFIX)ar |
OBJCOPY = $(BINUTILS_PREFIX)objcopy |
OBJDUMP = $(BINUTILS_PREFIX)objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),icc_native) |
68,6 → 76,7 |
AR = ar |
OBJCOPY = objcopy |
OBJDUMP = objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
ifeq ($(COMPILER),gcc_cross) |
77,5 → 86,5 |
AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar |
OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) |
endif |
/branches/dd/uspace/lib/libc/generic/time.c |
---|
47,6 → 47,8 |
#include <as.h> |
#include <ddi.h> |
#include <time.h> |
/* Pointers to public variables with time */ |
struct { |
volatile sysarg_t seconds1; |
/branches/dd/uspace/lib/libc/generic/ddi.c |
---|
33,8 → 33,12 |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <libc.h> |
#include <task.h> |
#include <as.h> |
#include <align.h> |
#include <libarch/config.h> |
#include <kernel/ddi/ddi_arg.h> |
/** Map piece of physical memory to task. |
41,18 → 45,20 |
* |
* Caller of this function must have the CAP_MEM_MANAGER capability. |
* |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the sterting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the starting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in creating address space area. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_MEM_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in creating address space area. |
*/ |
int physmem_map(void *pf, void *vp, unsigned long pages, int flags) |
{ |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags); |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, |
flags); |
} |
/** Enable I/O space range to task. |
59,13 → 65,14 |
* |
* Caller of this function must have the IO_MEM_MANAGER capability. |
* |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in allocating memory. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_IO_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in allocating memory. |
*/ |
int iospace_enable(task_id_t id, void *ioaddr, unsigned long size) |
{ |
80,7 → 87,7 |
/** Interrupt control |
* |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
*/ |
int preemption_control(int enable) |
{ |
87,5 → 94,36 |
return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable); |
} |
/** Enable PIO for specified I/O range. |
* |
* @param pio_addr I/O start address. |
* @param size Size of the I/O region. |
* @param use_addr Address where the final address for application's PIO |
* will be stored. |
* |
* @return Zero on success or negative error code. |
*/ |
int pio_enable(void *pio_addr, size_t size, void **use_addr) |
{ |
void *phys; |
void *virt; |
size_t offset; |
unsigned int pages; |
#ifdef IO_SPACE_BOUNDARY |
if (pio_addr < IO_SPACE_BOUNDARY) { |
*use_addr = pio_addr; |
return iospace_enable(task_get_id(), pio_addr, size); |
} |
#endif |
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); |
offset = pio_addr - phys; |
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH; |
virt = as_get_mappable_page(pages); |
*use_addr = virt + offset; |
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/kbd.c |
---|
0,0 → 1,61 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <io/stream.h> |
#include <kbd/kbd.h> |
#include <ipc/ipc.h> |
#include <ipc/console.h> |
#include <async.h> |
int kbd_get_event(kbd_event_t *ev) |
{ |
int console_phone = get_console_phone(); |
ipcarg_t r0, r1, r2, r3; |
int rc; |
rc = async_req_0_4(console_phone, CONSOLE_GETKEY, &r0, &r1, &r2, &r3); |
if (rc < 0) |
return -1; |
ev->type = r0; |
ev->key = r1; |
ev->mods = r2; |
ev->c = r3; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/task.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
34,6 → 35,10 |
#include <task.h> |
#include <libc.h> |
#include <stdlib.h> |
#include <errno.h> |
#include <loader/loader.h> |
#include <string.h> |
task_id_t task_get_id(void) |
{ |
44,5 → 49,74 |
return task_id; |
} |
/** Set the task name. |
* |
* @param name The new name, typically the command used to execute the |
* program. |
* @return Zero on success or negative error code. |
*/ |
int task_set_name(const char *name) |
{ |
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, strlen(name)); |
} |
/** Create a new task by running an executable from the filesystem. |
* |
* This is really just a convenience wrapper over the more complicated |
* loader API. |
* |
* @param path pathname of the binary to execute |
* @param argv command-line arguments |
* @return ID of the newly created task or zero on error. |
*/ |
task_id_t task_spawn(const char *path, char *const argv[]) |
{ |
loader_t *ldr; |
task_id_t task_id; |
int rc; |
/* Connect to a program loader. */ |
ldr = loader_connect(); |
if (ldr == NULL) |
return 0; |
/* Get task ID. */ |
rc = loader_get_task_id(ldr, &task_id); |
if (rc != EOK) |
goto error; |
/* Send program pathname. */ |
rc = loader_set_pathname(ldr, path); |
if (rc != EOK) |
goto error; |
/* Send arguments. */ |
rc = loader_set_args(ldr, argv); |
if (rc != EOK) |
goto error; |
/* Load the program. */ |
rc = loader_load_program(ldr); |
if (rc != EOK) |
goto error; |
/* Run it. */ |
rc = loader_run(ldr); |
if (rc != EOK) |
goto error; |
/* Success */ |
free(ldr); |
return task_id; |
/* Error exit */ |
error: |
loader_abort(ldr); |
free(ldr); |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/tls.c |
---|
116,7 → 116,7 |
tcb_t *tcb; |
size = ALIGN_UP(size, &_tls_alignment); |
*data = memalign(&_tls_alignment, sizeof(tcb_t) + size); |
*data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size); |
tcb = (tcb_t *) (*data + size); |
tcb->self = tcb; |
/branches/dd/uspace/lib/libc/generic/console.c |
---|
0,0 → 1,97 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
#include <console.h> |
void console_clear(void) |
{ |
int cons_phone = get_console_phone(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
} |
void console_goto(int row, int col) |
{ |
int cons_phone = get_console_phone(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
void console_flush(void) |
{ |
int cons_phone = get_console_phone(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
} |
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = get_console_phone(); |
ipcarg_t r, c; |
int rc; |
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
*rows = (int) r; |
*cols = (int) c; |
return rc; |
} |
void console_set_style(int style) |
{ |
int cons_phone = get_console_phone(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = get_console_phone(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = get_console_phone(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int show) |
{ |
int cons_phone = get_console_phone(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/getopt.c |
---|
0,0 → 1,478 |
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ |
/*- |
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
* All rights reserved. |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* by Dieter Baron and Thomas Klausner. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */ |
#include <assert.h> |
#include <stdarg.h> |
#include <err.h> |
#include <errno.h> |
#include <getopt.h> |
#include <stdlib.h> |
#include <string.h> |
/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers |
* to keep legacy getopt() usage from breaking. All references to REPLACE_GETOPT |
* are dropped, we just include the code */ |
int opterr = 1; /* if error message should be printed */ |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
#define PRINT_ERROR ((opterr) && ((*options != ':') \ |
|| (IGNORE_FIRST && options[1] != ':'))) |
/*HelenOS Port - POSIXLY_CORRECT is always false */ |
#define IS_POSIXLY_CORRECT 0 |
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) |
/* XXX: GNU ignores PC if *options == '-' */ |
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') |
/* return values */ |
#define BADCH (int)'?' |
#define BADARG ((IGNORE_FIRST && options[1] == ':') \ |
|| (*options == ':') ? (int)':' : (int)'?') |
#define INORDER (int)1 |
#define EMSG "" |
static int getopt_internal(int, char **, const char *); |
static int gcd(int, int); |
static void permute_args(int, int, int, char **); |
static const char *place = EMSG; /* option letter processing */ |
/* XXX: set optreset to 1 rather than these two */ |
static int nonopt_start = -1; /* first non option argument (for permute) */ |
static int nonopt_end = -1; /* first option after non options (for permute) */ |
/* Error messages */ |
/* HelenOS Port: Calls to warnx() were eliminated (as we have no stderr that |
* may be redirected) and replaced with printf. As such, error messages now |
* end in a newline */ |
static const char recargchar[] = "option requires an argument -- %c\n"; |
static const char recargstring[] = "option requires an argument -- %s\n"; |
static const char ambig[] = "ambiguous option -- %.*s\n"; |
static const char noarg[] = "option doesn't take an argument -- %.*s\n"; |
static const char illoptchar[] = "unknown option -- %c\n"; |
static const char illoptstring[] = "unknown option -- %s\n"; |
/* |
* Compute the greatest common divisor of a and b. |
*/ |
static int |
gcd(a, b) |
int a; |
int b; |
{ |
int c; |
c = a % b; |
while (c != 0) { |
a = b; |
b = c; |
c = a % b; |
} |
return b; |
} |
/* |
* Exchange the block from nonopt_start to nonopt_end with the block |
* from nonopt_end to opt_end (keeping the same order of arguments |
* in each block). |
*/ |
static void |
permute_args(panonopt_start, panonopt_end, opt_end, nargv) |
int panonopt_start; |
int panonopt_end; |
int opt_end; |
char **nargv; |
{ |
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
char *swap; |
assert(nargv != NULL); |
/* |
* compute lengths of blocks and number and size of cycles |
*/ |
nnonopts = panonopt_end - panonopt_start; |
nopts = opt_end - panonopt_end; |
ncycle = gcd(nnonopts, nopts); |
cyclelen = (opt_end - panonopt_start) / ncycle; |
for (i = 0; i < ncycle; i++) { |
cstart = panonopt_end+i; |
pos = cstart; |
for (j = 0; j < cyclelen; j++) { |
if (pos >= panonopt_end) |
pos -= nnonopts; |
else |
pos += nopts; |
swap = nargv[pos]; |
nargv[pos] = nargv[cstart]; |
nargv[cstart] = swap; |
} |
} |
} |
/* |
* getopt_internal -- |
* Parse argc/argv argument vector. Called by user level routines. |
* Returns -2 if -- is found (can be long option or end of options marker). |
*/ |
static int |
getopt_internal(nargc, nargv, options) |
int nargc; |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
assert(options != NULL); |
optarg = NULL; |
/* |
* XXX Some programs (like rsyncd) expect to be able to |
* XXX re-initialize optind to 0 and have getopt_long(3) |
* XXX properly function again. Work around this braindamage. |
*/ |
if (optind == 0) |
optind = 1; |
if (optreset) |
nonopt_start = nonopt_end = -1; |
start: |
if (optreset || !*place) { /* update scanning pointer */ |
optreset = 0; |
if (optind >= nargc) { /* end of argument vector */ |
place = EMSG; |
if (nonopt_end != -1) { |
/* do permutation, if we have to */ |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
optind -= nonopt_end - nonopt_start; |
} |
else if (nonopt_start != -1) { |
/* |
* If we skipped non-options, set optind |
* to the first of them. |
*/ |
optind = nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((*(place = nargv[optind]) != '-') |
|| (place[1] == '\0')) { /* found non-option */ |
place = EMSG; |
if (IN_ORDER) { |
/* |
* GNU extension: |
* return non-option as argument to option 1 |
*/ |
optarg = nargv[optind++]; |
return INORDER; |
} |
if (!PERMUTE) { |
/* |
* if no permutation wanted, stop parsing |
* at first non-option |
*/ |
return -1; |
} |
/* do permutation */ |
if (nonopt_start == -1) |
nonopt_start = optind; |
else if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
nonopt_start = optind - |
(nonopt_end - nonopt_start); |
nonopt_end = -1; |
} |
optind++; |
/* process next argument */ |
goto start; |
} |
if (nonopt_start != -1 && nonopt_end == -1) |
nonopt_end = optind; |
if (place[1] && *++place == '-') { /* found "--" */ |
place++; |
return -2; |
} |
} |
if ((optchar = (int)*place++) == (int)':' || |
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
/* option letter unknown or ':' */ |
if (!*place) |
++optind; |
if (PRINT_ERROR) |
printf(illoptchar, optchar); |
optopt = optchar; |
return BADCH; |
} |
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ |
/* XXX: what if no long options provided (called by getopt)? */ |
if (*place) |
return -2; |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else /* white space */ |
place = nargv[optind]; |
/* |
* Handle -W arg the same as --arg (which causes getopt to |
* stop parsing). |
*/ |
return -2; |
} |
if (*++oli != ':') { /* doesn't take argument */ |
if (!*place) |
++optind; |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else |
optarg = nargv[optind]; |
} |
place = EMSG; |
++optind; |
} |
/* dump back option letter */ |
return optchar; |
} |
/* |
* getopt -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt(nargc, nargv, options) |
int nargc; |
char * const *nargv; |
const char *options; |
{ |
int retval; |
assert(nargv != NULL); |
assert(options != NULL); |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
++optind; |
/* |
* We found an option (--), so if we skipped non-options, |
* we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, optind, |
(char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
retval = -1; |
} |
return retval; |
} |
/* |
* getopt_long -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt_long(nargc, nargv, options, long_options, idx) |
int nargc; |
char * const *nargv; |
const char *options; |
const struct option *long_options; |
int *idx; |
{ |
int retval; |
#define IDENTICAL_INTERPRETATION(_x, _y) \ |
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ |
long_options[(_x)].flag == long_options[(_y)].flag && \ |
long_options[(_x)].val == long_options[(_y)].val) |
assert(nargv != NULL); |
assert(options != NULL); |
assert(long_options != NULL); |
/* idx may be NULL */ |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
current_argv = (char *)place; |
match = -1; |
ambiguous = 0; |
optind++; |
place = EMSG; |
if (*current_argv == '\0') { /* found "--" */ |
/* |
* We found an option (--), so if we skipped |
* non-options, we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, (char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
/* argument found (--option=arg) */ |
current_argv_len = has_equal - current_argv; |
has_equal++; |
} else |
current_argv_len = strlen(current_argv); |
for (i = 0; long_options[i].name; i++) { |
/* find matching long option */ |
if (strncmp(current_argv, long_options[i].name, |
current_argv_len)) |
continue; |
if (strlen(long_options[i].name) == |
(unsigned)current_argv_len) { |
/* exact match */ |
match = i; |
ambiguous = 0; |
break; |
} |
if (match == -1) /* partial match */ |
match = i; |
else if (!IDENTICAL_INTERPRETATION(i, match)) |
ambiguous = 1; |
} |
if (ambiguous) { |
/* ambiguous abbreviation */ |
if (PRINT_ERROR) |
printf(ambig, (int)current_argv_len, |
current_argv); |
optopt = 0; |
return BADCH; |
} |
if (match != -1) { /* option found */ |
if (long_options[match].has_arg == no_argument |
&& has_equal) { |
if (PRINT_ERROR) |
printf(noarg, (int)current_argv_len, |
current_argv); |
/* |
* XXX: GNU sets optopt to val regardless of |
* flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
return BADARG; |
} |
if (long_options[match].has_arg == required_argument || |
long_options[match].has_arg == optional_argument) { |
if (has_equal) |
optarg = has_equal; |
else if (long_options[match].has_arg == |
required_argument) { |
/* |
* optional argument doesn't use |
* next nargv |
*/ |
optarg = nargv[optind++]; |
} |
} |
if ((long_options[match].has_arg == required_argument) |
&& (optarg == NULL)) { |
/* |
* Missing argument; leading ':' |
* indicates no error should be generated |
*/ |
if (PRINT_ERROR) |
printf(recargstring, current_argv); |
/* |
* XXX: GNU sets optopt to val regardless |
* of flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
--optind; |
return BADARG; |
} |
} else { /* unknown option */ |
if (PRINT_ERROR) |
printf(illoptstring, current_argv); |
optopt = 0; |
return BADCH; |
} |
if (long_options[match].flag) { |
*long_options[match].flag = long_options[match].val; |
retval = 0; |
} else |
retval = long_options[match].val; |
if (idx) |
*idx = match; |
} |
return retval; |
#undef IDENTICAL_INTERPRETATION |
} |
/branches/dd/uspace/lib/libc/generic/as.c |
---|
85,6 → 85,20 |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address); |
} |
/** Change address-space area flags. |
* |
* @param address Virtual address pointing into the address space area being |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
return __SYSCALL2(SYS_AS_AREA_CHANGE_FLAGS, (sysarg_t) address, |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
/branches/dd/uspace/lib/libc/generic/pcb.c |
---|
0,0 → 1,40 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <loader/pcb.h> |
pcb_t *__pcb; |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/string.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
33,96 → 34,16 |
*/ |
#include <string.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <limits.h> |
#include <ctype.h> |
#include <limits.h> |
#include <align.h> |
#include <sys/types.h> |
#include <malloc.h> |
/* Dummy implementation of mem/ functions */ |
void *memset(void *s, int c, size_t n) |
{ |
char *os = s; |
while (n--) |
*(os++) = c; |
return s; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
} |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1))) |
return unaligned_memcpy(dst, src, n); |
for (i = 0; i < n / sizeof(unsigned long); i++) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
} |
void *memmove(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (src > dst) |
return memcpy(dst, src, n); |
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--) |
((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j]; |
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
return (char *) src; |
} |
/** Compare two memory areas. |
/** Count the number of characters in the string, not including terminating 0. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have the same |
* length. |
* @return If len is 0, return zero. If the areas match, return zero. |
* Otherwise return non-zero. |
* @param str String. |
* @return Number of characters in string. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** Count the number of characters in the string, not including terminating 0. |
* @param str string |
* @return number of characters in string. |
*/ |
size_t strlen(const char *str) |
{ |
size_t counter = 0; |
141,7 → 62,6 |
c++; |
return (a[c] - b[c]); |
} |
int strncmp(const char *a, const char *b, size_t n) |
155,10 → 75,22 |
} |
/** Return pointer to the first occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
c++; |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Return pointer to the first occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strchr(const char *str, int c) |
{ |
171,10 → 103,12 |
return NULL; |
} |
/** Return pointer to the last occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
/** Return pointer to the last occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strrchr(const char *str, int c) |
{ |
191,13 → 125,16 |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @param sgn its set to 1 if minus found |
* @return result of conversion. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @param sgn It's set to 1 if minus found. |
* @return Result of conversion. |
*/ |
static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn) |
static unsigned long |
_strtoul(const char *nptr, char **endptr, int base, char *sgn) |
{ |
unsigned char c; |
unsigned long result = 0; |
219,7 → 156,8 |
/* FIXME: set errno to EINVAL */ |
return 0; |
} |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) { |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || |
(str[1] == 'X'))) { |
str += 2; |
} |
} else { |
238,7 → 176,8 |
while (*str) { |
c = *str; |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff))); |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : |
(c <= '9' ? c - '0' : 0xff))); |
if (c > base) { |
break; |
} |
257,7 → 196,10 |
} |
if (str == tmpptr) { |
/* no number was found => first invalid character is the first character of the string */ |
/* |
* No number was found => first invalid character is the first |
* character of the string. |
*/ |
/* FIXME: set errno to EINVAL */ |
str = nptr; |
result = 0; |
275,14 → 217,17 |
} |
/** Convert initial part of string to long int according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
long int strtol(const char *nptr, char **endptr, int base) |
{ |
305,14 → 250,17 |
/** Convert initial part of string to unsigned long according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
unsigned long strtoul(const char *nptr, char **endptr, int base) |
{ |
353,5 → 301,48 |
return orig; |
} |
char * strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
} |
char *strtok(char *s, const char *delim) |
{ |
static char *next; |
return strtok_r(s, delim, &next); |
} |
char *strtok_r(char *s, const char *delim, char **next) |
{ |
char *start, *end; |
if (s == NULL) |
s = *next; |
/* Skip over leading delimiters. */ |
while (*s && (strchr(delim, *s) != NULL)) ++s; |
start = s; |
/* Skip over token characters. */ |
while (*s && (strchr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
if (start == end) { |
return NULL; /* No more tokens. */ |
} |
/* Overwrite delimiter with NULL terminator. */ |
*end = '\0'; |
return start; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/loader.c |
---|
0,0 → 1,264 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <ipc/services.h> |
#include <libc.h> |
#include <task.h> |
#include <string.h> |
#include <stdlib.h> |
#include <async.h> |
#include <errno.h> |
#include <vfs/vfs.h> |
#include <loader/loader.h> |
/** Connect to a new program loader. |
* |
* Spawns a new program loader task and returns the connection structure. |
* @param name Symbolic name to set on the newly created task. |
* @return Pointer to the loader connection structure (should be |
* de-allocated using free() after use). |
*/ |
int loader_spawn(const char *name) |
{ |
return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER, |
(sysarg_t) name, strlen(name)); |
} |
loader_t *loader_connect(void) |
{ |
loader_t *ldr; |
int phone_id; |
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0); |
if (phone_id < 0) |
return NULL; |
ldr = malloc(sizeof(loader_t)); |
if (ldr == NULL) |
return NULL; |
ldr->phone_id = phone_id; |
return ldr; |
} |
/** Get ID of the new task. |
* |
* Retrieves the ID of the new task from the loader. |
* |
* @param ldr Loader connection structure. |
* @param task_id Points to a variable where the ID should be stored. |
* @return Zero on success or negative error code. |
*/ |
int loader_get_task_id(loader_t *ldr, task_id_t *task_id) |
{ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
/* Get task ID. */ |
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer); |
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &retval); |
return (int)retval; |
} |
/** Set pathname of the program to load. |
* |
* Sets the name of the program file to load. The name can be relative |
* to the current working directory (it will be absolutized before |
* sending to the loader). |
* |
* @param ldr Loader connection structure. |
* @param path Pathname of the program file. |
* @return Zero on success or negative error code. |
*/ |
int loader_set_pathname(loader_t *ldr, const char *path) |
{ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
char *pa; |
size_t pa_len; |
pa = absolutize(path, &pa_len); |
if (!pa) |
return 0; |
/* Send program pathname */ |
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
free(pa); |
async_wait_for(req, &retval); |
return (int)retval; |
} |
/** Set command-line arguments for the program. |
* |
* Sets the vector of command-line arguments to be passed to the loaded |
* program. By convention, the very first argument is typically the same as |
* the command used to execute the program. |
* |
* @param ldr Loader connection structure. |
* @param argv NULL-terminated array of pointers to arguments. |
* @return Zero on success or negative error code. |
*/ |
int loader_set_args(loader_t *ldr, char *const argv[]) |
{ |
aid_t req; |
ipc_call_t answer; |
ipcarg_t rc; |
char *const *ap; |
char *dp; |
char *arg_buf; |
size_t buffer_size; |
/* |
* Serialize the arguments into a single array. First |
* compute size of the buffer needed. |
*/ |
ap = argv; |
buffer_size = 0; |
while (*ap != NULL) { |
buffer_size += strlen(*ap) + 1; |
++ap; |
} |
arg_buf = malloc(buffer_size); |
if (arg_buf == NULL) return ENOMEM; |
/* Now fill the buffer with null-terminated argument strings */ |
ap = argv; |
dp = arg_buf; |
while (*ap != NULL) { |
strcpy(dp, *ap); |
dp += strlen(*ap) + 1; |
++ap; |
} |
/* Send serialized arguments to the loader */ |
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &rc); |
if (rc != EOK) return rc; |
/* Free temporary buffer */ |
free(arg_buf); |
return EOK; |
} |
/** Instruct loader to load the program. |
* |
* If this function succeeds, the program has been successfully loaded |
* and is ready to be executed. |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
int loader_load_program(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD); |
if (rc != EOK) |
return rc; |
return EOK; |
} |
/** Instruct loader to execute the program. |
* |
* Note that this function blocks until the loader actually replies |
* so you cannot expect this function to return if you are debugging |
* the task and its thread is stopped. |
* |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
int loader_run(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_RUN); |
if (rc != EOK) |
return rc; |
return EOK; |
} |
/** Cancel the loader session. |
* |
* Tells the loader not to load any program and terminate. |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
void loader_abort(loader_t *ldr) |
{ |
ipc_hangup(ldr->phone_id); |
ldr->phone_id = 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/fibril.c |
---|
342,4 → 342,3 |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/thread.c |
---|
108,8 → 108,8 |
uarg->uspace_thread_arg = arg; |
uarg->uspace_uarg = uarg; |
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) tid); |
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) strlen(name), (sysarg_t) tid); |
if (rc) { |
/* |
/branches/dd/uspace/lib/libc/generic/libc.c |
---|
48,28 → 48,41 |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
int _errno; |
void _exit(int status) |
{ |
thread_exit(status); |
} |
void __main(void) |
void __main(void *pcb_ptr) |
{ |
fibril_t *f; |
int argc; |
char **argv; |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
_async_init(); |
f = fibril_setup(); |
__tcb_set(f->tcb); |
} |
/* Save the PCB pointer */ |
__pcb = (pcb_t *)pcb_ptr; |
void __io_init(void) |
{ |
open_stdin(); |
open_stdout(); |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
} |
main(argc, argv); |
} |
void __exit(void) |
/branches/dd/uspace/lib/libc/generic/ipc.c |
---|
598,7 → 598,7 |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
605,6 → 605,30 |
return newphid; |
} |
/** Ask through phone for a new connection to some service. |
* |
* If the connection is not available at the moment, the |
* call will block. |
* |
* @param phoneid Phone handle used for contacting the other side. |
* @param arg1 User defined argument. |
* @param arg2 User defined argument. |
* @param arg3 User defined argument. |
* |
* @return New phone handle on success or a negative error code. |
*/ |
int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) |
{ |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
return newphid; |
} |
/** Hang up a phone. |
* |
* @param phoneid Handle of the phone to be hung up. |
666,6 → 690,23 |
arg2, mode); |
} |
int ipc_forward_slow(ipc_callid_t callid, int phoneid, int method, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
int mode) |
{ |
ipc_call_t data; |
IPC_SET_METHOD(data, method); |
IPC_SET_ARG1(data, arg1); |
IPC_SET_ARG2(data, arg2); |
IPC_SET_ARG3(data, arg3); |
IPC_SET_ARG4(data, arg4); |
IPC_SET_ARG5(data, arg5); |
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode); |
} |
/** Wrapper for making IPC_M_SHARE_IN calls. |
* |
* @param phoneid Phone that will be used to contact the receiving side. |
682,7 → 723,7 |
{ |
int res; |
sysarg_t tmp_flags; |
res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
(ipcarg_t) size, arg, NULL, &tmp_flags); |
if (flags) |
*flags = tmp_flags; |
742,7 → 783,7 |
*/ |
int ipc_share_out_start(int phoneid, void *src, int flags) |
{ |
return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
(ipcarg_t) flags); |
} |
803,7 → 844,7 |
*/ |
int ipc_data_read_start(int phoneid, void *dst, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
(ipcarg_t) size); |
} |
847,7 → 888,7 |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size) |
int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size); |
} |
860,9 → 901,9 |
* |
* @return Zero on success or a negative error code from errno.h. |
*/ |
int ipc_data_write_start(int phoneid, void *src, size_t size) |
int ipc_data_write_start(int phoneid, const void *src, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
(ipcarg_t) size); |
} |
909,6 → 950,18 |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) dst, (ipcarg_t) size); |
} |
#include <kernel/syscall/sysarg64.h> |
/** Connect to a task specified by id. |
*/ |
int ipc_connect_kbox(task_id_t id) |
{ |
sysarg64_t arg; |
arg.value = (unsigned long long) id; |
return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) &arg); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/udebug.c |
---|
0,0 → 1,103 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <udebug.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <async.h> |
int udebug_begin(int phoneid) |
{ |
return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_BEGIN); |
} |
int udebug_end(int phoneid) |
{ |
return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_END); |
} |
int udebug_set_evmask(int phoneid, udebug_evmask_t mask) |
{ |
return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_SET_EVMASK, |
mask); |
} |
int udebug_thread_read(int phoneid, void *buffer, size_t n, |
size_t *copied, size_t *needed) |
{ |
ipcarg_t a_copied, a_needed; |
int rc; |
rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_THREAD_READ, |
(sysarg_t)buffer, n, NULL, &a_copied, &a_needed); |
*copied = (size_t)a_copied; |
*needed = (size_t)a_needed; |
return rc; |
} |
int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n) |
{ |
return async_req_4_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_MEM_READ, |
(sysarg_t)buffer, addr, n); |
} |
int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer) |
{ |
return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_ARGS_READ, |
tid, (sysarg_t)buffer); |
} |
int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type, |
sysarg_t *val0, sysarg_t *val1) |
{ |
ipcarg_t a_ev_type; |
int rc; |
rc = async_req_2_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_GO, |
tid, &a_ev_type, val0, val1); |
*ev_type = a_ev_type; |
return rc; |
} |
int udebug_stop(int phoneid, thash_t tid) |
{ |
return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_STOP, |
tid); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/async.c |
---|
483,7 → 483,7 |
{ |
connection_t *conn; |
unsigned long key; |
conn = malloc(sizeof(*conn)); |
if (!conn) { |
if (callid) |
498,7 → 498,7 |
conn->call = *call; |
conn->wdata.active = 1; /* We will activate the fibril ASAP */ |
conn->cfibril = cfibril; |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
506,14 → 506,15 |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
/* Add connection to the connection hash table */ |
key = conn->in_phone_hash; |
futex_down(&async_futex); |
hash_table_insert(&conn_hash_table, &key, &conn->link); |
futex_up(&async_futex); |
fibril_add_ready(conn->wdata.fid); |
return conn->wdata.fid; |
} |
524,6 → 525,7 |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
533,8 → 535,8 |
(*interrupt_received)(callid, call); |
_in_interrupt_handler = 0; |
return; |
} |
} |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_CONNECT_ME_TO: |
/* Open new connection with fibril etc. */ |
542,11 → 544,11 |
client_connection); |
return; |
} |
/* Try to route the call through the connection hash table */ |
if (route_call(callid, call)) |
return; |
/* Unknown call from unknown phone - hang it up */ |
ipc_answer_0(callid, EHANGUP); |
} |
739,23 → 741,17 |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
msg->dataptr = dataptr; |
/* We may sleep in the next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
reply_received, 1); |
reply_received, !_in_interrupt_handler); |
return (aid_t) msg; |
} |
781,23 → 777,17 |
ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
msg->dataptr = dataptr; |
/* We may sleep in next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
reply_received, 1); |
reply_received, !_in_interrupt_handler); |
return (aid_t) msg; |
} |
884,21 → 874,16 |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot call async_usleep in interrupt handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
if (!msg) |
return; |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
futex_down(&async_futex); |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
1012,4 → 997,3 |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c |
---|
31,7 → 31,7 |
*/ |
/** @file |
*/ |
#include <vfs/vfs.h> |
#include <vfs/canonify.h> |
#include <stdlib.h> |
48,7 → 48,8 |
#include <futex.h> |
#include <errno.h> |
#include <string.h> |
#include "../../srv/vfs/vfs.h" |
#include <ipc/devmap.h> |
#include "../../../srv/vfs/vfs.h" |
int vfs_phone = -1; |
futex_t vfs_phone_futex = FUTEX_INITIALIZER; |
56,11 → 57,12 |
futex_t cwd_futex = FUTEX_INITIALIZER; |
DIR *cwd_dir = NULL; |
char *cwd_path = NULL; |
size_t cwd_len = 0; |
size_t cwd_len = 0; |
static char *absolutize(const char *path, size_t *retlen) |
char *absolutize(const char *path, size_t *retlen) |
{ |
char *ncwd_path; |
char *ncwd_path_nc; |
futex_down(&cwd_futex); |
size_t len = strlen(path); |
69,65 → 71,112 |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path = malloc(len + cwd_len + 1); |
if (!ncwd_path) { |
ncwd_path_nc = malloc(cwd_len + 1 + len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(ncwd_path, cwd_path); |
ncwd_path[cwd_len] = '/'; |
ncwd_path[cwd_len + 1] = '\0'; |
strcpy(ncwd_path_nc, cwd_path); |
ncwd_path_nc[cwd_len] = '/'; |
ncwd_path_nc[cwd_len + 1] = '\0'; |
} else { |
ncwd_path = malloc(len + 1); |
if (!ncwd_path) { |
ncwd_path_nc = malloc(len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path[0] = '\0'; |
ncwd_path_nc[0] = '\0'; |
} |
strcat(ncwd_path, path); |
if (!canonify(ncwd_path, retlen)) { |
strcat(ncwd_path_nc, path); |
ncwd_path = canonify(ncwd_path_nc, retlen); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
free(ncwd_path); |
free(ncwd_path_nc); |
return NULL; |
} |
/* |
* We need to clone ncwd_path because canonify() works in-place and thus |
* the address in ncwd_path need not be the same as ncwd_path_nc, even |
* though they both point into the same dynamically allocated buffer. |
*/ |
ncwd_path = strdup(ncwd_path); |
free(ncwd_path_nc); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
return NULL; |
} |
futex_up(&cwd_futex); |
return ncwd_path; |
} |
static int vfs_connect(void) |
static void vfs_connect(void) |
{ |
if (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
return vfs_phone; |
while (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
} |
int mount(const char *fs_name, const char *mp, const char *dev) |
static int device_get_handle(const char *name, dev_handle_t *handle, |
const unsigned int flags) |
{ |
int phone; |
if (flags & IPC_FLAG_BLOCKING) |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
else |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
ipc_hangup(phone); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (retval == EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
} |
ipc_hangup(phone); |
return retval; |
} |
int mount(const char *fs_name, const char *mp, const char *dev, |
const unsigned int flags) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
dev_handle_t dev_handle = 0; /* TODO */ |
dev_handle_t dev_handle; |
res = device_get_handle(dev, &dev_handle, flags); |
if (res != EOK) |
return res; |
size_t mpa_len; |
char *mpa = absolutize(mp, &mpa_len); |
if (!mpa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name)); |
vfs_connect(); |
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
135,7 → 184,8 |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len); |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, strlen(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
143,16 → 193,17 |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
static int _open(const char *path, int lflag, int oflag, ...) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
164,15 → 215,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
186,6 → 230,9 |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
196,22 → 243,14 |
int close(int fildes) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
220,7 → 259,6 |
ssize_t read(int fildes, void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
227,14 → 265,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
249,12 → 281,11 |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return rc; |
} |
ssize_t write(int fildes, const void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
261,14 → 292,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
288,23 → 313,15 |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
off_t newoffs; |
vfs_connect(); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
(ipcarg_t)&newoffs); |
&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
312,24 → 329,17 |
if (rc != EOK) |
return (off_t) -1; |
return newoffs; |
return (off_t) newoffs; |
} |
int ftruncate(int fildes, off_t length) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
371,7 → 381,6 |
int mkdir(const char *path, mode_t mode) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
379,18 → 388,11 |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
409,7 → 411,6 |
static int _unlink(const char *path, int lflag) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
420,15 → 421,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
457,7 → 451,6 |
int rename(const char *old, const char *new) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
475,16 → 468,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_len); |
if (rc != EOK) { |
537,6 → 522,7 |
cwd_path = pa; |
cwd_len = pa_len; |
futex_up(&cwd_futex); |
return EOK; |
} |
char *getcwd(char *buf, size_t size) |
/branches/dd/uspace/lib/libc/generic/vfs/canonify.c |
---|
36,6 → 36,7 |
*/ |
#include <stdlib.h> |
#include <vfs/canonify.h> |
/** Token types used for tokenization of path. */ |
typedef enum { |
125,6 → 126,7 |
static void set_first_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
*tfsl = *t; |
*tlcomp = *t; |
} |
static void save_component(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
/branches/dd/uspace/lib/libc/generic/mem.c |
---|
0,0 → 1,239 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <mem.h> |
#include <stdlib.h> |
#include <sys/types.h> |
/** Fill memory block with a constant value. */ |
void *memset(void *dest, int b, size_t n) |
{ |
char *pb; |
unsigned long *pw; |
size_t word_size; |
size_t n_words; |
unsigned long pattern; |
size_t i; |
size_t fill; |
/* Fill initial segment. */ |
word_size = sizeof(unsigned long); |
fill = word_size - ((uintptr_t) dest & (word_size - 1)); |
if (fill > n) fill = n; |
pb = dest; |
i = fill; |
while (i-- != 0) |
*pb++ = b; |
/* Compute remaining size. */ |
n -= fill; |
if (n == 0) return dest; |
n_words = n / word_size; |
n = n % word_size; |
pw = (unsigned long *) pb; |
/* Create word-sized pattern for aligned segment. */ |
pattern = 0; |
i = word_size; |
while (i-- != 0) |
pattern = (pattern << 8) | (uint8_t) b; |
/* Fill aligned segment. */ |
i = n_words; |
while (i-- != 0) |
*pw++ = pattern; |
pb = (char *) pw; |
/* Fill final segment. */ |
i = n; |
while (i-- != 0) |
*pb++ = b; |
return dest; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
/** Copy memory block. */ |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
size_t i; |
size_t mod, fill; |
size_t word_size; |
size_t n_words; |
const unsigned long *srcw; |
unsigned long *dstw; |
const uint8_t *srcb; |
uint8_t *dstb; |
word_size = sizeof(unsigned long); |
/* |
* Are source and destination addresses congruent modulo word_size? |
* If not, use unaligned_memcpy(). |
*/ |
if (((uintptr_t) dst & (word_size - 1)) != |
((uintptr_t) src & (word_size - 1))) |
return unaligned_memcpy(dst, src, n); |
/* |
* mod is the address modulo word size. fill is the length of the |
* initial buffer segment before the first word boundary. |
* If the buffer is very short, use unaligned_memcpy(), too. |
*/ |
mod = (uintptr_t) dst & (word_size - 1); |
fill = word_size - mod; |
if (fill > n) fill = n; |
/* Copy the initial segment. */ |
srcb = src; |
dstb = dst; |
i = fill; |
while (i-- != 0) |
*dstb++ = *srcb++; |
/* Compute remaining length. */ |
n -= fill; |
if (n == 0) return dst; |
/* Pointers to aligned segment. */ |
dstw = (unsigned long *) dstb; |
srcw = (const unsigned long *) srcb; |
n_words = n / word_size; /* Number of whole words to copy. */ |
n -= n_words * word_size; /* Remaining bytes at the end. */ |
/* "Fast" copy. */ |
i = n_words; |
while (i-- != 0) |
*dstw++ = *srcw++; |
/* |
* Copy the rest. |
*/ |
srcb = (const uint8_t *) srcw; |
dstb = (uint8_t *) dstw; |
i = n; |
while (i-- != 0) |
*dstb++ = *srcb++; |
return dst; |
} |
/** Move memory block with possible overlapping. */ |
void *memmove(void *dst, const void *src, size_t n) |
{ |
const uint8_t *sp; |
uint8_t *dp; |
/* Nothing to do? */ |
if (src == dst) |
return dst; |
/* Non-overlapping? */ |
if (dst >= src + n || src >= dst + n) { |
return memcpy(dst, src, n); |
} |
/* Which direction? */ |
if (src > dst) { |
/* Forwards. */ |
sp = src; |
dp = dst; |
while (n-- != 0) |
*dp++ = *sp++; |
} else { |
/* Backwards. */ |
sp = src + (n - 1); |
dp = dst + (n - 1); |
while (n-- != 0) |
*dp-- = *sp--; |
} |
return dst; |
} |
/** Compare two memory areas. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/lib/libc/generic/smc.c |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <sys/types.h> |
#include <smc.h> |
int smc_coherence(void *address, size_t size) |
{ |
return __SYSCALL2(SYS_SMC_COHERENCE, (sysarg_t) address, |
(sysarg_t) size); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/stdio.c |
---|
0,0 → 1,278 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** |
* @file |
* @brief ANSI C Stream I/O. |
*/ |
#include <stdlib.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <unistd.h> |
#include <errno.h> |
#include <bool.h> |
#include <stdio.h> |
FILE *stdin, *stdout, *stderr; |
/** |
* Open a stream. |
* |
* @param file_name Name of the file to open. |
* @param mode Mode string, (r|w|a)[b|t][+]. |
*/ |
FILE *fopen(const char *file_name, const char *mode) |
{ |
FILE *f; |
int flags; |
bool plus; |
const char *mp; |
/* Parse mode except first character. */ |
mp = mode; |
if (*mp++ == '\0') { |
errno = EINVAL; |
return NULL; |
} |
if (*mp == 'b' || *mp == 't') ++mp; |
if (*mp == '+') { |
++mp; |
plus = true; |
} else { |
plus = false; |
} |
if (*mp != '\0') { |
errno = EINVAL; |
return NULL; |
} |
/* Parse first character of mode and determine flags for open(). */ |
switch (mode[0]) { |
case 'r': |
flags = plus ? O_RDWR : O_RDONLY; |
break; |
case 'w': |
flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
break; |
case 'a': |
/* TODO: a+ must read from beginning, append to the end. */ |
if (plus) { |
errno = ENOTSUP; |
return NULL; |
} |
flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
default: |
errno = EINVAL; |
return NULL; |
} |
/* Open file. */ |
f = malloc(sizeof(FILE)); |
if (f == NULL) { |
errno = ENOMEM; |
return NULL; |
} |
f->fd = open(file_name, flags, 0666); |
if (f->fd < 0) { |
free(f); |
return NULL; /* errno was set by open() */ |
} |
f->error = 0; |
f->eof = 0; |
return f; |
} |
/** Close a stream. |
* |
* @param f Pointer to stream. |
* @return 0 on success, EOF on error. |
*/ |
int fclose(FILE *f) |
{ |
int rc; |
rc = close(f->fd); |
free(f); |
if (rc != 0) |
return EOF; /* errno was set by close() */ |
return 0; |
} |
/** Read from a stream. |
* |
* @param buf Destination buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to read. |
* @param f Pointer to the stream. |
*/ |
size_t fread(void *buf, size_t size, size_t nmemb, FILE *f) |
{ |
size_t left, done, n; |
left = size * nmemb; |
done = 0; |
while (left > 0 && !f->error && !f->eof) { |
n = read(f->fd, buf + done, left); |
if (n < 0) { |
f->error = 1; |
} else if (n == 0) { |
f->eof = 1; |
} else { |
left -= n; |
done += n; |
} |
} |
return done / size; |
} |
/** Write to a stream. |
* |
* @param buf Source buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to write. |
* @param f Pointer to the stream. |
*/ |
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f) |
{ |
size_t left, done, n; |
left = size * nmemb; |
done = 0; |
while (left > 0 && !f->error) { |
n = write(f->fd, buf + done, left); |
if (n <= 0) { |
f->error = 1; |
} else { |
left -= n; |
done += n; |
} |
} |
return done / size; |
} |
/** Return the end-of-file indicator of a stream. */ |
int feof(FILE *f) |
{ |
return f->eof; |
} |
/** Return the error indicator of a stream. */ |
int ferror(FILE *f) |
{ |
return f->error; |
} |
/** Clear the error and end-of-file indicators of a stream. */ |
void clearerr(FILE *f) |
{ |
f->eof = 0; |
f->error = 0; |
} |
/** Read character from a stream. */ |
int fgetc(FILE *f) |
{ |
unsigned char c; |
size_t n; |
n = fread(&c, sizeof(c), 1, f); |
if (n < 1) return EOF; |
return (int) c; |
} |
/** Write character to a stream. */ |
int fputc(int c, FILE *f) |
{ |
unsigned char cc; |
size_t n; |
cc = (unsigned char) c; |
n = fwrite(&cc, sizeof(cc), 1, f); |
if (n < 1) return EOF; |
return (int) cc; |
} |
/** Write string to a stream. */ |
int fputs(const char *s, FILE *f) |
{ |
int rc; |
rc = 0; |
while (*s && rc >= 0) { |
rc = fputc(*s++, f); |
} |
if (rc < 0) return EOF; |
return 0; |
} |
/** Seek to position in stream. */ |
int fseek(FILE *f, long offset, int origin) |
{ |
off_t rc; |
rc = lseek(f->fd, offset, origin); |
if (rc == (off_t) (-1)) { |
/* errno has been set by lseek. */ |
return -1; |
} |
f->eof = 0; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/sprintf.c |
---|
48,7 → 48,6 |
va_start(args, fmt); |
ret = vsprintf(str, fmt, args); |
va_end(args); |
return ret; |
/branches/dd/uspace/lib/libc/generic/io/asprintf.c |
---|
0,0 → 1,79 |
/* |
* Copyright (c) 2006 Josef Cejka |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <stdarg.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <io/printf_core.h> |
static int asprintf_prewrite(const char *str, size_t count, void *unused) |
{ |
return count; |
} |
/** Allocate and print to string. |
* |
* @param strp Address of the pointer where to store the address of |
* the newly allocated string. |
* @fmt Format strin. |
* |
* @return Number of characters printed or a negative error code. |
*/ |
int asprintf(char **strp, const char *fmt, ...) |
{ |
struct printf_spec ps = { |
asprintf_prewrite, |
NULL |
}; |
int ret; |
va_list args; |
va_start(args, fmt); |
ret = printf_core(fmt, &ps, args); |
va_end(args); |
if (ret > 0) { |
*strp = malloc(ret + 20); |
if (!*strp) |
return -1; |
va_start(args, fmt); |
vsprintf(*strp, fmt, args); |
va_end(args); |
} |
return ret; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/fprintf.c |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** |
* @file |
* @brief fprintf, vfprintf |
*/ |
#include <stdio.h> |
#include <sys/types.h> |
#include <io/printf_core.h> |
static int vfprintf_write(const char *s, size_t count, void *f) |
{ |
return fwrite(s, 1, count, (FILE *) f); |
} |
int vfprintf(FILE *f, const char *fmt, va_list ap) |
{ |
struct printf_spec ps = { |
(int (*)(void *, size_t, void *)) vfprintf_write, |
(void *) f |
}; |
return printf_core(fmt, &ps, ap); |
} |
int fprintf(FILE *f, const char *fmt, ...) |
{ |
int rv; |
va_list args; |
va_start(args, fmt); |
rv = vfprintf(f, fmt, args); |
va_end(args); |
return rv; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/vsnprintf.c |
---|
38,22 → 38,27 |
#include <io/printf_core.h> |
struct vsnprintf_data { |
size_t size; /* total space for string */ |
size_t len; /* count of currently used characters */ |
char *string; /* destination string */ |
size_t size; /* total space for string */ |
size_t len; /* count of currently used characters */ |
char *string; /* destination string */ |
}; |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
* number of really printed characters but size of input string. Number of really used characters |
* is stored in data->len. |
* @param str source string to print |
* @param count size of source string |
* @param data structure with destination string, counter of used space and total string size. |
* @return number of characters to print (not characters really printed!) |
* Write at most data->size characters including trailing zero. According to C99 |
* has snprintf to return number of characters that would have been written if |
* enough space had been available. Hence the return value is not number of |
* really printed characters but size of input string. Number of really used |
* characters is stored in data->len. |
* |
* @param str Source string to print. |
* @param count Size of the source string. |
* @param data Structure with destination string, counter of used space |
* and total string size. |
* @return Number of characters to print (not characters really |
* printed!) |
*/ |
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int |
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
{ |
size_t i; |
i = data->size - data->len; |
63,7 → 68,10 |
} |
if (i == 1) { |
/* We have only one free byte left in buffer => write there trailing zero */ |
/* |
* We have only one free byte left in buffer => write there |
* trailing zero. |
*/ |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
70,17 → 78,23 |
} |
if (i <= count) { |
/* We have not enought space for whole string with the trailing zero => print only a part of string */ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
/* |
* We have not enought space for whole string with the trailing |
* zero => print only a part of string. |
*/ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
} |
/* Buffer is big enought to print whole string */ |
memcpy((void *)(data->string + data->len), (void *)str, count); |
data->len += count; |
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */ |
/* |
* Put trailing zero at end, but not count it into data->len so it could |
* be rewritten next time. |
*/ |
data->string[data->len] = 0; |
return count; |
87,17 → 101,22 |
} |
/** Print formatted to the given buffer with limited size. |
* @param str buffer |
* @param size buffer size |
* @param fmt format string |
* @param str Buffer. |
* @param size Bffer size. |
* @param fmt Format string. |
* \see For more details about format string see printf_core. |
*/ |
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
{ |
struct vsnprintf_data data = {size, 0, str}; |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data}; |
struct printf_spec ps = { |
(int(*)(void *, size_t, void *)) vsnprintf_write, |
&data |
}; |
/* Print 0 at end of string - fix the case that nothing will be printed */ |
/* |
* Print 0 at end of string - fix the case that nothing will be printed. |
*/ |
if (size > 0) |
str[0] = 0; |
/branches/dd/uspace/lib/libc/generic/io/printf_core.c |
---|
94,12 → 94,9 |
if (str == NULL) |
return printf_putnchars("(NULL)", 6, ps); |
for (count = 0; str[count] != 0; count++); |
count = strlen(str); |
if (ps->write((void *) str, count, ps->data) == count) |
return 0; |
return EOF; |
return ps->write((void *) str, count, ps->data); |
} |
/** Print one character to output |
/branches/dd/uspace/lib/libc/generic/io/stream.c |
---|
42,7 → 42,8 |
#include <ipc/ns.h> |
#include <ipc/fb.h> |
#include <ipc/services.h> |
#include <console.h> |
#include <ipc/console.h> |
#include <kbd/kbd.h> |
#include <unistd.h> |
#include <async.h> |
#include <sys/types.h> |
56,54 → 57,77 |
ssize_t read_stdin(void *buf, size_t count) |
{ |
ipcarg_t r0, r1; |
size_t i = 0; |
open_console(); |
if (console_phone >= 0) { |
kbd_event_t ev; |
int rc; |
size_t i = 0; |
while (i < count) { |
do { |
rc = kbd_get_event(&ev); |
if (rc < 0) return -1; |
} while (ev.c == 0 || ev.type == KE_RELEASE); |
while (i < count) { |
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, |
&r1) < 0) { |
return -1; |
((char *) buf)[i++] = ev.c; |
} |
((char *) buf)[i++] = r0; |
return i; |
} else { |
return -1; |
} |
return i; |
} |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
int i; |
for (i = 0; i < count; i++) |
async_msg_1(console_phone, CONSOLE_PUTCHAR, |
((const char *) buf)[i]); |
open_console(); |
if (console_phone >= 0) { |
int i; |
return count; |
for (i = 0; i < count; i++) |
async_msg_1(console_phone, CONSOLE_PUTCHAR, |
((const char *) buf)[i]); |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
void open_stdin(void) |
void open_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
} |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, 0); |
if (phone >= 0) |
console_phone = phone; |
} |
} |
void open_stdout(void) |
void close_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
} |
} |
} |
int get_cons_phone(void) |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
} |
int get_console_phone(void) |
{ |
if (console_phone < 0) |
console_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_CONSOLE, 0, 0); |
return console_phone; |
} |
void console_wait(void) |
{ |
while (console_phone < 0) |
get_console_phone(); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/Makefile |
---|
31,7 → 31,6 |
LIBC_PREFIX = $(shell pwd) |
SOFTINT_PREFIX = ../softint |
CONSOLE_PREFIX = ../../srv/console |
## Setup toolchain |
# |
38,25 → 37,30 |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I$(CONSOLE_PREFIX) |
## Sources |
# |
GENERIC_SOURCES = \ |
generic/libc.c \ |
generic/ddi.c \ |
generic/as.c \ |
generic/cap.c \ |
generic/console.c \ |
generic/mem.c \ |
generic/string.c \ |
generic/fibril.c \ |
generic/pcb.c \ |
generic/smc.c \ |
generic/thread.c \ |
generic/tls.c \ |
generic/task.c \ |
generic/futex.c \ |
generic/io/asprintf.c \ |
generic/io/io.c \ |
generic/io/printf.c \ |
generic/io/fprintf.c \ |
generic/io/stdio.c \ |
generic/io/stream.c \ |
generic/io/sprintf.c \ |
generic/io/snprintf.c \ |
68,44 → 72,49 |
generic/sysinfo.c \ |
generic/ipc.c \ |
generic/async.c \ |
generic/loader.c \ |
generic/getopt.c \ |
generic/libadt/list.o \ |
generic/libadt/hash_table.o \ |
generic/time.c \ |
generic/err.c \ |
generic/stdlib.c \ |
generic/kbd.c \ |
generic/mman.c \ |
generic/udebug.c \ |
generic/vfs/vfs.c \ |
generic/vfs/canonify.c |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/entry.s \ |
arch/$(ARCH)/src/thread_entry.s |
arch/$(UARCH)/src/entry.s \ |
arch/$(UARCH)/src/thread_entry.s |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS) |
.PHONY: all clean depend kerninc |
all: kerninc libc.a arch/$(ARCH)/_link.ld |
all: kerninc libc.a arch/$(UARCH)/_link.ld |
kerninc: |
ln -sfn ../../../../kernel/generic/include include/kernel |
ln -sfn kernel/arch include/arch |
ln -sfn ../arch/$(ARCH)/include include/libarch |
ln -sfn ../arch/$(UARCH)/include include/libarch |
-include Makefile.depend |
clean: |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(ARCH)/_link.ld Makefile.depend |
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \; |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend |
find generic/ arch/$(UARCH)/ malloc -name '*.o' -follow -exec rm \{\} \; |
depend: kerninc |
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS) |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
/branches/dd/uspace/lib/libc/arch/ppc64/_link.ld.in |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/syscall.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/atomic.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/regname.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/stackarg.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/faddr.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/limits.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/tls.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/types.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/config.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/thread.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/include/fibril.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/Makefile.inc |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/src/entry.s |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/src/tls.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/src/fibril.S |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/src/thread_entry.s |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc64/src/syscall.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/sparc64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/sparc64/include/syscall.h |
---|
38,6 → 38,14 |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall |
#define __syscall1 __syscall |
#define __syscall2 __syscall |
#define __syscall3 __syscall |
#define __syscall4 __syscall |
#define __syscall5 __syscall |
#define __syscall6 __syscall |
static inline sysarg_t |
__syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3, |
const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, const syscall_t id) |
/branches/dd/uspace/lib/libc/arch/sparc64/include/ddi.h |
---|
0,0 → 1,92 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libsparc64 |
*/ |
#ifndef LIBC_sparc64_DDI_H_ |
#define LIBC_sparc64_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline memory_barrier(void) |
{ |
asm volatile ("membar #LoadLoad | #StoreStore\n" ::: "memory"); |
} |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
memory_barrier(); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uint8_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uint16_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uint32_t rv; |
rv = *port; |
memory_barrier(); |
return rv; |
} |
#endif |
/branches/dd/uspace/lib/libc/arch/sparc64/include/config.h |
---|
37,7 → 37,6 |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /**< Only one page color. */ |
#endif |
/branches/dd/uspace/lib/libc/arch/sparc64/Makefile.inc |
---|
30,10 → 30,10 |
# |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mcpu=ultrasparc -m64 |
LFLAGS += -no-check-sections -N |
/branches/dd/uspace/lib/libc/arch/sparc64/src/entry.s |
---|
31,27 → 31,18 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %o0 contains uarg |
# %o1 contains pcb_ptr |
# |
__entry: |
# Pass pcb_ptr as the first argument to __main() |
mov %o1, %o0 |
sethi %hi(_gp), %l7 |
call __main |
or %l7, %lo(_gp), %l7 |
call __io_init |
nop |
call main |
nop |
call __exit |
nop |
__entry_driver: |
sethi %hi(_gp), %l7 |
call __main |
or %l7, %lo(_gp), %l7 |
call main |
nop |
call __exit |
nop |
/branches/dd/uspace/lib/libc/arch/ia64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/ia64/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_ia64_SYSCALL_H_ |
#define LIBC_ia64_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/dd/uspace/lib/libc/arch/ia64/include/ddi.h |
---|
0,0 → 1,115 |
/* |
* Copyright (c) 2005 Jakub Vana |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_ia64_DDI_H_ |
#define LIBC_ia64_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
#define IO_SPACE_BOUNDARY (64 * 1024) |
uint64_t get_ia64_iospace_address(void); |
extern uint64_t ia64_iospace_address; |
#define IA64_IOSPACE_ADDRESS \ |
(ia64_iospace_address ? \ |
ia64_iospace_address : \ |
(ia64_iospace_address = get_ia64_iospace_address())) |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/arch/ia64/include/config.h |
---|
36,8 → 36,7 |
#define LIBC_ia64_CONFIG_H_ |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#endif |
/branches/dd/uspace/lib/libc/arch/ia64/Makefile.inc |
---|
30,14 → 30,15 |
# |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16 |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/ddi.c |
BFD_NAME = elf64-ia64-little |
BFD_ARCH = ia64-elf64 |
/branches/dd/uspace/lib/libc/arch/ia64/src/ddi.c |
---|
0,0 → 1,13 |
#include <libarch/ddi.h> |
#include <sysinfo.h> |
uint64_t ia64_iospace_address=0; |
uint64_t get_ia64_iospace_address(void) |
{ |
return sysinfo_value("ia64_iospace.address.virtual"); |
} |
/branches/dd/uspace/lib/libc/arch/ia64/src/entry.s |
---|
31,27 → 31,17 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# r2 contains the PCB pointer |
# |
__entry: |
alloc loc0 = ar.pfs, 0, 1, 2, 0 |
mov r1 = _gp |
br.call.sptk.many b0 = __main |
0: |
br.call.sptk.many b0 = __io_init |
1: |
br.call.sptk.many b0 = main |
2: |
br.call.sptk.many b0 = __exit |
movl r1 = _gp |
__entry_driver: |
alloc loc0 = ar.pfs, 0, 1, 2, 0 |
mov r1 = _gp |
# Pass PCB pointer as the first argument to __main |
mov out0 = r2 |
br.call.sptk.many b0 = __main |
0: |
br.call.sptk.many b0 = main |
1: |
br.call.sptk.many b0 = __exit |
/branches/dd/uspace/lib/libc/arch/ia64/src/thread_entry.s |
---|
36,7 → 36,7 |
__thread_entry: |
alloc loc0 = ar.pfs, 0, 1, 1, 0 |
mov r1 = _gp |
movl r1 = _gp |
# |
# r8 contains address of uarg structure. |
/branches/dd/uspace/lib/libc/arch/arm32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/arm32/include/syscall.h |
---|
30,12 → 30,14 |
* @{ |
*/ |
/** @file |
* @brief Empty. |
* @brief |
*/ |
#ifndef LIBC_arm32_SYSCALL_H_ |
#define LIBC_arm32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/dd/uspace/lib/libc/arch/arm32/include/byteorder.h |
---|
36,7 → 36,7 |
#ifndef LIBC_arm32_BYTEORDER_H_ |
#define LIBC_arm32_BYTEORDER_H_ |
#define ARCH_IS_BIG_ENDIAN |
#define ARCH_IS_LITTLE_ENDIAN |
#endif |
/branches/dd/uspace/lib/libc/arch/arm32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcarm32 |
*/ |
#ifndef LIBC_arm32_DDI_H_ |
#define LIBC_arm32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/dd/uspace/lib/libc/arch/arm32/include/config.h |
---|
38,7 → 38,6 |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#endif |
/branches/dd/uspace/lib/libc/arch/arm32/Makefile.inc |
---|
31,15 → 31,15 |
# |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
CFLAGS += -ffixed-r9 -mtp=soft |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
AFLAGS += |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c \ |
arch/$(ARCH)/src/eabi.S |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/eabi.S |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
/branches/dd/uspace/lib/libc/arch/arm32/src/entry.s |
---|
31,19 → 31,14 |
.org 0 |
.global __entry |
.global __entry_driver |
## User-space task entry point |
# |
# r1 contains the PCB pointer |
# |
__entry: |
# Pass pcb_ptr to __main as the first argument (in r0) |
mov r0, r1 |
bl __main |
bl __io_init |
bl main |
bl __exit |
__entry_driver: |
bl __main |
bl main |
bl __exit |
/branches/dd/uspace/lib/libc/arch/mips32eb/Makefile.inc |
---|
30,12 → 30,12 |
# |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = /usr/local/mips/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
LFLAGS += -N |
/branches/dd/uspace/lib/libc/arch/ppc32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/ppc32/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_ppc32_SYSCALL_H_ |
#define LIBC_ppc32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/dd/uspace/lib/libc/arch/ppc32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcppc32 |
*/ |
#ifndef LIBC_ppc32_DDI_H_ |
#define LIBC_ppc32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/dd/uspace/lib/libc/arch/ppc32/include/config.h |
---|
36,8 → 36,7 |
#define LIBC_ppc32_CONFIG_H_ |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#endif |
/branches/dd/uspace/lib/libc/arch/ppc32/Makefile.inc |
---|
30,11 → 30,11 |
# |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
/branches/dd/uspace/lib/libc/arch/ppc32/src/entry.s |
---|
31,18 → 31,15 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# r6 contains the PCB pointer |
# |
__entry: |
# Pass the PCB pointer to __main() as the first argument. |
# The first argument is passed in r3. |
mr %r3, %r6 |
bl __main |
bl __io_init |
bl main |
bl __exit |
__entry_driver: |
bl __main |
bl main |
bl __exit |
/branches/dd/uspace/lib/libc/arch/amd64/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/amd64/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_amd64_SYSCALL_H_ |
#define LIBC_amd64_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/dd/uspace/lib/libc/arch/amd64/include/atomic.h |
---|
38,11 → 38,11 |
#define LIBC_amd64_ATOMIC_H_ |
static inline void atomic_inc(atomic_t *val) { |
asm volatile ("lock incq %0\n" : "=m" (val->count)); |
asm volatile ("lock incq %0\n" : "+m" (val->count)); |
} |
static inline void atomic_dec(atomic_t *val) { |
asm volatile ("lock decq %0\n" : "=m" (val->count)); |
asm volatile ("lock decq %0\n" : "+m" (val->count)); |
} |
static inline long atomic_postinc(atomic_t *val) |
52,7 → 52,7 |
asm volatile ( |
"movq $1, %0\n" |
"lock xaddq %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
65,14 → 65,14 |
asm volatile ( |
"movq $-1, %0\n" |
"lock xaddq %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
} |
#define atomic_preinc(val) (atomic_postinc(val)+1) |
#define atomic_predec(val) (atomic_postdec(val)-1) |
#define atomic_preinc(val) (atomic_postinc(val) + 1) |
#define atomic_predec(val) (atomic_postdec(val) - 1) |
#endif |
/branches/dd/uspace/lib/libc/arch/amd64/include/config.h |
---|
36,8 → 36,7 |
#define LIBC_amd64_CONFIG_H_ |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#endif |
/branches/dd/uspace/lib/libc/arch/amd64/Makefile.inc |
---|
30,11 → 30,11 |
# |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/amd64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
LFLAGS += -N |
/branches/dd/uspace/lib/libc/arch/amd64/src/entry.s |
---|
31,18 → 31,14 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %rdi contains the PCB pointer |
# |
__entry: |
# %rdi was deliberately chosen as the first argument is also in %rdi |
# Pass PCB pointer to __main (no operation) |
call __main |
call __io_init |
call main |
call __exit |
__entry_driver: |
call __main |
call main |
call __exit |
/branches/dd/uspace/lib/libc/arch/mips32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/mips32/include/syscall.h |
---|
36,6 → 36,8 |
#ifndef LIBC_mips32_SYSCALL_H_ |
#define LIBC_mips32_SYSCALL_H_ |
#define LIBARCH_SYSCALL_GENERIC |
#include <syscall.h> |
#endif |
/branches/dd/uspace/lib/libc/arch/mips32/include/atomic.h |
---|
59,13 → 59,14 |
asm volatile ( |
"1:\n" |
" ll %0, %1\n" |
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */ |
" addu %0, %0, %3\n" /* same as add, but never traps on overflow */ |
" move %2, %0\n" |
" sc %0, %1\n" |
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ |
/* nop */ /* nop is inserted automatically by compiler */ |
: "=r" (tmp), "=m" (val->count), "=r" (v) |
: "i" (i), "i" (0) |
" nop\n" |
: "=&r" (tmp), "+m" (val->count), "=&r" (v) |
: "r" (i), "i" (0) |
); |
return v; |
/branches/dd/uspace/lib/libc/arch/mips32/include/ddi.h |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @file |
* @ingroup libcmips32 |
*/ |
#ifndef LIBC_mips32_DDI_H_ |
#define LIBC_mips32_DDI_H_ |
#include <sys/types.h> |
#include <libarch/types.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
{ |
*port = v; |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
{ |
*port = v; |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
{ |
*port = v; |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
return *port; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
return *port; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
return *port; |
} |
#endif |
/branches/dd/uspace/lib/libc/arch/mips32/include/config.h |
---|
36,8 → 36,7 |
#define LIBC_mips32_CONFIG_H_ |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#endif |
/branches/dd/uspace/lib/libc/arch/mips32/Makefile.inc |
---|
30,18 → 30,12 |
# |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
CFLAGS += -mips3 |
-include ../../Makefile.config |
ifeq ($(CONFIG_MIPS_FPU),y) |
CFLAGS += -DCONFIG_MIPS_FPU |
endif |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c |
BFD_ARCH = mips |
BFD_NAME = elf32-tradlittlemips |
/branches/dd/uspace/lib/libc/arch/mips32/src/entry.s |
---|
35,13 → 35,13 |
## User-space task entry point |
# |
# $a0 ($4) contains the PCB pointer |
# |
.ent __entry |
__entry: |
.frame $sp, 32, $31 |
.cpload $25 |
# Mips o32 may store its arguments on stack, make space (16 bytes), |
# so that it could work with -O0 |
# Make space additional 16 bytes for the stack frame |
48,42 → 48,18 |
addiu $sp, -32 |
.cprestore 16 # Allow PIC code |
jal __main |
nop |
jal __io_init |
nop |
jal main |
nop |
jal __exit |
nop |
.end |
.ent __entry_driver |
__entry_driver: |
.frame $sp, 32, $31 |
.cpload $25 |
# Mips o32 may store its arguments on stack, make space (16 bytes), |
# so that it could work with -O0 |
# Make space additional 16 bytes for the stack frame |
# Pass pcb_ptr to __main() as the first argument. pcb_ptr is already |
# in $a0. As the first argument is passed in $a0, no operation |
# is needed. |
addiu $sp, -32 |
.cprestore 16 # Allow PIC code |
jal __main |
nop |
jal main |
nop |
jal __exit |
nop |
.end |
# Alignment of output section data to 0x4000 |
.section .data |
.align 14 |
/branches/dd/uspace/lib/libc/arch/ia32/_link.ld.in |
---|
1,4 → 1,4 |
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o) |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
/branches/dd/uspace/lib/libc/arch/ia32/include/syscall.h |
---|
36,8 → 36,25 |
#ifndef LIBC_ia32_SYSCALL_H_ |
#define LIBC_ia32_SYSCALL_H_ |
#include <syscall.h> |
#include <sys/types.h> |
#include <kernel/syscall/syscall.h> |
#define __syscall0 __syscall_sysenter |
#define __syscall1 __syscall_sysenter |
#define __syscall2 __syscall_sysenter |
#define __syscall3 __syscall_sysenter |
#define __syscall4 __syscall_sysenter |
#define __syscall5 __syscall_int |
#define __syscall6 __syscall_int |
extern sysarg_t |
__syscall_sysenter(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t, |
const sysarg_t, const sysarg_t, const syscall_t); |
extern sysarg_t |
__syscall_int(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t, |
const sysarg_t, const sysarg_t, const syscall_t); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/arch/ia32/include/atomic.h |
---|
36,11 → 36,11 |
#define LIBC_ia32_ATOMIC_H_ |
static inline void atomic_inc(atomic_t *val) { |
asm volatile ("lock incl %0\n" : "=m" (val->count)); |
asm volatile ("lock incl %0\n" : "+m" (val->count)); |
} |
static inline void atomic_dec(atomic_t *val) { |
asm volatile ("lock decl %0\n" : "=m" (val->count)); |
asm volatile ("lock decl %0\n" : "+m" (val->count)); |
} |
static inline long atomic_postinc(atomic_t *val) |
50,7 → 50,7 |
asm volatile ( |
"movl $1, %0\n" |
"lock xaddl %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
63,14 → 63,14 |
asm volatile ( |
"movl $-1, %0\n" |
"lock xaddl %0, %1\n" |
: "=r" (r), "=m" (val->count) |
: "=r" (r), "+m" (val->count) |
); |
return r; |
} |
#define atomic_preinc(val) (atomic_postinc(val)+1) |
#define atomic_predec(val) (atomic_postdec(val)-1) |
#define atomic_preinc(val) (atomic_postinc(val) + 1) |
#define atomic_predec(val) (atomic_postdec(val) - 1) |
#endif |
/branches/dd/uspace/lib/libc/arch/ia32/include/ddi.h |
---|
33,43 → 33,72 |
#ifndef LIBC_ia32_DDI_H_ |
#define LIBC_ia32_DDI_H_ |
static inline void outb(int16_t port, uint8_t b) |
#include <sys/types.h> |
#include <libarch/types.h> |
#define IO_SPACE_BOUNDARY ((void *) (64 * 1024)) |
static inline uint8_t pio_read_8(ioport8_t *port) |
{ |
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port)); |
uint8_t val; |
asm volatile ( |
"inb %w[port], %b[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline void outw(int16_t port, int16_t w) |
static inline uint16_t pio_read_16(ioport16_t *port) |
{ |
asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port)); |
uint16_t val; |
asm volatile ( |
"inw %w[port], %w[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline void outl(int16_t port, uint32_t l) |
static inline uint32_t pio_read_32(ioport32_t *port) |
{ |
asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port)); |
uint32_t val; |
asm volatile ( |
"inl %w[port], %[val]\n" |
: [val] "=a" (val) |
: [port] "d" (port) |
); |
return val; |
} |
static inline uint8_t inb(int16_t port) |
static inline void pio_write_8(ioport8_t *port, uint8_t val) |
{ |
uint8_t val; |
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outb %b[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
static inline int16_t inw(int16_t port) |
static inline void pio_write_16(ioport16_t *port, uint16_t val) |
{ |
int16_t val; |
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outw %w[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
static inline uint32_t inl(int16_t port) |
static inline void pio_write_32(ioport32_t *port, uint32_t val) |
{ |
uint32_t val; |
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
asm volatile ( |
"outl %[val], %w[port]\n" |
:: [val] "a" (val), [port] "d" (port) |
); |
} |
#endif |
/branches/dd/uspace/lib/libc/arch/ia32/include/config.h |
---|
36,8 → 36,7 |
#define LIBC_ia32_CONFIG_H_ |
#define PAGE_WIDTH 12 |
#define PAGE_SIZE (1<<PAGE_WIDTH) |
#define PAGE_COLOR_BITS 0 /* dummy */ |
#define PAGE_SIZE (1 << PAGE_WIDTH) |
#endif |
/branches/dd/uspace/lib/libc/arch/ia32/Makefile.inc |
---|
30,12 → 30,12 |
# |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/i686/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/fibril.S \ |
arch/$(ARCH)/src/tls.c \ |
arch/$(ARCH)/src/setjmp.S |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/setjmp.S |
LFLAGS += -N |
/branches/dd/uspace/lib/libc/arch/ia32/src/entry.s |
---|
31,10 → 31,10 |
.org 0 |
.globl __entry |
.globl __entry_driver |
## User-space task entry point |
# |
# %ebx contains the PCB pointer |
# |
__entry: |
mov %ss, %ax |
42,19 → 42,9 |
mov %ax, %es |
mov %ax, %fs |
# Do not set %gs, it contains descriptor that can see TLS |
# Pass the PCB pointer to __main as the first argument |
pushl %ebx |
call __main |
call __io_init |
call main |
call __exit |
__entry_driver: |
mov %ss, %ax |
mov %ax, %ds |
mov %ax, %es |
mov %ax, %fs |
# Do not set %gs, it contains descriptor that can see TLS |
call __main |
call main |
call __exit |
/branches/dd/uspace/lib/libc/arch/ia32/src/syscall.S |
---|
28,14 → 28,14 |
.text |
/** Syscall wrapper. |
/** Syscall wrapper - INT $0x30 version. |
* |
* Mind the order of arguments. First two arguments and the syscall number go to |
* scratch registers. An optimized version of this wrapper for fewer arguments |
* could benefit from this and not save unused registers on the stack. |
*/ |
.global __syscall |
__syscall: |
.global __syscall_int |
__syscall_int: |
pushl %ebx |
pushl %esi |
pushl %edi |
54,3 → 54,37 |
popl %ebx |
ret |
/** Syscall wrapper - SYSENTER version. |
* |
* This is an optimized version of syscall for four or less arguments. Note |
* that EBP and EDI are used to remember user stack address and the return |
* address. The kernel part doesn't save DS, ES and FS so the handler restores |
* these to the selector immediately following CS (it must be the flat data |
* segment, otherwise the SYSENTER wouldn't work in the first place). |
*/ |
.global __syscall_sysenter |
__syscall_sysenter: |
pushl %ebx |
pushl %esi |
pushl %edi |
pushl %ebp |
mov %esp, %ebp |
lea ra, %edi |
movl 20(%esp), %edx # First argument. |
movl 24(%esp), %ecx # Second argument. |
movl 28(%esp), %ebx # Third argument. |
movl 32(%esp), %esi # Fourth argument. |
movl 44(%esp), %eax # Syscall number. |
sysenter |
ra: |
movw %cs, %cx |
addw $8, %cx |
movw %cx, %ds |
movw %cx, %es |
movw %cx, %fs |
popl %ebp |
popl %edi |
popl %esi |
popl %ebx |
ret |
/branches/dd/uspace/srv/kbd/arch/ia32/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia32/include/scanc.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia32/src/scanc.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia32/src/mouse.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia32/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/sparc64/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/sparc64/include/scanc.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/sparc64/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/sparc64/src/scanc.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia64/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ia64/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/arm32/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/arm32/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/arm32/src/kbd_gxemul.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/mips32eb |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/uspace/srv/kbd/arch/ppc32/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ppc32/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/amd64 |
---|
File deleted |
\ No newline at end of file |
Property changes: |
Deleted: svn:special |
-* |
\ No newline at end of property |
/branches/dd/uspace/srv/kbd/arch/ppc64/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/ppc64/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/mips32/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/arch/mips32/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/genarch/include/kbd.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/genarch/include/scanc.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/genarch/src/kbd.c |
---|
File deleted |
/branches/dd/uspace/srv/kbd/ctl/stty.c |
---|
0,0 → 1,329 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Serial TTY-like keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
static void parse_ds_start(int scancode); |
static void parse_ds_e(int scancode); |
static void parse_ds_e1(int scancode); |
static void parse_ds_e2(int scancode); |
static void parse_ds_e2a(int scancode); |
static void parse_ds_e2b(int scancode); |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
enum dec_state { |
ds_start, |
ds_e, |
ds_e1, |
ds_e2, |
ds_e2a, |
ds_e2b |
}; |
static int map_start[][2] = { |
[0x60] = { 0, KC_BACKTICK }, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
[0x0f] = { 0, KC_TAB }, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
[0x20] = { 0, KC_SPACE }, |
[0x1b] = { 0, KC_ESCAPE }, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
/* with Shift pressed */ |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
}; |
static int map_e1[][2] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
}; |
static int map_e2[][2] = |
{ |
[0x41] = { 0, KC_UP }, |
[0x42] = { 0, KC_DOWN }, |
[0x44] = { 0, KC_LEFT }, |
[0x43] = { 0, KC_RIGHT }, |
}; |
static int map_e2a[][2] = |
{ |
[0x35] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
}; |
static int map_e2b[][2] = |
{ |
[0x30] = { 0, KC_F9 }, |
[0x31] = { 0, KC_F10 }, |
[0x32] = { 0, KC_F11 }, |
[0x33] = { 0, KC_F12 }, |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
switch (ds) { |
case ds_start: parse_ds_start(scancode); break; |
case ds_e: parse_ds_e(scancode); break; |
case ds_e1: parse_ds_e1(scancode); break; |
case ds_e2: parse_ds_e2(scancode); break; |
case ds_e2a: parse_ds_e2a(scancode); break; |
case ds_e2b: parse_ds_e2b(scancode); break; |
} |
} |
static void parse_ds_start(int scancode) |
{ |
if (scancode == 0x1b) { |
ds = ds_e; |
return; |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
} |
static void parse_ds_e(int scancode) |
{ |
if (scancode < 0 || scancode >= 0x80) return; |
switch (scancode) { |
case 0x4f: ds = ds_e1; return; |
case 0x5b: ds = ds_e2; return; |
case 0x1b: ds = ds_start; break; |
default: ds = ds_start; return; |
} |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
} |
static void parse_ds_e1(int scancode) |
{ |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
} |
static void parse_ds_e2(int scancode) |
{ |
switch (scancode) { |
case 0x31: ds = ds_e2a; break; |
case 0x32: ds = ds_e2b; break; |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e2, sizeof(map_e2) / (2 * sizeof(int))); |
} |
static void parse_ds_e2a(int scancode) |
{ |
parse_leaf(scancode, map_e2a, sizeof(map_e2a) / (2 * sizeof(int))); |
} |
static void parse_ds_e2b(int scancode) |
{ |
parse_leaf(scancode, map_e2b, sizeof(map_e2b) / (2 * sizeof(int))); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
ds = ds_start; |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/ctl/gxe_fb.c |
---|
0,0 → 1,322 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief GXEmul framebuffer-mode keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
static void parse_ds_start(int scancode); |
static void parse_ds_e(int scancode); |
static void parse_ds_e1(int scancode); |
static void parse_ds_e1a(int scancode); |
static void parse_ds_e1b(int scancode); |
static void parse_ds_e1c(int scancode); |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
enum dec_state { |
ds_start, |
ds_e, |
ds_e1, |
ds_e1a, |
ds_e1b, |
ds_e1c |
}; |
static int map_start[][2] = { |
[0x60] = { 0, KC_BACKTICK }, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
[0x0f] = { 0, KC_TAB }, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
[0x20] = { 0, KC_SPACE }, |
[0x1b] = { 0, KC_ESCAPE }, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
/* with Shift pressed */ |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
}; |
static int map_e1[][2] = |
{ |
}; |
static int map_e1a[][2] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
}; |
static int map_e1b[][2] = |
{ |
[0x33] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
}; |
static int map_e1c[][2] = |
{ |
[0x38] = { 0, KC_F9 }, |
[0x39] = { 0, KC_F10 }, |
[0x33] = { 0, KC_F11 }, |
[0x34] = { 0, KC_F12 }, |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds = ds_start; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
switch (ds) { |
case ds_start: parse_ds_start(scancode); break; |
case ds_e: parse_ds_e(scancode); break; |
case ds_e1: parse_ds_e1(scancode); break; |
case ds_e1a: parse_ds_e1a(scancode); break; |
case ds_e1b: parse_ds_e1b(scancode); break; |
case ds_e1c: parse_ds_e1c(scancode); break; |
} |
} |
static void parse_ds_start(int scancode) |
{ |
if (scancode == 0x1b) { |
ds = ds_e; |
return; |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
} |
static void parse_ds_e(int scancode) |
{ |
switch (scancode) { |
case 0x5b: ds = ds_e1; return; |
case 0x1b: ds = ds_start; break; |
default: ds = ds_start; return; |
} |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
} |
static void parse_ds_e1(int scancode) |
{ |
switch (scancode) { |
case 0x4f: ds = ds_e1a; return; |
case 0x31: ds = ds_e1b; return; |
case 0x32: ds = ds_e1c; return; |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
} |
static void parse_ds_e1a(int scancode) |
{ |
parse_leaf(scancode, map_e1a, sizeof(map_e1a) / (2 * sizeof(int))); |
} |
static void parse_ds_e1b(int scancode) |
{ |
parse_leaf(scancode, map_e1b, sizeof(map_e1b) / (2 * sizeof(int))); |
} |
static void parse_ds_e1c(int scancode) |
{ |
parse_leaf(scancode, map_e1c, sizeof(map_e1c) / (2 * sizeof(int))); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
ds = ds_start; |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/ctl/pc.c |
---|
0,0 → 1,225 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief PC keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
enum dec_state { |
ds_s, |
ds_e |
}; |
static enum dec_state ds = ds_s; |
static int scanmap_simple[] = { |
[0x29] = KC_BACKTICK, |
[0x02] = KC_1, |
[0x03] = KC_2, |
[0x04] = KC_3, |
[0x05] = KC_4, |
[0x06] = KC_5, |
[0x07] = KC_6, |
[0x08] = KC_7, |
[0x09] = KC_8, |
[0x0a] = KC_9, |
[0x0b] = KC_0, |
[0x0c] = KC_MINUS, |
[0x0d] = KC_EQUALS, |
[0x0e] = KC_BACKSPACE, |
[0x0f] = KC_TAB, |
[0x10] = KC_Q, |
[0x11] = KC_W, |
[0x12] = KC_E, |
[0x13] = KC_R, |
[0x14] = KC_T, |
[0x15] = KC_Y, |
[0x16] = KC_U, |
[0x17] = KC_I, |
[0x18] = KC_O, |
[0x19] = KC_P, |
[0x1a] = KC_LBRACKET, |
[0x1b] = KC_RBRACKET, |
[0x3a] = KC_CAPS_LOCK, |
[0x1e] = KC_A, |
[0x1f] = KC_S, |
[0x20] = KC_D, |
[0x21] = KC_F, |
[0x22] = KC_G, |
[0x23] = KC_H, |
[0x24] = KC_J, |
[0x25] = KC_K, |
[0x26] = KC_L, |
[0x27] = KC_SEMICOLON, |
[0x28] = KC_QUOTE, |
[0x2b] = KC_BACKSLASH, |
[0x2a] = KC_LSHIFT, |
[0x2c] = KC_Z, |
[0x2d] = KC_X, |
[0x2e] = KC_C, |
[0x2f] = KC_V, |
[0x30] = KC_B, |
[0x31] = KC_N, |
[0x32] = KC_M, |
[0x33] = KC_COMMA, |
[0x34] = KC_PERIOD, |
[0x35] = KC_SLASH, |
[0x36] = KC_RSHIFT, |
[0x1d] = KC_LCTRL, |
[0x38] = KC_LALT, |
[0x39] = KC_SPACE, |
[0x01] = KC_ESCAPE, |
[0x3b] = KC_F1, |
[0x3c] = KC_F2, |
[0x3d] = KC_F3, |
[0x3e] = KC_F4, |
[0x3f] = KC_F5, |
[0x40] = KC_F6, |
[0x41] = KC_F7, |
[0x42] = KC_F8, |
[0x43] = KC_F9, |
[0x44] = KC_F10, |
[0x57] = KC_F11, |
[0x58] = KC_F12, |
[0x46] = KC_SCROLL_LOCK, |
[0x1c] = KC_ENTER, |
[0x45] = KC_NUM_LOCK, |
[0x37] = KC_NTIMES, |
[0x4a] = KC_NMINUS, |
[0x4e] = KC_NPLUS, |
[0x47] = KC_N7, |
[0x48] = KC_N8, |
[0x49] = KC_N9, |
[0x4b] = KC_N4, |
[0x4c] = KC_N5, |
[0x4d] = KC_N6, |
[0x4f] = KC_N1, |
[0x50] = KC_N2, |
[0x51] = KC_N3, |
[0x52] = KC_N0, |
[0x53] = KC_NPERIOD |
}; |
static int scanmap_e0[] = { |
[0x38] = KC_RALT, |
[0x1d] = KC_RSHIFT, |
[0x37] = KC_PRTSCR, |
[0x52] = KC_INSERT, |
[0x47] = KC_HOME, |
[0x49] = KC_PAGE_UP, |
[0x53] = KC_DELETE, |
[0x4f] = KC_END, |
[0x51] = KC_PAGE_DOWN, |
[0x48] = KC_UP, |
[0x4b] = KC_LEFT, |
[0x50] = KC_DOWN, |
[0x4d] = KC_RIGHT, |
[0x35] = KC_NSLASH, |
[0x1c] = KC_NENTER |
}; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
kbd_ev_type_t type; |
unsigned int key; |
int *map; |
size_t map_length; |
if (scancode == 0xe0) { |
ds = ds_e; |
return; |
} |
switch (ds) { |
case ds_s: |
map = scanmap_simple; |
map_length = sizeof(scanmap_simple) / sizeof(int); |
break; |
case ds_e: |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
} |
ds = ds_s; |
if (scancode & 0x80) { |
scancode &= ~0x80; |
type = KE_RELEASE; |
} else { |
type = KE_PRESS; |
} |
if (scancode < 0 || scancode >= map_length) |
return; |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/ctl/sun.c |
---|
0,0 → 1,204 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_ctl |
* @ingroup kbd |
* @{ |
*/ |
/** |
* @file |
* @brief Sun keyboard controller driver. |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
#define KBD_KEY_RELEASE 0x80 |
#define KBD_ALL_KEYS_UP 0x7f |
static int scanmap_simple[]; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
kbd_ev_type_t type; |
unsigned int key; |
if (scancode < 0 || scancode >= 0x100) |
return; |
if (scancode == KBD_ALL_KEYS_UP) |
return; |
if (scancode & KBD_KEY_RELEASE) { |
scancode &= ~KBD_KEY_RELEASE; |
type = KE_RELEASE; |
} else { |
type = KE_PRESS; |
} |
key = scanmap_simple[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
/** Primary meaning of scancodes. */ |
static int scanmap_simple[] = { |
[0x00] = 0, |
[0x01] = 0, |
[0x02] = 0, |
[0x03] = 0, |
[0x04] = 0, |
[0x05] = KC_F1, |
[0x06] = KC_F2, |
[0x07] = KC_F10, |
[0x08] = KC_F3, |
[0x09] = KC_F11, |
[0x0a] = KC_F4, |
[0x0b] = KC_F12, |
[0x0c] = KC_F5, |
[0x0d] = KC_RALT, |
[0x0e] = KC_F6, |
[0x0f] = 0, |
[0x10] = KC_F7, |
[0x11] = KC_F8, |
[0x12] = KC_F9, |
[0x13] = KC_LALT, |
[0x14] = KC_UP, |
[0x15] = KC_PAUSE, |
[0x16] = 0, |
[0x17] = KC_SCROLL_LOCK, |
[0x18] = KC_LEFT, |
[0x19] = 0, |
[0x1a] = 0, |
[0x1b] = KC_DOWN, |
[0x1c] = KC_RIGHT, |
[0x1d] = KC_ESCAPE, |
[0x1e] = KC_1, |
[0x1f] = KC_2, |
[0x20] = KC_3, |
[0x21] = KC_4, |
[0x22] = KC_5, |
[0x23] = KC_6, |
[0x24] = KC_7, |
[0x25] = KC_8, |
[0x26] = KC_9, |
[0x27] = KC_0, |
[0x28] = KC_MINUS, |
[0x29] = KC_EQUALS, |
[0x2a] = KC_BACKTICK, |
[0x2b] = KC_BACKSPACE, |
[0x2c] = KC_INSERT, |
[0x2d] = 0, |
[0x2e] = KC_NSLASH, |
[0x2f] = KC_NTIMES, |
[0x30] = 0, |
[0x31] = 0, |
[0x32] = KC_NPERIOD, |
[0x33] = 0, |
[0x34] = KC_HOME, |
[0x35] = KC_TAB, |
[0x36] = KC_Q, |
[0x37] = KC_W, |
[0x38] = KC_E, |
[0x39] = KC_R, |
[0x3a] = KC_T, |
[0x3b] = KC_Y, |
[0x3c] = KC_U, |
[0x3d] = KC_I, |
[0x3e] = KC_O, |
[0x3f] = KC_P, |
[0x40] = KC_LBRACKET, |
[0x41] = KC_RBRACKET, |
[0x42] = KC_DELETE, |
[0x43] = 0, |
[0x44] = KC_N7, |
[0x45] = KC_N8, |
[0x46] = KC_N9, |
[0x47] = KC_NMINUS, |
[0x48] = 0, |
[0x49] = 0, |
[0x4a] = KC_END, |
[0x4b] = 0, |
[0x4c] = KC_LCTRL, |
[0x4d] = KC_A, |
[0x4e] = KC_S, |
[0x4f] = KC_D, |
[0x50] = KC_F, |
[0x51] = KC_G, |
[0x52] = KC_H, |
[0x53] = KC_J, |
[0x54] = KC_K, |
[0x55] = KC_L, |
[0x56] = KC_SEMICOLON, |
[0x57] = KC_QUOTE, |
[0x58] = KC_BACKSLASH, |
[0x59] = KC_ENTER, |
[0x5a] = KC_NENTER, |
[0x5b] = KC_N4, |
[0x5c] = KC_N5, |
[0x5d] = KC_N6, |
[0x5e] = KC_N0, |
[0x5f] = 0, |
[0x60] = KC_PAGE_UP, |
[0x61] = 0, |
[0x62] = KC_NUM_LOCK, |
[0x63] = KC_LSHIFT, |
[0x64] = KC_Z, |
[0x65] = KC_X, |
[0x66] = KC_C, |
[0x67] = KC_V, |
[0x68] = KC_B, |
[0x69] = KC_N, |
[0x6a] = KC_M, |
[0x6b] = KC_COMMA, |
[0x6c] = KC_PERIOD, |
[0x6d] = KC_SLASH, |
[0x6e] = KC_RSHIFT, |
[0x6f] = 0, |
[0x70] = KC_N1, |
[0x71] = KC_N2, |
[0x72] = KC_N3, |
[0x73] = 0, |
[0x74] = 0, |
[0x75] = 0, |
[0x76] = 0, |
[0x77] = KC_CAPS_LOCK, |
[0x78] = 0, |
[0x79] = KC_SPACE, |
[0x7a] = 0, |
[0x7b] = KC_PAGE_DOWN, |
[0x7c] = 0, |
[0x7d] = KC_NPLUS, |
[0x7e] = 0, |
[0x7f] = 0 |
}; |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/include/keys.h |
---|
File deleted |
/branches/dd/uspace/srv/kbd/include/layout.h |
---|
0,0 → 1,49 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_LAYOUT_H_ |
#define KBD_LAYOUT_H_ |
#include <kbd/kbd.h> |
extern char layout_parse_ev(kbd_event_t *); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/include/kbd.h |
---|
39,10 → 39,18 |
#include <key_buffer.h> |
extern int kbd_arch_init(void); |
extern int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call); |
extern int mouse_arch_process(int phoneid, ipc_call_t *call); |
#define KBD_EVENT 1024 |
#define KBD_MS_LEFT 1025 |
#define KBD_MS_RIGHT 1026 |
#define KBD_MS_MIDDLE 1027 |
#define KBD_MS_MOVE 1028 |
extern int cir_service; |
extern int cir_phone; |
extern void kbd_push_scancode(int); |
extern void kbd_push_ev(int, unsigned int); |
#endif |
/** |
/branches/dd/uspace/srv/kbd/include/key_buffer.h |
---|
38,23 → 38,25 |
#define __KEY_BUFFER_H__ |
#include <sys/types.h> |
#include <kbd/kbd.h> |
/** Size of buffer for pressed keys */ |
#define KEYBUFFER_SIZE 128 |
typedef struct { |
int fifo[KEYBUFFER_SIZE]; |
kbd_event_t fifo[KEYBUFFER_SIZE]; |
unsigned long head; |
unsigned long tail; |
unsigned long items; |
} keybuffer_t; |
void keybuffer_free(keybuffer_t *keybuffer); |
void keybuffer_init(keybuffer_t *keybuffer); |
int keybuffer_available(keybuffer_t *keybuffer); |
int keybuffer_empty(keybuffer_t *keybuffer); |
void keybuffer_push(keybuffer_t *keybuffer, int key); |
int keybuffer_pop(keybuffer_t *keybuffer, int *c); |
extern void keybuffer_free(keybuffer_t *); |
extern void keybuffer_init(keybuffer_t *); |
extern int keybuffer_available(keybuffer_t *); |
extern int keybuffer_empty(keybuffer_t *); |
extern void keybuffer_push(keybuffer_t *, const kbd_event_t *); |
extern void keybuffer_push0(keybuffer_t *, int c); |
extern int keybuffer_pop(keybuffer_t *, kbd_event_t *); |
#endif |
/branches/dd/uspace/srv/kbd/include/kbd_ctl.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_CTL_H_ |
#define KBD_CTL_H_ |
extern void kbd_ctl_parse_scancode(int); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/include/kbd_port.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbdgen generic |
* @brief HelenOS generic uspace keyboard handler. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KBD_PORT_H_ |
#define KBD_PORT_H_ |
extern int kbd_port_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/port/ski.c |
---|
0,0 → 1,107 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Ski console keyboard port driver. |
*/ |
#include <stdlib.h> |
#include <unistd.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sys/types.h> |
#include <thread.h> |
#define SKI_GETCHAR 21 |
#define POLL_INTERVAL 10000 |
static void *ski_thread_impl(void *arg); |
static int32_t ski_getchar(void); |
/** Initialize Ski port driver. */ |
int kbd_port_init(void) |
{ |
thread_id_t tid; |
int rc; |
rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid); |
if (rc != 0) { |
return rc; |
} |
return 0; |
} |
/** Thread to poll Ski for keypresses. */ |
static void *ski_thread_impl(void *arg) |
{ |
int32_t c; |
(void) arg; |
while (1) { |
c = ski_getchar(); |
if (c != 0) |
kbd_push_scancode(c); |
usleep(POLL_INTERVAL); |
} |
} |
/** Ask Ski if a key was pressed. |
* |
* Use SSC (Simulator System Call) to get character from the debug console. |
* This call is non-blocking. |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
*/ |
static int32_t ski_getchar(void) |
{ |
uint64_t ch; |
asm volatile ( |
"mov r15 = %1\n" |
"break 0x80000;;\n" /* modifies r8 */ |
"mov %0 = r8;;\n" |
: "=r" (ch) |
: "i" (SKI_GETCHAR) |
: "r15", "r8" |
); |
return (int32_t) ch; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/ns16550.c |
---|
0,0 → 1,115 |
/* |
* Copyright (c) 2006 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief NS16550 port driver. |
*/ |
#include <ipc/ipc.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <ddi.h> |
/* NS16550 registers */ |
#define RBR_REG 0 /** Receiver Buffer Register. */ |
#define IER_REG 1 /** Interrupt Enable Register. */ |
#define IIR_REG 2 /** Interrupt Ident Register (read). */ |
#define FCR_REG 2 /** FIFO control register (write). */ |
#define LCR_REG 3 /** Line Control register. */ |
#define MCR_REG 4 /** Modem Control Register. */ |
#define LSR_REG 5 /** Line Status Register. */ |
#define LSR_DATA_READY 0x01 |
static irq_cmd_t ns16550_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = LSR_DATA_READY, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t ns16550_kbd = { |
sizeof(ns16550_cmds) / sizeof(irq_cmd_t), |
ns16550_cmds |
}; |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
static uintptr_t ns16550_physical; |
static uintptr_t ns16550_kernel; |
int kbd_port_init(void) |
{ |
void *vaddr; |
async_set_interrupt_received(ns16550_irq_handler); |
ns16550_physical = sysinfo_value("kbd.address.physical"); |
ns16550_kernel = sysinfo_value("kbd.address.kernel"); |
ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG); |
ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, &ns16550_kbd); |
return pio_enable((void *) ns16550_physical, 8, &vaddr); |
} |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/port/i8042.c |
---|
0,0 → 1,168 |
/* |
* Copyright (c) 2001-2004 Jakub Jermar |
* Copyright (c) 2006 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief i8042 port driver. |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <unistd.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
#include "i8042.h" |
/* Interesting bits for status register */ |
#define i8042_OUTPUT_FULL 0x1 |
#define i8042_INPUT_FULL 0x2 |
#define i8042_MOUSE_DATA 0x20 |
/* Command constants */ |
#define i8042_CMD_KBD 0x60 |
#define i8042_CMD_MOUSE 0xd4 |
/* Keyboard cmd byte */ |
#define i8042_KBD_IE 0x1 |
#define i8042_MOUSE_IE 0x2 |
#define i8042_KBD_DISABLE 0x10 |
#define i8042_MOUSE_DISABLE 0x20 |
#define i8042_KBD_TRANSLATE 0x40 |
/* Mouse constants */ |
#define MOUSE_OUT_INIT 0xf4 |
#define MOUSE_ACK 0xfa |
static irq_cmd_t i8042_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = i8042_OUTPUT_FULL, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = NULL, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
static irq_code_t i8042_kbd = { |
sizeof(i8042_cmds) / sizeof(irq_cmd_t), |
i8042_cmds |
}; |
static uintptr_t i8042_physical; |
static uintptr_t i8042_kernel; |
static i8042_t * i8042; |
static void wait_ready(void) { |
while (pio_read_8(&i8042->status) & i8042_INPUT_FULL) |
; |
} |
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
int mouseenabled = 0; |
void *vaddr; |
i8042_physical = sysinfo_value("kbd.address.physical"); |
i8042_kernel = sysinfo_value("kbd.address.kernel"); |
if (pio_enable((void *) i8042_physical, sizeof(i8042_t), &vaddr) != 0) |
return -1; |
i8042 = vaddr; |
async_set_interrupt_received(i8042_irq_handler); |
/* Disable kbd, enable mouse */ |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->data, i8042_KBD_DISABLE); |
wait_ready(); |
/* Flush all current IO */ |
while (pio_read_8(&i8042->status) & i8042_OUTPUT_FULL) |
(void) pio_read_8(&i8042->data); |
/* Enable kbd */ |
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data; |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &i8042_kbd); |
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE; |
if (mouseenabled) |
newcontrol |= i8042_MOUSE_IE; |
pio_write_8(&i8042->status, i8042_CMD_KBD); |
wait_ready(); |
pio_write_8(&i8042->data, newcontrol); |
wait_ready(); |
return 0; |
} |
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int status = IPC_GET_ARG1(*call); |
if ((status & i8042_MOUSE_DATA)) |
return; |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
return; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/port/z8530.c |
---|
0,0 → 1,108 |
/* |
* Copyright (c) 2006 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Z8530 keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/bus.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sys/types.h> |
#include <ddi.h> |
#define CHAN_A_STATUS 4 |
#define CHAN_A_DATA 6 |
#define RR0_RCA 1 |
static irq_cmd_t z8530_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = RR0_RCA, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t z8530_kbd = { |
sizeof(z8530_cmds) / sizeof(irq_cmd_t), |
z8530_cmds |
}; |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(z8530_irq_handler); |
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") + |
CHAN_A_STATUS; |
z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.kernel") + |
CHAN_A_DATA; |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
sysinfo_value("kbd.inr"), &z8530_kbd); |
return 0; |
} |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
if (cir_service) |
async_msg_1(cir_phone, BUS_CLEAR_INTERRUPT, |
IPC_GET_METHOD(*call)); |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/i8042.h |
---|
0,0 → 1,55 |
/* |
* Copyright (c) 2006 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief i8042 port driver. |
*/ |
#ifndef KBD_PORT_i8042_H_ |
#define KBD_PORT_i8042_H_ |
#include <libarch/ddi.h> |
#include <libarch/types.h> |
struct i8042 { |
ioport8_t data; |
uint8_t pad[3]; |
ioport8_t status; |
} __attribute__ ((packed)); |
typedef struct i8042 i8042_t; |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/port/msim.c |
---|
0,0 → 1,91 |
/* |
* Copyright (c) 2006 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief Msim keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
irq_cmd_t msim_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
irq_code_t msim_kbd = { |
sizeof(msim_cmds) / sizeof(irq_cmd_t), |
msim_cmds |
}; |
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(msim_irq_handler); |
msim_cmds[0].addr = sysinfo_value("kbd.address.virtual"); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, &msim_kbd); |
return 0; |
} |
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
// static int esc_count=0; |
// if (scan_code == 0x1b) { |
// esc_count++; |
// if (esc_count == 3) |
// __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
// } else { |
// esc_count=0; |
// } |
// if (fb_fb) |
// return kbd_arch_process_fb(keybuffer, scan_code); |
kbd_push_scancode(scan_code); |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/gxemul.c |
---|
0,0 → 1,86 |
/* |
* Copyright (c) 2007 Michal Kebrt |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @{ |
* @ingroup kbd |
*/ |
/** @file |
* @brief GXEmul keyboard port driver. |
*/ |
#include <ipc/ipc.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd_port.h> |
#include <kbd.h> |
static irq_cmd_t gxemul_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2, |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
}; |
static irq_code_t gxemul_kbd = { |
sizeof(gxemul_cmds) / sizeof(irq_cmd_t), |
gxemul_cmds |
}; |
static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
/** Initializes keyboard handler. */ |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(gxemul_irq_handler); |
gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual"); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, &gxemul_kbd); |
return 0; |
} |
/** Process data sent when a key is pressed. |
* |
* @param keybuffer Buffer of pressed keys. |
* @param call IPC call. |
* |
* @return Always 1. |
*/ |
static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
kbd_push_scancode(scan_code); |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/sgcn.c |
---|
0,0 → 1,141 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
* @brief SGCN (Serengeti Console) keyboard port driver. |
*/ |
#include <as.h> |
#include <ddi.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <kbd.h> |
#include <kbd_port.h> |
#include <sysinfo.h> |
#include <stdio.h> |
/** |
* SGCN buffer header. It is placed at the very beginning of the SGCN |
* buffer. |
*/ |
typedef struct { |
/** hard-wired to "CON" */ |
char magic[4]; |
/** we don't need this */ |
char unused[8]; |
/** offset within the SGCN buffer of the input buffer start */ |
uint32_t in_begin; |
/** offset within the SGCN buffer of the input buffer end */ |
uint32_t in_end; |
/** offset within the SGCN buffer of the input buffer read pointer */ |
uint32_t in_rdptr; |
/** offset within the SGCN buffer of the input buffer write pointer */ |
uint32_t in_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the console buffer beginning. |
*/ |
#define SGCN_BUFFER(type, offset) \ |
((type *) (sram_virt_addr + sram_buffer_offset + (offset))) |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** |
* Virtual address mapped to SRAM. |
*/ |
static uintptr_t sram_virt_addr; |
/** |
* SGCN buffer offset within SGCN. |
*/ |
static uintptr_t sram_buffer_offset; |
static void sgcn_irq_handler(ipc_callid_t iid, ipc_call_t *call); |
/** |
* Initializes the SGCN driver. |
* Maps the physical memory (SRAM) and registers the interrupt. |
*/ |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(sgcn_irq_handler); |
sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size")); |
if (physmem_map((void *) sysinfo_value("sram.address.physical"), |
(void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE, |
AS_AREA_READ | AS_AREA_WRITE) != 0) { |
printf("SGCN: uspace driver could not map physical memory."); |
return -1; |
} |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, (void *) 0); |
return 0; |
} |
/** |
* Handler of the "key pressed" event. Reads codes of all the pressed keys from |
* the buffer. |
*/ |
static void sgcn_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
char c; |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
uint32_t size = end - begin; |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
kbd_push_scancode(c); |
} |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/dummy.c |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd_port |
* @brief Dummy keyboard port driver. |
* @ingroup kbd |
* @{ |
*/ |
/** @file |
*/ |
#include <kbd_port.h> |
#include <kbd.h> |
int kbd_port_init(void) |
{ |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/generic/kbd.c |
---|
37,48 → 37,99 |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <errno.h> |
#include <arch/kbd.h> |
#include <libadt/fifo.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd.h> |
#include <libadt/fifo.h> |
#include <key_buffer.h> |
#include <async.h> |
#include <keys.h> |
#include <kbd_port.h> |
#include <kbd_ctl.h> |
#include <layout.h> |
#define NAME "KBD" |
#define NAME "kbd" |
int cons_connected = 0; |
int phone2cons = -1; |
keybuffer_t keybuffer; |
keybuffer_t keybuffer; |
static void irq_handler(ipc_callid_t iid, ipc_call_t *call) |
/** Currently active modifiers. */ |
static unsigned mods = KM_NUM_LOCK; |
/** Currently pressed lock keys. We track these to tackle autorepeat. */ |
static unsigned lock_keys; |
int cir_service = 0; |
int cir_phone = -1; |
void kbd_push_scancode(int scancode) |
{ |
int chr; |
/* printf("scancode: 0x%x\n", scancode);*/ |
kbd_ctl_parse_scancode(scancode); |
} |
#ifdef MOUSE_ENABLED |
if (mouse_arch_process(phone2cons, call)) |
return; |
#endif |
kbd_arch_process(&keybuffer, call); |
void kbd_push_ev(int type, unsigned int key) |
{ |
kbd_event_t ev; |
unsigned mod_mask; |
if (cons_connected && phone2cons != -1) { |
/* |
* recode to ASCII - one interrupt can produce more than one |
* code so result is stored in fifo |
*/ |
while (!keybuffer_empty(&keybuffer)) { |
if (!keybuffer_pop(&keybuffer, (int *)&chr)) |
break; |
switch (key) { |
case KC_LCTRL: mod_mask = KM_LCTRL; break; |
case KC_RCTRL: mod_mask = KM_RCTRL; break; |
case KC_LSHIFT: mod_mask = KM_LSHIFT; break; |
case KC_RSHIFT: mod_mask = KM_RSHIFT; break; |
case KC_LALT: mod_mask = KM_LALT; break; |
case KC_RALT: mod_mask = KM_RALT; break; |
default: mod_mask = 0; break; |
} |
async_msg_1(phone2cons, KBD_PUSHCHAR, chr); |
if (mod_mask != 0) { |
if (type == KE_PRESS) |
mods = mods | mod_mask; |
else |
mods = mods & ~mod_mask; |
} |
switch (key) { |
case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break; |
case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break; |
case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break; |
default: mod_mask = 0; break; |
} |
if (mod_mask != 0) { |
if (type == KE_PRESS) { |
/* |
* Only change lock state on transition from released |
* to pressed. This prevents autorepeat from messing |
* up the lock state. |
*/ |
mods = mods ^ (mod_mask & ~lock_keys); |
lock_keys = lock_keys | mod_mask; |
} else { |
lock_keys = lock_keys & ~mod_mask; |
} |
} |
/* |
printf("type: %d\n", type); |
printf("mods: 0x%x\n", mods); |
printf("keycode: %u\n", key); |
*/ |
ev.type = type; |
ev.key = key; |
ev.mods = mods; |
ev.c = layout_parse_ev(&ev); |
async_msg_4(phone2cons, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c); |
} |
static void console_connection(ipc_callid_t iid, ipc_call_t *icall) |
121,10 → 172,24 |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS Keyboard service\n"); |
ipcarg_t phonead; |
/* Initialize arch dependent parts */ |
if (kbd_arch_init()) |
if (sysinfo_value("kbd.cir.fhc") == 1) |
cir_service = SERVICE_FHC; |
else if (sysinfo_value("kbd.cir.obio") == 1) |
cir_service = SERVICE_OBIO; |
if (cir_service) { |
while (cir_phone < 0) { |
cir_phone = ipc_connect_me_to_blocking(PHONE_NS, cir_service, |
0, 0); |
} |
} |
/* Initialize port driver. */ |
if (kbd_port_init()) |
return -1; |
/* Initialize key buffer */ |
131,14 → 196,15 |
keybuffer_init(&keybuffer); |
async_set_client_connection(console_connection); |
async_set_interrupt_received(irq_handler); |
/* Register service at nameserver */ |
/* Register service at nameserver. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_KEYBOARD, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
/* Not reached. */ |
return 0; |
} |
145,4 → 211,3 |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/generic/key_buffer.c |
---|
40,7 → 40,7 |
/** Clear key buffer. |
*/ |
void keybuffer_free(keybuffer_t *keybuffer) |
void keybuffer_free(keybuffer_t *keybuffer) |
{ |
futex_down(&keybuffer_futex); |
keybuffer->head = 0; |
75,15 → 75,18 |
return (keybuffer->items == 0); |
} |
/** Push key to key buffer. |
* If buffer is full, character is ignored. |
* @param key code of stored key |
/** Push key event to key buffer. |
* |
* If the buffer is full, the event is ignored. |
* |
* @param keybuffer The keybuffer. |
* @param ev The event to push. |
*/ |
void keybuffer_push(keybuffer_t *keybuffer, int key) |
void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev) |
{ |
futex_down(&keybuffer_futex); |
if (keybuffer->items < KEYBUFFER_SIZE) { |
keybuffer->fifo[keybuffer->tail] = key; |
keybuffer->fifo[keybuffer->tail] = *ev; |
keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE; |
keybuffer->items++; |
} |
90,16 → 93,25 |
futex_up(&keybuffer_futex); |
} |
/** Pop character from buffer. |
* @param c pointer to space where to store character from buffer. |
* @return zero on empty buffer, nonzero else |
void keybuffer_push0(keybuffer_t *keybuffer, int c) |
{ |
kbd_event_t ev; |
ev.key = c; ev.mods = 0; ev.c = c; |
keybuffer_push(keybuffer, &ev); |
} |
/** Pop event from buffer. |
* |
* @param edst Pointer to where the event should be saved. |
* @return Zero on empty buffer, nonzero otherwise. |
*/ |
int keybuffer_pop(keybuffer_t *keybuffer, int *c) |
int keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst) |
{ |
futex_down(&keybuffer_futex); |
if (keybuffer->items > 0) { |
keybuffer->items--; |
*c = (keybuffer->fifo[keybuffer->head]) ; |
*edst = (keybuffer->fifo[keybuffer->head]) ; |
keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE; |
futex_up(&keybuffer_futex); |
return 1; |
/branches/dd/uspace/srv/kbd/Makefile |
---|
31,9 → 31,9 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include ../../../Makefile.config |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -Iinclude -I../libadt/include |
LIBS = $(LIBC_PREFIX)/libc.a |
46,65 → 46,105 |
generic/kbd.c \ |
generic/key_buffer.c |
ARCH_SOURCES = \ |
arch/$(ARCH)/src/kbd.c |
ARCH_SOURCES = |
GENARCH_SOURCES = |
ifeq ($(ARCH), ia32) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/mouse.c \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
CFLAGS += -DMOUSE_ENABLED |
ifeq ($(KBD_LAYOUT), us_qwerty) |
GENARCH_SOURCES += layout/us_qwerty.c |
endif |
ifeq ($(ARCH), amd64) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/mouse.c \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
CFLAGS += -DMOUSE_ENABLED |
ifeq ($(KBD_LAYOUT), us_dvorak) |
GENARCH_SOURCES += layout/us_dvorak.c |
endif |
ifeq ($(ARCH), sparc64) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/scanc.c |
GENARCH_SOURCES = \ |
genarch/src/kbd.c |
ifeq ($(UARCH), amd64) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(ARCH), arm32) |
ifeq ($(MACHINE), gxemul_testarm) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/kbd_gxemul.c |
ifeq ($(UARCH), arm32) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(UARCH), ia32) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(MACHINE), i640GX) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
endif |
ifeq ($(MACHINE), ski) |
GENARCH_SOURCES += \ |
port/ski.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), msim) |
GENARCH_SOURCES += \ |
port/msim.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), lgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(MACHINE), bgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c \ |
ctl/stty.c |
endif |
ifeq ($(UARCH), ppc32) |
GENARCH_SOURCES += \ |
port/dummy.c \ |
ctl/stty.c |
endif |
ifeq ($(UARCH), sparc64) |
GENARCH_SOURCES += \ |
port/z8530.c \ |
ctl/sun.c |
endif |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES))) |
OBJECTS := $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) |
.PHONY: all clean depend disasm links |
all: links $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
links: |
ln -sfn ../arch/$(ARCH)/include include/arch |
ln -sfn ../genarch/include include/genarch |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend include/arch include/genarch |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/kbd/layout/us_dvorak.c |
---|
0,0 → 1,238 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd |
* @brief US Dvorak Simplified Keyboard layout. |
* @{ |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <layout.h> |
static char map_lcase[] = { |
[KC_R] = 'p', |
[KC_T] = 'y', |
[KC_Y] = 'f', |
[KC_U] = 'g', |
[KC_I] = 'c', |
[KC_O] = 'r', |
[KC_P] = 'l', |
[KC_A] = 'a', |
[KC_S] = 'o', |
[KC_D] = 'e', |
[KC_F] = 'u', |
[KC_G] = 'i', |
[KC_H] = 'd', |
[KC_J] = 'h', |
[KC_K] = 't', |
[KC_L] = 'n', |
[KC_SEMICOLON] = 's', |
[KC_X] = 'q', |
[KC_C] = 'j', |
[KC_V] = 'k', |
[KC_B] = 'x', |
[KC_N] = 'b', |
[KC_M] = 'm', |
[KC_COMMA] = 'w', |
[KC_PERIOD] = 'v', |
[KC_SLASH] = 'z', |
}; |
static char map_ucase[] = { |
[KC_R] = 'P', |
[KC_T] = 'Y', |
[KC_Y] = 'F', |
[KC_U] = 'G', |
[KC_I] = 'C', |
[KC_O] = 'R', |
[KC_P] = 'L', |
[KC_A] = 'A', |
[KC_S] = 'O', |
[KC_D] = 'E', |
[KC_F] = 'U', |
[KC_G] = 'I', |
[KC_H] = 'D', |
[KC_J] = 'H', |
[KC_K] = 'T', |
[KC_L] = 'N', |
[KC_SEMICOLON] = 'S', |
[KC_X] = 'Q', |
[KC_C] = 'J', |
[KC_V] = 'K', |
[KC_B] = 'X', |
[KC_N] = 'B', |
[KC_M] = 'M', |
[KC_COMMA] = 'W', |
[KC_PERIOD] = 'V', |
[KC_SLASH] = 'Z', |
}; |
static char map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '[', |
[KC_EQUALS] = ']', |
[KC_Q] = '\'', |
[KC_W] = ',', |
[KC_E] = '.', |
[KC_LBRACKET] = '/', |
[KC_RBRACKET] = '=', |
[KC_QUOTE] = '-', |
[KC_BACKSLASH] = '\\', |
[KC_Z] = ';', |
}; |
static char map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '{', |
[KC_EQUALS] = '}', |
[KC_Q] = '"', |
[KC_W] = '<', |
[KC_E] = '>', |
[KC_LBRACKET] = '?', |
[KC_RBRACKET] = '+', |
[KC_QUOTE] = '_', |
[KC_BACKSLASH] = '|', |
[KC_Z] = ':', |
}; |
static char map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static char map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static int translate(unsigned int key, char *map, size_t map_length) |
{ |
if (key >= map_length) |
return 0; |
return map[key]; |
} |
char layout_parse_ev(kbd_event_t *ev) |
{ |
char c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(char)); |
if (c != 0) |
return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(char)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(char)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(char)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(char)); |
if (c != 0) |
return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(char)); |
else |
c = 0; |
return c; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/kbd/layout/us_qwerty.c |
---|
0,0 → 1,228 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @{ |
*/ |
#include <kbd.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <layout.h> |
static char map_lcase[] = { |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
[KC_R] = 'r', |
[KC_T] = 't', |
[KC_Y] = 'y', |
[KC_U] = 'u', |
[KC_I] = 'i', |
[KC_O] = 'o', |
[KC_P] = 'p', |
[KC_A] = 'a', |
[KC_S] = 's', |
[KC_D] = 'd', |
[KC_F] = 'f', |
[KC_G] = 'g', |
[KC_H] = 'h', |
[KC_J] = 'j', |
[KC_K] = 'k', |
[KC_L] = 'l', |
[KC_Z] = 'z', |
[KC_X] = 'x', |
[KC_C] = 'c', |
[KC_V] = 'v', |
[KC_B] = 'b', |
[KC_N] = 'n', |
[KC_M] = 'm', |
}; |
static char map_ucase[] = { |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
[KC_R] = 'R', |
[KC_T] = 'T', |
[KC_Y] = 'Y', |
[KC_U] = 'U', |
[KC_I] = 'I', |
[KC_O] = 'O', |
[KC_P] = 'P', |
[KC_A] = 'A', |
[KC_S] = 'S', |
[KC_D] = 'D', |
[KC_F] = 'F', |
[KC_G] = 'G', |
[KC_H] = 'H', |
[KC_J] = 'J', |
[KC_K] = 'K', |
[KC_L] = 'L', |
[KC_Z] = 'Z', |
[KC_X] = 'X', |
[KC_C] = 'C', |
[KC_V] = 'V', |
[KC_B] = 'B', |
[KC_N] = 'N', |
[KC_M] = 'M', |
}; |
static char map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '-', |
[KC_EQUALS] = '=', |
[KC_LBRACKET] = '[', |
[KC_RBRACKET] = ']', |
[KC_SEMICOLON] = ';', |
[KC_QUOTE] = '\'', |
[KC_BACKSLASH] = '\\', |
[KC_COMMA] = ',', |
[KC_PERIOD] = '.', |
[KC_SLASH] = '/', |
}; |
static char map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '_', |
[KC_EQUALS] = '+', |
[KC_LBRACKET] = '{', |
[KC_RBRACKET] = '}', |
[KC_SEMICOLON] = ':', |
[KC_QUOTE] = '"', |
[KC_BACKSLASH] = '|', |
[KC_COMMA] = '<', |
[KC_PERIOD] = '>', |
[KC_SLASH] = '?', |
}; |
static char map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static char map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static int translate(unsigned int key, char *map, size_t map_length) |
{ |
if (key >= map_length) return 0; |
return map[key]; |
} |
char layout_parse_ev(kbd_event_t *ev) |
{ |
char c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(char)); |
if (c != 0) return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(char)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(char)); |
if (c != 0) return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(char)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(char)); |
if (c != 0) return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(char)); |
else |
c = 0; |
return c; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/ns/ns.c |
---|
28,11 → 28,11 |
/** @addtogroup ns |
* @{ |
*/ |
*/ |
/** |
* @file ns.c |
* @brief Naming service for HelenOS IPC. |
* @file ns.c |
* @brief Naming service for HelenOS IPC. |
*/ |
40,6 → 40,7 |
#include <ipc/ns.h> |
#include <ipc/services.h> |
#include <stdio.h> |
#include <bool.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <errno.h> |
47,17 → 48,24 |
#include <libadt/list.h> |
#include <libadt/hash_table.h> |
#include <sysinfo.h> |
#include <loader/loader.h> |
#include <ddi.h> |
#include <as.h> |
#define NAME "NS" |
#define NAME "ns" |
#define NS_HASH_TABLE_CHAINS 20 |
#define NS_HASH_TABLE_CHAINS 20 |
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); |
static int connect_to_service(ipcarg_t service, ipc_call_t *call, |
static void connect_to_service(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid); |
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, |
ipc_callid_t callid); |
void connect_to_clonable(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid); |
/* Static functions implementing NS hash table operations. */ |
static hash_index_t ns_hash(unsigned long *key); |
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item); |
76,19 → 84,46 |
/** NS hash table item. */ |
typedef struct { |
link_t link; |
ipcarg_t service; /**< Number of the service. */ |
ipcarg_t phone; /**< Phone registered with the service. */ |
ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
ipcarg_t service; /**< Number of the service. */ |
ipcarg_t phone; /**< Phone registered with the service. */ |
ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
} hashed_service_t; |
/** Pending connection structure. */ |
typedef struct { |
link_t link; |
ipcarg_t service; /**< Number of the service. */ |
ipc_callid_t callid; /**< Call ID waiting for the connection */ |
ipcarg_t arg2; /**< Second argument */ |
ipcarg_t arg3; /**< Third argument */ |
} pending_req_t; |
static link_t pending_req; |
/** Request for connection to a clonable service. */ |
typedef struct { |
link_t link; |
ipcarg_t service; |
ipc_call_t call; |
ipc_callid_t callid; |
} cs_req_t; |
/** List of clonable-service connection requests. */ |
static link_t cs_req; |
static void *clockaddr = NULL; |
static void *klogaddr = NULL; |
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, |
void **addr) |
/** Return true if @a service is clonable. */ |
static bool service_clonable(int service) |
{ |
return (service == SERVICE_LOAD); |
} |
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, void **addr) |
{ |
void *ph_addr; |
if (!*addr) { |
ph_addr = (void *) sysinfo_value(name); |
if (!ph_addr) { |
96,36 → 131,76 |
return; |
} |
*addr = as_get_mappable_page(PAGE_SIZE); |
physmem_map(ph_addr, *addr, 1, |
AS_AREA_READ | AS_AREA_CACHEABLE); |
if (physmem_map(ph_addr, *addr, 1, |
AS_AREA_READ | AS_AREA_CACHEABLE) != 0) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
} |
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ); |
} |
/** Process pending connection requests */ |
static void process_pending_req() |
{ |
link_t *cur; |
loop: |
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
pending_req_t *pr = list_get_instance(cur, pending_req_t, link); |
unsigned long keys[3] = { |
pr->service, |
0, |
0 |
}; |
link_t *link = hash_table_find(&ns_hash_table, keys); |
if (!link) |
continue; |
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); |
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone, |
pr->arg2, pr->arg3, 0, IPC_FF_NONE); |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, retval); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
int main(int argc, char **argv) |
{ |
ipc_call_t call; |
ipc_callid_t callid; |
printf(NAME ": HelenOS IPC Naming Service\n"); |
ipcarg_t retval; |
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, |
&ns_hash_table_ops)) { |
printf(NAME ": No memory available for services\n"); |
return ENOMEM; |
} |
list_initialize(&pending_req); |
list_initialize(&cs_req); |
printf(NAME ": Accepting connections\n"); |
while (true) { |
process_pending_req(); |
while (1) { |
callid = ipc_wait_for_call(&call); |
ipc_call_t call; |
ipc_callid_t callid = ipc_wait_for_call(&call); |
ipcarg_t retval; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_SHARE_IN: |
switch (IPC_GET_ARG3(call)) { |
case SERVICE_MEM_REALTIME: |
get_as_area(callid, &call, "clock.faddr", |
&clockaddr); |
get_as_area(callid, &call, "clock.faddr", &clockaddr); |
break; |
case SERVICE_MEM_KLOG: |
get_as_area(callid, &call, "klog.faddr", |
&klogaddr); |
get_as_area(callid, &call, "klog.faddr", &klogaddr); |
break; |
default: |
ipc_answer_0(callid, ENOENT); |
138,33 → 213,50 |
/* |
* Server requests service registration. |
*/ |
retval = register_service(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call); |
if (service_clonable(IPC_GET_ARG1(call))) { |
register_clonable(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call, callid); |
continue; |
} else { |
retval = register_service(IPC_GET_ARG1(call), |
IPC_GET_ARG5(call), &call); |
} |
break; |
case IPC_M_CONNECT_ME_TO: |
/* |
* Client requests to be connected to a service. |
*/ |
retval = connect_to_service(IPC_GET_ARG1(call), &call, |
callid); |
if (service_clonable(IPC_GET_ARG1(call))) { |
connect_to_clonable(IPC_GET_ARG1(call), |
&call, callid); |
continue; |
} else { |
connect_to_service(IPC_GET_ARG1(call), &call, |
callid); |
continue; |
} |
break; |
default: |
retval = ENOENT; |
break; |
} |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
} |
} |
/* Not reached */ |
return 0; |
} |
/** Register service. |
* |
* @param service Service to be registered. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) |
{ |
173,23 → 265,20 |
call->in_phone_hash, |
0 |
}; |
hashed_service_t *hs; |
if (hash_table_find(&ns_hash_table, keys)) { |
if (hash_table_find(&ns_hash_table, keys)) |
return EEXISTS; |
} |
hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
if (!hs) { |
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
if (!hs) |
return ENOMEM; |
} |
link_initialize(&hs->link); |
hs->service = service; |
hs->phone = phone; |
hs->in_phone_hash = call->in_phone_hash; |
hash_table_insert(&ns_hash_table, keys, &hs->link); |
return 0; |
} |
196,36 → 285,135 |
/** Connect client to service. |
* |
* @param service Service to be connected to. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) |
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) |
{ |
unsigned long keys[3] = { service, 0, 0 }; |
link_t *hlp; |
hashed_service_t *hs; |
ipcarg_t retval; |
unsigned long keys[3] = { |
service, |
0, |
0 |
}; |
link_t *link = hash_table_find(&ns_hash_table, keys); |
if (!link) { |
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) { |
/* Blocking connection, add to pending list */ |
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
if (!pr) { |
retval = ENOMEM; |
goto out; |
} |
hlp = hash_table_find(&ns_hash_table, keys); |
if (!hlp) { |
return ENOENT; |
pr->service = service; |
pr->callid = callid; |
pr->arg2 = IPC_GET_ARG2(*call); |
pr->arg3 = IPC_GET_ARG3(*call); |
list_append(&pr->link, &pending_req); |
return; |
} |
retval = ENOENT; |
goto out; |
} |
hs = hash_table_get_instance(hlp, hashed_service_t, link); |
return ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); |
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
out: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
} |
/** Register clonable service. |
* |
* @param service Service to be registered. |
* @param phone Phone to be used for connections to the service. |
* @param call Pointer to call structure. |
* |
*/ |
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, |
ipc_callid_t callid) |
{ |
if (list_empty(&cs_req)) { |
/* There was no pending connection request. */ |
printf(NAME ": Unexpected clonable server.\n"); |
ipc_answer_0(callid, EBUSY); |
return; |
} |
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link); |
list_remove(&csr->link); |
/* Currently we can only handle a single type of clonable service. */ |
assert(csr->service == SERVICE_LOAD); |
ipc_answer_0(callid, EOK); |
int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call), |
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE); |
free(csr); |
} |
/** Connect client to clonable service. |
* |
* @param service Service to be connected to. |
* @param call Pointer to call structure. |
* @param callid Call ID of the request. |
* |
* @return Zero on success or a value from @ref errno.h. |
* |
*/ |
void connect_to_clonable(ipcarg_t service, ipc_call_t *call, |
ipc_callid_t callid) |
{ |
assert(service == SERVICE_LOAD); |
cs_req_t *csr = malloc(sizeof(cs_req_t)); |
if (csr == NULL) { |
ipc_answer_0(callid, ENOMEM); |
return; |
} |
/* Spawn a loader. */ |
int rc = loader_spawn("loader"); |
if (rc < 0) { |
free(csr); |
ipc_answer_0(callid, rc); |
return; |
} |
csr->service = service; |
csr->call = *call; |
csr->callid = callid; |
/* |
* We can forward the call only after the server we spawned connects |
* to us. Meanwhile we might need to service more connection requests. |
* Thus we store the call in a queue. |
*/ |
list_append(&csr->link, &cs_req); |
} |
/** Compute hash index into NS hash table. |
* |
* @param key Pointer keys. However, only the first key (i.e. service number) |
* is used to compute the hash index. |
* is used to compute the hash index. |
* |
* @return Hash index corresponding to key[0]. |
* |
*/ |
hash_index_t ns_hash(unsigned long *key) |
{ |
assert(key); |
return *key % NS_HASH_TABLE_CHAINS; |
return (*key % NS_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
236,20 → 424,20 |
* value. Note that this is close to being classified |
* as a nasty hack. |
* |
* @param key Array of keys. |
* @param key Array of keys. |
* @param keys Must be lesser or equal to 3. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
hashed_service_t *hs; |
assert(key); |
assert(keys <= 3); |
assert(item); |
hs = hash_table_get_instance(item, hashed_service_t, link); |
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link); |
if (keys == 2) |
return key[1] == hs->in_phone_hash; |
260,6 → 448,7 |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
void ns_remove(link_t *item) |
{ |
267,6 → 456,6 |
free(hash_table_get_instance(item, hashed_service_t, link)); |
} |
/** |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/ns/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
46,22 → 47,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/fhc/fhc.c |
---|
0,0 → 1,157 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fhc |
* @{ |
*/ |
/** |
* @file fhc.c |
* @brief FHC bus controller driver. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/bus.h> |
#include <ipc/ns.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include <align.h> |
#include <bool.h> |
#include <errno.h> |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#define NAME "fhc" |
#define FHC_UART_INR 0x39 |
#define FHC_UART_IMAP 0x0 |
#define FHC_UART_ICLR 0x4 |
static void *fhc_uart_phys; |
static volatile uint32_t *fhc_uart_virt; |
static size_t fhc_uart_size; |
/** Handle one connection to fhc. |
* |
* @param iid Hash of the request that opened the connection. |
* @param icall Call data of the request that opened the connection. |
*/ |
static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
ipc_answer_0(iid, EOK); |
while (1) { |
int inr; |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case BUS_CLEAR_INTERRUPT: |
inr = IPC_GET_ARG1(call); |
switch (inr) { |
case FHC_UART_INR: |
fhc_uart_virt[FHC_UART_ICLR] = 0; |
ipc_answer_0(callid, EOK); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
} |
break; |
default: |
ipc_answer_0(callid, EINVAL); |
break; |
} |
} |
} |
/** Initialize the FHC driver. |
* |
* So far, the driver heavily depends on information provided by the kernel via |
* sysinfo. In the future, there should be a standalone FHC driver. |
*/ |
static bool fhc_init(void) |
{ |
ipcarg_t phonead; |
fhc_uart_size = sysinfo_value("fhc.uart.size"); |
fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical"); |
if (!fhc_uart_size) { |
printf(NAME ": no FHC UART registers found\n"); |
return false; |
} |
fhc_uart_virt = as_get_mappable_page(fhc_uart_size); |
int flags = AS_AREA_READ | AS_AREA_WRITE; |
int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt, |
ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) { |
printf(NAME ": Error mapping FHC UART registers\n"); |
return false; |
} |
printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys, |
fhc_uart_size); |
async_set_client_connection(fhc_connection); |
ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead); |
return true; |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS FHC bus controller driver\n"); |
if (!fhc_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fhc/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = fhc |
SOURCES = \ |
fhc.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/srv/console/console.c |
---|
35,27 → 35,32 |
#include <libc.h> |
#include <fb.h> |
#include <ipc/ipc.h> |
#include <keys.h> |
#include <kbd.h> |
#include <kbd/keycode.h> |
#include <ipc/fb.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <key_buffer.h> |
#include <console.h> |
#include <ipc/console.h> |
#include <unistd.h> |
#include <async.h> |
#include <libadt/fifo.h> |
#include <screenbuffer.h> |
#include <sys/mman.h> |
#include <stdio.h> |
#include <sysinfo.h> |
#include "console.h" |
#include "gcons.h" |
#define MAX_KEYREQUESTS_BUFFERED 32 |
#define NAME "CONSOLE" |
#define NAME "console" |
/** Index of currently used virtual console. |
*/ |
int active_console = 0; |
int prev_console = 0; |
/** Information about framebuffer |
*/ |
85,10 → 90,7 |
* faster virtual console |
* switching */ |
static int kernel_pixmap = -1; /**< Number of fb pixmap, where kernel |
* console is stored */ |
/** Find unused virtual console. |
* |
*/ |
108,27 → 110,54 |
async_msg_0(fb_info.phone, FB_CLEAR); |
} |
static void curs_visibility(int v) |
static void curs_visibility(bool visible) |
{ |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, v); |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); |
} |
static void curs_hide_sync(void) |
{ |
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); |
} |
static void curs_goto(int row, int col) |
{ |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
} |
static void set_style(style_t *style) |
static void set_style(int style) |
{ |
async_msg_2(fb_info.phone, FB_SET_STYLE, style->fg_color, |
style->bg_color); |
async_msg_1(fb_info.phone, FB_SET_STYLE, style); |
} |
static void set_style_col(int fgcolor, int bgcolor) |
static void set_color(int fgcolor, int bgcolor, int flags) |
{ |
async_msg_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor); |
async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); |
} |
static void set_rgb_color(int fgcolor, int bgcolor) |
{ |
async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); |
} |
static void set_attrs(attrs_t *attrs) |
{ |
switch (attrs->t) { |
case at_style: |
set_style(attrs->a.s.style); |
break; |
case at_idx: |
set_color(attrs->a.i.fg_color, attrs->a.i.bg_color, |
attrs->a.i.flags); |
break; |
case at_rgb: |
set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color); |
break; |
} |
} |
static void prtchr(char c, int row, int col) |
{ |
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col); |
186,114 → 215,81 |
} |
/** Save current screen to pixmap, draw old pixmap |
* |
* @param oldpixmap Old pixmap |
* @return ID of pixmap of current screen |
*/ |
static int switch_screens(int oldpixmap) |
{ |
int newpmap; |
/* Save screen */ |
newpmap = async_req_0_0(fb_info.phone, FB_VP2PIXMAP); |
if (newpmap < 0) |
return -1; |
if (oldpixmap != -1) { |
/* Show old screen */ |
async_msg_2(fb_info.phone, FB_VP_DRAW_PIXMAP, 0, oldpixmap); |
/* Drop old pixmap */ |
async_msg_1(fb_info.phone, FB_DROP_PIXMAP, oldpixmap); |
} |
return newpmap; |
} |
/** Switch to new console */ |
static void change_console(int newcons) |
{ |
connection_t *conn; |
static int console_pixmap = -1; |
int i, j, rc; |
keyfield_t *field; |
style_t *style; |
attrs_t *attrs; |
if (newcons == active_console) |
return; |
if (newcons == KERNEL_CONSOLE) { |
if (active_console == KERNEL_CONSOLE) |
return; |
active_console = KERNEL_CONSOLE; |
curs_visibility(0); |
async_serialize_start(); |
if (kernel_pixmap == -1) { |
/* store/restore unsupported */ |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
} else { |
gcons_in_kernel(); |
console_pixmap = switch_screens(kernel_pixmap); |
kernel_pixmap = -1; |
} |
curs_hide_sync(); |
gcons_in_kernel(); |
async_serialize_end(); |
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
return; |
} |
async_serialize_start(); |
if (console_pixmap != -1) { |
kernel_pixmap = switch_screens(console_pixmap); |
console_pixmap = -1; |
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { |
prev_console = active_console; |
active_console = KERNEL_CONSOLE; |
} else |
newcons = active_console; |
} |
active_console = newcons; |
gcons_change_console(newcons); |
conn = &connections[active_console]; |
set_style(&conn->screenbuffer.style); |
curs_visibility(0); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
unsigned int size_x; |
size_x = conn->screenbuffer.size_x; |
interbuffer[i + j * size_x] = |
*get_field_at(&conn->screenbuffer, i, j); |
} |
/* This call can preempt, but we are already at the end */ |
rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA); |
} |
if ((!interbuffer) || (rc != 0)) { |
set_style(&conn->screenbuffer.style); |
clrscr(); |
style = &conn->screenbuffer.style; |
if (newcons != KERNEL_CONSOLE) { |
async_serialize_start(); |
if (active_console == KERNEL_CONSOLE) |
gcons_redraw_console(); |
active_console = newcons; |
gcons_change_console(newcons); |
conn = &connections[active_console]; |
set_attrs(&conn->screenbuffer.attrs); |
curs_visibility(false); |
if (interbuffer) { |
for (i = 0; i < conn->screenbuffer.size_x; i++) |
for (j = 0; j < conn->screenbuffer.size_y; j++) { |
unsigned int size_x; |
size_x = conn->screenbuffer.size_x; |
interbuffer[i + j * size_x] = |
*get_field_at(&conn->screenbuffer, i, j); |
} |
/* This call can preempt, but we are already at the end */ |
rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA); |
} |
if ((!interbuffer) || (rc != 0)) { |
set_attrs(&conn->screenbuffer.attrs); |
clrscr(); |
attrs = &conn->screenbuffer.attrs; |
for (j = 0; j < conn->screenbuffer.size_y; j++) |
for (i = 0; i < conn->screenbuffer.size_x; i++) { |
field = get_field_at(&conn->screenbuffer, i, j); |
if (!attrs_same(*attrs, field->attrs)) |
set_attrs(&field->attrs); |
attrs = &field->attrs; |
if ((field->character == ' ') && |
(attrs_same(field->attrs, |
conn->screenbuffer.attrs))) |
continue; |
for (j = 0; j < conn->screenbuffer.size_y; j++) |
for (i = 0; i < conn->screenbuffer.size_x; i++) { |
field = get_field_at(&conn->screenbuffer, i, j); |
if (!style_same(*style, field->style)) |
set_style(&field->style); |
style = &field->style; |
if ((field->character == ' ') && |
(style_same(field->style, |
conn->screenbuffer.style))) |
continue; |
prtchr(field->character, j, i); |
} |
prtchr(field->character, j, i); |
} |
} |
curs_goto(conn->screenbuffer.position_y, |
conn->screenbuffer.position_x); |
curs_visibility(conn->screenbuffer.is_cursor_visible); |
async_serialize_end(); |
} |
curs_goto(conn->screenbuffer.position_y, |
conn->screenbuffer.position_x); |
curs_visibility(conn->screenbuffer.is_cursor_visible); |
async_serialize_end(); |
} |
/** Handler for keyboard */ |
302,7 → 298,7 |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
int c; |
kbd_event_t ev; |
connection_t *conn; |
int newcon; |
324,23 → 320,24 |
IPC_GET_ARG2(call)); |
retval = 0; |
break; |
case KBD_PUSHCHAR: |
/* got key from keyboard driver */ |
case KBD_EVENT: |
/* Got event from keyboard driver. */ |
retval = 0; |
ev.type = IPC_GET_ARG1(call); |
ev.key = IPC_GET_ARG2(call); |
ev.mods = IPC_GET_ARG3(call); |
ev.c = IPC_GET_ARG4(call); |
retval = 0; |
c = IPC_GET_ARG1(call); |
/* switch to another virtual console */ |
conn = &connections[active_console]; |
/* |
* if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + |
* CONSOLE_COUNT)) { |
*/ |
if ((c >= 0x101) && (c < 0x101 + CONSOLE_COUNT)) { |
if (c == 0x112) |
if ((ev.key >= KC_F1) && (ev.key < KC_F1 + |
CONSOLE_COUNT)) { |
if (ev.key == KC_F12) |
change_console(KERNEL_CONSOLE); |
else |
change_console(c - 0x101); |
change_console(ev.key - KC_F1); |
break; |
} |
347,14 → 344,14 |
/* if client is awaiting key, send it */ |
if (conn->keyrequest_counter > 0) { |
conn->keyrequest_counter--; |
ipc_answer_1(fifo_pop(conn->keyrequests), EOK, |
c); |
ipc_answer_4(fifo_pop(conn->keyrequests), EOK, |
ev.type, ev.key, ev.mods, ev.c); |
break; |
} |
keybuffer_push(&conn->keybuffer, c); |
keybuffer_push(&conn->keybuffer, &ev); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
369,9 → 366,9 |
ipc_callid_t callid; |
ipc_call_t call; |
int consnum; |
ipcarg_t arg1, arg2; |
ipcarg_t arg1, arg2, arg3, arg4; |
connection_t *conn; |
if ((consnum = find_free_connection()) == -1) { |
ipc_answer_0(iid, ELIMIT); |
return; |
386,20 → 383,23 |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
while (1) { |
async_serialize_end(); |
callid = async_get_call(&call); |
async_serialize_start(); |
arg1 = 0; |
arg2 = 0; |
arg3 = 0; |
arg4 = 0; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
gcons_notify_disconnect(consnum); |
/* Answer all pending requests */ |
while (conn->keyrequest_counter > 0) { |
while (conn->keyrequest_counter > 0) { |
conn->keyrequest_counter--; |
ipc_answer_0(fifo_pop(conn->keyrequests), |
ENOENT); |
437,11 → 437,26 |
break; |
case CONSOLE_SET_STYLE: |
arg1 = IPC_GET_ARG1(call); |
screenbuffer_set_style(&conn->screenbuffer, arg1); |
if (consnum == active_console) |
set_style(arg1); |
break; |
case CONSOLE_SET_COLOR: |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_style(&conn->screenbuffer, arg1, |
arg3 = IPC_GET_ARG3(call); |
screenbuffer_set_color(&conn->screenbuffer, arg1, |
arg2, arg3); |
if (consnum == active_console) |
set_color(arg1, arg2, arg3); |
break; |
case CONSOLE_SET_RGB_COLOR: |
arg1 = IPC_GET_ARG1(call); |
arg2 = IPC_GET_ARG2(call); |
screenbuffer_set_rgb_color(&conn->screenbuffer, arg1, |
arg2); |
if (consnum == active_console) |
set_style_col(arg1, arg2); |
set_rgb_color(arg1, arg2); |
break; |
case CONSOLE_CURSOR_VISIBILITY: |
arg1 = IPC_GET_ARG1(call); |
449,7 → 464,7 |
if (consnum == active_console) |
curs_visibility(arg1); |
break; |
case CONSOLE_GETCHAR: |
case CONSOLE_GETKEY: |
if (keybuffer_empty(&conn->keybuffer)) { |
/* buffer is empty -> store request */ |
if (conn->keyrequest_counter < |
465,54 → 480,66 |
} |
continue; |
} |
keybuffer_pop(&conn->keybuffer, (int *) &arg1); |
kbd_event_t ev; |
keybuffer_pop(&conn->keybuffer, &ev); |
arg1 = ev.type; |
arg2 = ev.key; |
arg3 = ev.mods; |
arg4 = ev.c; |
break; |
} |
ipc_answer_2(callid, EOK, arg1, arg2); |
ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4); |
} |
} |
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
change_console(prev_console); |
} |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Console service\n"); |
ipcarg_t phonehash; |
int kbd_phone; |
size_t ib_size; |
int i; |
async_set_client_connection(client_connection); |
/* Connect to keyboard driver */ |
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
while (kbd_phone < 0) { |
usleep(10000); |
kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0); |
if (kbd_phone < 0) { |
printf(NAME ": Failed to connect to keyboard service\n"); |
return -1; |
} |
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { |
printf(NAME ": Failed to create callback from keyboard service\n"); |
return -1; |
} |
async_new_connection(phonehash, 0, NULL, keyboard_events); |
/* Connect to framebuffer driver */ |
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0); |
while (fb_info.phone < 0) { |
usleep(10000); |
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0); |
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0); |
if (fb_info.phone < 0) { |
printf(NAME ": Failed to connect to video service\n"); |
return -1; |
} |
/* Save old kernel screen */ |
kernel_pixmap = switch_screens(-1); |
/* Disable kernel output to the console */ |
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE); |
/* Initialize gcons */ |
gcons_init(fb_info.phone); |
/* Synchronize, the gcons can have something in queue */ |
async_req_0_0(fb_info.phone, FB_FLUSH); |
/* Enable double buffering */ |
async_msg_2(fb_info.phone, FB_VIEWPORT_DB, (sysarg_t) -1, 1); |
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows, |
&fb_info.cols); |
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND); |
clrscr(); |
/* Init virtual consoles */ |
532,32 → 559,48 |
} |
} |
connections[KERNEL_CONSOLE].used = 1; |
interbuffer = mmap(NULL, |
sizeof(keyfield_t) * fb_info.cols * fb_info.rows, |
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); |
if (!interbuffer) { |
/* Set up shared memory buffer. */ |
ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; |
interbuffer = as_get_mappable_page(ib_size); |
if (as_area_create(interbuffer, ib_size, AS_AREA_READ | |
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) { |
interbuffer = NULL; |
} |
if (interbuffer) { |
if (ipc_share_out_start(fb_info.phone, interbuffer, |
AS_AREA_READ) != EOK) { |
munmap(interbuffer, |
sizeof(keyfield_t) * fb_info.cols * fb_info.rows); |
as_area_destroy(interbuffer); |
interbuffer = NULL; |
} |
} |
curs_goto(0, 0); |
curs_visibility( |
connections[active_console].screenbuffer.is_cursor_visible); |
/* Register at NS */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { |
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) |
return -1; |
/* Receive kernel notifications */ |
if (sysinfo_value("kconsole.present")) { |
int devno = sysinfo_value("kconsole.devno"); |
int inr = sysinfo_value("kconsole.inr"); |
if (ipc_register_irq(inr, devno, 0, NULL) != EOK) |
printf(NAME ": Error registering kconsole notifications\n"); |
async_set_interrupt_received(interrupt_received); |
} |
// FIXME: avoid connectiong to itself, keep using klog |
// printf(NAME ": Accepting connections\n"); |
async_manager(); |
return 0; |
} |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/console/console.h |
---|
39,15 → 39,6 |
#define CONSOLE_COUNT 12 |
#define CONSOLE_GETCHAR 1026 |
#define CONSOLE_PUTCHAR 1027 |
#define CONSOLE_CLEAR 1028 |
#define CONSOLE_GOTO 1029 |
#define CONSOLE_GETSIZE 1030 |
#define CONSOLE_FLUSH 1031 |
#define CONSOLE_SET_STYLE 1032 |
#define CONSOLE_CURSOR_VISIBILITY 1033 |
#endif |
/** @} |
/branches/dd/uspace/srv/console/screenbuffer.c |
---|
33,6 → 33,7 |
*/ |
#include <screenbuffer.h> |
#include <console/style.h> |
#include <malloc.h> |
#include <unistd.h> |
49,7 → 50,7 |
field = get_field_at(scr, scr->position_x, scr->position_y); |
field->character = c; |
field->style = scr->style; |
field->attrs = scr->attrs; |
} |
/** Initilize screenbuffer. Allocate space for screen content in accordance to given size. |
67,8 → 68,8 |
scr->size_x = size_x; |
scr->size_y = size_y; |
scr->style.fg_color = DEFAULT_FOREGROUND; |
scr->style.bg_color = DEFAULT_BACKGROUND; |
scr->attrs.t = at_style; |
scr->attrs.a.s.style = STYLE_NORMAL; |
scr->is_cursor_visible = 1; |
screenbuffer_clear(scr); |
85,7 → 86,7 |
for (i = 0; i < (scr->size_x * scr->size_y); i++) { |
scr->buffer[i].character = ' '; |
scr->buffer[i].style = scr->style; |
scr->buffer[i].attrs = scr->attrs; |
} |
scr->top_line = 0; |
103,7 → 104,7 |
for (i = 0; i < scr->size_x; i++) { |
scr->buffer[i + line * scr->size_x].character = ' '; |
scr->buffer[i + line * scr->size_x].style = scr->style; |
scr->buffer[i + line * scr->size_x].attrs = scr->attrs; |
} |
} |
136,12 → 137,37 |
* @param fg_color |
* @param bg_color |
*/ |
void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color) |
void screenbuffer_set_style(screenbuffer_t *scr, int style) |
{ |
scr->style.fg_color = fg_color; |
scr->style.bg_color = bg_color; |
scr->attrs.t = at_style; |
scr->attrs.a.s.style = style; |
} |
/** Set new color. |
* @param scr |
* @param fg_color |
* @param bg_color |
*/ |
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color, unsigned int flags) |
{ |
scr->attrs.t = at_idx; |
scr->attrs.a.i.fg_color = fg_color; |
scr->attrs.a.i.bg_color = bg_color; |
scr->attrs.a.i.flags = flags; |
} |
/** Set new RGB color. |
* @param scr |
* @param fg_color |
* @param bg_color |
*/ |
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color) |
{ |
scr->attrs.t = at_rgb; |
scr->attrs.a.r.fg_color = fg_color; |
scr->attrs.a.r.bg_color = bg_color; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/console/gcons.c |
---|
81,7 → 81,7 |
static void vp_switch(int vp) |
{ |
async_msg_1(fbphone,FB_VIEWPORT_SWITCH, vp); |
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp); |
} |
/** Create view port */ |
97,15 → 97,15 |
async_msg_0(fbphone, FB_CLEAR); |
} |
static void set_style(int fgcolor, int bgcolor) |
static void set_rgb_color(int fgcolor, int bgcolor) |
{ |
async_msg_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor); |
async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor); |
} |
/** Transparent putchar */ |
static void tran_putch(char c, int row, int col) |
{ |
async_msg_3(fbphone, FB_TRANS_PUTCHAR, c, row, col); |
async_msg_3(fbphone, FB_PUTCHAR, c, row, col); |
} |
/** Redraw the button showing state of a given console */ |
189,10 → 189,10 |
console_state[consnum] = CONS_DISCONNECTED_SEL; |
else |
console_state[consnum] = CONS_DISCONNECTED; |
if (active_console == KERNEL_CONSOLE) |
return; |
redraw_state(consnum); |
vp_switch(console_vp); |
} |
217,16 → 217,10 |
/** Change to kernel console */ |
void gcons_in_kernel(void) |
{ |
if (console_state[active_console] == CONS_DISCONNECTED_SEL) |
console_state[active_console] = CONS_DISCONNECTED; |
else |
console_state[active_console] = CONS_IDLE; |
redraw_state(active_console); |
if (animation != -1) |
async_msg_1(fbphone, FB_ANIM_STOP, animation); |
active_console = KERNEL_CONSOLE; /* Set to kernel console */ |
active_console = KERNEL_CONSOLE; |
vp_switch(0); |
} |
250,8 → 244,8 |
*/ |
void gcons_mouse_move(int dx, int dy) |
{ |
mouse_x = limit(mouse_x+dx, 0, xres); |
mouse_y = limit(mouse_y+dy, 0, yres); |
mouse_x = limit(mouse_x + dx, 0, xres); |
mouse_y = limit(mouse_y + dy, 0, yres); |
async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y); |
} |
258,7 → 252,7 |
static int gcons_find_conbut(int x, int y) |
{ |
int status_start = STATUS_START + (xres - 800) / 2;; |
int status_start = STATUS_START + (xres - 800) / 2; |
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT) |
return -1; |
268,10 → 262,10 |
if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT) |
return -1; |
if (((x - status_start) % (STATUS_WIDTH+STATUS_SPACE)) < STATUS_SPACE) |
if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE) |
return -1; |
return (x - status_start) / (STATUS_WIDTH+STATUS_SPACE); |
return (x - status_start) / (STATUS_WIDTH + STATUS_SPACE); |
} |
/** Handle mouse click |
342,22 → 336,23 |
extern int _binary_helenos_ppm_size; |
extern char _binary_nameic_ppm_start[0]; |
extern int _binary_nameic_ppm_size; |
/** Redraws console graphics */ |
static void gcons_redraw_console(void) |
/** Redraws console graphics */ |
void gcons_redraw_console(void) |
{ |
int i; |
if (!use_gcons) |
return; |
vp_switch(0); |
set_style(MAIN_COLOR, MAIN_COLOR); |
set_rgb_color(MAIN_COLOR, MAIN_COLOR); |
clear(); |
draw_pixmap(_binary_helenos_ppm_start, |
(size_t) &_binary_helenos_ppm_size, xres - 66, 2); |
draw_pixmap(_binary_nameic_ppm_start, |
(size_t) &_binary_nameic_ppm_size, 5, 17); |
for (i = 0; i < CONSOLE_COUNT; i++) |
redraw_state(i); |
vp_switch(console_vp); |
459,16 → 454,16 |
int rc; |
int i; |
int status_start = STATUS_START; |
fbphone = phone; |
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres); |
if (rc) |
return; |
if (xres < 800 || yres < 600) |
if ((xres < 800) || (yres < 600)) |
return; |
/* create console viewport */ |
/* Align width & height to character size */ |
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP, |
486,7 → 481,7 |
if (cstatus_vp[i] < 0) |
return; |
vp_switch(cstatus_vp[i]); |
set_style(0x202020, 0xffffff); |
set_rgb_color(0x202020, 0xffffff); |
} |
/* Initialize icons */ |
506,13 → 501,12 |
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED]; |
make_anim(); |
use_gcons = 1; |
console_state[0] = CONS_DISCONNECTED_SEL; |
console_state[KERNEL_CONSOLE] = CONS_KERNEL; |
gcons_redraw_console(); |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/console/gcons.h |
---|
36,6 → 36,7 |
#define _GCONS_H_ |
void gcons_init(int phone); |
void gcons_redraw_console(void); |
void gcons_change_console(int consnum); |
void gcons_notify_char(int consnum); |
void gcons_in_kernel(void); |
/branches/dd/uspace/srv/console/screenbuffer.h |
---|
35,28 → 35,52 |
#ifndef __SCREENBUFFER_H__ |
#define __SCREENBUFFER_H__ |
#include <stdint.h> |
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */ |
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */ |
typedef struct { |
unsigned int bg_color; /**< background color */ |
unsigned int fg_color; /**< foreground color */ |
} style_t; |
uint8_t style; |
} attr_style_t; |
typedef struct { |
uint8_t fg_color; |
uint8_t bg_color; |
uint8_t flags; |
} attr_idx_t; |
typedef struct { |
uint32_t bg_color; /**< background color */ |
uint32_t fg_color; /**< foreground color */ |
} attr_rgb_t; |
typedef struct { |
enum { |
at_style, |
at_idx, |
at_rgb |
} t; |
union { |
attr_style_t s; |
attr_idx_t i; |
attr_rgb_t r; |
} a; |
} attrs_t; |
/** One field on screen. It contain one character and its attributes. */ |
typedef struct { |
char character; /**< Character itself */ |
style_t style; /**< Character`s attributes */ |
attrs_t attrs; /**< Character`s attributes */ |
} keyfield_t; |
/** Structure for buffering state of one virtual console. |
*/ |
typedef struct { |
keyfield_t *buffer; /**< Screen content - characters and its style. Used as cyclyc buffer. */ |
keyfield_t *buffer; /**< Screen content - characters and their attributes. Used as a circular buffer. */ |
unsigned int size_x, size_y; /**< Number of columns and rows */ |
unsigned int position_x, position_y; /**< Coordinates of last printed character for determining cursor position */ |
style_t style; /**< Current style */ |
attrs_t attrs; /**< Current attributes. */ |
unsigned int top_line; /**< Points to buffer[][] line that will be printed at screen as the first line */ |
unsigned char is_cursor_visible; /**< Cursor state - default is visible */ |
} screenbuffer_t; |
72,14 → 96,23 |
return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x; |
} |
/** Compares two styles. |
/** Compares two sets of attributes. |
* @param s1 first style |
* @param s2 second style |
* @return nonzero on equality |
*/ |
static inline int style_same(style_t s1, style_t s2) |
static inline int attrs_same(attrs_t a1, attrs_t a2) |
{ |
return s1.fg_color == s2.fg_color && s1.bg_color == s2.bg_color; |
if (a1.t != a2.t) return 0; |
switch (a1.t) { |
case at_style: return a1.a.s.style == a2.a.s.style; |
case at_idx: return a1.a.i.fg_color == a2.a.i.fg_color && |
a1.a.i.bg_color == a2.a.i.bg_color && |
a1.a.i.flags == a2.a.i.flags; |
case at_rgb: return a1.a.r.fg_color == a2.a.r.fg_color && |
a1.a.r.bg_color == a2.a.r.bg_color; |
} |
} |
90,7 → 123,11 |
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line); |
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest); |
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y); |
void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color); |
void screenbuffer_set_style(screenbuffer_t *scr, int style); |
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, |
unsigned int bg_color, unsigned int attr); |
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, |
unsigned int bg_color); |
#endif |
/branches/dd/uspace/srv/console/Makefile |
---|
31,8 → 31,9 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I. -I../kbd/include -I../fb |
LIBS = $(LIBC_PREFIX)/libc.a |
57,24 → 58,28 |
$(addsuffix .o,$(basename $(IMAGES))) |
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) |
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/rd/rd.c |
---|
51,8 → 51,12 |
#include <align.h> |
#include <async.h> |
#include <futex.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#include "rd.h" |
#define NAME "rd" |
/** Pointer to the ramdisk's image. */ |
static void *rd_addr; |
/** Size of the ramdisk. */ |
77,45 → 81,24 |
ipc_call_t call; |
int retval; |
void *fs_va = NULL; |
ipcarg_t offset; |
off_t offset; |
size_t block_size; |
size_t maxblock_size; |
/* |
* We allocate VA for communication per connection. |
* This allows us to potentionally have more clients and work |
* concurrently. |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE)); |
if (!fs_va) { |
/* |
* Hang up the phone if we cannot proceed any further. |
* This is the answer to the call that opened the connection. |
*/ |
ipc_answer_0(iid, EHANGUP); |
return; |
} else { |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
* Return supported block size as ARG1. |
*/ |
ipc_answer_1(iid, EOK, BLOCK_SIZE); |
} |
ipc_answer_0(iid, EOK); |
/* |
* Now we wait for the client to send us its communication as_area. |
*/ |
size_t size; |
if (ipc_share_out_receive(&callid, &size, NULL)) { |
if (size >= BLOCK_SIZE) { |
/* |
* The client sends an as_area that can absorb the whole |
* block. |
*/ |
int flags; |
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) { |
fs_va = as_get_mappable_page(maxblock_size); |
if (fs_va) { |
(void) ipc_share_out_finalize(callid, fs_va); |
} else { |
/* |
* The client offered as_area too small. |
* Close the connection. |
*/ |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
141,8 → 124,16 |
return; |
case RD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Reading past the end of the device. |
*/ |
retval = ELIMIT; |
149,14 → 140,22 |
break; |
} |
futex_down(&rd_futex); |
memcpy(fs_va, rd_addr + offset, BLOCK_SIZE); |
memcpy(fs_va, rd_addr + offset * block_size, block_size); |
futex_up(&rd_futex); |
retval = EOK; |
break; |
case RD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) { |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
/* |
* Maximum block size exceeded. |
*/ |
retval = ELIMIT; |
break; |
} |
if (offset * block_size > rd_size - block_size) { |
/* |
* Writing past the end of the device. |
*/ |
retval = ELIMIT; |
163,7 → 162,7 |
break; |
} |
futex_up(&rd_futex); |
memcpy(rd_addr + offset, fs_va, BLOCK_SIZE); |
memcpy(rd_addr + offset * block_size, fs_va, block_size); |
futex_down(&rd_futex); |
retval = EOK; |
break; |
181,46 → 180,117 |
} |
} |
static int driver_register(char *name) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
int phone; |
ipcarg_t callback_phonehash; |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
if (phone < 0) { |
printf(NAME ": Failed to connect to device mapper\n"); |
return -1; |
} |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *) name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return -1; |
} |
async_set_client_connection(rd_connection); |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
return phone; |
} |
static int device_register(int driver_phone, char *name, int *handle) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *) name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (EOK == retval) { |
if (NULL != handle) |
*handle = (int) IPC_GET_ARG1(answer); |
} |
return retval; |
} |
/** Prepare the ramdisk image for operation. */ |
static bool rd_init(void) |
{ |
int retval, flags; |
rd_size = sysinfo_value("rd.size"); |
void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical"); |
if (rd_size == 0) |
if (rd_size == 0) { |
printf(NAME ": No RAM disk found\n"); |
return false; |
} |
rd_addr = as_get_mappable_page(rd_size); |
flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE; |
retval = physmem_map(rd_ph_addr, rd_addr, |
int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE; |
int retval = physmem_map(rd_ph_addr, rd_addr, |
ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) |
if (retval < 0) { |
printf(NAME ": Error mapping RAM disk\n"); |
return false; |
} |
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size); |
int driver_phone = driver_register(NAME); |
if (driver_phone < 0) { |
printf(NAME ": Unable to register driver\n"); |
return false; |
} |
int dev_handle; |
if (EOK != device_register(driver_phone, "initrd", &dev_handle)) { |
ipc_hangup(driver_phone); |
printf(NAME ": Unable to register device\n"); |
return false; |
} |
return true; |
} |
int main(int argc, char **argv) |
{ |
if (rd_init()) { |
ipcarg_t phonead; |
async_set_client_connection(rd_connection); |
/* Register service at nameserver */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_RD, 0, 0, &phonead) != 0) |
return -1; |
async_manager(); |
/* Never reached */ |
return 0; |
} |
printf(NAME ": HelenOS RAM disk server\n"); |
return -1; |
if (!rd_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
/branches/dd/uspace/srv/rd/rd.h |
---|
43,8 → 43,6 |
#ifndef RD_RD_H_ |
#define RD_RD_H_ |
#define BLOCK_SIZE 1024 /**< Working block size */ |
#define RD_BASE 1024 |
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */ |
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */ |
/branches/dd/uspace/srv/rd/Makefile |
---|
29,8 → 29,10 |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
46,22 → 48,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/loader/main.c |
---|
0,0 → 1,381 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup loader |
* @brief Loads and runs programs from VFS. |
* @{ |
*/ |
/** |
* @file |
* @brief Loads and runs programs from VFS. |
* |
* The program loader is a special init binary. Its image is used |
* to create a new task upon a @c task_spawn syscall. The syscall |
* returns the id of a phone connected to the newly created task. |
* |
* The caller uses this phone to send the pathname and various other |
* information to the loader. This is normally done by the C library |
* and completely hidden from applications. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <bool.h> |
#include <fcntl.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/loader.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
#include <as.h> |
#include <elf.h> |
#include <elf_load.h> |
#define DPRINTF(...) |
/** Pathname of the file that will be loaded */ |
static char *pathname = NULL; |
/** The Program control block */ |
static pcb_t pcb; |
/** Number of arguments */ |
static int argc = 0; |
/** Argument vector */ |
static char **argv = NULL; |
/** Buffer holding all arguments */ |
static char *arg_buf = NULL; |
static elf_info_t prog_info; |
static elf_info_t interp_info; |
static bool is_dyn_linked; |
/** Used to limit number of connections to one. */ |
static bool connected; |
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
task_id_t task_id; |
size_t len; |
task_id = task_get_id(); |
if (!ipc_data_read_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (len > sizeof(task_id)) |
len = sizeof(task_id); |
ipc_data_read_finalize(callid, &task_id, len); |
ipc_answer_0(rid, EOK); |
} |
/** Receive a call setting pathname of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
char *name_buf; |
if (!ipc_data_write_receive(&callid, &len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
name_buf = malloc(len + 1); |
if (!name_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, name_buf, len); |
ipc_answer_0(rid, EOK); |
if (pathname != NULL) { |
free(pathname); |
pathname = NULL; |
} |
name_buf[len] = '\0'; |
pathname = name_buf; |
} |
/** Receive a call setting arguments of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t buf_len, arg_len; |
char *p; |
int n; |
if (!ipc_data_write_receive(&callid, &buf_len)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (arg_buf != NULL) { |
free(arg_buf); |
arg_buf = NULL; |
} |
if (argv != NULL) { |
free(argv); |
argv = NULL; |
} |
arg_buf = malloc(buf_len + 1); |
if (!arg_buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipc_data_write_finalize(callid, arg_buf, buf_len); |
ipc_answer_0(rid, EOK); |
arg_buf[buf_len] = '\0'; |
/* |
* Count number of arguments |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
/* Allocate argv */ |
argv = malloc((n + 1) * sizeof(char *)); |
if (argv == NULL) { |
free(arg_buf); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Fill argv with argument pointers |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
argv[n] = p; |
arg_len = strlen(p); |
p = p + arg_len + 1; |
++n; |
} |
argc = n; |
argv[n] = NULL; |
} |
/** Load the previously selected program. |
* |
* @param rid |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static int loader_load(ipc_callid_t rid, ipc_call_t *request) |
{ |
int rc; |
rc = elf_load_file(pathname, 0, &prog_info); |
if (rc < 0) { |
DPRINTF("Failed to load executable '%s'.\n", pathname); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
elf_create_pcb(&prog_info, &pcb); |
pcb.argc = argc; |
pcb.argv = argv; |
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
is_dyn_linked = false; |
ipc_answer_0(rid, EOK); |
return 0; |
} |
rc = elf_load_file(prog_info.interp, 0, &interp_info); |
if (rc < 0) { |
DPRINTF("Failed to load interpreter '%s.'\n", |
prog_info.interp); |
ipc_answer_0(rid, EINVAL); |
return 1; |
} |
is_dyn_linked = true; |
ipc_answer_0(rid, EOK); |
return 0; |
} |
/** Run the previously loaded program. |
* |
* @param rid |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static void loader_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
const char *cp; |
/* Set the task name. */ |
cp = strrchr(pathname, '/'); |
cp = (cp == NULL) ? pathname : (cp + 1); |
task_set_name(cp); |
if (is_dyn_linked == true) { |
/* Dynamically linked program */ |
DPRINTF("Run ELF interpreter.\n"); |
DPRINTF("Entry point: 0x%lx\n", interp_info.entry); |
close_console(); |
ipc_answer_0(rid, EOK); |
elf_run(&interp_info, &pcb); |
} else { |
/* Statically linked program */ |
close_console(); |
ipc_answer_0(rid, EOK); |
elf_run(&prog_info, &pcb); |
} |
/* Not reached */ |
} |
/** Handle loader connection. |
* |
* Receive and carry out commands (of which the last one should be |
* to execute the loaded program). |
*/ |
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
/* Already have a connection? */ |
if (connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
connected = true; |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
/* Ignore parameters, the connection is already open */ |
(void) iid; |
(void) icall; |
while (1) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
exit(0); |
case LOADER_GET_TASKID: |
loader_get_taskid(callid, &call); |
continue; |
case LOADER_SET_PATHNAME: |
loader_set_pathname(callid, &call); |
continue; |
case LOADER_SET_ARGS: |
loader_set_args(callid, &call); |
continue; |
case LOADER_LOAD: |
loader_load(callid, &call); |
continue; |
case LOADER_RUN: |
loader_run(callid, &call); |
/* Not reached */ |
default: |
retval = ENOENT; |
break; |
} |
if ((callid & IPC_CALLID_NOTIFICATION) == 0 && |
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) { |
DPRINTF("Responding EINVAL to method %d.\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, EINVAL); |
} |
} |
} |
/** Program loader main function. |
*/ |
int main(int argc, char *argv[]) |
{ |
ipcarg_t phonead; |
connected = false; |
/* Set a handler of incomming connections. */ |
async_set_client_connection(loader_connection); |
/* Register at naming service. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) |
return -1; |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/loader/Makefile |
---|
0,0 → 1,83 |
# |
# Copyright (c) 2005 Martin Decky |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
include arch/$(UARCH)/Makefile.inc |
CFLAGS += -Iinclude |
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a |
## Sources |
# |
OUTPUT = loader |
GENERIC_SOURCES = \ |
main.c \ |
elf_load.c \ |
interp.s |
SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(UARCH)/_link.ld Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(UARCH)/_link.ld |
$(LD) -T arch/$(UARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in |
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/srv/loader/arch/sparc64/_link.ld.in |
---|
0,0 → 1,59 |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000 + SIZEOF_HEADERS; |
.init : { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/sparc64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/sparc64.s |
/branches/dd/uspace/srv/loader/arch/sparc64/sparc64.s |
---|
0,0 → 1,42 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %o0 contains entry_point |
# %o1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb pointer to entry point in %o1. As it is already |
# there, no action is needed. |
call %o0 |
nop |
# fixme: use branch instead of call |
/branches/dd/uspace/srv/loader/arch/ia64/_link.ld.in |
---|
0,0 → 1,61 |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
/* On Itanium code sections must be aligned to 16 bytes. */ |
. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16); |
.init : { |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
. = . + 0x4000; |
.got : { |
_gp = .; |
*(.got*); |
} :data |
.data : { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/ia64/Makefile.inc |
---|
0,0 → 1,31 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/ia64.s |
AFLAGS += -xexplicit |
/branches/dd/uspace/srv/loader/arch/ia64/ia64.s |
---|
0,0 → 1,43 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# in0 (r32) contains entry_point |
# in1 (r33) contains pcb |
# |
# Jump to a program entry point |
program_run: |
# Pass pcb to the entry point in r2 |
mov b6 = r32 |
mov r2 = r33 ;; |
br b6 ;; |
/branches/dd/uspace/srv/loader/arch/arm32/_link.ld.in |
---|
0,0 → 1,59 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
. = 0x70001000; |
.init ALIGN(0x1000): SUBALIGN(0x1000) { |
*(.init); |
} : text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.opd); |
*(.data .data.*); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(.scommon); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/arm32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/arm32.s |
/branches/dd/uspace/srv/loader/arch/arm32/arm32.s |
---|
0,0 → 1,39 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# r0 contains entry_point |
# r1 contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb is passed to the entry point in r1 (where it already is) |
mov r15, r0 |
/branches/dd/uspace/srv/loader/arch/ppc32/_link.ld.in |
---|
0,0 → 1,57 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(.sbss); |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/ppc32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/ppc32.s |
/branches/dd/uspace/srv/loader/arch/ppc32/ppc32.s |
---|
0,0 → 1,40 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %r3 contains entry_point |
# %r4 contains pcb |
# |
# Jump to a program entry point |
program_run: |
mtctr %r3 |
mr %r6, %r4 # Pass pcb to the entry point in %r6 |
bctr |
/branches/dd/uspace/srv/loader/arch/amd64/_link.ld.in |
---|
0,0 → 1,52 |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} : interp |
/* . = 0x0000700000001000;*/ |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/amd64/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__64_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/amd64.s |
/branches/dd/uspace/srv/loader/arch/amd64/amd64.s |
---|
0,0 → 1,43 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# %rdi contains entry_point |
# %rsi contains pcb |
# |
# Jump to a program entry point |
program_run: |
# pcb must be passed in %rdi, use %rdx as a scratch register |
mov %rdi, %rdx |
mov %rsi, %rdi |
# jump to entry point |
jmp %rdx |
/branches/dd/uspace/srv/loader/arch/mips32/_link.ld.in |
---|
0,0 → 1,66 |
/* |
* The only difference from _link.ld.in for regular statically-linked apps |
* is the base address. |
*/ |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70004000; |
.init ALIGN(0x4000) : SUBALIGN(0x4000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data : { |
*(.data); |
*(.data.rel*); |
} :data |
.got : { |
_gp = .; |
*(.got); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.sbss : { |
*(.scommon); |
*(.sbss); |
} |
.bss : { |
*(.bss); |
*(COMMON); |
} :data |
. = ALIGN(0x4000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/mips32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/mips32.s |
/branches/dd/uspace/srv/loader/arch/mips32/mips32.s |
---|
0,0 → 1,49 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.section .text |
.global program_run |
.set noreorder |
## void program_run(void *entry_point, void *pcb); |
# |
# $a0 (=$4) contains entry_point |
# $a1 (=$5) contains pcb |
# |
# Jump to a program entry point |
.ent program_run |
program_run: |
# tmp := entry_point |
move $25, $a0 |
# Pass pcb to the entry point in $a0 |
move $a0, $a1 |
jr $25 |
nop |
.end |
/branches/dd/uspace/srv/loader/arch/ia32/_link.ld.in |
---|
0,0 → 1,55 |
/* |
* The difference from _link.ld.in for regular statically-linked apps |
* is the base address and the special interp section. |
*/ |
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o) |
ENTRY(__entry) |
PHDRS { |
interp PT_INTERP; |
text PT_LOAD FILEHDR PHDRS FLAGS(5); |
data PT_LOAD FLAGS(6); |
} |
SECTIONS { |
.interp : { |
*(.interp); |
} :interp |
. = 0x70001000; |
.init ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.init); |
} :text |
.text : { |
*(.text); |
*(.rodata*); |
} :text |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); |
.bss : { |
*(COMMON); |
*(.bss); |
} :data |
. = ALIGN(0x1000); |
_heap = .; |
/DISCARD/ : { |
*(*); |
} |
} |
/branches/dd/uspace/srv/loader/arch/ia32/Makefile.inc |
---|
0,0 → 1,30 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
CFLAGS += -D__32_BITS__ |
ARCH_SOURCES := arch/$(UARCH)/ia32.s |
/branches/dd/uspace/srv/loader/arch/ia32/ia32.s |
---|
0,0 → 1,49 |
# |
# Copyright (c) 2008 Jiri Svoboda |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.globl program_run |
## void program_run(void *entry_point, void *pcb); |
# |
# Jump to a program entry point |
program_run: |
# Use standard ia32 prologue not to confuse anybody |
push %ebp |
movl %esp, %ebp |
# %eax := entry_point |
movl 0x8(%ebp), %eax |
# %ebx := pcb |
# pcb is passed to the entry point int %ebx |
mov 0xc(%ebp), %ebx |
# Save a tiny bit of stack space |
pop %ebp |
jmp %eax |
/branches/dd/uspace/srv/loader/arch/mips32eb |
---|
0,0 → 1,0 |
link mips32 |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/dd/uspace/srv/loader/elf_load.c |
---|
0,0 → 1,469 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Userspace ELF loader. |
* |
* This module allows loading ELF binaries (both executables and |
* shared objects) from VFS. The current implementation allocates |
* anonymous memory, fills it with segment data and then adjusts |
* the memory areas' flags to the final value. In the future, |
* the segments will be mapped directly from the file. |
*/ |
#include <stdio.h> |
#include <sys/types.h> |
#include <align.h> |
#include <assert.h> |
#include <as.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <smc.h> |
#include <loader/pcb.h> |
#include "elf.h" |
#include "elf_load.h" |
#include "arch.h" |
#define DPRINTF(...) |
static char *error_codes[] = { |
"no error", |
"invalid image", |
"address space error", |
"incompatible image", |
"unsupported image type", |
"irrecoverable error" |
}; |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias); |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry); |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry); |
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); |
/** Read until the buffer is read in its entirety. */ |
static int my_read(int fd, char *buf, size_t len) |
{ |
int cnt = 0; |
do { |
buf += cnt; |
len -= cnt; |
cnt = read(fd, buf, len); |
} while ((cnt > 0) && ((len - cnt) > 0)); |
return cnt; |
} |
/** Load ELF binary from a file. |
* |
* Load an ELF binary from the specified file. If the file is |
* an executable program, it is loaded unbiased. If it is a shared |
* object, it is loaded with the bias @a so_bias. Some information |
* extracted from the binary is stored in a elf_info_t structure |
* pointed to by @a info. |
* |
* @param file_name Path to the ELF file. |
* @param so_bias Bias to use if the file is a shared object. |
* @param info Pointer to a structure for storing information |
* extracted from the binary. |
* |
* @return EOK on success or negative error code. |
*/ |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info) |
{ |
elf_ld_t elf; |
int fd; |
int rc; |
fd = open(file_name, O_RDONLY); |
if (fd < 0) { |
DPRINTF("failed opening file\n"); |
return -1; |
} |
elf.fd = fd; |
elf.info = info; |
rc = elf_load(&elf, so_bias); |
close(fd); |
return rc; |
} |
/** Run an ELF executable. |
* |
* Transfers control to the entry point of an ELF executable loaded |
* earlier with elf_load_file(). This function does not return. |
* |
* @param info Info structure filled earlier by elf_load_file() |
*/ |
void elf_run(elf_info_t *info, pcb_t *pcb) |
{ |
program_run(info->entry, pcb); |
/* not reached */ |
} |
/** Create the program control block (PCB). |
* |
* Fills the program control block @a pcb with information from |
* @a info. |
* |
* @param info Program info structure |
* @return EOK on success or negative error code |
*/ |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb) |
{ |
pcb->entry = info->entry; |
pcb->dynamic = info->dynamic; |
} |
/** Load an ELF binary. |
* |
* The @a elf structure contains the loader state, including |
* an open file, from which the binary will be loaded, |
* a pointer to the @c info structure etc. |
* |
* @param elf Pointer to loader state buffer. |
* @param so_bias Bias to use if the file is a shared object. |
* @return EE_OK on success or EE_xx error code. |
*/ |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias) |
{ |
elf_header_t header_buf; |
elf_header_t *header = &header_buf; |
int i, rc; |
rc = my_read(elf->fd, header, sizeof(elf_header_t)); |
if (rc < 0) { |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
elf->header = header; |
/* Identify ELF */ |
if (header->e_ident[EI_MAG0] != ELFMAG0 || |
header->e_ident[EI_MAG1] != ELFMAG1 || |
header->e_ident[EI_MAG2] != ELFMAG2 || |
header->e_ident[EI_MAG3] != ELFMAG3) { |
DPRINTF("Invalid header.\n"); |
return EE_INVALID; |
} |
/* Identify ELF compatibility */ |
if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || |
header->e_machine != ELF_MACHINE || |
header->e_ident[EI_VERSION] != EV_CURRENT || |
header->e_version != EV_CURRENT || |
header->e_ident[EI_CLASS] != ELF_CLASS) { |
DPRINTF("Incompatible data/version/class.\n"); |
return EE_INCOMPATIBLE; |
} |
if (header->e_phentsize != sizeof(elf_segment_header_t)) { |
DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize, |
sizeof(elf_segment_header_t)); |
return EE_INCOMPATIBLE; |
} |
if (header->e_shentsize != sizeof(elf_section_header_t)) { |
DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize, |
sizeof(elf_section_header_t)); |
return EE_INCOMPATIBLE; |
} |
/* Check if the object type is supported. */ |
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) { |
DPRINTF("Object type %d is not supported\n", header->e_type); |
return EE_UNSUPPORTED; |
} |
/* Shared objects can be loaded with a bias */ |
if (header->e_type == ET_DYN) |
elf->bias = so_bias; |
else |
elf->bias = 0; |
elf->info->interp = NULL; |
elf->info->dynamic = NULL; |
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t segment_hdr; |
/* Seek to start of segment header */ |
lseek(elf->fd, header->e_phoff |
+ i * sizeof(elf_segment_header_t), SEEK_SET); |
rc = my_read(elf->fd, &segment_hdr, |
sizeof(elf_segment_header_t)); |
if (rc < 0) { |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
rc = segment_header(elf, &segment_hdr); |
if (rc != EE_OK) |
return rc; |
} |
DPRINTF("Parse sections.\n"); |
/* Inspect all section headers and proccess them. */ |
for (i = 0; i < header->e_shnum; i++) { |
elf_section_header_t section_hdr; |
/* Seek to start of section header */ |
lseek(elf->fd, header->e_shoff |
+ i * sizeof(elf_section_header_t), SEEK_SET); |
rc = my_read(elf->fd, §ion_hdr, |
sizeof(elf_section_header_t)); |
if (rc < 0) { |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
rc = section_header(elf, §ion_hdr); |
if (rc != EE_OK) |
return rc; |
} |
elf->info->entry = |
(entry_point_t)((uint8_t *)header->e_entry + elf->bias); |
DPRINTF("Done.\n"); |
return EE_OK; |
} |
/** Print error message according to error code. |
* |
* @param rc Return code returned by elf_load(). |
* |
* @return NULL terminated description of error. |
*/ |
char *elf_error(unsigned int rc) |
{ |
assert(rc < sizeof(error_codes) / sizeof(char *)); |
return error_codes[rc]; |
} |
/** Process segment header. |
* |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
break; |
case PT_LOAD: |
return load_segment(elf, entry); |
break; |
case PT_INTERP: |
/* Assume silently interp == "/rtld.so" */ |
elf->info->interp = "/rtld.so"; |
break; |
case PT_DYNAMIC: |
case PT_SHLIB: |
case PT_NOTE: |
case PT_LOPROC: |
case PT_HIPROC: |
default: |
DPRINTF("Segment p_type %d unknown.\n", entry->p_type); |
return EE_UNSUPPORTED; |
break; |
} |
return EE_OK; |
} |
/** Load segment described by program header entry. |
* |
* @param elf Loader state. |
* @param entry Program header entry describing segment to be loaded. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
void *a; |
int flags = 0; |
uintptr_t bias; |
uintptr_t base; |
size_t mem_sz; |
int rc; |
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr, |
entry->p_memsz); |
bias = elf->bias; |
if (entry->p_align > 1) { |
if ((entry->p_offset % entry->p_align) != |
(entry->p_vaddr % entry->p_align)) { |
DPRINTF("Align check 1 failed offset%%align=%d, " |
"vaddr%%align=%d\n", |
entry->p_offset % entry->p_align, |
entry->p_vaddr % entry->p_align |
); |
return EE_INVALID; |
} |
} |
/* Final flags that will be set for the memory area */ |
if (entry->p_flags & PF_X) |
flags |= AS_AREA_EXEC; |
if (entry->p_flags & PF_W) |
flags |= AS_AREA_WRITE; |
if (entry->p_flags & PF_R) |
flags |= AS_AREA_READ; |
flags |= AS_AREA_CACHEABLE; |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias, |
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
/* |
* For the course of loading, the area needs to be readable |
* and writeable. |
*/ |
a = as_area_create((uint8_t *)base + bias, mem_sz, |
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); |
if (a == (void *)(-1)) { |
DPRINTF("Memory mapping failed.\n"); |
return EE_MEMORY; |
} |
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a); |
/* |
* Load segment data |
*/ |
rc = lseek(elf->fd, entry->p_offset, SEEK_SET); |
if (rc < 0) { |
printf("seek error\n"); |
return EE_INVALID; |
} |
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/ |
/* Long reads are not possible yet. Load segment piecewise. */ |
unsigned left, now; |
uint8_t *dp; |
left = entry->p_filesz; |
dp = (uint8_t *)(entry->p_vaddr + bias); |
while (left > 0) { |
now = 16384; |
if (now > left) now = left; |
rc = my_read(elf->fd, dp, now); |
if (rc < 0) { |
DPRINTF("Read error.\n"); |
return EE_INVALID; |
} |
left -= now; |
dp += now; |
} |
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags); |
if (rc != 0) { |
DPRINTF("Failed to set memory area flags.\n"); |
return EE_MEMORY; |
} |
if (flags & AS_AREA_EXEC) { |
/* Enforce SMC coherence for the segment */ |
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz)) |
return EE_MEMORY; |
} |
return EE_OK; |
} |
/** Process section header. |
* |
* @param elf Loader state. |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry) |
{ |
switch (entry->sh_type) { |
case SHT_PROGBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tdata */ |
} |
break; |
case SHT_NOBITS: |
if (entry->sh_flags & SHF_TLS) { |
/* .tbss */ |
} |
break; |
case SHT_DYNAMIC: |
/* Record pointer to dynamic section into info structure */ |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
DPRINTF("Dynamic section found at 0x%x.\n", |
(uintptr_t)elf->info->dynamic); |
break; |
default: |
break; |
} |
return EE_OK; |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/loader/interp.s |
---|
0,0 → 1,7 |
# |
# Provide a string to be included in a special DT_INTERP header, even though |
# this is a statically-linked executable. This will mark the binary as |
# the program loader. |
# |
.section .interp , "" |
.string "kernel" |
/branches/dd/uspace/srv/loader/include/arch.h |
---|
0,0 → 1,45 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** @file |
* @brief |
*/ |
#ifndef LOADER_ARCH_H_ |
#define LOADER_ARCH_H_ |
void program_run(void *entry_point, void *pcb); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/loader/include/elf_load.h |
---|
0,0 → 1,83 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
* @brief ELF loader structures and public functions. |
*/ |
#ifndef ELF_LOAD_H_ |
#define ELF_LOAD_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
#include <loader/pcb.h> |
#include "elf.h" |
/** |
* Some data extracted from the headers are stored here |
*/ |
typedef struct { |
/** Entry point */ |
entry_point_t entry; |
/** ELF interpreter name or NULL if statically-linked */ |
char *interp; |
/** Pointer to the dynamic section */ |
void *dynamic; |
} elf_info_t; |
/** |
* Holds information about an ELF binary being loaded. |
*/ |
typedef struct { |
/** Filedescriptor of the file from which we are loading */ |
int fd; |
/** Difference between run-time addresses and link-time addresses */ |
uintptr_t bias; |
/** A copy of the ELF file header */ |
elf_header_t *header; |
/** Store extracted info here */ |
elf_info_t *info; |
} elf_ld_t; |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info); |
void elf_run(elf_info_t *info, pcb_t *pcb); |
void elf_create_pcb(elf_info_t *info, pcb_t *pcb); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/srv/loader/include/elf.h |
---|
0,0 → 1,344 |
/* |
* Copyright (c) 2006 Sergey Bondari |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef ELF_H_ |
#define ELF_H_ |
#include <arch/elf.h> |
#include <sys/types.h> |
/** |
* current ELF version |
*/ |
#define EV_CURRENT 1 |
/** |
* ELF types |
*/ |
#define ET_NONE 0 /* No type */ |
#define ET_REL 1 /* Relocatable file */ |
#define ET_EXEC 2 /* Executable */ |
#define ET_DYN 3 /* Shared object */ |
#define ET_CORE 4 /* Core */ |
#define ET_LOPROC 0xff00 /* Processor specific */ |
#define ET_HIPROC 0xffff /* Processor specific */ |
/** |
* ELF machine types |
*/ |
#define EM_NO 0 /* No machine */ |
#define EM_SPARC 2 /* SPARC */ |
#define EM_386 3 /* i386 */ |
#define EM_MIPS 8 /* MIPS RS3000 */ |
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 LE */ |
#define EM_PPC 20 /* PPC32 */ |
#define EM_PPC64 21 /* PPC64 */ |
#define EM_ARM 40 /* ARM */ |
#define EM_SPARCV9 43 /* SPARC64 */ |
#define EM_IA_64 50 /* IA-64 */ |
#define EM_X86_64 62 /* AMD64/EMT64 */ |
/** |
* ELF identification indexes |
*/ |
#define EI_MAG0 0 |
#define EI_MAG1 1 |
#define EI_MAG2 2 |
#define EI_MAG3 3 |
#define EI_CLASS 4 /* File class */ |
#define EI_DATA 5 /* Data encoding */ |
#define EI_VERSION 6 /* File version */ |
#define EI_OSABI 7 |
#define EI_ABIVERSION 8 |
#define EI_PAD 9 /* Start of padding bytes */ |
#define EI_NIDENT 16 /* ELF identification table size */ |
/** |
* ELF magic number |
*/ |
#define ELFMAG0 0x7f |
#define ELFMAG1 'E' |
#define ELFMAG2 'L' |
#define ELFMAG3 'F' |
/** |
* ELF file classes |
*/ |
#define ELFCLASSNONE 0 |
#define ELFCLASS32 1 |
#define ELFCLASS64 2 |
/** |
* ELF data encoding types |
*/ |
#define ELFDATANONE 0 |
#define ELFDATA2LSB 1 /* Least significant byte first (little endian) */ |
#define ELFDATA2MSB 2 /* Most signigicant byte first (big endian) */ |
/** |
* ELF error return codes |
*/ |
#define EE_OK 0 /* No error */ |
#define EE_INVALID 1 /* Invalid ELF image */ |
#define EE_MEMORY 2 /* Cannot allocate address space */ |
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ |
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ |
#define EE_IRRECOVERABLE 5 |
/** |
* ELF section types |
*/ |
#define SHT_NULL 0 |
#define SHT_PROGBITS 1 |
#define SHT_SYMTAB 2 |
#define SHT_STRTAB 3 |
#define SHT_RELA 4 |
#define SHT_HASH 5 |
#define SHT_DYNAMIC 6 |
#define SHT_NOTE 7 |
#define SHT_NOBITS 8 |
#define SHT_REL 9 |
#define SHT_SHLIB 10 |
#define SHT_DYNSYM 11 |
#define SHT_LOOS 0x60000000 |
#define SHT_HIOS 0x6fffffff |
#define SHT_LOPROC 0x70000000 |
#define SHT_HIPROC 0x7fffffff |
#define SHT_LOUSER 0x80000000 |
#define SHT_HIUSER 0xffffffff |
/** |
* ELF section flags |
*/ |
#define SHF_WRITE 0x1 |
#define SHF_ALLOC 0x2 |
#define SHF_EXECINSTR 0x4 |
#define SHF_TLS 0x400 |
#define SHF_MASKPROC 0xf0000000 |
/** |
* Symbol binding |
*/ |
#define STB_LOCAL 0 |
#define STB_GLOBAL 1 |
#define STB_WEAK 2 |
#define STB_LOPROC 13 |
#define STB_HIPROC 15 |
/** |
* Symbol types |
*/ |
#define STT_NOTYPE 0 |
#define STT_OBJECT 1 |
#define STT_FUNC 2 |
#define STT_SECTION 3 |
#define STT_FILE 4 |
#define STT_LOPROC 13 |
#define STT_HIPROC 15 |
/** |
* Program segment types |
*/ |
#define PT_NULL 0 |
#define PT_LOAD 1 |
#define PT_DYNAMIC 2 |
#define PT_INTERP 3 |
#define PT_NOTE 4 |
#define PT_SHLIB 5 |
#define PT_PHDR 6 |
#define PT_LOPROC 0x70000000 |
#define PT_HIPROC 0x7fffffff |
/** |
* Program segment attributes. |
*/ |
#define PF_X 1 |
#define PF_W 2 |
#define PF_R 4 |
/** |
* ELF data types |
* |
* These types are found to be identical in both 32-bit and 64-bit |
* ELF object file specifications. They are the only types used |
* in ELF header. |
*/ |
typedef uint64_t elf_xword; |
typedef int64_t elf_sxword; |
typedef uint32_t elf_word; |
typedef int32_t elf_sword; |
typedef uint16_t elf_half; |
/** |
* 32-bit ELF data types. |
* |
* These types are specific for 32-bit format. |
*/ |
typedef uint32_t elf32_addr; |
typedef uint32_t elf32_off; |
/** |
* 64-bit ELF data types. |
* |
* These types are specific for 64-bit format. |
*/ |
typedef uint64_t elf64_addr; |
typedef uint64_t elf64_off; |
/** ELF header */ |
struct elf32_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf32_addr e_entry; |
elf32_off e_phoff; |
elf32_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
struct elf64_header { |
uint8_t e_ident[EI_NIDENT]; |
elf_half e_type; |
elf_half e_machine; |
elf_word e_version; |
elf64_addr e_entry; |
elf64_off e_phoff; |
elf64_off e_shoff; |
elf_word e_flags; |
elf_half e_ehsize; |
elf_half e_phentsize; |
elf_half e_phnum; |
elf_half e_shentsize; |
elf_half e_shnum; |
elf_half e_shstrndx; |
}; |
/* |
* ELF segment header. |
* Segments headers are also known as program headers. |
*/ |
struct elf32_segment_header { |
elf_word p_type; |
elf32_off p_offset; |
elf32_addr p_vaddr; |
elf32_addr p_paddr; |
elf_word p_filesz; |
elf_word p_memsz; |
elf_word p_flags; |
elf_word p_align; |
}; |
struct elf64_segment_header { |
elf_word p_type; |
elf_word p_flags; |
elf64_off p_offset; |
elf64_addr p_vaddr; |
elf64_addr p_paddr; |
elf_xword p_filesz; |
elf_xword p_memsz; |
elf_xword p_align; |
}; |
/* |
* ELF section header |
*/ |
struct elf32_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_word sh_flags; |
elf32_addr sh_addr; |
elf32_off sh_offset; |
elf_word sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_word sh_addralign; |
elf_word sh_entsize; |
}; |
struct elf64_section_header { |
elf_word sh_name; |
elf_word sh_type; |
elf_xword sh_flags; |
elf64_addr sh_addr; |
elf64_off sh_offset; |
elf_xword sh_size; |
elf_word sh_link; |
elf_word sh_info; |
elf_xword sh_addralign; |
elf_xword sh_entsize; |
}; |
/* |
* ELF symbol table entry |
*/ |
struct elf32_symbol { |
elf_word st_name; |
elf32_addr st_value; |
elf_word st_size; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
}; |
struct elf64_symbol { |
elf_word st_name; |
uint8_t st_info; |
uint8_t st_other; |
elf_half st_shndx; |
elf64_addr st_value; |
elf_xword st_size; |
}; |
#ifdef __32_BITS__ |
typedef struct elf32_header elf_header_t; |
typedef struct elf32_segment_header elf_segment_header_t; |
typedef struct elf32_section_header elf_section_header_t; |
typedef struct elf32_symbol elf_symbol_t; |
#endif |
#ifdef __64_BITS__ |
typedef struct elf64_header elf_header_t; |
typedef struct elf64_segment_header elf_segment_header_t; |
typedef struct elf64_section_header elf_section_header_t; |
typedef struct elf64_symbol elf_symbol_t; |
#endif |
extern char *elf_error(unsigned int rc); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/srv/fb/sysio.h |
---|
File deleted |
/branches/dd/uspace/srv/fb/sysio.c |
---|
File deleted |
/branches/dd/uspace/srv/fb/sgcn.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup sgcnfb SGCN |
* @brief userland driver of the Serengeti console output |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SGCN_H_ |
#define FB_SGCN_H_ |
int sgcn_init(void); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/serial_console.c |
---|
0,0 → 1,306 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** |
* @defgroup serial Serial console |
* @brief Serial console services (putc, puts, clear screen, cursor goto,...) |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <ipc/ipc.h> |
#include <async.h> |
#include <ipc/fb.h> |
#include <bool.h> |
#include <errno.h> |
#include <console/color.h> |
#include <console/style.h> |
#include "serial_console.h" |
#define MAX_CONTROL 20 |
static void serial_sgr(const unsigned int mode); |
static int width; |
static int height; |
static bool color = true; /** True if producing color output. */ |
static putc_function_t putc_function; |
/* Allow only 1 connection */ |
static int client_connected = 0; |
enum sgr_color_index { |
CI_BLACK = 0, |
CI_RED = 1, |
CI_GREEN = 2, |
CI_BROWN = 3, |
CI_BLUE = 4, |
CI_MAGENTA = 5, |
CI_CYAN = 6, |
CI_WHITE = 7, |
}; |
enum sgr_command { |
SGR_RESET = 0, |
SGR_BOLD = 1, |
SGR_BLINK = 5, |
SGR_REVERSE = 7, |
SGR_NORMAL_INT = 22, |
SGR_BLINK_OFF = 25, |
SGR_REVERSE_OFF = 27, |
SGR_FGCOLOR = 30, |
SGR_BGCOLOR = 40 |
}; |
static int color_map[] = { |
[COLOR_BLACK] = CI_BLACK, |
[COLOR_BLUE] = CI_RED, |
[COLOR_GREEN] = CI_GREEN, |
[COLOR_CYAN] = CI_CYAN, |
[COLOR_RED] = CI_RED, |
[COLOR_MAGENTA] = CI_MAGENTA, |
[COLOR_YELLOW] = CI_BROWN, |
[COLOR_WHITE] = CI_WHITE |
}; |
void serial_puts(char *str) |
{ |
while (*str) |
putc_function(*(str++)); |
} |
void serial_goto(const unsigned int row, const unsigned int col) |
{ |
if ((row > height) || (col > width)) |
return; |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1); |
serial_puts(control); |
} |
void serial_clrscr(void) |
{ |
/* Initialize graphic rendition attributes. */ |
serial_sgr(SGR_RESET); |
if (color) { |
serial_sgr(SGR_FGCOLOR + CI_BLACK); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_puts("\033[2J"); |
} |
void serial_scroll(int i) |
{ |
if (i > 0) { |
serial_goto(height - 1, 0); |
while (i--) |
serial_puts("\033D"); |
} else if (i < 0) { |
serial_goto(0, 0); |
while (i++) |
serial_puts("\033M"); |
} |
} |
/** ECMA-48 Set Graphics Rendition. */ |
static void serial_sgr(const unsigned int mode) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[%um", mode); |
serial_puts(control); |
} |
/** Set scrolling region. */ |
void serial_set_scroll_region(unsigned last_row) |
{ |
char control[MAX_CONTROL]; |
snprintf(control, MAX_CONTROL, "\033[0;%ur", last_row); |
serial_puts(control); |
} |
void serial_cursor_disable(void) |
{ |
serial_puts("\033[?25l"); |
} |
void serial_cursor_enable(void) |
{ |
serial_puts("\033[?25h"); |
} |
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h) |
{ |
width = w; |
height = h; |
putc_function = putc_fn; |
} |
/** |
* Main function of the thread serving client connections. |
*/ |
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
ipc_callid_t callid; |
ipc_call_t call; |
char c; |
int lastcol = 0; |
int lastrow = 0; |
int newcol; |
int newrow; |
int fgcolor; |
int bgcolor; |
int style; |
int i; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
/* Clear the terminal, set scrolling region |
to 0 - height rows. */ |
serial_clrscr(); |
serial_goto(0, 0); |
serial_set_scroll_region(height); |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
ipc_answer_0(callid, EOK); |
return; |
case FB_PUTCHAR: |
c = IPC_GET_ARG1(call); |
newrow = IPC_GET_ARG2(call); |
newcol = IPC_GET_ARG3(call); |
if ((lastcol != newcol) || (lastrow != newrow)) |
serial_goto(newrow, newcol); |
lastcol = newcol + 1; |
lastrow = newrow; |
(*putc_function)(c); |
retval = 0; |
break; |
case FB_CURSOR_GOTO: |
newrow = IPC_GET_ARG1(call); |
newcol = IPC_GET_ARG2(call); |
serial_goto(newrow, newcol); |
lastrow = newrow; |
lastcol = newcol; |
retval = 0; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, height, width); |
continue; |
case FB_CLEAR: |
serial_clrscr(); |
retval = 0; |
break; |
case FB_SET_STYLE: |
style = IPC_GET_ARG1(call); |
if (style == STYLE_EMPHASIS) { |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + CI_RED); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_sgr(SGR_BOLD); |
} else { |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + CI_BLACK); |
serial_sgr(SGR_BGCOLOR + CI_WHITE); |
} |
serial_sgr(SGR_NORMAL_INT); |
} |
retval = 0; |
break; |
case FB_SET_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (color) { |
serial_sgr(SGR_RESET); |
serial_sgr(SGR_FGCOLOR + color_map[fgcolor]); |
serial_sgr(SGR_BGCOLOR + color_map[bgcolor]); |
} else { |
if (fgcolor < bgcolor) |
serial_sgr(SGR_RESET); |
else |
serial_sgr(SGR_REVERSE); |
} |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
if (fgcolor < bgcolor) |
serial_sgr(SGR_REVERSE_OFF); |
else |
serial_sgr(SGR_REVERSE); |
retval = 0; |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if ((i > height) || (i < -height)) { |
retval = EINVAL; |
break; |
} |
serial_scroll(i); |
serial_goto(lastrow, lastcol); |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
serial_cursor_enable(); |
else |
serial_cursor_disable(); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
ipc_answer_0(callid, retval); |
} |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/msim.c |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup msimfb MSIM text console |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <libc.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "msim.h" |
#define WIDTH 80 |
#define HEIGHT 25 |
static char *virt_addr; |
static void msim_putc(const char c) |
{ |
*virt_addr = c; |
} |
int msim_init(void) |
{ |
void *phys_addr = (void *) sysinfo_value("fb.address.physical"); |
virt_addr = (char *) as_get_mappable_page(1); |
if (physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
serial_console_init(msim_putc, WIDTH, HEIGHT); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/serial_console.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** |
* @defgroup serial Serial console |
* @brief Serial console services (putc, puts, clear screen, cursor goto,...) |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SERIAL_CONSOLE_H_ |
#define FB_SERIAL_CONSOLE_H_ |
#include <ipc/ipc.h> |
typedef void (*putc_function_t)(char); |
void serial_puts(char *str); |
void serial_goto(const unsigned int row, const unsigned int col); |
void serial_clrscr(void); |
void serial_scroll(int i); |
void serial_set_style(const unsigned int mode); |
void serial_cursor_disable(void); |
void serial_cursor_enable(void); |
void serial_set_scroll_region(unsigned height); |
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h); |
void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall); |
#endif |
/branches/dd/uspace/srv/fb/font-8x16.c |
---|
28,7 → 28,7 |
#include "font-8x16.h" |
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = { |
unsigned char fb_font[FONT_GLYPHS * FONT_SCANLINES] = { |
/* 0 0x00 '^@' */ |
0x00, /* 00000000 */ |
/branches/dd/uspace/srv/fb/msim.h |
---|
0,0 → 1,47 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup msimfb |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_MSIM_H_ |
#define FB_MSIM_H_ |
extern int msim_init(void); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/srv/fb/font-8x16.h |
---|
29,9 → 29,11 |
#ifndef FB_FONT_8X16_H_ |
#define FB_FONT_8X16_H_ |
#define FONT_GLIPHS 256 |
#define FONT_SCANLINES 16 |
#define FONT_GLYPHS 256 |
#define FONT_WIDTH 8 |
#define FONT_SCANLINES 16 |
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES]; |
extern unsigned char fb_font[FONT_GLYPHS * FONT_SCANLINES]; |
#endif |
/branches/dd/uspace/srv/fb/main.c |
---|
33,16 → 33,21 |
#include <as.h> |
#include <align.h> |
#include <errno.h> |
#include <stdio.h> |
#include "fb.h" |
#include "sysio.h" |
#include "ega.h" |
#include "msim.h" |
#include "ski.h" |
#include "sgcn.h" |
#include "main.h" |
#define NAME "fb" |
void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area) |
{ |
void *dest; |
dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest) == 0) { |
if (*area) |
53,29 → 58,51 |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Framebuffer service\n"); |
ipcarg_t phonead; |
int initialized = 0; |
bool initialized = false; |
#ifdef FB_ENABLED |
if (sysinfo_value("fb.kind") == 1) { |
if (fb_init() == 0) |
initialized = 1; |
} |
initialized = true; |
} |
#endif |
#ifdef EGA_ENABLED |
if (!initialized && sysinfo_value("fb.kind") == 2) { |
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) { |
if (ega_init() == 0) |
initialized = 1; |
initialized = true; |
} |
#endif |
#ifdef MSIM_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 3)) { |
if (msim_init() == 0) |
initialized = true; |
} |
#endif |
#ifdef SGCN_ENABLED |
if ((!initialized) && (sysinfo_value("fb.kind") == 4)) { |
if (sgcn_init() == 0) |
initialized = true; |
} |
#endif |
#ifdef SKI_ENABLED |
if ((!initialized) && (sysinfo_value("fb") != true)) { |
if (ski_init() == 0) |
initialized = true; |
} |
#endif |
if (!initialized) |
sysio_init(); |
return -1; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/branches/dd/uspace/srv/fb/ski.c |
---|
0,0 → 1,84 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup msimfb MSIM text console |
* @brief HelenOS MSIM text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <libc.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "ski.h" |
#define SKI_PUTCHAR 31 |
#define WIDTH 80 |
#define HEIGHT 25 |
/** Display character on ski debug console |
* |
* Use SSC (Simulator System Call) to |
* display character on debug console. |
* |
* @param ch Character to be printed. |
*/ |
static void ski_putc(const char ch) |
{ |
asm volatile ( |
"mov r15 = %0\n" |
"mov r32 = %1\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: "i" (SKI_PUTCHAR), "r" (ch) |
: "r15", "in0", "r8" |
); |
if (ch == '\n') |
ski_putc('\r'); |
} |
int ski_init(void) |
{ |
serial_console_init(ski_putc, WIDTH, HEIGHT); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/fb.c |
---|
1,4 → 1,5 |
/* |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2006 Jakub Vana |
* Copyright (c) 2006 Ondrej Palkovsky |
* All rights reserved. |
32,7 → 33,7 |
* @brief HelenOS graphical framebuffer. |
* @ingroup fbs |
* @{ |
*/ |
*/ |
/** @file |
*/ |
50,6 → 51,8 |
#include <ipc/services.h> |
#include <kernel/errno.h> |
#include <kernel/genarch/fb/visuals.h> |
#include <console/color.h> |
#include <console/style.h> |
#include <async.h> |
#include <bool.h> |
62,427 → 65,433 |
#include "pointer.xbm" |
#include "pointer_mask.xbm" |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x0 |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x000000 |
/***************************************************************/ |
/* Pixel specific fuctions */ |
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
#define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
#define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
typedef void (*conv2scr_fn_t)(void *, int); |
typedef int (*conv2rgb_fn_t)(void *); |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
struct { |
uint8_t *fbaddress; |
uint8_t *fb_addr; |
unsigned int xres; |
unsigned int yres; |
unsigned int scanline; |
unsigned int glyphscanline; |
unsigned int pixelbytes; |
unsigned int invert_colors; |
conv2scr_fn_t rgb2scr; |
conv2rgb_fn_t scr2rgb; |
unsigned int glyphbytes; |
rgb_conv_t rgb_conv; |
} screen; |
/** Backbuffer character cell. */ |
typedef struct { |
int initialized; |
unsigned int x, y; |
unsigned int width, height; |
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
} bb_cell_t; |
typedef struct { |
bool initialized; |
unsigned int x; |
unsigned int y; |
unsigned int width; |
unsigned int height; |
/* Text support in window */ |
unsigned int rows, cols; |
/* Style for text printing */ |
style_t style; |
unsigned int cols; |
unsigned int rows; |
/* |
* Style and glyphs for text printing |
*/ |
/** Current attributes. */ |
attr_rgb_t attr; |
/** Pre-rendered mask for rendering glyphs. Different viewports |
* might use different drawing functions depending on whether their |
* scanlines are aligned on a word boundary.*/ |
uint8_t *glyphs; |
uint8_t *bgpixel; |
/** Glyph drawing function for this viewport. */ |
dg_t dglyph; |
/* Auto-cursor position */ |
int cursor_active, cur_col, cur_row; |
int cursor_shown; |
/* Double buffering */ |
uint8_t *dbdata; |
unsigned int dboffset; |
unsigned int paused; |
bool cursor_active; |
unsigned int cur_col; |
unsigned int cur_row; |
bool cursor_shown; |
/* Back buffer */ |
bb_cell_t *backbuf; |
unsigned int bbsize; |
} viewport_t; |
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
typedef struct { |
int initialized; |
int enabled; |
bool initialized; |
bool enabled; |
unsigned int vp; |
unsigned int pos; |
unsigned int animlen; |
unsigned int pixmaps[MAX_ANIM_LEN]; |
} animation_t; |
static animation_t animations[MAX_ANIMATIONS]; |
static int anims_enabled; |
static bool anims_enabled; |
/** Maximum number of saved pixmaps |
* Pixmap is a saved rectangle |
*/ |
#define MAX_PIXMAPS 256 |
typedef struct { |
unsigned int width; |
unsigned int height; |
uint8_t *data; |
} pixmap_t; |
static pixmap_t pixmaps[MAX_PIXMAPS]; |
/* Viewport is a rectangular area on the screen */ |
#define MAX_VIEWPORTS 128 |
static viewport_t viewports[128]; |
/* Allow only 1 connection */ |
static int client_connected = 0; |
static bool client_connected = false; /**< Allow only 1 connection */ |
#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
static uint32_t color_table[16] = { |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
#define COL_WIDTH 8 |
#define ROW_BYTES (screen.scanline * FONT_SCANLINES) |
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
}; |
#define POINTPOS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes) |
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a); |
static int rgb_from_style(attr_rgb_t *rgb, int style); |
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags); |
static inline int COLOR(int color) |
{ |
return screen.invert_colors ? ~color : color; |
} |
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t attr); |
/* Conversion routines between different color representations */ |
static void |
rgb_byte0888(void *dst, int rgb) |
{ |
*(int *)dst = rgb; |
} |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
static int |
byte0888_rgb(void *src) |
{ |
return (*(int *)src) & 0xffffff; |
} |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row); |
static void |
bgr_byte0888(void *dst, int rgb) |
{ |
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 | |
RED(rgb, 8); |
} |
static int |
byte0888_bgr(void *src) |
{ |
int color = *(uint32_t *)(src); |
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) | |
((color >> 16) & 0xff); |
} |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
static void |
rgb_byte888(void *dst, int rgb) |
{ |
uint8_t *scr = dst; |
#if defined(FB_INVERT_ENDIAN) |
scr[0] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[2] = BLUE(rgb, 8); |
#else |
scr[2] = RED(rgb, 8); |
scr[1] = GREEN(rgb, 8); |
scr[0] = BLUE(rgb, 8); |
#endif |
} |
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
static int |
byte888_rgb(void *src) |
{ |
uint8_t *scr = src; |
#if defined(FB_INVERT_ENDIAN) |
return scr[0] << 16 | scr[1] << 8 | scr[2]; |
#else |
return scr[2] << 16 | scr[1] << 8 | scr[0]; |
#endif |
} |
#define X2COL(x) ((x) / FONT_WIDTH) |
#define Y2ROW(y) ((y) / FONT_SCANLINES) |
/** 16-bit depth (5:5:5) */ |
static void |
rgb_byte555(void *dst, int rgb) |
{ |
/* 5-bit, 5-bits, 5-bits */ |
*((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 | |
BLUE(rgb, 5); |
} |
#define FB_POS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes) |
#define BB_POS(vport, col, row) ((row) * vport->cols + (col)) |
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline) |
/** 16-bit depth (5:5:5) */ |
static int |
byte555_rgb(void *src) |
/** ARGB 8:8:8:8 conversion |
* |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 10) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3); |
*((uint32_t *) dst) = rgb & 0xffffff; |
} |
/** 16-bit depth (5:6:5) */ |
static void |
rgb_byte565(void *dst, int rgb) |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
/* 5-bit, 6-bits, 5-bits */ |
*((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | |
BLUE(rgb, 5); |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
} |
/** 16-bit depth (5:6:5) */ |
static int |
byte565_rgb(void *src) |
/** RGB 8:8:8 conversion |
* |
*/ |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
int color = *(uint16_t *)(src); |
return (((color >> 11) & 0x1f) << (16 + 3)) | |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3); |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
/** Put pixel - 8-bit depth (3:2:3) */ |
static void |
rgb_byte8(void *dst, int rgb) |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
*(uint8_t *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3); |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
/** Return pixel color - 8-bit depth (3:2:3) */ |
static int |
byte8_rgb(void *src) |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
{ |
int color = *(uint8_t *)src; |
return (((color >> 5) & 0x7) << (16 + 5)) | |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
/** Put pixel into viewport |
/** RGB 5:6:5 conversion |
* |
* @param vport Viewport identification |
* @param x X coord relative to viewport |
* @param y Y coord relative to viewport |
* @param color RGB color |
*/ |
static void |
putpixel(viewport_t *vport, unsigned int x, unsigned int y, int color) |
static void rgb_565(void *dst, uint32_t rgb) |
{ |
int dx = vport->x + x; |
int dy = vport->y + y; |
if (! (vport->paused && vport->dbdata)) |
(*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)], |
COLOR(color)); |
if (vport->dbdata) { |
int dline = (y + vport->dboffset) % vport->height; |
int doffset = screen.pixelbytes * (dline * vport->width + x); |
(*screen.rgb2scr)(&vport->dbdata[doffset], COLOR(color)); |
} |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
/** Get pixel from viewport */ |
static int |
getpixel(viewport_t *vport, unsigned int x, unsigned int y) |
{ |
int dx = vport->x + x; |
int dy = vport->y + y; |
return COLOR((*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx, dy)])); |
} |
static inline void |
putpixel_mem(char *mem, unsigned int x, unsigned int y, int color) |
/** RGB 3:2:3 |
* |
*/ |
static void rgb_323(void *dst, uint32_t rgb) |
{ |
(*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color)); |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
static void |
draw_rectangle(viewport_t *vport, unsigned int sx, unsigned int sy, |
unsigned int width, unsigned int height, int color) |
/** Draw a filled rectangle. |
* |
* @note Need real implementation that does not access VRAM twice. |
*/ |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
unsigned int x, y; |
static void *tmpline; |
unsigned int copy_bytes; |
if (!tmpline) |
tmpline = malloc(screen.scanline * screen.pixelbytes); |
uint8_t *sp, *dp; |
uint8_t cbuf[4]; |
/* Clear first line */ |
for (x = 0; x < width; x++) |
putpixel_mem(tmpline, x, 0, color); |
if (y0 >= y1 || x0 >= x1) return; |
screen.rgb_conv(cbuf, color); |
if (!vport->paused) { |
/* Recompute to screen coords */ |
sx += vport->x; |
sy += vport->y; |
/* Copy the rest */ |
for (y = sy;y < sy+height; y++) |
memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline, |
screen.pixelbytes * width); |
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
dp = sp; |
/* Draw the first line. */ |
for (x = x0; x < x1; x++) { |
memcpy(dp, cbuf, screen.pixelbytes); |
dp += screen.pixelbytes; |
} |
if (vport->dbdata) { |
for (y = sy; y < sy + height; y++) { |
int rline = (y + vport->dboffset) % vport->height; |
int rpos = (rline * vport->width + sx) * |
screen.pixelbytes; |
memcpy(&vport->dbdata[rpos], tmpline, |
screen.pixelbytes * width); |
} |
} |
} |
dp = sp + screen.scanline; |
copy_bytes = (x1 - x0) * screen.pixelbytes; |
/** Fill viewport with background color */ |
static void |
clear_port(viewport_t *vport) |
{ |
draw_rectangle(vport, 0, 0, vport->width, vport->height, |
vport->style.bg_color); |
/* Draw the remaining lines by copying. */ |
for (y = y0 + 1; y < y1; y++) { |
memcpy(dp, sp, copy_bytes); |
dp += screen.scanline; |
} |
} |
/** Scroll unbuffered viewport up/down |
/** Redraw viewport. |
* |
* @param vport Viewport to scroll |
* @param lines Positive number - scroll up, negative - scroll down |
* @param vport Viewport to redraw |
* |
*/ |
static void |
scroll_port_nodb(viewport_t *vport, int lines) |
static void vport_redraw(viewport_t *vport) |
{ |
int y; |
unsigned int row, col; |
if (lines > 0) { |
for (y = vport->y; y < vport->y+vport->height - lines; y++) |
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], |
&screen.fbaddress[POINTPOS(vport->x,y + lines)], |
screen.pixelbytes * vport->width); |
draw_rectangle(vport, 0, vport->height - lines, vport->width, |
lines, vport->style.bg_color); |
} else if (lines < 0) { |
lines = -lines; |
for (y = vport->y + vport->height-1; y >= vport->y + lines; y--) |
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], |
&screen.fbaddress[POINTPOS(vport->x,y - lines)], |
screen.pixelbytes * vport->width); |
draw_rectangle(vport, 0, 0, vport->width, lines, |
vport->style.bg_color); |
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
draw_vp_glyph(vport, false, col, row); |
} |
} |
} |
/** Refresh given viewport from double buffer */ |
static void |
refresh_viewport_db(viewport_t *vport) |
{ |
unsigned int y, srcy, srcoff, dsty, dstx; |
if (COL2X(vport->cols) < vport->width) { |
draw_filled_rect( |
vport->x + COL2X(vport->cols), vport->y, |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
for (y = 0; y < vport->height; y++) { |
srcy = (y + vport->dboffset) % vport->height; |
srcoff = (vport->width * srcy) * screen.pixelbytes; |
dstx = vport->x; |
dsty = vport->y + y; |
memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)], |
&vport->dbdata[srcoff], vport->width * screen.pixelbytes); |
if (ROW2Y(vport->rows) < vport->height) { |
draw_filled_rect( |
vport->x, vport->y + ROW2Y(vport->rows), |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
} |
/** Scroll viewport that has double buffering enabled */ |
static void |
scroll_port_db(viewport_t *vport, int lines) |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
++vport->paused; |
if (lines > 0) { |
draw_rectangle(vport, 0, 0, vport->width, lines, |
vport->style.bg_color); |
vport->dboffset += lines; |
vport->dboffset %= vport->height; |
} else if (lines < 0) { |
lines = -lines; |
draw_rectangle(vport, 0, vport->height-lines, vport->width, |
lines, vport->style.bg_color); |
unsigned i; |
if (vport->dboffset < lines) |
vport->dboffset += vport->height; |
vport->dboffset -= lines; |
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
backbuf[i].fg_color = fg_color; |
backbuf[i].bg_color = bg_color; |
} |
--vport->paused; |
refresh_viewport_db(vport); |
} |
/** Scrolls viewport given number of lines */ |
static void |
scroll_port(viewport_t *vport, int lines) |
/** Clear viewport. |
* |
* @param vport Viewport to clear |
* |
*/ |
static void vport_clear(viewport_t *vport) |
{ |
if (vport->dbdata) |
scroll_port_db(vport, lines); |
else |
scroll_port_nodb(vport, lines); |
backbuf_clear(vport->backbuf, vport->cols * vport->rows, |
vport->attr.fg_color, vport->attr.bg_color); |
vport_redraw(vport); |
} |
static void |
invert_pixel(viewport_t *vport, unsigned int x, unsigned int y) |
/** Scroll viewport by the specified number of lines. |
* |
* @param vport Viewport to scroll |
* @param lines Number of lines to scroll |
* |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
putpixel(vport, x, y, ~getpixel(vport, x, y)); |
} |
unsigned int row, col; |
unsigned int x, y; |
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp, *xbp; |
/* |
* Redraw. |
*/ |
/***************************************************************/ |
/* Character-console functions */ |
y = vport->y; |
for (row = 0; row < vport->rows; row++) { |
x = vport->x; |
for (col = 0; col < vport->cols; col++) { |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
/** Draw character at given position |
* |
* @param vport Viewport where the character is printed |
* @param sx Coordinates of top-left of the character |
* @param sy Coordinates of top-left of the character |
* @param style Color of the character |
* @param transparent If false, print background color |
*/ |
static void |
draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy, |
style_t style, int transparent) |
{ |
int i; |
unsigned int y; |
unsigned int glline; |
glyph = xbp->glyph; |
fg_color = xbp->fg_color; |
bg_color = xbp->bg_color; |
for (y = 0; y < FONT_SCANLINES; y++) { |
glline = fb_font[glyph * FONT_SCANLINES + y]; |
for (i = 0; i < 8; i++) { |
if (glline & (1 << (7 - i))) |
putpixel(vport, sx + i, sy + y, style.fg_color); |
else if (!transparent) |
putpixel(vport, sx + i, sy + y, style.bg_color); |
if (bbp->glyph == glyph && |
bbp->fg_color == xbp->fg_color && |
bbp->bg_color == xbp->bg_color) { |
x += FONT_WIDTH; |
continue; |
} |
} else { |
glyph = 0; |
fg_color = vport->attr.fg_color; |
bg_color = vport->attr.bg_color; |
} |
(*vport->dglyph)(x, y, false, vport->glyphs, glyph, |
fg_color, bg_color); |
x += FONT_WIDTH; |
} |
y += FONT_SCANLINES; |
} |
/* |
* Scroll backbuffer. |
*/ |
if (lines > 0) { |
memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
vport->cols * (vport->rows - lines) * sizeof(bb_cell_t)); |
backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], |
vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color); |
} else { |
memmove(vport->backbuf - vport->cols * lines, vport->backbuf, |
vport->cols * (vport->rows + lines) * sizeof(bb_cell_t)); |
backbuf_clear(vport->backbuf, - vport->cols * lines, |
vport->attr.fg_color, vport->attr.bg_color); |
} |
} |
/** Invert character at given position */ |
static void |
invert_char(viewport_t *vport,unsigned int row, unsigned int col) |
/** Render glyphs |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
* @param vport Viewport |
* |
*/ |
static void render_glyphs(viewport_t* vport) |
{ |
unsigned int x; |
unsigned int y; |
for (x = 0; x < COL_WIDTH; x++) |
for (y = 0; y < FONT_SCANLINES; y++) |
invert_pixel(vport, col * COL_WIDTH + x, row * |
FONT_SCANLINES + y); |
unsigned int glyph; |
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) { |
unsigned int y; |
for (y = 0; y < FONT_SCANLINES; y++) { |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) { |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? 0xffffff : 0x000000); |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? 0x000000 : 0xffffff); |
} |
} |
} |
screen.rgb_conv(vport->bgpixel, vport->attr.bg_color); |
} |
/***************************************************************/ |
/* Stdout specific functions */ |
/** Create new viewport |
* |
* @return New viewport number |
* @param x Origin of the viewport (x). |
* @param y Origin of the viewport (y). |
* @param width Width of the viewport. |
* @param height Height of the viewport. |
* |
* @return New viewport number. |
* |
*/ |
static int |
viewport_create(unsigned int x, unsigned int y,unsigned int width, |
unsigned int height) |
static int vport_create(unsigned int x, unsigned int y, |
unsigned int width, unsigned int height) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < MAX_VIEWPORTS; i++) { |
if (!viewports[i].initialized) |
break; |
489,75 → 498,124 |
} |
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
unsigned int cols = width / FONT_WIDTH; |
unsigned int rows = height / FONT_SCANLINES; |
unsigned int bbsize = cols * rows * sizeof(bb_cell_t); |
unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
unsigned int word_size = sizeof(unsigned long); |
bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize); |
if (!backbuf) |
return ENOMEM; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) { |
free(backbuf); |
return ENOMEM; |
} |
uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes); |
if (!bgpixel) { |
free(glyphs); |
free(backbuf); |
return ENOMEM; |
} |
backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR); |
memset(glyphs, 0, glyphsize); |
memset(bgpixel, 0, screen.pixelbytes); |
viewports[i].x = x; |
viewports[i].y = y; |
viewports[i].width = width; |
viewports[i].height = height; |
viewports[i].rows = height / FONT_SCANLINES; |
viewports[i].cols = width / COL_WIDTH; |
viewports[i].cols = cols; |
viewports[i].rows = rows; |
viewports[i].attr.bg_color = DEFAULT_BGCOLOR; |
viewports[i].attr.fg_color = DEFAULT_FGCOLOR; |
viewports[i].glyphs = glyphs; |
viewports[i].bgpixel = bgpixel; |
viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
/* |
* Conditions necessary to select aligned version: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
*/ |
if ((word_size % screen.pixelbytes) == 0 && |
(FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
(x * screen.pixelbytes) % word_size == 0 && |
screen.scanline % word_size == 0) { |
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
} |
viewports[i].cur_col = 0; |
viewports[i].cur_row = 0; |
viewports[i].cursor_active = 0; |
viewports[i].initialized = 1; |
viewports[i].cursor_active = false; |
viewports[i].cursor_shown = false; |
viewports[i].bbsize = bbsize; |
viewports[i].backbuf = backbuf; |
viewports[i].initialized = true; |
render_glyphs(&viewports[i]); |
return i; |
} |
/** Initialize framebuffer as a chardev output device |
* |
* @param addr Address of theframebuffer |
* @param xres Screen width in pixels |
* @param yres Screen height in pixels |
* @param visual Bits per pixel (8, 16, 24, 32) |
* @param scan Bytes per one scanline |
* @param invert_colors Inverted colors. |
* @param addr Address of the framebuffer |
* @param xres Screen width in pixels |
* @param yres Screen height in pixels |
* @param visual Bits per pixel (8, 16, 24, 32) |
* @param scan Bytes per one scanline |
* |
*/ |
static bool |
screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual, bool invert_colors) |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb2scr = rgb_byte8; |
screen.scr2rgb = byte8_rgb; |
screen.rgb_conv = rgb_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb2scr = rgb_byte555; |
screen.scr2rgb = byte555_rgb; |
screen.rgb_conv = rgb_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb2scr = rgb_byte565; |
screen.scr2rgb = byte565_rgb; |
screen.rgb_conv = rgb_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb2scr = rgb_byte888; |
screen.scr2rgb = byte888_rgb; |
screen.rgb_conv = rgb_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
screen.rgb_conv = bgr_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb2scr = rgb_byte888; |
screen.scr2rgb = byte888_rgb; |
screen.rgb_conv = rgb_888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
screen.rgb2scr = rgb_byte0888; |
screen.scr2rgb = byte0888_rgb; |
screen.rgb_conv = rgb_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
screen.rgb2scr = bgr_byte0888; |
screen.scr2rgb = byte0888_bgr; |
screen.rgb_conv = bgr_0888; |
screen.pixelbytes = 4; |
break; |
default: |
564,72 → 622,239 |
return false; |
} |
screen.fbaddress = (unsigned char *) addr; |
screen.fb_addr = (unsigned char *) addr; |
screen.xres = xres; |
screen.yres = yres; |
screen.scanline = scan; |
screen.invert_colors = invert_colors; |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
/* Create first viewport */ |
viewport_create(0, 0, xres, yres); |
vport_create(0, 0, xres, yres); |
return true; |
} |
/** Hide cursor if it is shown */ |
static void |
cursor_hide(viewport_t *vport) |
/** Draw a glyph, takes advantage of alignment. |
* |
* This version can only be used if the following conditions are met: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
* It makes use of the pre-rendered mask to process (possibly) several |
* pixels at once (word size / pixelbytes pixels at a time are processed) |
* making it very fast. Most notably this version is not applicable at 24 bits |
* per pixel. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
if (vport->cursor_active && vport->cursor_shown) { |
invert_char(vport, vport->cur_row, vport->cur_col); |
vport->cursor_shown = 0; |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned long mask; |
unsigned int ww, d_add; |
/* |
* Prepare a pair of words, one filled with foreground-color |
* pattern and the other filled with background-color pattern. |
*/ |
for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
fg_color); |
screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
bg_color); |
} |
/* Pointer to the current position in the mask. */ |
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
/* Pointer to the current position on the screen. */ |
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
/* Width of the character cell in words. */ |
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
* Now process the cell scanline, combining foreground |
* and background color patters using the pre-rendered mask. |
*/ |
for (i = 0; i < ww; i++) { |
mask = *maskp++; |
*dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp = (unsigned long *) ((uint8_t *) dp + d_add); |
} |
} |
/** Show cursor if cursor showing is enabled */ |
static void |
cursor_print(viewport_t *vport) |
/** Draw a glyph, fallback version. |
* |
* This version does not make use of the pre-rendered mask, it uses |
* the font bitmap directly. It works always, but it is slower. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
uint8_t b; |
/* Pre-render 1x the foreground and background color pixels. */ |
if (cursor) { |
screen.rgb_conv(fg_buf, bg_color); |
screen.rgb_conv(bg_buf, fg_color); |
} else { |
screen.rgb_conv(fg_buf, fg_color); |
screen.rgb_conv(bg_buf, bg_color); |
} |
/* Pointer to the current position on the screen. */ |
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
b = fb_font[glyph * FONT_SCANLINES + yd]; |
for (i = 0; i < FONT_WIDTH; i++) { |
/* Choose color based on the current bit. */ |
sp = (b & 0x80) ? fg_buf : bg_buf; |
/* Copy the pixel. */ |
for (j = 0; j < screen.pixelbytes; j++) { |
*dp++ = *sp++; |
} |
/* Move to the next bit. */ |
b = b << 1; |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp += d_add; |
} |
} |
/** Draw glyph at specified position in viewport. |
* |
* @param vport Viewport identification |
* @param cursor Draw glyph with cursor |
* @param col Screen position relative to viewport |
* @param row Screen position relative to viewport |
* |
*/ |
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row) |
{ |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
(*vport->dglyph)(x, y, cursor, vport->glyphs, glyph, |
fg_color, bg_color); |
} |
/** Hide cursor if it is shown |
* |
*/ |
static void cursor_hide(viewport_t *vport) |
{ |
if ((vport->cursor_active) && (vport->cursor_shown)) { |
draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row); |
vport->cursor_shown = false; |
} |
} |
/** Show cursor if cursor showing is enabled |
* |
*/ |
static void cursor_show(viewport_t *vport) |
{ |
/* Do not check for cursor_shown */ |
if (vport->cursor_active) { |
invert_char(vport, vport->cur_row, vport->cur_col); |
vport->cursor_shown = 1; |
draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row); |
vport->cursor_shown = true; |
} |
} |
/** Invert cursor, if it is enabled */ |
static void |
cursor_blink(viewport_t *vport) |
/** Invert cursor, if it is enabled |
* |
*/ |
static void cursor_blink(viewport_t *vport) |
{ |
if (vport->cursor_shown) |
cursor_hide(vport); |
else |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Draw character at given position relative to viewport |
* |
* @param vport Viewport identification |
* @param c Character to print |
* @param row Screen position relative to viewport |
* @param col Screen position relative to viewport |
* @param transparent If false, print background color with character |
/** Draw character at given position relative to viewport |
* |
* @param vport Viewport identification |
* @param c Character to draw |
* @param col Screen position relative to viewport |
* @param row Screen position relative to viewport |
* |
*/ |
static void |
draw_char(viewport_t *vport, char c, unsigned int row, unsigned int col, |
style_t style, int transparent) |
static void draw_char(viewport_t *vport, uint8_t c, unsigned int col, unsigned int row) |
{ |
/* Optimize - do not hide cursor if we are going to overwrite it */ |
if (vport->cursor_active && vport->cursor_shown && |
(vport->cur_col != col || vport->cur_row != row)) |
invert_char(vport, vport->cur_row, vport->cur_col); |
bb_cell_t *bbp; |
/* Do not hide cursor if we are going to overwrite it */ |
if ((vport->cursor_active) && (vport->cursor_shown) && |
((vport->cur_col != col) || (vport->cur_row != row))) |
cursor_hide(vport); |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
bbp->glyph = c; |
bbp->fg_color = vport->attr.fg_color; |
bbp->bg_color = vport->attr.bg_color; |
draw_vp_glyph(vport, false, col, row); |
draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style, |
transparent); |
vport->cur_col = col; |
vport->cur_row = row; |
vport->cur_col++; |
if (vport->cur_col >= vport->cols) { |
vport->cur_col = 0; |
637,65 → 862,91 |
if (vport->cur_row >= vport->rows) |
vport->cur_row--; |
} |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Draw text data to viewport |
* |
* @param vport Viewport id |
* @param data Text data fitting exactly into viewport |
* @param data Text data fitting exactly into viewport |
* |
*/ |
static void |
draw_text_data(viewport_t *vport, keyfield_t *data) |
static void draw_text_data(viewport_t *vport, keyfield_t *data) |
{ |
int i; |
int col,row; |
unsigned int i; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |
for (i = 0; i < vport->cols * vport->rows; i++) { |
unsigned int col = i % vport->cols; |
unsigned int row = i / vport->cols; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
uint8_t glyph = bbp->glyph; |
clear_port(vport); |
for (i = 0; i < vport->cols * vport->rows; i++) { |
if (data[i].character == ' ' && style_same(data[i].style, |
vport->style)) |
continue; |
col = i % vport->cols; |
row = i / vport->cols; |
draw_glyph(vport, data[i].character, col * COL_WIDTH, row * |
FONT_SCANLINES, data[i].style, style_same(data[i].style, |
vport->style)); |
a = &data[i].attrs; |
rgb_from_attr(&rgb, a); |
bbp->glyph = data[i].character; |
bbp->fg_color = rgb.fg_color; |
bbp->bg_color = rgb.bg_color; |
draw_vp_glyph(vport, false, col, row); |
} |
cursor_print(vport); |
cursor_show(vport); |
} |
/** Return first free pixmap */ |
static int |
find_free_pixmap(void) |
static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color) |
{ |
int i; |
int pm = *((int *) data); |
pixmap_t *pmap = &pixmaps[pm]; |
unsigned int pos = (y * pmap->width + x) * screen.pixelbytes; |
for (i = 0;i < MAX_PIXMAPS;i++) |
screen.rgb_conv(&pmap->data[pos], color); |
} |
static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color) |
{ |
viewport_t *vport = (viewport_t *) data; |
unsigned int dx = vport->x + x; |
unsigned int dy = vport->y + y; |
screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color); |
} |
/** Return first free pixmap |
* |
*/ |
static int find_free_pixmap(void) |
{ |
unsigned int i; |
for (i = 0; i < MAX_PIXMAPS; i++) |
if (!pixmaps[i].data) |
return i; |
return -1; |
} |
static void |
putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color) |
{ |
pixmap_t *pmap = &pixmaps[pm]; |
int pos = (y * pmap->width + x) * screen.pixelbytes; |
(*screen.rgb2scr)(&pmap->data[pos],COLOR(color)); |
} |
/** Create a new pixmap and return appropriate ID */ |
static int |
shm2pixmap(unsigned char *shm, size_t size) |
/** Create a new pixmap and return appropriate ID |
* |
*/ |
static int shm2pixmap(unsigned char *shm, size_t size) |
{ |
int pm; |
pixmap_t *pmap; |
pm = find_free_pixmap(); |
if (pm == -1) |
return ELIMIT; |
pmap = &pixmaps[pm]; |
if (ppm_get_data(shm, size, &pmap->width, &pmap->height)) |
704,19 → 955,19 |
pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes); |
if (!pmap->data) |
return ENOMEM; |
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, |
(putpixel_cb_t)putpixel_pixmap, (void *)pm); |
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm); |
return pm; |
} |
/** Handle shared memory communication calls |
* |
* Protocol for drawing pixmaps: |
* - FB_PREPARE_SHM(client shm identification) |
* - IPC_M_AS_AREA_SEND |
* - FB_DRAW_PPM(startx,starty) |
* - FB_DRAW_PPM(startx, starty) |
* - FB_DROP_SHM |
* |
* Protocol for text drawing |
724,28 → 975,30 |
* - FB_DRAW_TEXT_DATA |
* |
* @param callid Callid of the current call |
* @param call Current call data |
* @param vp Active viewport |
* @return 0 if the call was not handled byt this function, 1 otherwise |
* @param call Current call data |
* @param vp Active viewport |
* |
* note: this function is not threads safe, you would have |
* @return false if the call was not handled byt this function, true otherwise |
* |
* Note: this function is not threads safe, you would have |
* to redefine static variables with __thread |
* |
*/ |
static int |
shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
static keyfield_t *interbuffer = NULL; |
static size_t intersize = 0; |
static unsigned char *shm = NULL; |
static ipcarg_t shm_id = 0; |
static size_t shm_size; |
int handled = 1; |
int retval = 0; |
bool handled = true; |
int retval = EOK; |
viewport_t *vport = &viewports[vp]; |
unsigned int x, y; |
unsigned int x; |
unsigned int y; |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_SHARE_OUT: |
/* We accept one area for data interchange */ |
752,19 → 1005,20 |
if (IPC_GET_ARG1(*call) == shm_id) { |
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
shm_size = IPC_GET_ARG2(*call); |
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) |
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) |
shm = dest; |
else |
shm_id = 0; |
if (shm[0] != 'P') |
while (1) |
; |
return 1; |
return false; |
return true; |
} else { |
intersize = IPC_GET_ARG2(*call); |
receive_comm_area(callid, call, (void *) &interbuffer); |
} |
return 1; |
return true; |
case FB_PREPARE_SHM: |
if (shm_id) |
retval = EBUSY; |
779,7 → 1033,7 |
} |
shm_id = 0; |
break; |
case FB_SHM2PIXMAP: |
if (!shm) { |
retval = EINVAL; |
794,14 → 1048,14 |
} |
x = IPC_GET_ARG1(*call); |
y = IPC_GET_ARG2(*call); |
if (x > vport->width || y > vport->height) { |
if ((x > vport->width) || (y > vport->height)) { |
retval = EINVAL; |
break; |
} |
ppm_draw(shm, shm_size, IPC_GET_ARG1(*call), |
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, |
(putpixel_cb_t)putpixel, vport); |
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport); |
break; |
case FB_DRAW_TEXT_DATA: |
if (!interbuffer) { |
808,8 → 1062,7 |
retval = EINVAL; |
break; |
} |
if (intersize < vport->cols * vport->rows * |
sizeof(*interbuffer)) { |
if (intersize < vport->cols * vport->rows * sizeof(*interbuffer)) { |
retval = EINVAL; |
break; |
} |
816,7 → 1069,7 |
draw_text_data(vport, interbuffer); |
break; |
default: |
handled = 0; |
handled = false; |
} |
if (handled) |
824,41 → 1077,39 |
return handled; |
} |
static void |
copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap) |
static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap) |
{ |
int y; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
int width = vport->width; |
int height = vport->height; |
unsigned int width = vport->width; |
unsigned int height = vport->height; |
if (width + vport->x > screen.xres) |
width = screen.xres - vport->x; |
if (height + vport->y > screen.yres) |
height = screen.yres - vport->y; |
realwidth = pmap->width <= width ? pmap->width : width; |
realheight = pmap->height <= height ? pmap->height : height; |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
unsigned int realwidth = pmap->width <= width ? pmap->width : width; |
unsigned int realheight = pmap->height <= height ? pmap->height : height; |
unsigned int srcrowsize = vport->width * screen.pixelbytes; |
unsigned int realrowsize = realwidth * screen.pixelbytes; |
unsigned int y; |
for (y = 0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + |
vport->x * screen.pixelbytes; |
memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp, |
realrowsize); |
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize); |
} |
} |
/** Save viewport to pixmap */ |
static int |
save_vp_to_pixmap(viewport_t *vport) |
/** Save viewport to pixmap |
* |
*/ |
static int save_vp_to_pixmap(viewport_t *vport) |
{ |
int pm; |
pixmap_t *pmap; |
pm = find_free_pixmap(); |
if (pm == -1) |
return ELIMIT; |
867,58 → 1118,60 |
pmap->data = malloc(screen.pixelbytes * vport->width * vport->height); |
if (!pmap->data) |
return ENOMEM; |
pmap->width = vport->width; |
pmap->height = vport->height; |
copy_vp_to_pixmap(vport, pmap); |
return pm; |
} |
/** Draw pixmap on screen |
* |
* @param vp Viewport to draw on |
* @param pm Pixmap identifier |
* |
*/ |
static int draw_pixmap(int vp, int pm) |
{ |
pixmap_t *pmap = &pixmaps[pm]; |
viewport_t *vport = &viewports[vp]; |
int y; |
int tmp, srcrowsize; |
int realwidth, realheight, realrowsize; |
int width = vport->width; |
int height = vport->height; |
unsigned int width = vport->width; |
unsigned int height = vport->height; |
if (width + vport->x > screen.xres) |
width = screen.xres - vport->x; |
if (height + vport->y > screen.yres) |
height = screen.yres - vport->y; |
if (!pmap->data) |
return EINVAL; |
realwidth = pmap->width <= width ? pmap->width : width; |
realheight = pmap->height <= height ? pmap->height : height; |
srcrowsize = vport->width * screen.pixelbytes; |
realrowsize = realwidth * screen.pixelbytes; |
unsigned int realwidth = pmap->width <= width ? pmap->width : width; |
unsigned int realheight = pmap->height <= height ? pmap->height : height; |
unsigned int srcrowsize = vport->width * screen.pixelbytes; |
unsigned int realrowsize = realwidth * screen.pixelbytes; |
unsigned int y; |
for (y = 0; y < realheight; y++) { |
tmp = (vport->y + y) * screen.scanline + |
vport->x * screen.pixelbytes; |
memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, |
realrowsize); |
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes; |
memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize); |
} |
return 0; |
return EOK; |
} |
/** Tick animation one step forward */ |
static void |
anims_tick(void) |
/** Tick animation one step forward |
* |
*/ |
static void anims_tick(void) |
{ |
int i; |
unsigned int i; |
static int counts = 0; |
/* Limit redrawing */ |
927,37 → 1180,36 |
return; |
for (i = 0; i < MAX_ANIMATIONS; i++) { |
if (!animations[i].animlen || !animations[i].initialized || |
!animations[i].enabled) |
if ((!animations[i].animlen) || (!animations[i].initialized) || |
(!animations[i].enabled)) |
continue; |
draw_pixmap(animations[i].vp, |
animations[i].pixmaps[animations[i].pos]); |
animations[i].pos = (animations[i].pos + 1) % |
animations[i].animlen; |
draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]); |
animations[i].pos = (animations[i].pos + 1) % animations[i].animlen; |
} |
} |
static int pointer_x, pointer_y; |
static int pointer_shown, pointer_enabled; |
static unsigned int pointer_x; |
static unsigned int pointer_y; |
static bool pointer_shown, pointer_enabled; |
static int pointer_vport = -1; |
static int pointer_pixmap = -1; |
static void |
mouse_show(void) |
static void mouse_show(void) |
{ |
int i, j; |
int visibility; |
int color; |
int bytepos; |
if (pointer_shown || !pointer_enabled) |
if ((pointer_shown) || (!pointer_enabled)) |
return; |
/* Save image under the cursor */ |
/* Save image under the pointer. */ |
if (pointer_vport == -1) { |
pointer_vport = viewport_create(pointer_x, pointer_y, |
pointer_width, pointer_height); |
pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height); |
if (pointer_vport < 0) |
return; |
} else { |
964,14 → 1216,13 |
viewports[pointer_vport].x = pointer_x; |
viewports[pointer_vport].y = pointer_y; |
} |
if (pointer_pixmap == -1) |
pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]); |
else |
copy_vp_to_pixmap(&viewports[pointer_vport], |
&pixmaps[pointer_pixmap]); |
/* Draw cursor */ |
copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]); |
/* Draw mouse pointer. */ |
for (i = 0; i < pointer_height; i++) |
for (j = 0; j < pointer_width; j++) { |
bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; |
989,10 → 1240,10 |
pointer_shown = 1; |
} |
static void |
mouse_hide(void) |
static void mouse_hide(void) |
{ |
/* Restore image under the cursor */ |
/* Restore image under the pointer. */ |
if (pointer_shown) { |
draw_pixmap(pointer_vport, pointer_pixmap); |
pointer_shown = 0; |
999,8 → 1250,8 |
} |
} |
static void |
mouse_move(unsigned int x, unsigned int y) |
static void mouse_move(unsigned int x, unsigned int y) |
{ |
mouse_hide(); |
pointer_x = x; |
1008,14 → 1259,14 |
mouse_show(); |
} |
static int |
anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
int handled = 1; |
int retval = 0; |
int i,nvp; |
bool handled = true; |
int retval = EOK; |
int i, nvp; |
int newval; |
switch (IPC_GET_METHOD(*call)) { |
case FB_ANIM_CREATE: |
nvp = IPC_GET_ARG1(*call); |
1105,14 → 1356,16 |
return handled; |
} |
/** Handler for messages concerning pixmap handling */ |
static int |
pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
/** Handler for messages concerning pixmap handling |
* |
*/ |
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
{ |
int handled = 1; |
int retval = 0; |
int i,nvp; |
bool handled = true; |
int retval = EOK; |
int i, nvp; |
switch (IPC_GET_METHOD(*call)) { |
case FB_VP_DRAW_PIXMAP: |
nvp = IPC_GET_ARG1(*call); |
1150,7 → 1403,7 |
default: |
handled = 0; |
} |
if (handled) |
ipc_answer_0(callid, retval); |
return handled; |
1157,35 → 1410,99 |
} |
static int rgb_from_style(attr_rgb_t *rgb, int style) |
{ |
switch (style) { |
case STYLE_NORMAL: |
rgb->fg_color = color_table[COLOR_BLACK]; |
rgb->bg_color = color_table[COLOR_WHITE]; |
break; |
case STYLE_EMPHASIS: |
rgb->fg_color = color_table[COLOR_RED]; |
rgb->bg_color = color_table[COLOR_WHITE]; |
break; |
default: |
return EINVAL; |
} |
return EOK; |
} |
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags) |
{ |
fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0); |
bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0); |
rgb->fg_color = color_table[fg_color]; |
rgb->bg_color = color_table[bg_color]; |
return EOK; |
} |
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a) |
{ |
int rc; |
switch (a->t) { |
case at_style: |
rc = rgb_from_style(rgb, a->a.s.style); |
break; |
case at_idx: |
rc = rgb_from_idx(rgb, a->a.i.fg_color, |
a->a.i.bg_color, a->a.i.flags); |
break; |
case at_rgb: |
*rgb = a->a.r; |
rc = EOK; |
break; |
} |
return rc; |
} |
static int fb_set_style(viewport_t *vport, ipcarg_t style) |
{ |
return rgb_from_style(&vport->attr, (int) style); |
} |
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color, |
ipcarg_t bg_color, ipcarg_t flags) |
{ |
return rgb_from_idx(&vport->attr, fg_color, bg_color, flags); |
} |
/** Function for handling connections to FB |
* |
*/ |
static void |
fb_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
int i; |
unsigned int row,col; |
char c; |
int vp = 0; |
viewport_t *vport = &viewports[0]; |
unsigned int vp = 0; |
viewport_t *vport = &viewports[vp]; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
return; |
} |
client_connected = 1; |
ipc_answer_0(iid, EOK); /* Accept connection */ |
while (1) { |
if (vport->cursor_active || anims_enabled) |
/* Accept connection */ |
client_connected = true; |
ipc_answer_0(iid, EOK); |
while (true) { |
ipc_callid_t callid; |
ipc_call_t call; |
int retval; |
unsigned int i; |
int scroll; |
uint8_t glyph; |
unsigned int row, col; |
if ((vport->cursor_active) || (anims_enabled)) |
callid = async_get_call_timeout(&call, 250000); |
else |
callid = async_get_call(&call); |
mouse_hide(); |
if (!callid) { |
cursor_blink(vport); |
1193,105 → 1510,89 |
mouse_show(); |
continue; |
} |
if (shm_handle(callid, &call, vp)) |
continue; |
if (pixmap_handle(callid, &call, vp)) |
continue; |
if (anim_handle(callid, &call, vp)) |
continue; |
switch (IPC_GET_METHOD(call)) { |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
client_connected = 0; |
/* cleanup other viewports */ |
client_connected = false; |
/* Cleanup other viewports */ |
for (i = 1; i < MAX_VIEWPORTS; i++) |
vport->initialized = 0; |
return; /* Exit thread */ |
vport->initialized = false; |
/* Exit thread */ |
return; |
case FB_PUTCHAR: |
case FB_TRANS_PUTCHAR: |
c = IPC_GET_ARG1(call); |
glyph = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
col = IPC_GET_ARG3(call); |
if (row >= vport->rows || col >= vport->cols) { |
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, EOK); |
draw_char(vport, c, row, col, vport->style, |
IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR); |
continue; /* msg already answered */ |
draw_char(vport, glyph, col, row); |
/* Message already answered */ |
continue; |
case FB_CLEAR: |
clear_port(vport); |
cursor_print(vport); |
retval = 0; |
vport_clear(vport); |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_CURSOR_GOTO: |
case FB_CURSOR_GOTO: |
row = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
if (row >= vport->rows || col >= vport->cols) { |
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
break; |
} |
retval = 0; |
retval = EOK; |
cursor_hide(vport); |
vport->cur_col = col; |
vport->cur_row = row; |
cursor_print(vport); |
break; |
cursor_show(vport); |
break; |
case FB_CURSOR_VISIBILITY: |
cursor_hide(vport); |
vport->cursor_active = IPC_GET_ARG1(call); |
cursor_print(vport); |
retval = 0; |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, vport->rows, vport->cols); |
continue; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if (i > vport->rows || i < (- (int)vport->rows)) { |
scroll = IPC_GET_ARG1(call); |
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) { |
retval = EINVAL; |
break; |
} |
cursor_hide(vport); |
scroll_port(vport, i*FONT_SCANLINES); |
cursor_print(vport); |
retval = 0; |
vport_scroll(vport, scroll); |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_VIEWPORT_DB: |
/* Enable double buffering */ |
i = IPC_GET_ARG1(call); |
if (i == -1) |
i = vp; |
if (i < 0 || i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (!viewports[i].initialized ) { |
retval = EADDRNOTAVAIL; |
break; |
} |
viewports[i].dboffset = 0; |
if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata) |
viewports[i].dbdata = |
malloc(screen.pixelbytes * |
viewports[i].width * viewports[i].height); |
else if (IPC_GET_ARG2(call) == 0 && |
viewports[i].dbdata) { |
free(viewports[i].dbdata); |
viewports[i].dbdata = NULL; |
} |
retval = 0; |
break; |
case FB_VIEWPORT_SWITCH: |
i = IPC_GET_ARG1(call); |
if (i < 0 || i >= MAX_VIEWPORTS) { |
if (i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (! viewports[i].initialized ) { |
if (!viewports[i].initialized) { |
retval = EADDRNOTAVAIL; |
break; |
} |
1298,11 → 1599,11 |
cursor_hide(vport); |
vp = i; |
vport = &viewports[vp]; |
cursor_print(vport); |
retval = 0; |
cursor_show(vport); |
retval = EOK; |
break; |
case FB_VIEWPORT_CREATE: |
retval = viewport_create(IPC_GET_ARG1(call) >> 16, |
retval = vport_create(IPC_GET_ARG1(call) >> 16, |
IPC_GET_ARG1(call) & 0xffff, |
IPC_GET_ARG2(call) >> 16, |
IPC_GET_ARG2(call) & 0xffff); |
1309,33 → 1610,42 |
break; |
case FB_VIEWPORT_DELETE: |
i = IPC_GET_ARG1(call); |
if (i < 0 || i >= MAX_VIEWPORTS) { |
if (i >= MAX_VIEWPORTS) { |
retval = EINVAL; |
break; |
} |
if (! viewports[i].initialized ) { |
if (!viewports[i].initialized) { |
retval = EADDRNOTAVAIL; |
break; |
} |
viewports[i].initialized = 0; |
if (viewports[i].dbdata) { |
free(viewports[i].dbdata); |
viewports[i].dbdata = NULL; |
} |
retval = 0; |
viewports[i].initialized = false; |
if (viewports[i].glyphs) |
free(viewports[i].glyphs); |
if (viewports[i].bgpixel) |
free(viewports[i].bgpixel); |
if (viewports[i].backbuf) |
free(viewports[i].backbuf); |
retval = EOK; |
break; |
case FB_SET_STYLE: |
vport->style.fg_color = IPC_GET_ARG1(call); |
vport->style.bg_color = IPC_GET_ARG2(call); |
retval = 0; |
retval = fb_set_style(vport, IPC_GET_ARG1(call)); |
break; |
case FB_SET_COLOR: |
retval = fb_set_color(vport, IPC_GET_ARG1(call), |
IPC_GET_ARG2(call), IPC_GET_ARG3(call)); |
break; |
case FB_SET_RGB_COLOR: |
vport->attr.fg_color = IPC_GET_ARG1(call); |
vport->attr.bg_color = IPC_GET_ARG2(call); |
retval = EOK; |
break; |
case FB_GET_RESOLUTION: |
ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
continue; |
case FB_POINTER_MOVE: |
pointer_enabled = 1; |
pointer_enabled = true; |
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
retval = 0; |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
1344,41 → 1654,33 |
} |
} |
/** Initialization of framebuffer */ |
int |
fb_init(void) |
/** Initialization of framebuffer |
* |
*/ |
int fb_init(void) |
{ |
void *fb_ph_addr; |
unsigned int fb_width; |
unsigned int fb_height; |
unsigned int fb_scanline; |
unsigned int fb_visual; |
bool fb_invert_colors; |
void *fb_addr; |
size_t asz; |
async_set_client_connection(fb_client_connection); |
fb_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
fb_width = sysinfo_value("fb.width"); |
fb_height = sysinfo_value("fb.height"); |
fb_scanline = sysinfo_value("fb.scanline"); |
fb_visual = sysinfo_value("fb.visual"); |
fb_invert_colors = sysinfo_value("fb.invert-colors"); |
asz = fb_scanline * fb_height; |
fb_addr = as_get_mappable_page(asz); |
physmem_map(fb_ph_addr, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); |
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual, |
fb_invert_colors)) |
void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
unsigned int fb_offset = sysinfo_value("fb.offset"); |
unsigned int fb_width = sysinfo_value("fb.width"); |
unsigned int fb_height = sysinfo_value("fb.height"); |
unsigned int fb_scanline = sysinfo_value("fb.scanline"); |
unsigned int fb_visual = sysinfo_value("fb.visual"); |
unsigned int fbsize = fb_scanline * fb_height; |
void *fb_addr = as_get_mappable_page(fbsize); |
if (physmem_map(fb_ph_addr + fb_offset, fb_addr, |
ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual)) |
return 0; |
return -1; |
} |
/** |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/sgcn.c |
---|
0,0 → 1,142 |
/* |
* Copyright (c) 2006 Ondrej Palkovsky |
* Copyright (c) 2008 Martin Decky |
* Copyright (c) 2008 Pavel Rimsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @defgroup sgcnfb SGCN |
* @brief userland driver of the Serengeti console output |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <errno.h> |
#include <stdio.h> |
#include <ddi.h> |
#include "serial_console.h" |
#include "sgcn.h" |
#define WIDTH 80 |
#define HEIGHT 24 |
/** |
* Virtual address mapped to SRAM. |
*/ |
static uintptr_t sram_virt_addr; |
/** |
* SGCN buffer offset within SGCN. |
*/ |
static uintptr_t sram_buffer_offset; |
/** |
* SGCN buffer header. It is placed at the very beginning of the SGCN |
* buffer. |
*/ |
typedef struct { |
/** hard-wired to "CON" */ |
char magic[4]; |
/** we don't need this */ |
char unused[24]; |
/** offset within the SGCN buffer of the output buffer start */ |
uint32_t out_begin; |
/** offset within the SGCN buffer of the output buffer end */ |
uint32_t out_end; |
/** offset within the SGCN buffer of the output buffer read pointer */ |
uint32_t out_rdptr; |
/** offset within the SGCN buffer of the output buffer write pointer */ |
uint32_t out_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
/* |
* Returns a pointer to the object of a given type which is placed at the given |
* offset from the console buffer beginning. |
*/ |
#define SGCN_BUFFER(type, offset) \ |
((type *) (sram_virt_addr + sram_buffer_offset + (offset))) |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** |
* Pushes the character to the SGCN serial. |
* @param c character to be pushed |
*/ |
static void sgcn_putc(char c) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->out_begin; |
uint32_t end = SGCN_BUFFER_HEADER->out_end; |
uint32_t size = end - begin; |
/* we need pointers to volatile variables */ |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr); |
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr); |
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin; |
while (*out_rdptr_ptr == new_wrptr) |
; |
*buf_ptr = c; |
*out_wrptr_ptr = new_wrptr; |
} |
/** |
* Initializes the SGCN serial driver. |
*/ |
int sgcn_init(void) |
{ |
sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size")); |
if (physmem_map((void *) sysinfo_value("sram.address.physical"), |
(void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE, |
AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
serial_console_init(sgcn_putc, WIDTH, HEIGHT); |
sram_buffer_offset = sysinfo_value("sram.buffer.offset"); |
async_set_client_connection(serial_client_connection); |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/ski.h |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup skifb |
* @brief HelenOS ski text console. |
* @ingroup fbs |
* @{ |
*/ |
/** @file |
*/ |
#ifndef FB_SKI_H_ |
#define FB_SKI_H_ |
extern int ski_init(void); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/srv/fb/ppm.c |
---|
92,23 → 92,23 |
int i; |
unsigned int color; |
unsigned int coef; |
/* Read magic */ |
if (data[0] != 'P' || data[1] != '6') |
if ((data[0] != 'P') || (data[1] != '6')) |
return EINVAL; |
data+=2; |
data += 2; |
skip_whitespace(&data); |
read_num(&data, &width); |
skip_whitespace(&data); |
read_num(&data,&height); |
read_num(&data, &height); |
skip_whitespace(&data); |
read_num(&data,&maxcolor); |
read_num(&data, &maxcolor); |
data++; |
if (maxcolor == 0 || maxcolor > 255 || width * height > datasz) { |
if ((maxcolor == 0) || (maxcolor > 255) || (width * height > datasz)) |
return EINVAL; |
} |
coef = 255 / maxcolor; |
if (coef * maxcolor > 255) |
coef -= 1; |
125,6 → 125,6 |
(*putpixel)(vport, sx + (i % width), sy + (i / width), color); |
data += 3; |
} |
return 0; |
} |
/branches/dd/uspace/srv/fb/fb.h |
---|
29,7 → 29,7 |
/** @addtogroup fb |
* @ingroup fbs |
* @{ |
*/ |
*/ |
/** @file |
*/ |
36,8 → 36,10 |
#ifndef FB_FB_H_ |
#define FB_FB_H_ |
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, int); |
#include <stdint.h> |
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t); |
extern int fb_init(void); |
#endif |
/branches/dd/uspace/srv/fb/ega.c |
---|
49,6 → 49,9 |
#include <ipc/ns.h> |
#include <ipc/services.h> |
#include <libarch/ddi.h> |
#include <console/style.h> |
#include <console/color.h> |
#include <sys/types.h> |
#include "ega.h" |
#include "../console/screenbuffer.h" |
61,13 → 64,14 |
saved_screen saved_screens[MAX_SAVED_SCREENS]; |
#define EGA_IO_ADDRESS 0x3d4 |
#define EGA_IO_BASE ((ioport8_t *) 0x3d4) |
#define EGA_IO_SIZE 2 |
#define NORMAL_COLOR 0x0f |
#define INVERTED_COLOR 0xf0 |
int ega_normal_color = 0x0f; |
int ega_inverted_color = 0xf0; |
#define EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR) |
#define NORMAL_COLOR ega_normal_color |
#define INVERTED_COLOR ega_inverted_color |
/* Allow only 1 connection */ |
static int client_connected = 0; |
76,8 → 80,10 |
static unsigned int scr_height; |
static char *scr_addr; |
static unsigned int style = NORMAL_COLOR; |
static unsigned int style; |
static unsigned attr_to_ega_style(const attrs_t *a); |
static void clrscr(void) |
{ |
int i; |
94,10 → 100,10 |
ega_cursor = col + scr_width * row; |
outb(EGA_IO_ADDRESS, 0xe); |
outb(EGA_IO_ADDRESS + 1, (ega_cursor >> 8) & 0xff); |
outb(EGA_IO_ADDRESS, 0xf); |
outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff); |
pio_write_8(EGA_IO_BASE, 0xe); |
pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff); |
pio_write_8(EGA_IO_BASE, 0xf); |
pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff); |
} |
static void cursor_disable(void) |
104,10 → 110,10 |
{ |
uint8_t stat; |
outb(EGA_IO_ADDRESS, 0xa); |
stat=inb(EGA_IO_ADDRESS + 1); |
outb(EGA_IO_ADDRESS, 0xa); |
outb(EGA_IO_ADDRESS + 1, stat | (1 << 5)); |
pio_write_8(EGA_IO_BASE, 0xa); |
stat = pio_read_8(EGA_IO_BASE + 1); |
pio_write_8(EGA_IO_BASE, 0xa); |
pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5)); |
} |
static void cursor_enable(void) |
114,10 → 120,10 |
{ |
uint8_t stat; |
outb(EGA_IO_ADDRESS, 0xa); |
stat=inb(EGA_IO_ADDRESS + 1); |
outb(EGA_IO_ADDRESS, 0xa); |
outb(EGA_IO_ADDRESS + 1, stat & (~(1 << 5))); |
pio_write_8(EGA_IO_BASE, 0xa); |
stat = pio_read_8(EGA_IO_BASE + 1); |
pio_write_8(EGA_IO_BASE, 0xa); |
pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5))); |
} |
static void scroll(int rows) |
124,13 → 130,13 |
{ |
int i; |
if (rows > 0) { |
memcpy(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, |
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, |
scr_width * scr_height * 2 - rows * scr_width * 2); |
for (i = 0; i < rows * scr_width; i++) |
(((short *) scr_addr) + scr_width * scr_height - rows * |
scr_width)[i] = ((style << 8) + ' '); |
} else if (rows < 0) { |
memcpy(((char *)scr_addr) - rows * scr_width * 2, scr_addr, |
memmove(((char *)scr_addr) - rows * scr_width * 2, scr_addr, |
scr_width * scr_height * 2 + rows * scr_width * 2); |
for (i = 0; i < -rows * scr_width; i++) |
((short *)scr_addr)[i] = ((style << 8 ) + ' '); |
151,8 → 157,7 |
for (i = 0; i < scr_width * scr_height; i++) { |
scr_addr[i * 2] = data[i].character; |
scr_addr[i * 2 + 1] = EGA_STYLE(data[i].style.fg_color, |
data[i].style.bg_color); |
scr_addr[i * 2 + 1] = attr_to_ega_style(&data[i].attrs); |
} |
} |
181,7 → 186,51 |
return i; |
} |
static int style_to_ega_style(int style) |
{ |
unsigned int ega_style; |
switch (style) { |
case STYLE_NORMAL: |
ega_style = INVERTED_COLOR; |
break; |
case STYLE_EMPHASIS: |
ega_style = INVERTED_COLOR | 4; |
break; |
default: |
return INVERTED_COLOR; |
} |
return ega_style; |
} |
static unsigned int color_to_ega_style(int fg_color, int bg_color, int attr) |
{ |
unsigned int style; |
style = (fg_color & 7) | ((bg_color & 7) << 4); |
if (attr & CATTR_BRIGHT) |
style = style | 0x08; |
return style; |
} |
static unsigned int rgb_to_ega_style(uint32_t fg, uint32_t bg) |
{ |
return (fg > bg) ? NORMAL_COLOR : INVERTED_COLOR; |
} |
static unsigned attr_to_ega_style(const attrs_t *a) |
{ |
switch (a->t) { |
case at_style: return style_to_ega_style(a->a.s.style); |
case at_rgb: return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color); |
case at_idx: return color_to_ega_style(a->a.i.fg_color, |
a->a.i.bg_color, a->a.i.flags); |
default: return INVERTED_COLOR; |
} |
} |
static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
int retval; |
189,7 → 238,8 |
ipc_call_t call; |
char c; |
unsigned int row, col; |
int bgcolor,fgcolor; |
int bg_color, fg_color, attr; |
uint32_t bg_rgb, fg_rgb; |
keyfield_t *interbuf = NULL; |
size_t intersize = 0; |
int i; |
265,7 → 315,7 |
retval = 0; |
break; |
case FB_CURSOR_VISIBILITY: |
if(IPC_GET_ARG1(call)) |
if (IPC_GET_ARG1(call)) |
cursor_enable(); |
else |
cursor_disable(); |
272,11 → 322,22 |
retval = 0; |
break; |
case FB_SET_STYLE: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
style = EGA_STYLE(fgcolor, bgcolor); |
style = style_to_ega_style(IPC_GET_ARG1(call)); |
retval = 0; |
break; |
case FB_SET_COLOR: |
fg_color = IPC_GET_ARG1(call); |
bg_color = IPC_GET_ARG2(call); |
attr = IPC_GET_ARG3(call); |
style = color_to_ega_style(fg_color, bg_color, attr); |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
fg_rgb = IPC_GET_ARG1(call); |
bg_rgb = IPC_GET_ARG2(call); |
style = rgb_to_ega_style(fg_rgb, bg_rgb); |
retval = 0; |
break; |
case FB_VP_DRAW_PIXMAP: |
i = IPC_GET_ARG2(call); |
retval = print_screen(i); |
312,13 → 373,22 |
ega_ph_addr = (void *) sysinfo_value("fb.address.physical"); |
scr_width = sysinfo_value("fb.width"); |
scr_height = sysinfo_value("fb.height"); |
iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2); |
if (sysinfo_value("fb.blinking")) { |
ega_normal_color &= 0x77; |
ega_inverted_color &= 0x77; |
} |
style = NORMAL_COLOR; |
iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2); |
sz = scr_width * scr_height * 2; |
scr_addr = as_get_mappable_page(sz); |
physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); |
if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> |
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
async_set_client_connection(ega_client_connection); |
326,6 → 396,6 |
} |
/** |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fb/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
43,50 → 44,69 |
OUTPUT = fb |
SOURCES = \ |
main.c \ |
sysio.c \ |
ppm.c |
ifneq ($(ARCH), ia64) |
ifneq ($(UARCH),ia64) |
SOURCES += fb.c \ |
font-8x16.c |
CFLAGS += -DFB_ENABLED |
endif |
ifeq ($(ARCH), ia32) |
ifeq ($(UARCH),ia32) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), amd64) |
ifeq ($(UARCH),ia64) |
SOURCES += ega.c \ |
ski.c \ |
serial_console.c |
CFLAGS += -DSKI_ENABLED |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(UARCH),amd64) |
SOURCES += ega.c |
CFLAGS += -DEGA_ENABLED |
endif |
ifeq ($(ARCH), mips32) |
CFLAGS += -DFB_INVERT_ENDIAN |
ifeq ($(UARCH),mips32) |
SOURCES += msim.c \ |
serial_console.c |
CFLAGS += -DMSIM_ENABLED |
endif |
CFLAGS += -D$(ARCH) |
ifeq ($(UARCH),sparc64) |
SOURCES += sgcn.c \ |
serial_console.c |
CFLAGS += -DSGCN_ENABLED |
endif |
CFLAGS += -D$(UARCH) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld -e __entry_driver $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.h |
---|
40,8 → 40,16 |
#include <bool.h> |
#include <libadt/hash_table.h> |
#ifndef dprintf |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} tmpfs_dentry_type_t; |
typedef struct tmpfs_dentry { |
fs_index_t index; /**< TMPFS node index. */ |
link_t dh_link; /**< Dentries hash table link. */ |
48,11 → 56,7 |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
hash_table_t names; /**< All names linking to this TMPFS node. */ |
enum { |
TMPFS_NONE, |
TMPFS_FILE, |
TMPFS_DIRECTORY |
} type; |
tmpfs_dentry_type_t type; |
unsigned lnkcnt; /**< Link count. */ |
size_t size; /**< File size if type is TMPFS_FILE. */ |
void *data; /**< File content's if type is TMPFS_FILE. */ |
60,6 → 64,9 |
extern fs_reg_t tmpfs_reg; |
extern libfs_ops_t tmpfs_libfs_ops; |
extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_read(ipc_callid_t, ipc_call_t *); |
67,6 → 74,8 |
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *); |
extern bool tmpfs_restore(dev_handle_t); |
#endif |
/** |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
0,0 → 1,197 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file tmpfs_dump.c |
* @brief Support for loading TMPFS file system dump. |
*/ |
#include "tmpfs.h" |
#include "../../vfs/vfs.h" |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
#include <sys/types.h> |
#include <as.h> |
#include <libblock.h> |
#include <byteorder.h> |
#define TMPFS_BLOCK_SIZE 1024 |
struct rdentry { |
uint8_t type; |
uint32_t len; |
} __attribute__((packed)); |
static bool |
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos, |
tmpfs_dentry_t *parent) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
int rc; |
do { |
char *fname; |
tmpfs_dentry_t *node; |
uint32_t size; |
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry), |
TMPFS_BLOCK_SIZE) != EOK) |
return false; |
entry.len = uint32_t_le2host(entry.len); |
switch (entry.type) { |
case TMPFS_NONE: |
break; |
case TMPFS_FILE: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
rc = ops->link((void *) parent, (void *) node, fname); |
if (rc != EOK) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
free(fname); |
if (block_read(dev, bufpos, buflen, pos, &size, |
sizeof(size), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
size = uint32_t_le2host(size); |
node->data = malloc(size); |
if (node->data == NULL) |
return false; |
node->size = size; |
if (block_read(dev, bufpos, buflen, pos, node->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
return false; |
break; |
case TMPFS_DIRECTORY: |
fname = malloc(entry.len + 1); |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY); |
if (node == NULL) { |
free(fname); |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
rc = ops->link((void *) parent, (void *) node, fname); |
if (rc != EOK) { |
ops->destroy((void *) node); |
free(fname); |
return false; |
} |
free(fname); |
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos, |
node)) |
return false; |
break; |
default: |
return false; |
} |
} while (entry.type != TMPFS_NONE); |
return true; |
} |
bool tmpfs_restore(dev_handle_t dev) |
{ |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
int rc; |
rc = block_init(dev, TMPFS_BLOCK_SIZE); |
if (rc != EOK) |
return false; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = 0; |
char tag[6]; |
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE) != EOK) |
goto error; |
tag[5] = 0; |
if (strcmp(tag, "TMPFS") != 0) |
goto error; |
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, |
ops->root_get(dev))) |
goto error; |
block_fini(dev); |
return true; |
error: |
block_fini(dev); |
return false; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.c |
---|
50,18 → 50,11 |
#include <libfs.h> |
#include "../../vfs/vfs.h" |
#define NAME "tmpfs" |
vfs_info_t tmpfs_vfs_info = { |
.name = "tmpfs", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_DESTROY)] = VFS_OP_DEFINED, |
} |
}; |
fs_reg_t tmpfs_reg; |
103,6 → 96,9 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
tmpfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
tmpfs_mount(callid, &call); |
break; |
130,27 → 126,22 |
int main(int argc, char **argv) |
{ |
int vfs_phone; |
printf("TMPFS: HelenOS TMPFS file system server.\n"); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
usleep(10000); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
printf(NAME ": HelenOS TMPFS file system server\n"); |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
return -1; |
} |
int rc; |
rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info, |
int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info, |
tmpfs_connection); |
if (rc != EOK) { |
printf("Failed to register the TMPFS file system (%d)\n", rc); |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
dprintf("TMPFS filesystem registered, fs_handle=%d.\n", |
tmpfs_reg.fs_handle); |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* not reached */ |
return 0; |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
64,6 → 64,8 |
*/ |
static tmpfs_dentry_t *root; |
#define TMPFS_DEV 0 /**< Dummy device handle for TMPFS */ |
/* |
* Implementation of the libfs interface. |
*/ |
72,8 → 74,8 |
static void *tmpfs_match(void *, const char *); |
static void *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(void *); |
static void *tmpfs_create_node(int); |
static bool tmpfs_link_node(void *, void *, const char *); |
static void *tmpfs_create_node(dev_handle_t, int); |
static int tmpfs_link_node(void *, void *, const char *); |
static int tmpfs_unlink_node(void *, void *); |
static int tmpfs_destroy_node(void *); |
228,12 → 230,12 |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
return false; |
root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY); |
root = (tmpfs_dentry_t *) tmpfs_create_node(TMPFS_DEV, L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return false; |
} |
root->lnkcnt = 1; |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
282,7 → 284,7 |
/* nothing to do */ |
} |
void *tmpfs_create_node(int lflag) |
void *tmpfs_create_node(dev_handle_t dev_handle, int lflag) |
{ |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
306,7 → 308,7 |
return (void *) node; |
} |
bool tmpfs_link_node(void *prnt, void *chld, const char *nm) |
int tmpfs_link_node(void *prnt, void *chld, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld; |
315,13 → 317,13 |
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t)); |
if (!namep) |
return false; |
return ENOMEM; |
tmpfs_name_initialize(namep); |
size_t len = strlen(nm); |
namep->name = malloc(len + 1); |
if (!namep->name) { |
free(namep); |
return false; |
return ENOMEM; |
} |
strcpy(namep->name, nm); |
namep->parent = parentp; |
341,7 → 343,7 |
parentp->child = childp; |
} |
return true; |
return EOK; |
} |
int tmpfs_unlink_node(void *prnt, void *chld) |
393,28 → 395,39 |
return EOK; |
} |
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request) |
void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t mr_dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t mr_index = (fs_index_t)IPC_GET_ARG2(*request); |
fs_handle_t mp_fs_handle = (fs_handle_t)IPC_GET_ARG3(*request); |
dev_handle_t mp_dev_handle = (dev_handle_t)IPC_GET_ARG4(*request); |
fs_index_t mp_index = (fs_index_t)IPC_GET_ARG5(*request); |
if ((mr_index == root->index) && |
(mp_fs_handle == tmpfs_reg.fs_handle) && |
(mp_index == mr_index)) |
ipc_answer_0(rid, EOK); |
else |
ipc_answer_0(rid, ENOTSUP); |
} |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Initialize TMPFS. */ |
if (!root && !tmpfs_init()) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if (dev_handle >= 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
else |
ipc_answer_0(rid, ELIMIT); |
} else { |
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt); |
} |
} |
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
ipc_answer_0(rid, ENOTSUP); |
} |
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
/branches/dd/uspace/srv/fs/tmpfs/Makefile |
---|
31,12 → 31,17 |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
44,28 → 49,31 |
OUTPUT = tmpfs |
SOURCES = \ |
tmpfs.c \ |
tmpfs_ops.c |
tmpfs_ops.c \ |
tmpfs_dump.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/fs/fat/fat_idx.c |
---|
74,6 → 74,32 |
/** List of unused structures. */ |
static LIST_INITIALIZE(unused_head); |
static void unused_initialize(unused_t *u, dev_handle_t dev_handle) |
{ |
link_initialize(&u->link); |
u->dev_handle = dev_handle; |
u->next = 0; |
u->remaining = ((uint64_t)((fs_index_t)-1)) + 1; |
list_initialize(&u->freed_head); |
} |
static unused_t *unused_find(dev_handle_t dev_handle, bool lock) |
{ |
unused_t *u; |
link_t *l; |
if (lock) |
futex_down(&unused_futex); |
for (l = unused_head.next; l != &unused_head; l = l->next) { |
u = list_get_instance(l, unused_t, link); |
if (u->dev_handle == dev_handle) |
return u; |
} |
if (lock) |
futex_up(&unused_futex); |
return NULL; |
} |
/** Futex protecting the up_hash and ui_hash. */ |
static futex_t used_futex = FUTEX_INITIALIZER; |
188,24 → 214,15 |
}; |
/** Allocate a VFS index which is not currently in use. */ |
static bool fat_idx_alloc(dev_handle_t dev_handle, fs_index_t *index) |
static bool fat_index_alloc(dev_handle_t dev_handle, fs_index_t *index) |
{ |
link_t *l; |
unused_t *u; |
assert(index); |
futex_down(&unused_futex); |
for (l = unused_head.next; l != &unused_head; l = l->next) { |
u = list_get_instance(l, unused_t, link); |
if (u->dev_handle == dev_handle) |
goto hit; |
} |
futex_up(&unused_futex); |
/* dev_handle not found */ |
return false; |
u = unused_find(dev_handle, true); |
if (!u) |
return false; |
hit: |
if (list_empty(&u->freed_head)) { |
if (u->remaining) { |
/* |
259,23 → 276,13 |
} |
/** Free a VFS index, which is no longer in use. */ |
static void fat_idx_free(dev_handle_t dev_handle, fs_index_t index) |
static void fat_index_free(dev_handle_t dev_handle, fs_index_t index) |
{ |
link_t *l; |
unused_t *u; |
futex_down(&unused_futex); |
for (l = unused_head.next; l != &unused_head; l = l->next) { |
u = list_get_instance(l, unused_t, link); |
if (u->dev_handle == dev_handle) |
goto hit; |
} |
futex_up(&unused_futex); |
u = unused_find(dev_handle, true); |
assert(u); |
/* should not happen */ |
assert(0); |
hit: |
if (u->next == index + 1) { |
/* The index can be returned directly to the counter. */ |
u->next--; |
331,6 → 338,52 |
futex_up(&unused_futex); |
} |
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
if (!fidx) |
return NULL; |
if (!fat_index_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
return NULL; |
} |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = FAT_CLST_RES0; /* no parent yet */ |
fidx->pdi = 0; |
fidx->nodep = NULL; |
return fidx; |
} |
fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) |
{ |
fat_idx_t *fidx; |
futex_down(&used_futex); |
fidx = fat_idx_create(dev_handle); |
if (!fidx) { |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
[UIH_INDEX_KEY] = fidx->index, |
}; |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
return fidx; |
} |
fat_idx_t * |
fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
{ |
347,16 → 400,11 |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
} else { |
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
fidx = fat_idx_create(dev_handle); |
if (!fidx) { |
futex_up(&used_futex); |
return NULL; |
} |
if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
free(fidx); |
futex_up(&used_futex); |
return NULL; |
} |
unsigned long ikey[] = { |
[UIH_DH_KEY] = dev_handle, |
363,13 → 411,8 |
[UIH_INDEX_KEY] = fidx->index, |
}; |
link_initialize(&fidx->uph_link); |
link_initialize(&fidx->uih_link); |
futex_initialize(&fidx->lock, 1); |
fidx->dev_handle = dev_handle; |
fidx->pfc = pfc; |
fidx->pdi = pdi; |
fidx->nodep = NULL; |
hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
380,6 → 423,32 |
return fidx; |
} |
void fat_idx_hashin(fat_idx_t *idx) |
{ |
unsigned long pkey[] = { |
[UPH_DH_KEY] = idx->dev_handle, |
[UPH_PFC_KEY] = idx->pfc, |
[UPH_PDI_KEY] = idx->pdi, |
}; |
futex_down(&used_futex); |
hash_table_insert(&up_hash, pkey, &idx->uph_link); |
futex_up(&used_futex); |
} |
void fat_idx_hashout(fat_idx_t *idx) |
{ |
unsigned long pkey[] = { |
[UPH_DH_KEY] = idx->dev_handle, |
[UPH_PFC_KEY] = idx->pfc, |
[UPH_PDI_KEY] = idx->pdi, |
}; |
futex_down(&used_futex); |
hash_table_remove(&up_hash, pkey, 3); |
futex_up(&used_futex); |
} |
fat_idx_t * |
fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index) |
{ |
401,3 → 470,87 |
return fidx; |
} |
/** Destroy the index structure. |
* |
* @param idx The index structure to be destroyed. |
*/ |
void fat_idx_destroy(fat_idx_t *idx) |
{ |
unsigned long ikey[] = { |
[UIH_DH_KEY] = idx->dev_handle, |
[UIH_INDEX_KEY] = idx->index, |
}; |
assert(idx->pfc == FAT_CLST_RES0); |
futex_down(&used_futex); |
/* |
* Since we can only free unlinked nodes, the index structure is not |
* present in the position hash (uph). We therefore hash it out from |
* the index hash only. |
*/ |
hash_table_remove(&ui_hash, ikey, 2); |
futex_up(&used_futex); |
/* Release the VFS index. */ |
fat_index_free(idx->dev_handle, idx->index); |
/* Deallocate the structure. */ |
free(idx); |
} |
int fat_idx_init(void) |
{ |
if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops)) |
return ENOMEM; |
if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) { |
hash_table_destroy(&up_hash); |
return ENOMEM; |
} |
return EOK; |
} |
void fat_idx_fini(void) |
{ |
/* We assume the hash tables are empty. */ |
hash_table_destroy(&up_hash); |
hash_table_destroy(&ui_hash); |
} |
int fat_idx_init_by_dev_handle(dev_handle_t dev_handle) |
{ |
unused_t *u; |
int rc = EOK; |
u = (unused_t *) malloc(sizeof(unused_t)); |
if (!u) |
return ENOMEM; |
unused_initialize(u, dev_handle); |
futex_down(&unused_futex); |
if (!unused_find(dev_handle, false)) |
list_append(&u->link, &unused_head); |
else |
rc = EEXIST; |
futex_up(&unused_futex); |
return rc; |
} |
void fat_idx_fini_by_dev_handle(dev_handle_t dev_handle) |
{ |
unused_t *u; |
u = unused_find(dev_handle, true); |
assert(u); |
list_remove(&u->link); |
futex_up(&unused_futex); |
while (!list_empty(&u->freed_head)) { |
freed_t *f; |
f = list_get_instance(u->freed_head.next, freed_t, link); |
list_remove(&f->link); |
free(f); |
} |
free(u); |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/fat.h |
---|
33,6 → 33,7 |
#ifndef FAT_FAT_H_ |
#define FAT_FAT_H_ |
#include "fat_fat.h" |
#include <ipc/ipc.h> |
#include <libfs.h> |
#include <atomic.h> |
40,9 → 41,16 |
#include <bool.h> |
#include "../../vfs/vfs.h" |
#ifndef dprintf |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
typedef struct { |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define BS_BLOCK 0 |
#define BS_SIZE 512 |
typedef struct fat_bs { |
uint8_t ji[3]; /**< Jump instruction. */ |
uint8_t oem_name[8]; |
/* BIOS Parameter Block */ |
113,34 → 121,6 |
}; |
} __attribute__ ((packed)) fat_bs_t; |
#define FAT_ATTR_RDONLY (1 << 0) |
#define FAT_ATTR_VOLLABEL (1 << 3) |
#define FAT_ATTR_SUBDIR (1 << 4) |
typedef struct { |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t reserved; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
uint16_t adate; |
union { |
uint16_t eaidx; /* FAT12/FAT16 */ |
uint16_t firstc_hi; /* FAT32 */ |
}; |
uint16_t mtime; |
uint16_t mdate; |
union { |
uint16_t firstc; /* FAT12/FAT16 */ |
uint16_t firstc_lo; /* FAT32 */ |
}; |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
typedef uint16_t fat_cluster_t; |
typedef enum { |
FAT_INVALID, |
FAT_DIRECTORY, |
217,11 → 197,26 |
extern fs_reg_t fat_reg; |
extern void fat_mounted(ipc_callid_t, ipc_call_t *); |
extern void fat_mount(ipc_callid_t, ipc_call_t *); |
extern void fat_lookup(ipc_callid_t, ipc_call_t *); |
extern void fat_read(ipc_callid_t, ipc_call_t *); |
extern void fat_write(ipc_callid_t, ipc_call_t *); |
extern void fat_truncate(ipc_callid_t, ipc_call_t *); |
extern void fat_destroy(ipc_callid_t, ipc_call_t *); |
extern fat_idx_t *fat_idx_get_new(dev_handle_t); |
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned); |
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t); |
extern void fat_idx_destroy(fat_idx_t *); |
extern void fat_idx_hashin(fat_idx_t *); |
extern void fat_idx_hashout(fat_idx_t *); |
extern int fat_idx_init(void); |
extern void fat_idx_fini(void); |
extern int fat_idx_init_by_dev_handle(dev_handle_t); |
extern void fat_idx_fini_by_dev_handle(dev_handle_t); |
#endif |
/** |
/branches/dd/uspace/srv/fs/fat/fat_dentry.c |
---|
0,0 → 1,204 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file fat_dentry.c |
* @brief Functions that work with FAT directory entries. |
*/ |
#include "fat_dentry.h" |
#include <ctype.h> |
#include <string.h> |
static bool is_d_char(const char ch) |
{ |
if (isalnum(ch) || ch == '_') |
return true; |
else |
return false; |
} |
/** Compare path component with the name read from the dentry. |
* |
* This function compares the path component with the name read from the dentry. |
* The comparison is case insensitive and tolerates a mismatch on the trailing |
* dot character at the end of the name (i.e. when there is a dot, but no |
* extension). |
* |
* @param name Node name read from the dentry. |
* @param component Path component. |
* |
* @return Zero on match, non-zero otherwise. |
*/ |
int fat_dentry_namecmp(char *name, const char *component) |
{ |
int rc; |
if (!(rc = stricmp(name, component))) |
return rc; |
if (!strchr(name, '.')) { |
/* |
* There is no '.' in the name, so we know that there is enough |
* space for appending an extra '.' to name. |
*/ |
name[strlen(name)] = '.'; |
name[strlen(name) + 1] = '\0'; |
rc = stricmp(name, component); |
} |
return rc; |
} |
bool fat_dentry_name_verify(const char *name) |
{ |
unsigned i, dot; |
bool dot_found = false; |
for (i = 0; name[i]; i++) { |
if (name[i] == '.') { |
if (dot_found) { |
return false; |
} else { |
dot_found = true; |
dot = i; |
} |
} else { |
if (!is_d_char(name[i])) |
return false; |
} |
} |
if (dot_found) { |
if (dot > FAT_NAME_LEN) |
return false; |
if (i - dot > FAT_EXT_LEN + 1) |
return false; |
} else { |
if (i > FAT_NAME_LEN) |
return false; |
} |
return true; |
} |
void fat_dentry_name_get(const fat_dentry_t *d, char *buf) |
{ |
int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) |
break; |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->name[i]; |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->ext[i]; |
} |
*buf = '\0'; |
} |
void fat_dentry_name_set(fat_dentry_t *d, const char *name) |
{ |
int i; |
const char fake_ext[] = " "; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
switch ((uint8_t) *name) { |
case 0xe5: |
d->name[i] = FAT_DENTRY_E5_ESC; |
name++; |
break; |
case '\0': |
case '.': |
d->name[i] = FAT_PAD; |
break; |
default: |
d->name[i] = toupper(*name++); |
break; |
} |
} |
if (*name++ != '.') |
name = fake_ext; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
switch ((uint8_t) *name) { |
case 0xe5: |
d->ext[i] = FAT_DENTRY_E5_ESC; |
name++; |
break; |
case '\0': |
d->ext[i] = FAT_PAD; |
break; |
default: |
d->ext[i] = toupper(*name++); |
break; |
} |
} |
} |
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) |
{ |
if (d->attr & FAT_ATTR_VOLLABEL) { |
/* volume label entry */ |
return FAT_DENTRY_SKIP; |
} |
if (d->name[0] == FAT_DENTRY_ERASED) { |
/* not-currently-used entry */ |
return FAT_DENTRY_FREE; |
} |
if (d->name[0] == FAT_DENTRY_UNUSED) { |
/* never used entry */ |
return FAT_DENTRY_LAST; |
} |
if (d->name[0] == FAT_DENTRY_DOT) { |
/* |
* Most likely '.' or '..'. |
* It cannot occur in a regular file name. |
*/ |
return FAT_DENTRY_SKIP; |
} |
return FAT_DENTRY_VALID; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/fat_dentry.h |
---|
0,0 → 1,96 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef FAT_FAT_DENTRY_H_ |
#define FAT_FAT_DENTRY_H_ |
#include <stdint.h> |
#include <bool.h> |
#define FAT_NAME_LEN 8 |
#define FAT_EXT_LEN 3 |
#define FAT_NAME_DOT ". " |
#define FAT_NAME_DOT_DOT ".. " |
#define FAT_EXT_PAD " " |
#define FAT_ATTR_RDONLY (1 << 0) |
#define FAT_ATTR_VOLLABEL (1 << 3) |
#define FAT_ATTR_SUBDIR (1 << 4) |
#define FAT_PAD ' ' |
#define FAT_DENTRY_UNUSED 0x00 |
#define FAT_DENTRY_E5_ESC 0x05 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
typedef enum { |
FAT_DENTRY_SKIP, |
FAT_DENTRY_LAST, |
FAT_DENTRY_FREE, |
FAT_DENTRY_VALID |
} fat_dentry_clsf_t; |
typedef struct { |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t reserved; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
uint16_t adate; |
union { |
uint16_t eaidx; /* FAT12/FAT16 */ |
uint16_t firstc_hi; /* FAT32 */ |
} __attribute__ ((packed)); |
uint16_t mtime; |
uint16_t mdate; |
union { |
uint16_t firstc; /* FAT12/FAT16 */ |
uint16_t firstc_lo; /* FAT32 */ |
} __attribute__ ((packed)); |
uint32_t size; |
} __attribute__ ((packed)) fat_dentry_t; |
extern int fat_dentry_namecmp(char *, const char *); |
extern bool fat_dentry_name_verify(const char *); |
extern void fat_dentry_name_get(const fat_dentry_t *, char *); |
extern void fat_dentry_name_set(fat_dentry_t *, const char *); |
extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/fat_fat.c |
---|
0,0 → 1,454 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file fat_fat.c |
* @brief Functions that manipulate the File Allocation Tables. |
*/ |
#include "fat_fat.h" |
#include "fat_dentry.h" |
#include "fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <libblock.h> |
#include <errno.h> |
#include <byteorder.h> |
#include <align.h> |
#include <assert.h> |
#include <futex.h> |
/** |
* The fat_alloc_lock futex protects all copies of the File Allocation Table |
* during allocation of clusters. The lock does not have to be held durring |
* deallocation of clusters. |
*/ |
static futex_t fat_alloc_lock = FUTEX_INITIALIZER; |
/** Walk the cluster chain. |
* |
* @param bs Buffer holding the boot sector for the file. |
* @param dev_handle Device handle of the device with the file. |
* @param firstc First cluster to start the walk with. |
* @param lastc If non-NULL, output argument hodling the last cluster number visited. |
* @param max_clusters Maximum number of clusters to visit. |
* |
* @return Number of clusters seen during the walk. |
*/ |
uint16_t |
fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, |
fat_cluster_t *lastc, uint16_t max_clusters) |
{ |
block_t *b; |
unsigned bps; |
unsigned rscnt; /* block address of the first FAT */ |
uint16_t clusters = 0; |
fat_cluster_t clst = firstc; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
if (firstc == FAT_CLST_RES0) { |
/* No space allocated to the file. */ |
if (lastc) |
*lastc = firstc; |
return 0; |
} |
while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { |
bn_t fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST); |
if (lastc) |
*lastc = clst; /* remember the last cluster number */ |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
block_put(b); |
clusters++; |
} |
if (lastc && clst < FAT_CLST_LAST1) |
*lastc = clst; |
return clusters; |
} |
/** Read block from file located on a FAT file system. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param firstc First cluster used by the file. Can be zero if the file |
* is empty. |
* @param bn Block number. |
* @param flags Flags passed to libblock. |
* |
* @return Block structure holding the requested block. |
*/ |
block_t * |
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, |
bn_t bn, int flags) |
{ |
block_t *b; |
unsigned bps; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned rde; |
unsigned rds; /* root directory size */ |
unsigned sf; |
unsigned ssa; /* size of the system area */ |
unsigned clusters, max_clusters; |
fat_cluster_t lastc; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
rde = uint16_t_le2host(bs->root_ent_max); |
sf = uint16_t_le2host(bs->sec_per_fat); |
rds = (sizeof(fat_dentry_t) * rde) / bps; |
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
ssa = rscnt + bs->fatcnt * sf + rds; |
if (firstc == FAT_CLST_ROOT) { |
/* root directory special case */ |
assert(bn < rds); |
b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags); |
return b; |
} |
max_clusters = bn / bs->spc; |
clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc, |
max_clusters); |
assert(clusters == max_clusters); |
b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc + |
bn % bs->spc, flags); |
return b; |
} |
/** Fill the gap between EOF and a new file position. |
* |
* @param bs Buffer holding the boot sector for nodep. |
* @param nodep FAT node with the gap. |
* @param mcl First cluster in an independent cluster chain that will |
* be later appended to the end of the node's own cluster |
* chain. If pos is still in the last allocated cluster, |
* this argument is ignored. |
* @param pos Position in the last node block. |
*/ |
void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos) |
{ |
uint16_t bps; |
unsigned spc; |
block_t *b; |
off_t o, boundary; |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
boundary = ROUND_UP(nodep->size, bps * spc); |
/* zero out already allocated space */ |
for (o = nodep->size; o < pos && o < boundary; |
o = ALIGN_DOWN(o + bps, bps)) { |
int flags = (o % bps == 0) ? |
BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE; |
b = fat_block_get(bs, nodep, o / bps, flags); |
memset(b->data + o % bps, 0, bps - o % bps); |
b->dirty = true; /* need to sync node */ |
block_put(b); |
} |
if (o >= pos) |
return; |
/* zero out the initial part of the new cluster chain */ |
for (o = boundary; o < pos; o += bps) { |
b = _fat_block_get(bs, nodep->idx->dev_handle, mcl, |
(o - boundary) / bps, BLOCK_FLAGS_NOREAD); |
memset(b->data, 0, min(bps, pos - o)); |
b->dirty = true; /* need to sync node */ |
block_put(b); |
} |
} |
/** Get cluster from the first FAT. |
* |
* @param bs Buffer holding the boot sector for the file system. |
* @param dev_handle Device handle for the file system. |
* @param clst Cluster which to get. |
* |
* @return Value found in the cluster. |
*/ |
fat_cluster_t |
fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst) |
{ |
block_t *b; |
uint16_t bps; |
uint16_t rscnt; |
fat_cluster_t *cp, value; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps, |
BLOCK_FLAGS_NONE); |
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); |
value = uint16_t_le2host(*cp); |
block_put(b); |
return value; |
} |
/** Set cluster in one instance of FAT. |
* |
* @param bs Buffer holding the boot sector for the file system. |
* @param dev_handle Device handle for the file system. |
* @param fatno Number of the FAT instance where to make the change. |
* @param clst Cluster which is to be set. |
* @param value Value to set the cluster with. |
*/ |
void |
fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno, |
fat_cluster_t clst, fat_cluster_t value) |
{ |
block_t *b; |
uint16_t bps; |
uint16_t rscnt; |
uint16_t sf; |
fat_cluster_t *cp; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
sf = uint16_t_le2host(bs->sec_per_fat); |
assert(fatno < bs->fatcnt); |
b = block_get(dev_handle, rscnt + sf * fatno + |
(clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); |
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); |
*cp = host2uint16_t_le(value); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
} |
/** Replay the allocatoin of clusters in all shadow instances of FAT. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param lifo Chain of allocated clusters. |
* @param nclsts Number of clusters in the lifo chain. |
*/ |
void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle, |
fat_cluster_t *lifo, unsigned nclsts) |
{ |
uint8_t fatno; |
unsigned c; |
for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { |
for (c = 0; c < nclsts; c++) { |
fat_set_cluster(bs, dev_handle, fatno, lifo[c], |
c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); |
} |
} |
} |
/** Allocate clusters in all copies of FAT. |
* |
* This function will attempt to allocate the requested number of clusters in |
* all instances of the FAT. The FAT will be altered so that the allocated |
* clusters form an independent chain (i.e. a chain which does not belong to any |
* file yet). |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param nclsts Number of clusters to allocate. |
* @param mcl Output parameter where the first cluster in the chain |
* will be returned. |
* @param lcl Output parameter where the last cluster in the chain |
* will be returned. |
* |
* @return EOK on success, a negative error code otherwise. |
*/ |
int |
fat_alloc_clusters(fat_bs_t *bs, dev_handle_t dev_handle, unsigned nclsts, |
fat_cluster_t *mcl, fat_cluster_t *lcl) |
{ |
uint16_t bps; |
uint16_t rscnt; |
uint16_t sf; |
block_t *blk; |
fat_cluster_t *lifo; /* stack for storing free cluster numbers */ |
unsigned found = 0; /* top of the free cluster number stack */ |
unsigned b, c, cl; |
lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); |
if (!lifo) |
return ENOMEM; |
bps = uint16_t_le2host(bs->bps); |
rscnt = uint16_t_le2host(bs->rscnt); |
sf = uint16_t_le2host(bs->sec_per_fat); |
/* |
* Search FAT1 for unused clusters. |
*/ |
futex_down(&fat_alloc_lock); |
for (b = 0, cl = 0; b < sf; b++) { |
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE); |
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { |
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; |
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { |
/* |
* The cluster is free. Put it into our stack |
* of found clusters and mark it as non-free. |
*/ |
lifo[found] = cl; |
*clst = (found == 0) ? |
host2uint16_t_le(FAT_CLST_LAST1) : |
host2uint16_t_le(lifo[found - 1]); |
blk->dirty = true; /* need to sync block */ |
if (++found == nclsts) { |
/* we are almost done */ |
block_put(blk); |
/* update the shadow copies of FAT */ |
fat_alloc_shadow_clusters(bs, |
dev_handle, lifo, nclsts); |
*mcl = lifo[found - 1]; |
*lcl = lifo[0]; |
free(lifo); |
futex_up(&fat_alloc_lock); |
return EOK; |
} |
} |
} |
block_put(blk); |
} |
futex_up(&fat_alloc_lock); |
/* |
* We could not find enough clusters. Now we need to free the clusters |
* we have allocated so far. |
*/ |
while (found--) { |
fat_set_cluster(bs, dev_handle, FAT1, lifo[found], |
FAT_CLST_RES0); |
} |
free(lifo); |
return ENOSPC; |
} |
/** Free clusters forming a cluster chain in all copies of FAT. |
* |
* @param bs Buffer hodling the boot sector of the file system. |
* @param dev_handle Device handle of the file system. |
* @param firstc First cluster in the chain which is to be freed. |
*/ |
void |
fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc) |
{ |
unsigned fatno; |
fat_cluster_t nextc; |
/* Mark all clusters in the chain as free in all copies of FAT. */ |
while (firstc < FAT_CLST_LAST1) { |
assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); |
nextc = fat_get_cluster(bs, dev_handle, firstc); |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, dev_handle, fatno, firstc, |
FAT_CLST_RES0); |
firstc = nextc; |
} |
} |
/** Append a cluster chain to the last file cluster in all FATs. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param nodep Node representing the file. |
* @param mcl First cluster of the cluster chain to append. |
*/ |
void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) |
{ |
dev_handle_t dev_handle = nodep->idx->dev_handle; |
fat_cluster_t lcl; |
uint8_t fatno; |
if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, |
(uint16_t) -1) == 0) { |
/* No clusters allocated to the node yet. */ |
nodep->firstc = mcl; |
nodep->dirty = true; /* need to sync node */ |
return; |
} |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl); |
} |
/** Chop off node clusters in all copies of FAT. |
* |
* @param bs Buffer holding the boot sector of the file system. |
* @param nodep FAT node where the chopping will take place. |
* @param lastc Last cluster which will remain in the node. If this |
* argument is FAT_CLST_RES0, then all clusters will |
* be chopped off. |
*/ |
void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) |
{ |
dev_handle_t dev_handle = nodep->idx->dev_handle; |
if (lastc == FAT_CLST_RES0) { |
/* The node will have zero size and no clusters allocated. */ |
fat_free_clusters(bs, dev_handle, nodep->firstc); |
nodep->firstc = FAT_CLST_RES0; |
nodep->dirty = true; /* need to sync node */ |
} else { |
fat_cluster_t nextc; |
unsigned fatno; |
nextc = fat_get_cluster(bs, dev_handle, lastc); |
/* Terminate the cluster chain in all copies of FAT. */ |
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) |
fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1); |
/* Free all following clusters. */ |
fat_free_clusters(bs, dev_handle, nextc); |
} |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/fat_fat.h |
---|
0,0 → 1,91 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef FAT_FAT_FAT_H_ |
#define FAT_FAT_FAT_H_ |
#include "../../vfs/vfs.h" |
#include <stdint.h> |
#include <libblock.h> |
#define FAT1 0 |
#define FAT_CLST_RES0 0x0000 |
#define FAT_CLST_RES1 0x0001 |
#define FAT_CLST_FIRST 0x0002 |
#define FAT_CLST_BAD 0xfff7 |
#define FAT_CLST_LAST1 0xfff8 |
#define FAT_CLST_LAST8 0xffff |
/* internally used to mark root directory's parent */ |
#define FAT_CLST_ROOTPAR FAT_CLST_RES0 |
/* internally used to mark root directory */ |
#define FAT_CLST_ROOT FAT_CLST_RES1 |
/* forward declarations */ |
struct block; |
struct fat_node; |
struct fat_bs; |
typedef uint16_t fat_cluster_t; |
#define fat_clusters_get(bs, dh, fc) \ |
fat_cluster_walk((bs), (dh), (fc), NULL, (uint16_t) -1) |
extern uint16_t fat_cluster_walk(struct fat_bs *, dev_handle_t, fat_cluster_t, |
fat_cluster_t *, uint16_t); |
#define fat_block_get(bs, np, bn, flags) \ |
_fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (bn), (flags)) |
extern struct block *_fat_block_get(struct fat_bs *, dev_handle_t, |
fat_cluster_t, bn_t, int); |
extern void fat_append_clusters(struct fat_bs *, struct fat_node *, |
fat_cluster_t); |
extern void fat_chop_clusters(struct fat_bs *, struct fat_node *, |
fat_cluster_t); |
extern int fat_alloc_clusters(struct fat_bs *, dev_handle_t, unsigned, |
fat_cluster_t *, fat_cluster_t *); |
extern void fat_free_clusters(struct fat_bs *, dev_handle_t, fat_cluster_t); |
extern void fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t, |
fat_cluster_t *, unsigned); |
extern fat_cluster_t fat_get_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t); |
extern void fat_set_cluster(struct fat_bs *, dev_handle_t, unsigned, |
fat_cluster_t, fat_cluster_t); |
extern void fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t, |
off_t); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/fat.c |
---|
49,14 → 49,6 |
vfs_info_t fat_vfs_info = { |
.name = "fat", |
.ops = { |
[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED, |
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_NULL, |
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL, |
} |
}; |
fs_reg_t fat_reg; |
97,9 → 89,27 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
fat_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
fat_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
fat_read(callid, &call); |
break; |
case VFS_WRITE: |
fat_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
fat_truncate(callid, &call); |
break; |
case VFS_DESTROY: |
fat_destroy(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
110,20 → 120,24 |
int main(int argc, char **argv) |
{ |
int vfs_phone; |
int rc; |
printf("FAT: HelenOS FAT file system server.\n"); |
printf("fat: HelenOS FAT file system server.\n"); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
while (vfs_phone < EOK) { |
usleep(10000); |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
rc = fat_idx_init(); |
if (rc != EOK) |
goto err; |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf("fat: failed to connect to VFS\n"); |
return -1; |
} |
int rc; |
rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection); |
if (rc != EOK) { |
printf("Failed to register the FAT file system (%d)\n", rc); |
return rc; |
fat_idx_fini(); |
goto err; |
} |
dprintf("FAT filesystem registered, fs_handle=%d.\n", |
132,6 → 146,10 |
async_manager(); |
/* not reached */ |
return 0; |
err: |
printf("Failed to register the FAT file system (%d)\n", rc); |
return rc; |
} |
/** |
/branches/dd/uspace/srv/fs/fat/fat_ops.c |
---|
36,9 → 36,14 |
*/ |
#include "fat.h" |
#include "fat_dentry.h" |
#include "fat_fat.h" |
#include "../../vfs/vfs.h" |
#include <libfs.h> |
#include <libblock.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <async.h> |
#include <errno.h> |
#include <string.h> |
47,9 → 52,9 |
#include <libadt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <sys/mman.h> |
#include <align.h> |
#define BS_BLOCK 0 |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
56,130 → 61,6 |
/** List of cached free FAT nodes. */ |
static LIST_INITIALIZE(ffn_head); |
#define FAT_NAME_LEN 8 |
#define FAT_EXT_LEN 3 |
#define FAT_PAD ' ' |
#define FAT_DENTRY_UNUSED 0x00 |
#define FAT_DENTRY_E5_ESC 0x05 |
#define FAT_DENTRY_DOT 0x2e |
#define FAT_DENTRY_ERASED 0xe5 |
static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
{ |
int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) { |
buf++; |
break; |
} |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->name[i]; |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->ext[i]; |
} |
} |
/* TODO move somewhere else */ |
typedef struct { |
void *data; |
} block_t; |
static block_t *block_get(dev_handle_t dev_handle, off_t offset) |
{ |
return NULL; /* TODO */ |
} |
static void block_put(block_t *block) |
{ |
/* TODO */ |
} |
#define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
#define FAT_CLST_RES0 0x0000 |
#define FAT_CLST_RES1 0x0001 /* internally used to mark root directory */ |
#define FAT_CLST_FIRST 0x0002 |
#define FAT_CLST_BAD 0xfff7 |
#define FAT_CLST_LAST1 0xfff8 |
#define FAT_CLST_LAST8 0xffff |
#define fat_block_get(np, off) \ |
_fat_block_get((np)->idx->dev_handle, (np)->firstc, (off)) |
static block_t * |
_fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset) |
{ |
block_t *bb; |
block_t *b; |
unsigned bps; |
unsigned spc; |
unsigned rscnt; /* block address of the first FAT */ |
unsigned fatcnt; |
unsigned rde; |
unsigned rds; /* root directory size */ |
unsigned sf; |
unsigned ssa; /* size of the system area */ |
unsigned clusters; |
fat_cluster_t clst = firstc; |
unsigned i; |
bb = block_get(dev_handle, BS_BLOCK); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
spc = FAT_BS(bb)->spc; |
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
fatcnt = FAT_BS(bb)->fatcnt; |
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); |
block_put(bb); |
rds = (sizeof(fat_dentry_t) * rde) / bps; |
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
ssa = rscnt + fatcnt * sf + rds; |
if (firstc == FAT_CLST_RES1) { |
/* root directory special case */ |
assert(offset < rds); |
b = block_get(dev_handle, rscnt + fatcnt * sf + offset); |
return b; |
} |
clusters = offset / spc; |
for (i = 0; i < clusters; i++) { |
unsigned fsec; /* sector offset relative to FAT1 */ |
unsigned fidx; /* FAT1 entry index */ |
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); |
fsec = (clst * sizeof(fat_cluster_t)) / bps; |
fidx = clst % (bps / sizeof(fat_cluster_t)); |
/* read FAT1 */ |
b = block_get(dev_handle, rscnt + fsec); |
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
assert(clst != FAT_CLST_BAD); |
assert(clst < FAT_CLST_LAST1); |
block_put(b); |
} |
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + |
offset % spc); |
return b; |
} |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
192,84 → 73,43 |
node->dirty = false; |
} |
static uint16_t fat_bps_get(dev_handle_t dev_handle) |
static void fat_node_sync(fat_node_t *node) |
{ |
block_t *bb; |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
uint16_t bps; |
unsigned dps; |
bb = block_get(dev_handle, BS_BLOCK); |
assert(bb != NULL); |
bps = uint16_t_le2host(FAT_BS(bb)->bps); |
block_put(bb); |
assert(node->dirty); |
return bps; |
} |
bs = block_bb_get(node->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc, |
(node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); |
typedef enum { |
FAT_DENTRY_SKIP, |
FAT_DENTRY_LAST, |
FAT_DENTRY_VALID |
} fat_dentry_clsf_t; |
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); |
static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d) |
{ |
if (d->attr & FAT_ATTR_VOLLABEL) { |
/* volume label entry */ |
return FAT_DENTRY_SKIP; |
d->firstc = host2uint16_t_le(node->firstc); |
if (node->type == FAT_FILE) { |
d->size = host2uint32_t_le(node->size); |
} else if (node->type == FAT_DIRECTORY) { |
d->attr = FAT_ATTR_SUBDIR; |
} |
if (d->name[0] == FAT_DENTRY_ERASED) { |
/* not-currently-used entry */ |
return FAT_DENTRY_SKIP; |
} |
if (d->name[0] == FAT_DENTRY_UNUSED) { |
/* never used entry */ |
return FAT_DENTRY_LAST; |
} |
if (d->name[0] == FAT_DENTRY_DOT) { |
/* |
* Most likely '.' or '..'. |
* It cannot occur in a regular file name. |
*/ |
return FAT_DENTRY_SKIP; |
} |
return FAT_DENTRY_VALID; |
/* TODO: update other fields? (e.g time fields) */ |
b->dirty = true; /* need to sync block */ |
block_put(b); |
} |
static void fat_node_sync(fat_node_t *node) |
static fat_node_t *fat_node_get_new(void) |
{ |
/* TODO */ |
} |
/** Internal version of fat_node_get(). |
* |
* @param idxp Locked index structure. |
*/ |
static void *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_dentry_t *d; |
fat_node_t *nodep; |
unsigned bps; |
unsigned dps; |
if (idxp->nodep) { |
/* |
* We are lucky. |
* The node is already instantiated in memory. |
*/ |
futex_down(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
return idxp->nodep; |
} |
/* |
* We must instantiate the node from the file system. |
*/ |
assert(idxp->pfc); |
futex_down(&ffn_futex); |
if (!list_empty(&ffn_head)) { |
/* Try to use a cached free node structure. */ |
298,13 → 138,54 |
return NULL; |
} |
fat_node_initialize(nodep); |
return nodep; |
} |
bps = fat_bps_get(idxp->dev_handle); |
/** Internal version of fat_node_get(). |
* |
* @param idxp Locked index structure. |
*/ |
static void *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_bs_t *bs; |
fat_dentry_t *d; |
fat_node_t *nodep = NULL; |
unsigned bps; |
unsigned spc; |
unsigned dps; |
if (idxp->nodep) { |
/* |
* We are lucky. |
* The node is already instantiated in memory. |
*/ |
futex_down(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&idxp->nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
return idxp->nodep; |
} |
/* |
* We must instantiate the node from the file system. |
*/ |
assert(idxp->pfc); |
nodep = fat_node_get_new(); |
if (!nodep) |
return NULL; |
bs = block_bb_get(idxp->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
dps = bps / sizeof(fat_dentry_t); |
/* Read the block that contains the dentry of interest. */ |
b = _fat_block_get(idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps); |
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc, |
(idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); |
assert(b); |
d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); |
315,11 → 196,18 |
* and initialized elsewhere. |
*/ |
nodep->type = FAT_DIRECTORY; |
/* |
* Unfortunately, the 'size' field of the FAT dentry is not |
* defined for the directory entry type. We must determine the |
* size of the directory by walking the FAT. |
*/ |
nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle, |
uint16_t_le2host(d->firstc)); |
} else { |
nodep->type = FAT_FILE; |
nodep->size = uint32_t_le2host(d->size); |
} |
nodep->firstc = uint16_t_le2host(d->firstc); |
nodep->size = uint32_t_le2host(d->size); |
nodep->lnkcnt = 1; |
nodep->refcnt = 1; |
332,8 → 220,31 |
return nodep; |
} |
/* |
* Forward declarations of FAT libfs operations. |
*/ |
static void *fat_node_get(dev_handle_t, fs_index_t); |
static void fat_node_put(void *); |
static void *fat_create_node(dev_handle_t, int); |
static int fat_destroy_node(void *); |
static int fat_link(void *, void *, const char *); |
static int fat_unlink(void *, void *); |
static void *fat_match(void *, const char *); |
static fs_index_t fat_index_get(void *); |
static size_t fat_size_get(void *); |
static unsigned fat_lnkcnt_get(void *); |
static bool fat_has_children(void *); |
static void *fat_root_get(dev_handle_t); |
static char fat_plb_get_char(unsigned); |
static bool fat_is_directory(void *); |
static bool fat_is_file(void *node); |
/* |
* FAT libfs operations. |
*/ |
/** Instantiate a FAT in-core node. */ |
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
void *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
void *node; |
fat_idx_t *idxp; |
347,41 → 258,318 |
return node; |
} |
static void fat_node_put(void *node) |
void fat_node_put(void *node) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
bool destroy = false; |
futex_down(&nodep->lock); |
if (!--nodep->refcnt) { |
futex_down(&ffn_futex); |
list_append(&nodep->ffn_link, &ffn_head); |
futex_up(&ffn_futex); |
if (nodep->idx) { |
futex_down(&ffn_futex); |
list_append(&nodep->ffn_link, &ffn_head); |
futex_up(&ffn_futex); |
} else { |
/* |
* The node does not have any index structure associated |
* with itself. This can only mean that we are releasing |
* the node after a failed attempt to allocate the index |
* structure for it. |
*/ |
destroy = true; |
} |
} |
futex_up(&nodep->lock); |
if (destroy) |
free(node); |
} |
static void *fat_create(int flags) |
void *fat_create_node(dev_handle_t dev_handle, int flags) |
{ |
return NULL; /* not supported at the moment */ |
fat_idx_t *idxp; |
fat_node_t *nodep; |
fat_bs_t *bs; |
fat_cluster_t mcl, lcl; |
uint16_t bps; |
int rc; |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
if (flags & L_DIRECTORY) { |
/* allocate a cluster */ |
rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); |
if (rc != EOK) |
return NULL; |
} |
nodep = fat_node_get_new(); |
if (!nodep) { |
fat_free_clusters(bs, dev_handle, mcl); |
return NULL; |
} |
idxp = fat_idx_get_new(dev_handle); |
if (!idxp) { |
fat_free_clusters(bs, dev_handle, mcl); |
fat_node_put(nodep); |
return NULL; |
} |
/* idxp->lock held */ |
if (flags & L_DIRECTORY) { |
int i; |
block_t *b; |
/* |
* Populate the new cluster with unused dentries. |
*/ |
for (i = 0; i < bs->spc; i++) { |
b = _fat_block_get(bs, dev_handle, mcl, i, |
BLOCK_FLAGS_NOREAD); |
/* mark all dentries as never-used */ |
memset(b->data, 0, bps); |
b->dirty = false; |
block_put(b); |
} |
nodep->type = FAT_DIRECTORY; |
nodep->firstc = mcl; |
nodep->size = bps * bs->spc; |
} else { |
nodep->type = FAT_FILE; |
nodep->firstc = FAT_CLST_RES0; |
nodep->size = 0; |
} |
nodep->lnkcnt = 0; /* not linked anywhere */ |
nodep->refcnt = 1; |
nodep->dirty = true; |
nodep->idx = idxp; |
idxp->nodep = nodep; |
futex_up(&idxp->lock); |
return nodep; |
} |
static int fat_destroy(void *node) |
int fat_destroy_node(void *node) |
{ |
return ENOTSUP; /* not supported at the moment */ |
fat_node_t *nodep = (fat_node_t *)node; |
fat_bs_t *bs; |
/* |
* The node is not reachable from the file system. This means that the |
* link count should be zero and that the index structure cannot be |
* found in the position hash. Obviously, we don't need to lock the node |
* nor its index structure. |
*/ |
assert(nodep->lnkcnt == 0); |
/* |
* The node may not have any children. |
*/ |
assert(fat_has_children(node) == false); |
bs = block_bb_get(nodep->idx->dev_handle); |
if (nodep->firstc != FAT_CLST_RES0) { |
assert(nodep->size); |
/* Free all clusters allocated to the node. */ |
fat_free_clusters(bs, nodep->idx->dev_handle, nodep->firstc); |
} |
fat_idx_destroy(nodep->idx); |
free(nodep); |
return EOK; |
} |
static bool fat_link(void *prnt, void *chld, const char *name) |
int fat_link(void *prnt, void *chld, const char *name) |
{ |
return false; /* not supported at the moment */ |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_node_t *childp = (fat_node_t *)chld; |
fat_dentry_t *d; |
fat_bs_t *bs; |
block_t *b; |
int i, j; |
uint16_t bps; |
unsigned dps; |
unsigned blocks; |
fat_cluster_t mcl, lcl; |
int rc; |
futex_down(&childp->lock); |
if (childp->lnkcnt == 1) { |
/* |
* On FAT, we don't support multiple hard links. |
*/ |
futex_up(&childp->lock); |
return EMLINK; |
} |
assert(childp->lnkcnt == 0); |
futex_up(&childp->lock); |
if (!fat_dentry_name_verify(name)) { |
/* |
* Attempt to create unsupported name. |
*/ |
return ENOTSUP; |
} |
/* |
* Get us an unused parent node's dentry or grow the parent and allocate |
* a new one. |
*/ |
futex_down(&parentp->idx->lock); |
bs = block_bb_get(parentp->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
blocks = parentp->size / bps; |
for (i = 0; i < blocks; i++) { |
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); |
for (j = 0; j < dps; j++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
case FAT_DENTRY_VALID: |
/* skipping used and meta entries */ |
continue; |
case FAT_DENTRY_FREE: |
case FAT_DENTRY_LAST: |
/* found an empty slot */ |
goto hit; |
} |
} |
block_put(b); |
} |
j = 0; |
/* |
* We need to grow the parent in order to create a new unused dentry. |
*/ |
if (parentp->idx->pfc == FAT_CLST_ROOT) { |
/* Can't grow the root directory. */ |
futex_up(&parentp->idx->lock); |
return ENOSPC; |
} |
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); |
if (rc != EOK) { |
futex_up(&parentp->idx->lock); |
return rc; |
} |
fat_append_clusters(bs, parentp, mcl); |
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NOREAD); |
d = (fat_dentry_t *)b->data; |
/* |
* Clear all dentries in the block except for the first one (the first |
* dentry will be cleared in the next step). |
*/ |
memset(d + 1, 0, bps - sizeof(fat_dentry_t)); |
hit: |
/* |
* At this point we only establish the link between the parent and the |
* child. The dentry, except of the name and the extension, will remain |
* uninitialized until the corresponding node is synced. Thus the valid |
* dentry data is kept in the child node structure. |
*/ |
memset(d, 0, sizeof(fat_dentry_t)); |
fat_dentry_name_set(d, name); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
futex_up(&parentp->idx->lock); |
futex_down(&childp->idx->lock); |
/* |
* If possible, create the Sub-directory Identifier Entry and the |
* Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries |
* are not mandatory according to Standard ECMA-107 and HelenOS VFS does |
* not use them anyway, so this is rather a sign of our good will. |
*/ |
b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE); |
d = (fat_dentry_t *)b->data; |
if (fat_classify_dentry(d) == FAT_DENTRY_LAST || |
strcmp(d->name, FAT_NAME_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
strcpy(d->name, FAT_NAME_DOT); |
strcpy(d->ext, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = host2uint16_t_le(childp->firstc); |
/* TODO: initialize also the date/time members. */ |
} |
d++; |
if (fat_classify_dentry(d) == FAT_DENTRY_LAST || |
strcmp(d->name, FAT_NAME_DOT_DOT) == 0) { |
memset(d, 0, sizeof(fat_dentry_t)); |
strcpy(d->name, FAT_NAME_DOT_DOT); |
strcpy(d->ext, FAT_EXT_PAD); |
d->attr = FAT_ATTR_SUBDIR; |
d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? |
host2uint16_t_le(FAT_CLST_RES0) : |
host2uint16_t_le(parentp->firstc); |
/* TODO: initialize also the date/time members. */ |
} |
b->dirty = true; /* need to sync block */ |
block_put(b); |
childp->idx->pfc = parentp->firstc; |
childp->idx->pdi = i * dps + j; |
futex_up(&childp->idx->lock); |
futex_down(&childp->lock); |
childp->lnkcnt = 1; |
childp->dirty = true; /* need to sync node */ |
futex_up(&childp->lock); |
/* |
* Hash in the index structure into the position hash. |
*/ |
fat_idx_hashin(childp->idx); |
return EOK; |
} |
static int fat_unlink(void *prnt, void *chld) |
int fat_unlink(void *prnt, void *chld) |
{ |
return ENOTSUP; /* not supported at the moment */ |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_node_t *childp = (fat_node_t *)chld; |
fat_bs_t *bs; |
fat_dentry_t *d; |
uint16_t bps; |
block_t *b; |
futex_down(&parentp->lock); |
futex_down(&childp->lock); |
assert(childp->lnkcnt == 1); |
futex_down(&childp->idx->lock); |
bs = block_bb_get(childp->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
b = _fat_block_get(bs, childp->idx->dev_handle, childp->idx->pfc, |
(childp->idx->pdi * sizeof(fat_dentry_t)) / bps, |
BLOCK_FLAGS_NONE); |
d = (fat_dentry_t *)b->data + |
(childp->idx->pdi % (bps / sizeof(fat_dentry_t))); |
/* mark the dentry as not-currently-used */ |
d->name[0] = FAT_DENTRY_ERASED; |
b->dirty = true; /* need to sync block */ |
block_put(b); |
/* remove the index structure from the position hash */ |
fat_idx_hashout(childp->idx); |
/* clear position information */ |
childp->idx->pfc = FAT_CLST_RES0; |
childp->idx->pdi = 0; |
futex_up(&childp->idx->lock); |
childp->lnkcnt = 0; |
childp->dirty = true; |
futex_up(&childp->lock); |
futex_up(&parentp->lock); |
return EOK; |
} |
static void *fat_match(void *prnt, const char *component) |
void *fat_match(void *prnt, const char *component) |
{ |
fat_bs_t *bs; |
fat_node_t *parentp = (fat_node_t *)prnt; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
unsigned i, j; |
392,20 → 580,17 |
block_t *b; |
futex_down(&parentp->idx->lock); |
bps = fat_bps_get(parentp->idx->dev_handle); |
bs = block_bb_get(parentp->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
blocks = parentp->size / bps + (parentp->size % bps != 0); |
blocks = parentp->size / bps; |
for (i = 0; i < blocks; i++) { |
unsigned dentries; |
b = fat_block_get(parentp, i); |
dentries = (i == blocks - 1) ? |
parentp->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); |
for (j = 0; j < dps; j++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
case FAT_DENTRY_FREE: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
413,10 → 598,10 |
return NULL; |
default: |
case FAT_DENTRY_VALID: |
dentry_name_canonify(d, name); |
fat_dentry_name_get(d, name); |
break; |
} |
if (strcmp(name, component) == 0) { |
if (fat_dentry_namecmp(name, component) == 0) { |
/* hit */ |
void *node; |
/* |
445,11 → 630,12 |
} |
block_put(b); |
} |
futex_up(&parentp->idx->lock); |
return NULL; |
} |
static fs_index_t fat_index_get(void *node) |
fs_index_t fat_index_get(void *node) |
{ |
fat_node_t *fnodep = (fat_node_t *)node; |
if (!fnodep) |
457,18 → 643,19 |
return fnodep->idx->index; |
} |
static size_t fat_size_get(void *node) |
size_t fat_size_get(void *node) |
{ |
return ((fat_node_t *)node)->size; |
} |
static unsigned fat_lnkcnt_get(void *node) |
unsigned fat_lnkcnt_get(void *node) |
{ |
return ((fat_node_t *)node)->lnkcnt; |
} |
static bool fat_has_children(void *node) |
bool fat_has_children(void *node) |
{ |
fat_bs_t *bs; |
fat_node_t *nodep = (fat_node_t *)node; |
unsigned bps; |
unsigned dps; |
478,25 → 665,23 |
if (nodep->type != FAT_DIRECTORY) |
return false; |
futex_down(&nodep->idx->lock); |
bps = fat_bps_get(nodep->idx->dev_handle); |
bs = block_bb_get(nodep->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
dps = bps / sizeof(fat_dentry_t); |
blocks = nodep->size / bps + (nodep->size % bps != 0); |
blocks = nodep->size / bps; |
for (i = 0; i < blocks; i++) { |
unsigned dentries; |
fat_dentry_t *d; |
b = fat_block_get(nodep, i); |
dentries = (i == blocks - 1) ? |
nodep->size % sizeof(fat_dentry_t) : |
dps; |
for (j = 0; j < dentries; j++) { |
b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE); |
for (j = 0; j < dps; j++) { |
d = ((fat_dentry_t *)b->data) + j; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
case FAT_DENTRY_FREE: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
519,22 → 704,22 |
return false; |
} |
static void *fat_root_get(dev_handle_t dev_handle) |
void *fat_root_get(dev_handle_t dev_handle) |
{ |
return NULL; /* TODO */ |
return fat_node_get(dev_handle, 0); |
} |
static char fat_plb_get_char(unsigned pos) |
char fat_plb_get_char(unsigned pos) |
{ |
return fat_reg.plb_ro[pos % PLB_SIZE]; |
} |
static bool fat_is_directory(void *node) |
bool fat_is_directory(void *node) |
{ |
return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
} |
static bool fat_is_file(void *node) |
bool fat_is_file(void *node) |
{ |
return ((fat_node_t *)node)->type == FAT_FILE; |
} |
544,8 → 729,8 |
.match = fat_match, |
.node_get = fat_node_get, |
.node_put = fat_node_put, |
.create = fat_create, |
.destroy = fat_destroy, |
.create = fat_create_node, |
.destroy = fat_destroy_node, |
.link = fat_link, |
.unlink = fat_unlink, |
.index_get = fat_index_get, |
558,11 → 743,388 |
.is_file = fat_is_file |
}; |
/* |
* VFS operations. |
*/ |
void fat_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fat_bs_t *bs; |
uint16_t bps; |
uint16_t rde; |
int rc; |
/* initialize libblock */ |
rc = block_init(dev_handle, BS_SIZE); |
if (rc != EOK) { |
ipc_answer_0(rid, rc); |
return; |
} |
/* prepare the boot block */ |
rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
/* get the buffer with the boot sector */ |
bs = block_bb_get(dev_handle); |
/* Read the number of root directory entries. */ |
bps = uint16_t_le2host(bs->bps); |
rde = uint16_t_le2host(bs->root_ent_max); |
if (bps != BS_SIZE) { |
block_fini(dev_handle); |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* Initialize the block cache */ |
rc = block_cache_init(dev_handle, bps, 0 /* XXX */); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
rc = fat_idx_init_by_dev_handle(dev_handle); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
return; |
} |
/* Initialize the root node. */ |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fat_node_initialize(rootp); |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
block_fini(dev_handle); |
free(rootp); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
assert(ridxp->index == 0); |
/* ridxp->lock held */ |
rootp->type = FAT_DIRECTORY; |
rootp->firstc = FAT_CLST_ROOT; |
rootp->refcnt = 1; |
rootp->lnkcnt = 0; /* FS root is not linked */ |
rootp->size = rde * sizeof(fat_dentry_t); |
rootp->idx = ridxp; |
ridxp->nodep = rootp; |
futex_up(&ridxp->lock); |
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); |
} |
void fat_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
uint16_t bps; |
size_t bytes; |
block_t *b; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
fat_node_put(nodep); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
if (nodep->type == FAT_FILE) { |
/* |
* Our strategy for regular file reads is to read one block at |
* most and make use of the possibility to return less data than |
* requested. This keeps the code very simple. |
*/ |
if (pos >= nodep->size) { |
/* reading beyond the EOF */ |
bytes = 0; |
(void) ipc_data_read_finalize(callid, NULL, 0); |
} else { |
bytes = min(len, bps - pos % bps); |
bytes = min(bytes, nodep->size - pos); |
b = fat_block_get(bs, nodep, pos / bps, |
BLOCK_FLAGS_NONE); |
(void) ipc_data_read_finalize(callid, b->data + pos % bps, |
bytes); |
block_put(b); |
} |
} else { |
unsigned bnum; |
off_t spos = pos; |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
fat_dentry_t *d; |
assert(nodep->type == FAT_DIRECTORY); |
assert(nodep->size % bps == 0); |
assert(bps % sizeof(fat_dentry_t) == 0); |
/* |
* Our strategy for readdir() is to use the position pointer as |
* an index into the array of all dentries. On entry, it points |
* to the first unread dentry. If we skip any dentries, we bump |
* the position pointer accordingly. |
*/ |
bnum = (pos * sizeof(fat_dentry_t)) / bps; |
while (bnum < nodep->size / bps) { |
off_t o; |
b = fat_block_get(bs, nodep, bnum, BLOCK_FLAGS_NONE); |
for (o = pos % (bps / sizeof(fat_dentry_t)); |
o < bps / sizeof(fat_dentry_t); |
o++, pos++) { |
d = ((fat_dentry_t *)b->data) + o; |
switch (fat_classify_dentry(d)) { |
case FAT_DENTRY_SKIP: |
case FAT_DENTRY_FREE: |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
goto miss; |
default: |
case FAT_DENTRY_VALID: |
fat_dentry_name_get(d, name); |
block_put(b); |
goto hit; |
} |
} |
block_put(b); |
bnum++; |
} |
miss: |
fat_node_put(nodep); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
hit: |
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
bytes = (pos - spos) + 1; |
} |
fat_node_put(nodep); |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
void fat_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
size_t bytes; |
block_t *b; |
uint16_t bps; |
unsigned spc; |
unsigned bpc; /* bytes per cluster */ |
off_t boundary; |
int flags = BLOCK_FLAGS_NONE; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
fat_node_put(nodep); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
/* |
* In all scenarios, we will attempt to write out only one block worth |
* of data at maximum. There might be some more efficient approaches, |
* but this one greatly simplifies fat_write(). Note that we can afford |
* to do this because the client must be ready to handle the return |
* value signalizing a smaller number of bytes written. |
*/ |
bytes = min(len, bps - pos % bps); |
if (bytes == bps) |
flags |= BLOCK_FLAGS_NOREAD; |
boundary = ROUND_UP(nodep->size, bpc); |
if (pos < boundary) { |
/* |
* This is the easier case - we are either overwriting already |
* existing contents or writing behind the EOF, but still within |
* the limits of the last cluster. The node size may grow to the |
* next block size boundary. |
*/ |
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); |
b = fat_block_get(bs, nodep, pos / bps, flags); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
if (pos + bytes > nodep->size) { |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
} |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
return; |
} else { |
/* |
* This is the more difficult case. We must allocate new |
* clusters for the node and zero them out. |
*/ |
int status; |
unsigned nclsts; |
fat_cluster_t mcl, lcl; |
nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; |
/* create an independent chain of nclsts clusters in all FATs */ |
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); |
if (status != EOK) { |
/* could not allocate a chain of nclsts clusters */ |
fat_node_put(nodep); |
ipc_answer_0(callid, status); |
ipc_answer_0(rid, status); |
return; |
} |
/* zero fill any gaps */ |
fat_fill_gap(bs, nodep, mcl, pos); |
b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc, |
flags); |
(void) ipc_data_write_finalize(callid, b->data + pos % bps, |
bytes); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
/* |
* Append the cluster chain starting in mcl to the end of the |
* node's cluster chain. |
*/ |
fat_append_clusters(bs, nodep, mcl); |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
return; |
} |
} |
void fat_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
size_t size = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fat_bs_t *bs; |
uint16_t bps; |
uint8_t spc; |
unsigned bpc; /* bytes per cluster */ |
int rc; |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
bpc = bps * spc; |
if (nodep->size == size) { |
rc = EOK; |
} else if (nodep->size < size) { |
/* |
* The standard says we have the freedom to grow the node. |
* For now, we simply return an error. |
*/ |
rc = EINVAL; |
} else if (ROUND_UP(nodep->size, bpc) == ROUND_UP(size, bpc)) { |
/* |
* The node will be shrunk, but no clusters will be deallocated. |
*/ |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} else { |
/* |
* The node will be shrunk, clusters will be deallocated. |
*/ |
if (size == 0) { |
fat_chop_clusters(bs, nodep, FAT_CLST_RES0); |
} else { |
fat_cluster_t lastc; |
(void) fat_cluster_walk(bs, dev_handle, nodep->firstc, |
&lastc, (size - 1) / bpc); |
fat_chop_clusters(bs, nodep, lastc); |
} |
nodep->size = size; |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} |
fat_node_put(nodep); |
ipc_answer_0(rid, rc); |
return; |
} |
void fat_destroy(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
int rc; |
fat_node_t *nodep = fat_node_get(dev_handle, index); |
if (!nodep) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
rc = fat_destroy_node(nodep); |
ipc_answer_0(rid, rc); |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/fat/Makefile |
---|
31,12 → 31,17 |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
LIBBLOCK_PREFIX = ../../../lib/libblock |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a $(LIBFS_PREFIX)/libfs.a |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBBLOCK_PREFIX)/libblock.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
45,28 → 50,32 |
SOURCES = \ |
fat.c \ |
fat_ops.c \ |
fat_idx.c |
fat_idx.c \ |
fat_dentry.c \ |
fat_fat.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/obio/obio.c |
---|
0,0 → 1,158 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup obio |
* @{ |
*/ |
/** |
* @file obio.c |
* @brief OBIO driver. |
* |
* OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P, |
* there is a piece of the root PCI bus controller address space, which |
* contains interrupt mapping and clear registers for all on-board devices. |
* Although UltraSPARC IIi and U2P are different in general, these registers can |
* be found at the same addresses. |
*/ |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/bus.h> |
#include <ipc/ns.h> |
#include <sysinfo.h> |
#include <as.h> |
#include <ddi.h> |
#include <align.h> |
#include <bool.h> |
#include <errno.h> |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#define NAME "obio" |
#define OBIO_SIZE 0x1898 |
#define OBIO_IMR_BASE 0x200 |
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK)) |
#define OBIO_CIR_BASE 0x300 |
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK)) |
#define INO_MASK 0x1f |
static void *base_phys; |
static volatile uint64_t *base_virt; |
/** Handle one connection to obio. |
* |
* @param iid Hash of the request that opened the connection. |
* @param icall Call data of the request that opened the connection. |
*/ |
static void obio_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* |
* Answer the first IPC_M_CONNECT_ME_TO call. |
*/ |
ipc_answer_0(iid, EOK); |
while (1) { |
int inr; |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case BUS_CLEAR_INTERRUPT: |
inr = IPC_GET_ARG1(call); |
base_virt[OBIO_CIR(inr) & INO_MASK] = 0; |
ipc_answer_0(callid, EOK); |
break; |
default: |
ipc_answer_0(callid, EINVAL); |
break; |
} |
} |
} |
/** Initialize the OBIO driver. |
* |
* So far, the driver heavily depends on information provided by the kernel via |
* sysinfo. In the future, there should be a standalone OBIO driver. |
*/ |
static bool obio_init(void) |
{ |
ipcarg_t phonead; |
base_phys = (void *) sysinfo_value("obio.base.physical"); |
if (!base_phys) { |
printf(NAME ": no OBIO registers found\n"); |
return false; |
} |
base_virt = as_get_mappable_page(OBIO_SIZE); |
int flags = AS_AREA_READ | AS_AREA_WRITE; |
int retval = physmem_map(base_phys, (void *) base_virt, |
ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags); |
if (retval < 0) { |
printf(NAME ": Error mapping OBIO registers\n"); |
return false; |
} |
printf(NAME ": OBIO registers with base at %p\n", base_phys); |
async_set_client_connection(obio_connection); |
ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead); |
return true; |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS OBIO driver\n"); |
if (!obio_init()) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
/** |
* @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/srv/obio/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = obio |
SOURCES = \ |
obio.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/srv/obio |
---|
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/srv/pci/update-ids |
---|
2,15 → 2,14 |
wget http://pciids.sourceforge.net/v2.2/pci.ids |
cat >pci_ids.h <<EOF |
cat > pci_ids.h <<EOF |
/* DO NOT EDIT, THIS FILE IS AUTOMATICALLY GENERATED */ |
char *pci_ids[] = { |
EOF |
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | sed -n 's/\(.*\)/"\1",/p' >>pci_ids.h |
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | sed -n 's/\(.*\)/"\1",/p' >> pci_ids.h |
cat >>pci_ids.h <<EOF |
cat >> pci_ids.h <<EOF |
"" |
}; |
EOF |
/branches/dd/uspace/srv/pci/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
52,7 → 53,7 |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
$(MAKE) -C libpci clean |
depend: |
60,7 → 61,7 |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(MAKE) -C libpci |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
/branches/dd/uspace/srv/devmap/devmap.h |
---|
File deleted |
/branches/dd/uspace/srv/devmap/Makefile |
---|
31,6 → 31,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
44,28 → 45,30 |
SOURCES = \ |
devmap.c |
CFLAGS += -D$(ARCH) |
CFLAGS += -D$(UARCH) |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/devmap/devmap.c |
---|
28,9 → 28,9 |
/** |
* @defgroup devmap Device mapper. |
* @brief HelenOS device mapper. |
* @brief HelenOS device mapper. |
* @{ |
*/ |
*/ |
/** @file |
*/ |
44,18 → 44,26 |
#include <futex.h> |
#include <stdlib.h> |
#include <string.h> |
#include <ipc/devmap.h> |
#include "devmap.h" |
#define NAME "devmap" |
/** Pending lookup structure. */ |
typedef struct { |
link_t link; |
char *name; /**< Device name */ |
ipc_callid_t callid; /**< Call ID waiting for the lookup */ |
} pending_req_t; |
LIST_INITIALIZE(devices_list); |
LIST_INITIALIZE(drivers_list); |
LIST_INITIALIZE(pending_req); |
/* order of locking: |
* drivers_list_futex |
* devices_list_futex |
* (devmap_driver_t *)->devices_futex |
* create_handle_futex |
/* Locking order: |
* drivers_list_futex |
* devices_list_futex |
* (devmap_driver_t *)->devices_futex |
* create_handle_futex |
**/ |
static atomic_t devices_list_futex = FUTEX_INITIALIZER; |
62,27 → 70,28 |
static atomic_t drivers_list_futex = FUTEX_INITIALIZER; |
static atomic_t create_handle_futex = FUTEX_INITIALIZER; |
static int devmap_create_handle(void) |
{ |
static int last_handle = 0; |
int handle; |
/* TODO: allow reusing old handles after their unregistration |
and implement some version of LRU algorithm */ |
* and implement some version of LRU algorithm |
*/ |
/* FIXME: overflow */ |
futex_down(&create_handle_futex); |
futex_down(&create_handle_futex); |
last_handle += 1; |
handle = last_handle; |
futex_up(&create_handle_futex); |
futex_up(&create_handle_futex); |
return handle; |
} |
/** Initialize device mapper. |
/** Initialize device mapper. |
* |
* |
*/ |
89,7 → 98,7 |
static int devmap_init() |
{ |
/* TODO: */ |
return EOK; |
} |
98,169 → 107,153 |
*/ |
static devmap_device_t *devmap_device_find_name(const char *name) |
{ |
link_t *item; |
link_t *item = devices_list.next; |
devmap_device_t *device = NULL; |
item = devices_list.next; |
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (0 == strcmp(device->name, name)) { |
if (0 == strcmp(device->name, name)) |
break; |
} |
item = item->next; |
} |
if (item == &devices_list) { |
printf("DEVMAP: no device named %s.\n", name); |
if (item == &devices_list) |
return NULL; |
} |
device = list_get_instance(item, devmap_device_t, devices); |
return device; |
} |
/** Find device with given handle. |
* |
* @todo: use hash table |
* |
*/ |
static devmap_device_t *devmap_device_find_handle(int handle) |
{ |
link_t *item; |
futex_down(&devices_list_futex); |
link_t *item = (&devices_list)->next; |
devmap_device_t *device = NULL; |
futex_down(&devices_list_futex); |
item = (&devices_list)->next; |
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (device->handle == handle) { |
if (device->handle == handle) |
break; |
} |
item = item->next; |
} |
if (item == &devices_list) { |
futex_up(&devices_list_futex); |
return NULL; |
} |
device = list_get_instance(item, devmap_device_t, devices); |
futex_up(&devices_list_futex); |
return device; |
} |
/** |
* |
* Unregister device and free it. It's assumed that driver's device list is |
* already locked. |
* |
*/ |
static int devmap_device_unregister_core(devmap_device_t *device) |
{ |
list_remove(&(device->devices)); |
list_remove(&(device->driver_devices)); |
free(device->name); |
free(device->name); |
free(device); |
return EOK; |
} |
/** |
* |
* Read info about new driver and add it into linked list of registered |
* drivers. |
* |
*/ |
static void devmap_driver_register(devmap_driver_t **odriver) |
{ |
size_t name_size; |
ipc_callid_t callid; |
ipc_call_t call; |
devmap_driver_t *driver; |
ipc_callid_t iid; |
ipc_call_t icall; |
*odriver = NULL; |
iid = async_get_call(&icall); |
ipc_call_t icall; |
ipc_callid_t iid = async_get_call(&icall); |
if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (NULL == |
(driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) { |
} |
devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t)); |
if (driver == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* |
/* |
* Get driver name |
*/ |
ipc_callid_t callid; |
size_t name_size; |
if (!ipc_data_write_receive(&callid, &name_size)) { |
printf("Unexpected request.\n"); |
free(driver); |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (name_size > DEVMAP_NAME_MAXLEN) { |
printf("Too logn name: %u: maximum is %u.\n", name_size, |
DEVMAP_NAME_MAXLEN); |
free(driver); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* |
* Allocate buffer for device name. |
*/ |
if (NULL == (driver->name = (char *)malloc(name_size + 1))) { |
printf("Cannot allocate space for driver name.\n"); |
driver->name = (char *) malloc(name_size + 1); |
if (driver->name == NULL) { |
free(driver); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
} |
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) { |
printf("Cannot read driver name.\n"); |
free(driver->name); |
free(driver); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
driver->name[name_size] = 0; |
printf("Read driver name: '%s'.\n", driver->name); |
/* Initialize futex for list of devices owned by this driver */ |
futex_initialize(&(driver->devices_futex), 1); |
/* |
/* |
* Initialize list of asociated devices |
*/ |
list_initialize(&(driver->devices)); |
/* |
/* |
* Create connection to the driver |
*/ |
ipc_call_t call; |
callid = async_get_call(&call); |
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) { |
printf("DEVMAP: Unexpected method: %u.\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, ENOTSUP); |
free(driver->name); |
268,78 → 261,92 |
ipc_answer_0(iid, ENOTSUP); |
return; |
} |
driver->phone = IPC_GET_ARG5(call); |
ipc_answer_0(callid, EOK); |
list_initialize(&(driver->drivers)); |
futex_down(&drivers_list_futex); |
futex_down(&drivers_list_futex); |
/* TODO: |
* check that no driver with name equal to driver->name is registered |
*/ |
/* |
/* |
* Insert new driver into list of registered drivers |
*/ |
list_append(&(driver->drivers), &drivers_list); |
futex_up(&drivers_list_futex); |
futex_up(&drivers_list_futex); |
ipc_answer_0(iid, EOK); |
printf("Driver registered.\n"); |
*odriver = driver; |
return; |
} |
/** Unregister device driver, unregister all its devices and free driver |
/** |
* Unregister device driver, unregister all its devices and free driver |
* structure. |
* |
*/ |
static int devmap_driver_unregister(devmap_driver_t *driver) |
{ |
devmap_device_t *device; |
if (NULL == driver) { |
printf("Error: driver == NULL.\n"); |
if (driver == NULL) |
return EEXISTS; |
} |
printf("Unregister driver '%s'.\n", driver->name); |
futex_down(&drivers_list_futex); |
futex_down(&drivers_list_futex); |
ipc_hangup(driver->phone); |
/* remove it from list of drivers */ |
list_remove(&(driver->drivers)); |
/* unregister all its devices */ |
futex_down(&devices_list_futex); |
futex_down(&devices_list_futex); |
futex_down(&(driver->devices_futex)); |
while (!list_empty(&(driver->devices))) { |
device = list_get_instance(driver->devices.next, |
devmap_device_t *device = list_get_instance(driver->devices.next, |
devmap_device_t, driver_devices); |
printf("Unregister device '%s'.\n", device->name); |
devmap_device_unregister_core(device); |
} |
futex_up(&(driver->devices_futex)); |
futex_up(&devices_list_futex); |
futex_up(&drivers_list_futex); |
futex_up(&devices_list_futex); |
futex_up(&drivers_list_futex); |
/* free name and driver */ |
if (NULL != driver->name) { |
if (NULL != driver->name) |
free(driver->name); |
} |
free(driver); |
return EOK; |
} |
printf("Driver unregistered.\n"); |
return EOK; |
/** Process pending lookup requests */ |
static void process_pending_lookup() |
{ |
link_t *cur; |
loop: |
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
pending_req_t *pr = list_get_instance(cur, pending_req_t, link); |
const devmap_device_t *dev = devmap_device_find_name(pr->name); |
if (!dev) |
continue; |
ipc_answer_1(pr->callid, EOK, dev->handle); |
free(pr->name); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
349,45 → 356,38 |
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall, |
devmap_driver_t *driver) |
{ |
ipc_callid_t callid; |
size_t size; |
devmap_device_t *device; |
if (NULL == driver) { |
printf("Invalid driver registration.\n"); |
if (driver == NULL) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* Create new device entry */ |
if (NULL == |
(device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) { |
printf("Cannot allocate new device.\n"); |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
/* Get device name */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
free(device); |
printf("Cannot read device name.\n"); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (size > DEVMAP_NAME_MAXLEN) { |
printf("Too long device name: %u.\n", size); |
free(device); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* +1 for terminating \0 */ |
device->name = (char *)malloc(size + 1); |
if (NULL == device->name) { |
printf("Cannot read device name.\n"); |
/* +1 for terminating \0 */ |
device->name = (char *) malloc(size + 1); |
if (device->name == NULL) { |
free(device); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
396,15 → 396,15 |
ipc_data_write_finalize(callid, device->name, size); |
device->name[size] = 0; |
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
futex_down(&devices_list_futex); |
futex_down(&devices_list_futex); |
/* Check that device with such name is not already registered */ |
if (NULL != devmap_device_find_name(device->name)) { |
printf("Device '%s' already registered.\n", device->name); |
printf(NAME ": Device '%s' already registered\n", device->name); |
futex_up(&devices_list_futex); |
free(device->name); |
free(device); |
411,27 → 411,26 |
ipc_answer_0(iid, EEXISTS); |
return; |
} |
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
device->handle = devmap_create_handle(); |
device->driver = driver; |
/* Insert device into list of all devices */ |
list_append(&device->devices, &devices_list); |
/* Insert device into list of devices that belog to one driver */ |
futex_down(&device->driver->devices_futex); |
list_append(&device->driver_devices, &device->driver->devices); |
futex_up(&device->driver->devices_futex); |
futex_up(&devices_list_futex); |
printf("Device '%s' registered.\n", device->name); |
futex_up(&device->driver->devices_futex); |
futex_up(&devices_list_futex); |
ipc_answer_1(iid, EOK, device->handle); |
return; |
process_pending_lookup(); |
} |
/** |
441,179 → 440,174 |
devmap_driver_t *driver) |
{ |
/* TODO */ |
return EOK; |
} |
/** Connect client to the device. |
* |
* Find device driver owning requested device and forward |
* the message to it. |
* |
*/ |
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) |
{ |
devmap_device_t *dev; |
int handle; |
/* |
* Get handle from request |
*/ |
handle = IPC_GET_ARG2(*call); |
dev = devmap_device_find_handle(handle); |
int handle = IPC_GET_ARG2(*call); |
devmap_device_t *dev = devmap_device_find_handle(handle); |
if (NULL == dev) { |
printf("DEVMAP: No registered device with handle %d.\n", |
handle); |
ipc_answer_0(callid, ENOENT); |
return; |
} |
} |
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
return; |
} |
/** Find handle for device instance identified by name. |
* |
* In answer will be send EOK and device handle in arg1 or a error |
* code from errno.h. |
* code from errno.h. |
* |
*/ |
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall) |
{ |
char *name = NULL; |
size_t name_size; |
const devmap_device_t *dev; |
ipc_callid_t callid; |
ipcarg_t retval; |
/* |
/* |
* Wait for incoming message with device name (but do not |
* read the name itself until the buffer is allocated). |
*/ |
if (!ipc_data_write_receive(&callid, &name_size)) { |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if (name_size > DEVMAP_NAME_MAXLEN) { |
if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
/* |
* Allocate buffer for device name. |
*/ |
if (NULL == (name = (char *)malloc(name_size))) { |
char *name = (char *) malloc(size); |
if (name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
} |
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
if (EOK != (retval = ipc_data_write_finalize(callid, name, |
name_size))) { |
ipcarg_t retval = ipc_data_write_finalize(callid, name, size); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(name); |
return; |
} |
name[size] = '\0'; |
/* |
* Find device name in linked list of known devices. |
*/ |
dev = devmap_device_find_name(name); |
const devmap_device_t *dev = devmap_device_find_name(name); |
/* |
* Device was not found. |
*/ |
if (NULL == dev) { |
printf("DEVMAP: device %s has not been registered.\n", name); |
if (dev == NULL) { |
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) { |
/* Blocking lookup, add to pending list */ |
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
if (!pr) { |
ipc_answer_0(iid, ENOMEM); |
free(name); |
return; |
} |
pr->name = name; |
pr->callid = iid; |
list_append(&pr->link, &pending_req); |
return; |
} |
ipc_answer_0(iid, ENOENT); |
free(name); |
return; |
} |
printf("DEVMAP: device %s has handler %d.\n", name, dev->handle); |
ipc_answer_1(iid, EOK, dev->handle); |
return; |
free(name); |
} |
/** Find name of device identified by id and send it to caller. |
/** Find name of device identified by id and send it to caller. |
* |
*/ |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
{ |
const devmap_device_t *device; |
size_t name_size; |
device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
/* |
* Device not found. |
*/ |
if (NULL == device) { |
if (device == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
} |
ipc_answer_0(iid, EOK); |
name_size = strlen(device->name); |
/* FIXME: |
we have no channel from DEVMAP to client -> |
sending must be initiated by client |
int rc = ipc_data_write_send(phone, device->name, name_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
*/ |
size_t name_size = strlen(device->name); |
/* FIXME: |
* We have no channel from DEVMAP to client, therefore |
* sending must be initiated by client. |
* |
* int rc = ipc_data_write_send(phone, device->name, name_size); |
* if (rc != EOK) { |
* async_wait_for(req, NULL); |
* return rc; |
* } |
*/ |
/* TODO: send name in response */ |
return; |
} |
/** Handle connection with device driver. |
* |
*/ |
static void |
devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
bool cont = true; |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
devmap_driver_t *driver = NULL; |
ipc_answer_0(iid, EOK); |
devmap_driver_register(&driver); |
if (NULL == driver) { |
printf("DEVMAP: driver registration failed.\n"); |
if (NULL == driver) |
return; |
} |
bool cont = true; |
while (cont) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("DEVMAP: connection hung up.\n"); |
cont = false; |
continue; /* Exit thread */ |
/* Exit thread */ |
continue; |
case DEVMAP_DRIVER_UNREGISTER: |
printf("DEVMAP: unregister driver.\n"); |
if (NULL == driver) { |
printf("DEVMAP: driver was not registered!\n"); |
if (NULL == driver) |
ipc_answer_0(callid, ENOENT); |
} else { |
else |
ipc_answer_0(callid, EOK); |
} |
break; |
case DEVMAP_DEVICE_REGISTER: |
/* Register one instance of device */ |
630,46 → 624,40 |
devmap_get_handle(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
} |
if (NULL != driver) { |
/* |
/* |
* Unregister the device driver and all its devices. |
*/ |
devmap_driver_unregister(driver); |
driver = NULL; |
} |
} |
/** Handle connection with device client. |
* |
*/ |
static void |
devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
ipc_call_t call; |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
bool cont = true; |
ipc_answer_0(iid, EOK); /* Accept connection */ |
while (cont) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("DEVMAP: connection hung up.\n"); |
cont = false; |
continue; /* Exit thread */ |
/* Exit thread */ |
continue; |
case DEVMAP_DEVICE_GET_HANDLE: |
devmap_get_handle(callid, &call); |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
/* TODO */ |
676,24 → 664,19 |
devmap_get_name(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
} |
} |
/** Function for handling connections to devmap |
/** Function for handling connections to devmap |
* |
*/ |
static void |
devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
printf("DEVMAP: new connection.\n"); |
/* Select interface */ |
switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) { |
/* Select interface */ |
switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) { |
case DEVMAP_DRIVER: |
devmap_connection_driver(iid, icall); |
break; |
701,21 → 684,13 |
devmap_connection_client(iid, icall); |
break; |
case DEVMAP_CONNECT_TO_DEVICE: |
/* Connect client to selected device */ |
printf("DEVMAP: connect to device %d.\n", |
IPC_GET_ARG2(*icall)); |
/* Connect client to selected device */ |
devmap_forward(iid, icall); |
break; |
default: |
ipc_answer_0(iid, ENOENT); /* No such interface */ |
printf("DEVMAP: Unknown interface %u.\n", |
(ipcarg_t)(IPC_GET_ARG1(*icall))); |
/* No such interface */ |
ipc_answer_0(iid, ENOENT); |
} |
/* Cleanup */ |
printf("DEVMAP: connection closed.\n"); |
return; |
} |
/** |
723,23 → 698,24 |
*/ |
int main(int argc, char *argv[]) |
{ |
ipcarg_t phonead; |
printf("DEVMAP: HelenOS device mapper.\n"); |
printf(NAME ": HelenOS Device Mapper\n"); |
if (devmap_init() != 0) { |
printf("Error while initializing DEVMAP service.\n"); |
printf(NAME ": Error while initializing service\n"); |
return -1; |
} |
/* Set a handler of incomming connections */ |
/* Set a handler of incomming connections */ |
async_set_client_connection(devmap_connection); |
/* Register device mapper at naming service */ |
ipcarg_t phonead; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Never reached */ |
return 0; |
} |
747,4 → 723,3 |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/vfs/vfs.c |
---|
28,11 → 28,11 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs.c |
* @brief VFS service for HelenOS. |
* @file vfs.c |
* @brief VFS service for HelenOS. |
*/ |
#include <ipc/ipc.h> |
47,20 → 47,18 |
#include <atomic.h> |
#include "vfs.h" |
#define dprintf(...) printf(__VA_ARGS__) |
#define NAME "vfs" |
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
bool keep_on_going = 1; |
printf("Connection opened from %p\n", icall->in_phone_hash); |
bool keep_on_going = true; |
/* |
* The connection was opened via the IPC_CONNECT_ME_TO call. |
* This call needs to be answered. |
*/ |
ipc_answer_0(iid, EOK); |
/* |
* Here we enter the main connection fibril loop. |
* The logic behind this loop and the protocol is that we'd like to keep |
72,20 → 70,38 |
* connection later. |
*/ |
while (keep_on_going) { |
ipc_callid_t callid; |
ipc_call_t call; |
callid = async_get_call(&call); |
printf("Received call, method=%d\n", IPC_GET_METHOD(call)); |
ipc_callid_t callid = async_get_call(&call); |
fs_handle_t fs_handle; |
int phone; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
break; |
case IPC_M_CONNECT_ME_TO: |
/* |
* Connect the client file system to another one. |
*/ |
/* FIXME: |
* Prevent ordinary clients from connecting to file |
* system servers directly. This should be solved by |
* applying some security mechanisms. |
*/ |
fs_handle = IPC_GET_ARG1(call); |
phone = vfs_grab_phone(fs_handle); |
(void) ipc_forward_fast(callid, phone, 0, 0, 0, |
IPC_FF_NONE); |
vfs_release_phone(phone); |
break; |
case VFS_REGISTER: |
vfs_register(callid, &call); |
keep_on_going = false; |
/* |
* Keep the connection open so that a file system can |
* later ask us to connect it to another file system. |
* This is necessary to support non-root mounts. |
*/ |
break; |
case VFS_MOUNT: |
vfs_mount(callid, &call); |
122,30 → 138,27 |
break; |
} |
} |
/* TODO: cleanup after the client */ |
} |
int main(int argc, char **argv) |
{ |
ipcarg_t phonead; |
printf("VFS: HelenOS VFS server\n"); |
printf(NAME ": HelenOS VFS server\n"); |
/* |
* Initialize the list of registered file systems. |
*/ |
list_initialize(&fs_head); |
/* |
* Initialize VFS node hash table. |
*/ |
if (!vfs_nodes_init()) { |
printf("Failed to initialize the VFS node hash table.\n"); |
printf(NAME ": Failed to initialize VFS node hash table\n"); |
return ENOMEM; |
} |
/* |
* Allocate and initialize the Path Lookup Buffer. |
*/ |
152,12 → 165,13 |
list_initialize(&plb_head); |
plb = as_get_mappable_page(PLB_SIZE); |
if (!plb) { |
printf("Cannot allocate a mappable piece of address space\n"); |
printf(NAME ": Cannot allocate a mappable piece of address space\n"); |
return ENOMEM; |
} |
if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE | |
AS_AREA_CACHEABLE) != plb) { |
printf("Cannot create address space area.\n"); |
printf(NAME ": Cannot create address space area\n"); |
return ENOMEM; |
} |
memset(plb, 0, PLB_SIZE); |
166,15 → 180,17 |
* Set a connectio handling function/fibril. |
*/ |
async_set_client_connection(vfs_connection); |
/* |
* Register at the naming service. |
*/ |
ipcarg_t phonead; |
ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, 0, &phonead); |
/* |
* Start accepting connections. |
*/ |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
return 0; |
} |
181,4 → 197,4 |
/** |
* @} |
*/ |
*/ |
/branches/dd/uspace/srv/vfs/vfs_ops.c |
---|
28,11 → 28,11 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs_ops.c |
* @brief Operations that VFS offers to its clients. |
* @file vfs_ops.c |
* @brief Operations that VFS offers to its clients. |
*/ |
#include "vfs.h" |
55,6 → 55,18 |
/* Forward declarations of static functions. */ |
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t); |
/** Pending mount structure. */ |
typedef struct { |
link_t link; |
char *fs_name; /**< File system name */ |
char *mp; /**< Mount point */ |
ipc_callid_t callid; /**< Call ID waiting for the mount */ |
ipc_callid_t rid; /**< Request ID */ |
dev_handle_t dev_handle; /**< Device handle */ |
} pending_req_t; |
LIST_INITIALIZE(pending_req); |
/** |
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a |
* concurrent VFS operation which modifies the file system namespace. |
62,161 → 74,48 |
RWLOCK_INITIALIZE(namespace_rwlock); |
futex_t rootfs_futex = FUTEX_INITIALIZER; |
vfs_triplet_t rootfs = { |
vfs_pair_t rootfs = { |
.fs_handle = 0, |
.dev_handle = 0, |
.index = 0, |
.dev_handle = 0 |
}; |
static int |
lookup_root(fs_handle_t fs_handle, dev_handle_t dev_handle, |
vfs_lookup_res_t *result) |
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
fs_handle_t fs_handle, char *mp) |
{ |
vfs_pair_t altroot = { |
.fs_handle = fs_handle, |
.dev_handle = dev_handle, |
}; |
return vfs_lookup_internal("/", L_DIRECTORY, result, &altroot); |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t dev_handle; |
/* Resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
vfs_node_t *mp_node = NULL; |
int rc; |
int phone; |
/* |
* We expect the library to do the device-name to device-handle |
* translation for us, thus the device handle will arrive as ARG1 |
* in the request. |
*/ |
dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
/* |
* For now, don't make use of ARG2 and ARG3, but they can be used to |
* carry mount options in the future. |
*/ |
ipc_callid_t callid; |
size_t size; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
*/ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Don't receive more than is necessary for storing a full file system |
* name. |
*/ |
if (size < 1 || size > FS_NAME_MAXLEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Deliver the file system name. */ |
char fs_name[FS_NAME_MAXLEN + 1]; |
(void) ipc_data_write_finalize(callid, fs_name, size); |
fs_name[size] = '\0'; |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* Now, we want the client to send us the mount point. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Check whether size is reasonable wrt. the mount point. */ |
if (size < 1 || size > MAX_PATH_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Allocate buffer for the mount point data being received. */ |
uint8_t *buf; |
buf = malloc(size + 1); |
if (!buf) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Deliver the mount point. */ |
(void) ipc_data_write_finalize(callid, buf, size); |
buf[size] = '\0'; |
/* |
* Lookup the root node of the filesystem being mounted. |
* In this case, we don't need to take the namespace_futex as the root |
* node cannot be removed. However, we do take a reference to it so |
* that we can track how many times it has been mounted. |
*/ |
vfs_lookup_res_t mr_res; |
rc = lookup_root(fs_handle, dev_handle, &mr_res); |
if (rc != EOK) { |
free(buf); |
ipc_answer_0(rid, rc); |
return; |
} |
vfs_node_t *mr_node = vfs_node_get(&mr_res); |
if (!mr_node) { |
free(buf); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Finally, we need to resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
futex_down(&rootfs_futex); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
rwlock_write_lock(&namespace_rwlock); |
if ((size == 1) && (buf[0] == '/')) { |
if ((strlen(mp) == 1) && (mp[0] == '/')) { |
/* Trying to mount root FS over root FS */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); |
free(buf); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL); |
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL); |
if (rc != EOK) { |
/* The lookup failed for some reason. */ |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
free(buf); |
ipc_answer_0(rid, rc); |
return; |
} |
mp_node = vfs_node_get(&mp_res); |
if (!mp_node) { |
rwlock_write_unlock(&namespace_rwlock); |
futex_up(&rootfs_futex); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
free(buf); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* |
* Now we hold a reference to mp_node. |
* It will be dropped upon the corresponding VFS_UNMOUNT. |
225,29 → 124,45 |
rwlock_write_unlock(&namespace_rwlock); |
} else { |
/* We still don't have the root file system mounted. */ |
if ((size == 1) && (buf[0] == '/')) { |
if ((strlen(mp) == 1) && (mp[0] == '/')) { |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
/* |
* For this simple, but important case, |
* we are almost done. |
*/ |
free(buf); |
/* Inform the mount point about the root mount. */ |
phone = vfs_grab_phone(mr_res.triplet.fs_handle); |
rc = async_req_5_0(phone, VFS_MOUNT, |
(ipcarg_t) mr_res.triplet.dev_handle, |
(ipcarg_t) mr_res.triplet.index, |
(ipcarg_t) mr_res.triplet.fs_handle, |
(ipcarg_t) mr_res.triplet.dev_handle, |
(ipcarg_t) mr_res.triplet.index); |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
vfs_release_phone(phone); |
if (rc == EOK) |
rootfs = mr_res.triplet; |
else |
vfs_node_put(mr_node); |
if (rc != EOK) { |
futex_up(&rootfs_futex); |
ipc_answer_0(rid, rc); |
return; |
} |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
rootfs.fs_handle = fs_handle; |
rootfs.dev_handle = dev_handle; |
futex_up(&rootfs_futex); |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
ipc_answer_0(rid, rc); |
return; |
} else { |
256,8 → 171,6 |
* being mounted first. |
*/ |
futex_up(&rootfs_futex); |
free(buf); |
vfs_node_put(mr_node); /* failed -> drop reference */ |
ipc_answer_0(rid, ENOENT); |
return; |
} |
264,30 → 177,21 |
} |
futex_up(&rootfs_futex); |
free(buf); /* The buffer is not needed anymore. */ |
/* |
* At this point, we have all necessary pieces: file system and device |
* handles, and we know the mount point VFS node and also the root node |
* of the file system being mounted. |
* handles, and we know the mount point VFS node. |
*/ |
/** |
* @todo |
* Add more IPC parameters so that we can send mount mode/flags. |
*/ |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
rc = async_req_5_0(phone, VFS_MOUNT, |
rc = async_req_4_0(phone, VFS_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) mr_res.triplet.fs_handle, |
(ipcarg_t) mr_res.triplet.dev_handle, |
(ipcarg_t) mr_res.triplet.index); |
(ipcarg_t) fs_handle, |
(ipcarg_t) dev_handle); |
vfs_release_phone(phone); |
if (rc != EOK) { |
/* Mount failed, drop references to mr_node and mp_node. */ |
vfs_node_put(mr_node); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
} |
295,6 → 199,170 |
ipc_answer_0(rid, rc); |
} |
/** Process pending mount requests */ |
void vfs_process_pending_mount() |
{ |
link_t *cur; |
loop: |
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { |
pending_req_t *pr = list_get_instance(cur, pending_req_t, link); |
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true); |
if (!fs_handle) |
continue; |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(pr->callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
free(pr->fs_name); |
free(pr->mp); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* |
* We expect the library to do the device-name to device-handle |
* translation for us, thus the device handle will arrive as ARG1 |
* in the request. |
*/ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* |
* Mount flags are passed as ARG2. |
*/ |
unsigned int flags = (unsigned int) IPC_GET_ARG2(*request); |
/* |
* For now, don't make use of ARG3, but it can be used to |
* carry mount options in the future. |
*/ |
/* We want the client to send us the mount point. */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Check whether size is reasonable wrt. the mount point. */ |
if ((size < 1) || (size > MAX_PATH_LEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* Allocate buffer for the mount point data being received. */ |
char *mp = malloc(size + 1); |
if (!mp) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
/* Deliver the mount point. */ |
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
free(mp); |
return; |
} |
mp[size] = '\0'; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
*/ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* |
* Don't receive more than is necessary for storing a full file system |
* name. |
*/ |
if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* |
* Allocate buffer for file system name. |
*/ |
char *fs_name = (char *) malloc(size + 1); |
if (fs_name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, EREFUSED); |
free(mp); |
return; |
} |
/* Deliver the file system name. */ |
retval = ipc_data_write_finalize(callid, fs_name, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
free(mp); |
free(fs_name); |
return; |
} |
fs_name[size] = '\0'; |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
if (flags & IPC_FLAG_BLOCKING) { |
/* Blocking mount, add to pending list */ |
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
if (!pr) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(fs_name); |
return; |
} |
pr->fs_name = fs_name; |
pr->mp = mp; |
pr->callid = callid; |
pr->rid = rid; |
pr->dev_handle = dev_handle; |
list_append(&pr->link, &pending_req); |
return; |
} |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
free(mp); |
free(fs_name); |
return; |
} |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
free(mp); |
free(fs_name); |
} |
void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
{ |
if (!vfs_files_init()) { |
315,6 → 383,16 |
int mode = IPC_GET_ARG3(*request); |
size_t len; |
/* |
* Make sure that we are called with exactly one of L_FILE and |
* L_DIRECTORY. |
*/ |
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 || |
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) { |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (oflag & O_CREAT) |
lflag |= L_CREATE; |
if (oflag & O_EXCL) |
422,12 → 500,8 |
void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
if (fd >= MAX_OPEN_FILES) { |
ipc_answer_0(rid, EBADF); |
return; |
} |
vfs_fd_free(fd); |
ipc_answer_0(rid, EOK); |
int rc = vfs_fd_free(fd); |
ipc_answer_0(rid, rc); |
} |
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
444,7 → 518,7 |
*/ |
int fd = IPC_GET_ARG1(*request); |
/* Lookup the file structure corresponding to the file descriptor. */ |
vfs_file_t *file = vfs_file_get(fd); |
if (!file) { |
451,7 → 525,7 |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* |
* Now we need to receive a call with client's |
* IPC_M_DATA_READ/IPC_M_DATA_WRITE request. |
467,7 → 541,7 |
ipc_answer_0(rid, EINVAL); |
return; |
} |
/* |
* Lock the open file structure so that no other thread can manipulate |
* the same open file at a time. |
483,6 → 557,15 |
else |
rwlock_write_lock(&file->node->contents_rwlock); |
if (file->node->type == VFS_NODE_DIRECTORY) { |
/* |
* Make sure that no one is modifying the namespace |
* while we are in readdir(). |
*/ |
assert(read); |
rwlock_read_lock(&namespace_rwlock); |
} |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ |
500,14 → 583,17 |
* don't have to bother. |
*/ |
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
size_t bytes = IPC_GET_ARG1(answer); |
if (file->node->type == VFS_NODE_DIRECTORY) |
rwlock_read_unlock(&namespace_rwlock); |
/* Unlock the VFS node. */ |
if (read) |
rwlock_read_unlock(&file->node->contents_rwlock); |
517,12 → 603,12 |
file->node->size = IPC_GET_ARG2(answer); |
rwlock_write_unlock(&file->node->contents_rwlock); |
} |
/* Update the position pointer and unlock the open file. */ |
if (rc == EOK) |
file->pos += bytes; |
futex_up(&file->lock); |
/* |
* FS server's reply is the final result of the whole operation we |
* return to the client. |
/branches/dd/uspace/srv/vfs/vfs_register.c |
---|
28,10 → 28,10 |
/** @addtogroup fs |
* @{ |
*/ |
*/ |
/** |
* @file vfs_register.c |
* @file vfs_register.c |
* @brief |
*/ |
98,30 → 98,6 |
return false; |
} |
/* |
* Check if the FS implements mandatory VFS operations. |
*/ |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_LOOKUP)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_LOOKUP not defined by the client.\n"); |
return false; |
} |
if (info->ops[IPC_METHOD_TO_VFS_OP(VFS_READ)] != VFS_OP_DEFINED) { |
dprintf("Operation VFS_READ not defined by the client.\n"); |
return false; |
} |
/* |
* Check if each operation is either not defined, defined or default. |
*/ |
for (i = VFS_FIRST; i < VFS_LAST_CLNT; i++) { |
if ((info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_NULL) && |
(info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_DEFAULT) && |
(info->ops[IPC_METHOD_TO_VFS_OP(i)] != VFS_OP_DEFINED)) { |
dprintf("Operation info not understood.\n"); |
return false; |
} |
} |
return true; |
} |
302,6 → 278,11 |
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n", |
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle); |
/* Process pending mount requests possibly waiting |
* for this filesystem implementation. |
*/ |
vfs_process_pending_mount(); |
} |
/** For a given file system handle, implement policy for allocating a phone. |
/branches/dd/uspace/srv/vfs/vfs.h |
---|
40,12 → 40,13 |
#include <sys/types.h> |
#include <bool.h> |
#define dprintf(...) printf(__VA_ARGS__) |
// FIXME: according to CONFIG_DEBUG |
// #define dprintf(...) printf(__VA_ARGS__) |
#define dprintf(...) |
#define VFS_FIRST IPC_FIRST_USER_METHOD |
#define IPC_METHOD_TO_VFS_OP(m) ((m) - VFS_FIRST) |
/* Basic types. */ |
typedef int16_t fs_handle_t; |
typedef int16_t dev_handle_t; |
62,6 → 63,7 |
typedef enum { |
VFS_LOOKUP = VFS_LAST_CMN, |
VFS_MOUNTED, |
VFS_DESTROY, |
VFS_LAST_CLNT, /* keep this the last member of this enum */ |
} vfs_request_clnt_t; |
77,32 → 79,16 |
VFS_LAST_SRV, /* keep this the last member of this enum */ |
} vfs_request_srv_t; |
/** |
* An instance of this structure is associated with a particular FS operation. |
* It tells VFS if the FS supports the operation or maybe if a default one |
* should be used. |
*/ |
typedef enum { |
VFS_OP_NULL = 0, |
VFS_OP_DEFAULT, |
VFS_OP_DEFINED |
} vfs_op_t; |
#define FS_NAME_MAXLEN 20 |
/** |
* A structure like this is passed to VFS by each individual FS upon its |
* registration. It assosiates a human-readable identifier with each |
* registered FS. More importantly, through this structure, the FS announces |
* what operations it supports. |
* registered FS. |
*/ |
typedef struct { |
/** Unique identifier of the fs. */ |
char name[FS_NAME_MAXLEN + 1]; |
/** Operations. */ |
vfs_op_t ops[VFS_LAST_CLNT - VFS_FIRST]; |
} vfs_info_t; |
/** |
186,8 → 172,15 |
*/ |
#define L_PARENT 64 |
typedef enum vfs_node_type { |
VFS_NODE_UNKNOWN, |
VFS_NODE_FILE, |
VFS_NODE_DIRECTORY, |
} vfs_node_type_t; |
typedef struct { |
vfs_triplet_t triplet; |
vfs_node_type_t type; |
size_t size; |
unsigned lnkcnt; |
} vfs_lookup_res_t; |
209,6 → 202,9 |
unsigned lnkcnt; |
link_t nh_link; /**< Node hash-table link. */ |
vfs_node_type_t type; /**< Partial info about the node type. */ |
size_t size; /**< Cached size if the node is a file. */ |
/** |
241,7 → 237,7 |
extern link_t fs_head; /**< List of registered file systems. */ |
extern vfs_triplet_t rootfs; /**< Root node of the root file system. */ |
extern vfs_pair_t rootfs; /**< Root file system. */ |
#define MAX_PATH_LEN (64 * 1024) |
278,7 → 274,7 |
extern bool vfs_files_init(void); |
extern vfs_file_t *vfs_file_get(int); |
extern int vfs_fd_alloc(void); |
extern void vfs_fd_free(int); |
extern int vfs_fd_free(int); |
extern void vfs_file_addref(vfs_file_t *); |
extern void vfs_file_delref(vfs_file_t *); |
286,6 → 282,7 |
extern void vfs_node_addref(vfs_node_t *); |
extern void vfs_node_delref(vfs_node_t *); |
extern void vfs_process_pending_mount(void); |
extern void vfs_register(ipc_callid_t, ipc_call_t *); |
extern void vfs_mount(ipc_callid_t, ipc_call_t *); |
extern void vfs_open(ipc_callid_t, ipc_call_t *); |
/branches/dd/uspace/srv/vfs/vfs_node.c |
---|
175,15 → 175,22 |
node->index = result->triplet.index; |
node->size = result->size; |
node->lnkcnt = result->lnkcnt; |
node->type = result->type; |
link_initialize(&node->nh_link); |
rwlock_initialize(&node->contents_rwlock); |
hash_table_insert(&nodes, key, &node->nh_link); |
} else { |
node = hash_table_get_instance(tmp, vfs_node_t, nh_link); |
if (node->type == VFS_NODE_UNKNOWN && |
result->type != VFS_NODE_UNKNOWN) { |
/* Upgrade the node type. */ |
node->type = result->type; |
} |
} |
assert(node->size == result->size); |
assert(node->lnkcnt == result->lnkcnt); |
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN); |
_vfs_node_addref(node); |
futex_up(&nodes_futex); |
/branches/dd/uspace/srv/vfs/vfs_lookup.c |
---|
72,7 → 72,7 |
if (altroot) |
root = altroot; |
else |
root = (vfs_pair_t *) &rootfs; |
root = &rootfs; |
if (!root->fs_handle) |
return ENOENT; |
182,6 → 182,12 |
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer); |
result->size = (size_t) IPC_GET_ARG4(answer); |
result->lnkcnt = (unsigned) IPC_GET_ARG5(answer); |
if (lflag & L_FILE) |
result->type = VFS_NODE_FILE; |
else if (lflag & L_DIRECTORY) |
result->type = VFS_NODE_DIRECTORY; |
else |
result->type = VFS_NODE_UNKNOWN; |
} |
return rc; |
/branches/dd/uspace/srv/vfs/Makefile |
---|
32,6 → 32,7 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
52,22 → 53,24 |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/vfs/vfs_file.c |
---|
97,13 → 97,17 |
/** Release file descriptor. |
* |
* @param fd File descriptor being released. |
* |
* @return EOK on success or EBADF if fd is an invalid file |
* descriptor. |
*/ |
void vfs_fd_free(int fd) |
int vfs_fd_free(int fd) |
{ |
assert(fd < MAX_OPEN_FILES); |
assert(files[fd] != NULL); |
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
return EBADF; |
vfs_file_delref(files[fd]); |
files[fd] = NULL; |
return EOK; |
} |
/** Increment reference count of VFS file structure. |
/branches/dd/uspace/Makefile |
---|
29,14 → 29,16 |
## Include configuration |
# |
-include Makefile.config |
-include ../Makefile.config |
DIRS = \ |
lib/libc \ |
lib/libfs \ |
lib/libblock \ |
lib/softint \ |
lib/softfloat \ |
srv/ns \ |
srv/loader \ |
srv/fb \ |
srv/kbd \ |
srv/console \ |
47,48 → 49,36 |
srv/devmap \ |
app/tetris \ |
app/tester \ |
app/trace \ |
app/klog \ |
app/init |
app/init \ |
app/bdsh |
ifeq ($(ARCH), amd64) |
ifeq ($(UARCH),amd64) |
DIRS += srv/pci |
endif |
ifeq ($(ARCH), ia32) |
ifeq ($(UARCH),ia32) |
DIRS += srv/pci |
endif |
ifeq ($(ARCH), mips32) |
CFLAGS += -DCONFIG_MIPS_FPU |
ifeq ($(UARCH),sparc64) |
DIRS += \ |
srv/fhc \ |
srv/obio |
endif |
ifeq ($(ARCH), mips32eb) |
CFLAGS += -DCONFIG_MIPS_FPU |
endif |
BUILDS := $(addsuffix .build,$(DIRS)) |
CLEANS := $(addsuffix .clean,$(DIRS)) |
.PHONY: all config build $(BUILDS) $(CLEANS) clean distclean |
.PHONY: all $(BUILDS) $(CLEANS) clean |
all: |
../tools/config.py uspace.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) |
$(MAKE) -C . build |
all: ../Makefile.config ../config.h ../config.defs $(BUILDS) |
config: |
../tools/config.py uspace.config |
build: $(BUILDS) |
clean: $(CLEANS) |
find $(DIRS) -name '*.o' -follow -exec rm \{\} \; |
find lib/libc -name "_link.ld" -exec rm \{\} \; |
distclean: clean |
-rm Makefile.config |
$(CLEANS): |
-$(MAKE) -C $(basename $@) clean ARCH=$(ARCH) |
-$(MAKE) -C $(basename $@) clean |
$(BUILDS): |
$(MAKE) -C $(basename $@) all ARCH=$(ARCH) COMPILER=$(COMPILER) |
$(MAKE) -C $(basename $@) all |
/branches/dd/HelenOS.config |
---|
1,5 → 1,6 |
# |
# Copyright (c) 2006 Ondrej Palkovsky |
# Copyright (c) 2006 Ondrej Palkovsky |
# Copyright (c) 2009 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
26,60 → 27,408 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## General configuration directives |
## General platform options |
# Platform |
% Platform |
@ "amd64" AMD64/Intel EM64T (PC) |
@ "arm32" ARM 32-bit |
@ "ia32" Intel IA-32 (PC) |
@ "ia32xen" Intel IA-32 on Xen hypervisor |
@ "ia64" Intel IA-64 |
@ "mips32" MIPS 32-bit |
@ "ppc32" PowerPC 32-bit (iMac G4) |
@ "ppc64" PowerPC 64-bit (iMac G5) |
@ "sparc64" Sun UltraSPARC 64-bit |
! PLATFORM (choice) |
# Machine |
% Machine type |
@ "msim" MSIM |
@ "simics" Simics |
@ "bgxemul" GXEmul big endian |
@ "lgxemul" GXEmul little endia |
@ "indy" Sgi Indy |
@ "lgxemul" GXEmul little endian |
! [PLATFORM=mips32] MACHINE (choice) |
# Machine type |
% Machine type |
@ "gxemul" GXEmul |
! [PLATFORM=arm32] MACHINE (choice) |
% Machine type |
@ "i460GX" i460GX chipset machine |
@ "ski" Ski ia64 simulator |
@ "i460GX" i460GX chipset machine |
! [PLATFORM=ia64] MACHINE (choice) |
# Machine |
@ "gxemul_testarm" GXEmul testarm |
! [PLATFORM=arm32] MACHINE (choice) |
% Machine type |
@ "generic" Generic Sun workstation or server |
@ "serengeti" Serengeti system |
! [PLATFORM=sparc64] MACHINE (choice) |
# Compiler |
% CPU type |
@ "pentium4" Pentium 4 |
@ "pentium3" Pentium 3 |
@ "core" Core Solo/Duo |
@ "athlon_xp" Athlon XP |
@ "athlon_mp" Athlon MP |
! [PLATFORM=ia32] PROCESSOR (choice) |
% CPU type |
@ "opteron" Opteron |
! [PLATFORM=amd64] PROCESSOR (choice) |
% CPU type |
@ "us" UltraSPARC I-II subarchitecture |
@ "us3" UltraSPARC III-IV subarchitecture |
! [PLATFORM=sparc64&MACHINE=generic] PROCESSOR (choice) |
% CPU type |
@ "us3" |
! [PLATFORM=sparc64&MACHINE=serengeti] PROCESSOR (choice) |
% Ramdisk format |
@ "tmpfs" TMPFS image |
@ "fat" FAT16 image |
! RDFMT (choice) |
## Mapping between platform and kernel architecture |
% Kernel architecture |
@ "amd64" |
! [PLATFORM=amd64] KARCH (choice) |
% Kernel architecture |
@ "arm32" |
! [PLATFORM=arm32] KARCH (choice) |
% Kernel architecture |
@ "ia32" |
! [PLATFORM=ia32] KARCH (choice) |
% Kernel architecture |
@ "ia32xen" |
! [PLATFORM=ia32xen] KARCH (choice) |
% Kernel architecture |
@ "ia64" |
! [PLATFORM=ia64] KARCH (choice) |
% Kernel architecture |
@ "mips32" |
! [PLATFORM=mips32] KARCH (choice) |
% Kernel architecture |
@ "ppc32" |
! [PLATFORM=ppc32] KARCH (choice) |
% Kernel architecture |
@ "ppc64" |
! [PLATFORM=ppc64] KARCH (choice) |
% Kernel architecture |
@ "sparc64" |
! [PLATFORM=sparc64] KARCH (choice) |
## Mapping between platform and user space architecture |
% User space architecture |
@ "amd64" |
! [PLATFORM=amd64] UARCH (choice) |
% User space architecture |
@ "arm32" |
! [PLATFORM=arm32] UARCH (choice) |
% User space architecture |
@ "ia32" |
! [PLATFORM=ia32|PLATFORM=ia32xen] UARCH (choice) |
% User space architecture |
@ "ia64" |
! [PLATFORM=ia64] UARCH (choice) |
% User space architecture |
@ "mips32" |
! [PLATFORM=mips32&(MACHINE=msim|MACHINE=simics|MACHINE=lgxemul)] UARCH (choice) |
% User space architecture |
@ "mips32eb" |
! [PLATFORM=mips32&MACHINE=bgxemul] UARCH (choice) |
% User space architecture |
@ "ppc32" |
! [PLATFORM=ppc32] UARCH (choice) |
% User space architecture |
@ "ppc64" |
! [PLATFORM=ppc64] UARCH (choice) |
% User space architecture |
@ "sparc64" |
! [PLATFORM=sparc64] UARCH (choice) |
## Mapping between platform and boot architecture |
% Boot architecture |
@ "amd64" |
! [PLATFORM=amd64] BARCH (choice) |
% Boot architecture |
@ "arm32" |
! [PLATFORM=arm32] BARCH (choice) |
% Boot architecture |
@ "ia32" |
! [PLATFORM=ia32] BARCH (choice) |
% Boot architecture |
@ "ia32xen" |
! [PLATFORM=ia32xen] BARCH (choice) |
% Boot architecture |
@ "ia64" |
! [PLATFORM=ia64] BARCH (choice) |
% Boot architecture |
@ "mips32" |
! [PLATFORM=mips32] BARCH (choice) |
% Boot architecture |
@ "ppc32" |
! [PLATFORM=ppc32] BARCH (choice) |
% Boot architecture |
@ "ppc64" |
! [PLATFORM=ppc64] BARCH (choice) |
% Boot architecture |
@ "sparc64" |
! [PLATFORM=sparc64] BARCH (choice) |
## Mapping between platform and image format |
% Image format |
@ "binary" |
! [PLATFORM=mips32&MACHINE=msim] IMAGE (choice) |
% Image format |
@ "ecoff" |
! [PLATFORM=mips32&(MACHINE=simics|MACHINE=bgxemul|MACHINE=lgxemul)] IMAGE (choice) |
## Compiler options |
% Compiler |
@ "gcc_cross" GCC Cross-compiler |
@ "gcc_native" GCC Native |
@ "icc_native" ICC Native |
@ "suncc_native" Sun Studio C Compiler |
! [PLATFORM=amd64|PLATFORM=ia32|PLATFORM=ia32xen] COMPILER (choice) |
! [PLATFORM=amd64|PLATFORM=ia32] COMPILER (choice) |
# Compiler |
% Compiler |
@ "gcc_cross" GCC Cross-compiler |
@ "gcc_native" GCC Native |
@ "icc_native" ICC Native |
! [PLATFORM=ia64] COMPILER (choice) |
# Compiler |
% Compiler |
@ "gcc_cross" GCC Cross-compiler |
@ "gcc_native" GCC Native |
@ "suncc_native" Sun Studio C Compiler |
! [PLATFORM=sparc64] COMPILER (choice) |
# Compiler |
% Compiler |
@ "gcc_cross" GCC Cross-compiler |
@ "gcc_native" GCC Native |
! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=ppc64] COMPILER (choice) |
! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] COMPILER (choice) |
# Debug build |
## Debug build options |
% Debug build |
! CONFIG_DEBUG (y/n) |
% Deadlock detection support for spinlocks |
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n) |
## Kernel configuration |
% Fences |
! [PLATFORM=ia32&(PROCESSOR=athlon_xp|PROCESSOR=athlon_mp|PROCESSOR=pentium3)] CONFIG_FENCES_P3 (y) |
% Fences |
! [PLATFORM=ia32&(PROCESSOR=pentium4|PROCESSOR=core)] CONFIG_FENCES_P4 (y) |
% Fences |
! [PLATFORM=amd64] CONFIG_FENCES_P4 (y) |
% ACPI support |
! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_ACPI (y) |
% Hierarchical page tables support |
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] CONFIG_PAGE_PT (y) |
% Page hash table support |
! [PLATFORM=ia64|PLATFORM=sparc64] CONFIG_PAGE_HT (y) |
% Software integer division support |
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32] CONFIG_SOFTINT (y) |
% ASID support |
! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID (y) |
% ASID FIFO support |
! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID_FIFO (y) |
% OpenFirmware tree support |
! [PLATFORM=sparc64] CONFIG_OFW_TREE (y) |
% Multiboot standard support |
! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_MULTIBOOT (y) |
% FPU support |
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=ia64|PLATFORM=sparc64] CONFIG_FPU (y) |
% FPU support |
! [PLATFORM=mips32&(MACHINE=lgxemul|MACHINE=bgxemul)] CONFIG_FPU (y) |
## Kernel features options |
% Support for SMP |
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=amd64&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=ia32&PROCESSOR!=athlon_xp&PROCESSOR!=athlon_mp&PROCESSOR!=pentium3&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Lazy FPU context switching |
! [CONFIG_FPU=y] CONFIG_FPU_LAZY (y/n) |
% Use VHPT |
! [PLATFORM=ia64] CONFIG_VHPT (n/y) |
% Use TSB |
! [PLATFORM=sparc64] CONFIG_TSB (y/n) |
% IO SAPIC on default address support |
! [PLATFORM=ia64&MACHINE!=ski] CONFIG_IOSAPIC (y/n) |
% Virtually indexed D-cache support |
! [PLATFORM=sparc64] CONFIG_VIRT_IDX_DCACHE (y/n) |
% Support for userspace debuggers |
! CONFIG_UDEBUG (y/n) |
% Kernel console support |
! CONFIG_KCONSOLE (y/n) |
% Detailed kernel logging |
! CONFIG_LOG (n/y) |
% Compile kernel tests |
! CONFIG_TEST (y/n) |
## Hardware support |
% What is your input device? |
@ "generic" Keyboard or serial line |
@ "keyboard" Keyboard |
@ "serial" Serial line |
@ "none" No input device |
! [MACHINE!=msim&MACHINE!=ski&MACHINE!=serengeti] CONFIG_HID_IN (choice) |
% What is your input device? |
@ "serial" Serial line |
! [MACHINE=msim|MACHINE=ski|machine=serengeti] CONFIG_HID_IN (choice) |
% What is your output device? |
@ "generic" Monitor or serial line |
@ "monitor" Monitor |
@ "serial" Serial line |
@ "none" No output device |
! [MACHINE!=msim&MACHINE!=ski&MACHINE!=serengeti] CONFIG_HID_OUT (choice) |
% What is your output device? |
@ "serial" Serial line |
! [MACHINE=msim|MACHINE=ski&MACHINE=serengeti] CONFIG_HID_OUT (choice) |
% i8042 controller support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_I8042 (y/n) |
% i8042 controller support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&MACHINE=i460GX] CONFIG_I8042 (y/n) |
% Support for NS16550 controller |
! [CONFIG_HID_IN=generic|CONFIG_HID_IN=serial|(PLATFORM=sparc64&CONFIG_HID_OUT!=none&CONFIG_HID_IN!=none)] CONFIG_NS16550 (y/n) |
% Support for NS16550 serial port |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=serial|CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&MACHINE=i460GX] CONFIG_NS16550 (y/n) |
% Support for Z8530 controller |
! [(CONFIG_HID_IN!=none|CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=sparc64] CONFIG_Z8530 (y/n) |
% Support for Serengeti console |
! [(CONFIG_HID_IN=serial|CONFIG_HID_OUT=serial)&MACHINE=serengeti] CONFIG_SGCN (y/n) |
% PC keyboard support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_PC_KBD (y/n) |
% PC keyboard support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&MACHINE=i460GX] CONFIG_PC_KBD (y/n) |
% Sun keyboard support |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64] CONFIG_SUN_KBD (y/n) |
% Serial line input module |
! [CONFIG_HID_IN=generic|CONFIG_HID_IN=serial] CONFIG_SRLN (y/n) |
% EGA support |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor)&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_EGA (y/n) |
% EGA support |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor)&MACHINE=i460GX] CONFIG_EGA (y/n) |
% Framebuffer support |
! [CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor] CONFIG_FB (y/n) |
% Framebuffer width |
@ "640" |
@ "800" |
@ "1024" |
@ "1152" |
@ "1280" |
@ "1400" |
@ "1440" |
@ "1600" |
@ "2048" |
! [(PLATFORM=ia32|PLATFORM=amd64)&CONFIG_FB=y] CONFIG_VESA_WIDTH (choice) |
% Framebuffer height |
@ "480" |
@ "600" |
@ "768" |
@ "852" |
@ "900" |
@ "960" |
@ "1024" |
@ "1050" |
@ "1200" |
@ "1536" |
! [(PLATFORM=ia32|PLATFORM=amd64)&CONFIG_FB=y] CONFIG_VESA_HEIGHT (choice) |
% Framebuffer depth |
@ "8" |
@ "16" |
@ "24" |
! [(PLATFORM=ia32|PLATFORM=amd64)&CONFIG_FB=y] CONFIG_VESA_BPP (choice) |
% Start AP processors by the loader |
! [PLATFORM=sparc64&CONFIG_SMP=y] CONFIG_AP (y/n) |
% Use Block Address Translation by the loader |
! [PLATFORM=ppc32] CONFIG_BAT (y/n) |
% Preserve A.OUT header in isofs.b |
! [PLATFORM=sparc64&MACHINE=generic] CONFIG_AOUT_ISOFS_B (y) |
% External ramdisk |
! [PLATFORM=sparc64] CONFIG_RD_EXTERNAL (y/n) |
% Keyboard layout |
@ "us_qwerty" US QWERTY |
@ "us_dvorak" US Dvorak |
! KBD_LAYOUT (choice) |
/branches/dd/boot/boot.config |
---|
File deleted |
/branches/dd/boot/tools/ppc32/font-8x16.c |
---|
File deleted |
/branches/dd/boot/tools/ppc32/Makefile |
---|
File deleted |
/branches/dd/boot/tools/ppc32/font-8x16.h |
---|
File deleted |
/branches/dd/boot/tools/ppc32/debug.c |
---|
File deleted |
/branches/dd/boot/tools/ia64/vmaxlma.c |
---|
File deleted |
/branches/dd/boot/tools/pack.py |
---|
0,0 → 1,132 |
#!/usr/bin/env python |
# |
# Copyright (c) 2008 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
""" |
Binary package creator |
""" |
import sys |
import os |
import subprocess |
def usage(prname): |
"Print usage syntax" |
print prname + " <OBJCOPY> <FORMAT> <ARCH> <ALIGNMENT> <UINTPTR>" |
def main(): |
if (len(sys.argv) < 6): |
usage(sys.argv[0]) |
return |
if (not sys.argv[4].isdigit()): |
print "<ALIGNMENT> must be a number" |
return |
objcopy = sys.argv[1] |
format = sys.argv[2] |
arch = sys.argv[3] |
align = int(sys.argv[4], 0) |
uintptr = sys.argv[5] |
workdir = os.getcwd() |
header = file("_components.h", "w") |
data = file("_components.c", "w") |
header.write("#ifndef ___COMPONENTS_H__\n") |
header.write("#define ___COMPONENTS_H__\n\n") |
data.write("#include \"_components.h\"\n\n") |
data.write("void init_components(component_t *components)\n") |
data.write("{\n") |
cnt = 0 |
link = "" |
for task in sys.argv[6:]: |
basename = os.path.basename(task) |
plainname = os.path.splitext(basename)[0] |
path = os.path.dirname(task) |
object = plainname + ".o" |
symbol = "_binary_" + basename.replace(".", "_") |
macro = plainname.upper() |
print task + " -> " + object |
if (align > 1): |
link += "\t\t. = ALIGN(" + ("%d" % align) + ");\n" |
link += "\t\t*(." + plainname + "_image);\n" |
header.write("extern int " + symbol + "_start;\n") |
header.write("extern int " + symbol + "_end;\n\n") |
header.write("#define " + macro + "_START ((void *) &" + symbol + "_start)\n") |
header.write("#define " + macro + "_END ((void *) &" + symbol + "_end)\n") |
header.write("#define " + macro + "_SIZE ((" + uintptr + ") " + macro + "_END - (" + uintptr + ") " + macro + "_START)\n\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].name = \"" + plainname + "\";\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].start = " + macro + "_START;\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].end = " + macro + "_END;\n") |
data.write("\tcomponents[" + ("%d" % cnt) + "].size = " + macro + "_SIZE;\n\n") |
os.chdir(path) |
subprocess.call([objcopy, |
"-I", "binary", |
"-O", format, |
"-B", arch, |
"--rename-section", ".data=." + plainname + "_image", |
basename, os.path.join(workdir, object)]) |
os.chdir(workdir) |
cnt += 1 |
header.write("#define COMPONENTS " + ("%d" % cnt) + "\n\n") |
header.write("typedef struct {\n") |
header.write("\tchar *name;\n\n") |
header.write("\tvoid *start;\n") |
header.write("\tvoid *end;\n") |
header.write("\t" + uintptr + " size;\n") |
header.write("} component_t;\n\n") |
header.write("extern void init_components(component_t *components);\n\n") |
header.write("#endif\n") |
data.write("}\n") |
header.close() |
data.close() |
linkname = "_link.ld" |
link_in = file(linkname + ".in", "r") |
template = link_in.read(os.path.getsize(linkname + ".in")) |
link_in.close() |
link_out = file(linkname, "w") |
link_out.write(template.replace("[[COMPONENTS]]", link)) |
link_out.close() |
if __name__ == '__main__': |
main() |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/boot/tools/ia32/gen_vga323.c |
---|
1,8 → 1,36 |
/* |
* Copyright (c) 2008 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#define RED(i) ((i >> 5) & ((1 << 3) - 1)) |
#define GREEN(i) ((i >> 3) & ((1 << 2) - 1)) |
#define BLUE(i) (i & ((1 << 3) - 1)) |
#define RED(i) (((i) >> 5) & ((1 << 3) - 1)) |
#define GREEN(i) (((i) >> 3) & ((1 << 2) - 1)) |
#define BLUE(i) ((i) & ((1 << 3) - 1)) |
int main(int argc, char *argv[]) { |
unsigned int i; |
/branches/dd/boot/genarch/ofw.h |
---|
74,7 → 74,7 |
typedef struct { |
void *addr; |
uint32_t size; |
} keyboard_t; |
} macio_t; |
typedef struct { |
uint32_t info; |
122,7 → 122,8 |
extern int ofw_map(const void *phys, const void *virt, const int size, const int mode); |
extern int ofw_memmap(memmap_t *map); |
extern int ofw_screen(screen_t *screen); |
extern int ofw_keyboard(keyboard_t *keyboard); |
extern int ofw_macio(macio_t *macio); |
extern int ofw_setup_palette(void); |
extern void ofw_quiesce(void); |
#endif |
/branches/dd/boot/genarch/balloc.h |
---|
31,7 → 31,7 |
#include <types.h> |
#define BALLOC_MAX_SIZE (1024 * 1024) |
#define BALLOC_MAX_SIZE (128 * 1024) |
typedef struct { |
uintptr_t base; |
/branches/dd/boot/genarch/ofw_tree.c |
---|
42,10 → 42,11 |
static ofw_tree_property_t *ofw_tree_properties_alloc(unsigned count) |
{ |
return balloc(count * sizeof(ofw_tree_property_t), sizeof(ofw_tree_property_t)); |
return balloc(count * sizeof(ofw_tree_property_t), |
sizeof(ofw_tree_property_t)); |
} |
static void * ofw_tree_space_alloc(size_t size) |
static void *ofw_tree_space_alloc(size_t size) |
{ |
char *addr; |
65,23 → 66,26 |
return addr; |
} |
/** Transfer information from one OpenFirmware node into its memory representation. |
/** Transfer information from one OpenFirmware node into its memory |
* representation. |
* |
* Transfer entire information from the OpenFirmware device tree 'current' node to |
* its memory representation in 'current_node'. This function recursively processes |
* all node's children. Node's peers are processed iteratively in order to prevent |
* stack from overflowing. |
* Transfer entire information from the OpenFirmware device tree 'current' node |
* to its memory representation in 'current_node'. This function recursively |
* processes all node's children. Node's peers are processed iteratively in |
* order to prevent stack from overflowing. |
* |
* @param current_node Pointer to uninitialized ofw_tree_node structure that will |
* become the memory represenation of 'current'. |
* @param parent_node Parent ofw_tree_node structure or NULL in case of root node. |
* @param current_node Pointer to uninitialized ofw_tree_node structure that |
* will become the memory represenation of 'current'. |
* @param parent_node Parent ofw_tree_node structure or NULL in case of root |
* node. |
* @param current OpenFirmware phandle to the current device tree node. |
*/ |
static void ofw_tree_node_process(ofw_tree_node_t *current_node, |
ofw_tree_node_t *parent_node, phandle current) |
ofw_tree_node_t *parent_node, phandle current) |
{ |
static char path[MAX_PATH_LEN+1]; |
static char path[MAX_PATH_LEN + 1]; |
static char name[OFW_TREE_PROPERTY_MAX_NAMELEN]; |
static char name2[OFW_TREE_PROPERTY_MAX_NAMELEN]; |
phandle peer; |
phandle child; |
size_t len; |
121,7 → 125,6 |
memcpy(current_node->da_name, &path[i], len); |
current_node->da_name[len] = '\0'; |
/* |
* Recursively process the potential child node. |
*/ |
131,7 → 134,8 |
child_node = ofw_tree_node_alloc(); |
if (child_node) { |
ofw_tree_node_process(child_node, current_node, child); |
ofw_tree_node_process(child_node, current_node, |
child); |
current_node->child = child_node; |
} |
} |
140,9 → 144,11 |
* Count properties. |
*/ |
name[0] = '\0'; |
while (ofw_next_property(current, name, name) == 1) |
while (ofw_next_property(current, name, name2) == 1) { |
current_node->properties++; |
memcpy(name, name2, OFW_TREE_PROPERTY_MAX_NAMELEN); |
} |
if (!current_node->properties) |
return; |
149,20 → 155,23 |
/* |
* Copy properties. |
*/ |
current_node->property = ofw_tree_properties_alloc(current_node->properties); |
current_node->property = |
ofw_tree_properties_alloc(current_node->properties); |
if (!current_node->property) |
return; |
name[0] = '\0'; |
for (i = 0; ofw_next_property(current, name, name) == 1; i++) { |
for (i = 0; ofw_next_property(current, name, name2) == 1; i++) { |
size_t size; |
if (i == current_node->properties) |
break; |
memcpy(name, name2, OFW_TREE_PROPERTY_MAX_NAMELEN); |
memcpy(current_node->property[i].name, name, |
OFW_TREE_PROPERTY_MAX_NAMELEN); |
current_node->property[i].name[OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0'; |
OFW_TREE_PROPERTY_MAX_NAMELEN); |
current_node->property[i].name[ |
OFW_TREE_PROPERTY_MAX_NAMELEN] = '\0'; |
size = ofw_get_proplen(current, name); |
current_node->property[i].size = size; |
174,7 → 183,8 |
/* |
* Copy property value to memory node. |
*/ |
(void) ofw_get_property(current, name, buf, size); |
(void) ofw_get_property(current, name, |
buf, size); |
} |
} else { |
current_node->property[i].value = NULL; |
181,7 → 191,8 |
} |
} |
current_node->properties = i; /* Just in case we ran out of memory. */ |
/* Just in case we ran out of memory. */ |
current_node->properties = i; |
/* |
* Iteratively process the next peer node. |
214,15 → 225,33 |
/** Construct memory representation of OpenFirmware device tree. |
* |
* @return NULL on failure or pointer to the root node. |
* @return NULL on failure or pointer to the root node. |
*/ |
ofw_tree_node_t *ofw_tree_build(void) |
{ |
ofw_tree_node_t *root; |
phandle ssm_node; |
ofw_tree_node_t *ssm; |
root = ofw_tree_node_alloc(); |
if (root) |
ofw_tree_node_process(root, NULL, ofw_root); |
/* |
* The firmware client interface does not automatically include the |
* "ssm" node in the list of children of "/". A nasty yet working |
* solution is to explicitly stick "ssm" to the OFW tree. |
*/ |
ssm_node = ofw_find_device("/ssm@0,0"); |
if (ssm_node != -1) { |
ssm = ofw_tree_node_alloc(); |
if (ssm) { |
ofw_tree_node_process(ssm, root, |
ofw_find_device("/ssm@0,0")); |
ssm->peer = root->child; |
root->child = ssm; |
} |
} |
return root; |
} |
/branches/dd/boot/genarch/ofw.c |
---|
25,7 → 25,7 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <ofw.h> |
#include <ofwarch.h> |
#include <printf.h> |
48,7 → 48,8 |
if (ofw_chosen == -1) |
halt(); |
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) <= 0) |
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, |
sizeof(ofw_stdout)) <= 0) |
ofw_stdout = 0; |
ofw_root = ofw_find_device("/"); |
57,11 → 58,13 |
halt(); |
} |
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, sizeof(ofw_mmu)) <= 0) { |
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, |
sizeof(ofw_mmu)) <= 0) { |
puts("\r\nError: Unable to get mmu property, halted.\r\n"); |
halt(); |
} |
if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop, sizeof(ofw_memory_prop)) <= 0) { |
if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop, |
sizeof(ofw_memory_prop)) <= 0) { |
puts("\r\nError: Unable to get memory property, halted.\r\n"); |
halt(); |
} |
81,14 → 84,18 |
/** Perform a call to OpenFirmware client interface. |
* |
* @param service String identifying the service requested. |
* @param nargs Number of input arguments. |
* @param nret Number of output arguments. This includes the return value. |
* @param rets Buffer for output arguments or NULL. The buffer must accommodate nret - 1 items. |
* @param service String identifying the service requested. |
* @param nargs Number of input arguments. |
* @param nret Number of output arguments. This includes the return |
* value. |
* @param rets Buffer for output arguments or NULL. The buffer must |
* accommodate nret - 1 items. |
* |
* @return Return value returned by the client interface. |
* @return Return value returned by the client interface. |
*/ |
unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...) |
unsigned long |
ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, |
...) |
{ |
va_list list; |
ofw_args_t args; |
119,7 → 126,9 |
return ofw_call("finddevice", 1, 1, NULL, name); |
} |
int ofw_get_property(const phandle device, const char *name, void *buf, const int buflen) |
int |
ofw_get_property(const phandle device, const char *name, void *buf, |
const int buflen) |
{ |
return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen); |
} |
144,7 → 153,8 |
unsigned int ret = 1; |
if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0) |
if (ofw_get_property(ofw_root, "#address-cells", &ret, sizeof(ret)) <= 0) |
if (ofw_get_property(ofw_root, "#address-cells", &ret, |
sizeof(ret)) <= 0) |
ret = OFW_ADDRESS_CELLS; |
return ret; |
156,7 → 166,8 |
unsigned int ret; |
if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0) |
if (ofw_get_property(ofw_root, "#size-cells", &ret, sizeof(ret)) <= 0) |
if (ofw_get_property(ofw_root, "#size-cells", &ret, |
sizeof(ret)) <= 0) |
ret = OFW_SIZE_CELLS; |
return ret; |
192,7 → 203,8 |
ofw_arg_t result[4]; |
int shift; |
if (ofw_call("call-method", 3, 5, result, "translate", ofw_mmu, virt) != 0) { |
if (ofw_call("call-method", 4, 5, result, "translate", ofw_mmu, |
virt, 0) != 0) { |
puts("Error: MMU method translate() failed, halting.\n"); |
halt(); |
} |
212,7 → 224,8 |
{ |
ofw_arg_t retaddr; |
if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, virt) != 0) { |
if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, |
virt) != 0) { |
puts("Error: MMU method claim() failed, halting.\n"); |
halt(); |
} |
269,8 → 282,8 |
phys_lo = (uintptr_t) phys; |
} |
return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, virt, |
phys_hi, phys_lo); |
return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, |
virt, phys_hi, phys_lo); |
} |
/** Save OpenFirmware physical memory map. |
281,10 → 294,12 |
*/ |
int ofw_memmap(memmap_t *map) |
{ |
unsigned int ac = ofw_get_address_cells(ofw_memory); |
unsigned int sc = ofw_get_size_cells(ofw_memory); |
unsigned int ac = ofw_get_address_cells(ofw_memory) / |
(sizeof(uintptr_t) / sizeof(uint32_t)); |
unsigned int sc = ofw_get_size_cells(ofw_memory) / |
(sizeof(uintptr_t) / sizeof(uint32_t)); |
uint32_t buf[((ac + sc) * MEMMAP_MAX_RECORDS)]; |
uintptr_t buf[((ac + sc) * MEMMAP_MAX_RECORDS)]; |
int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(buf)); |
if (ret <= 0) /* ret is the number of written bytes */ |
return false; |
292,11 → 307,22 |
int pos; |
map->total = 0; |
map->count = 0; |
for (pos = 0; (pos < ret / sizeof(uint32_t)) && |
for (pos = 0; (pos < ret / sizeof(uintptr_t)) && |
(map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) { |
void * start = (void *) ((uintptr_t) buf[pos + ac - 1]); |
void *start = (void *) (buf[pos + ac - 1]); |
unsigned int size = buf[pos + ac + sc - 1]; |
/* |
* This is a hot fix of the issue which occurs on machines |
* where there are holes in the physical memory (such as |
* SunBlade 1500). Should we detect a hole in the physical |
* memory, we will ignore any memory detected behind |
* the hole and pretend the hole does not exist. |
*/ |
if ((map->count > 0) && (map->zones[map->count - 1].start + |
map->zones[map->count - 1].size < start)) |
break; |
if (size > 0) { |
map->zones[map->count].start = start; |
map->zones[map->count].size = size; |
308,13 → 334,13 |
return true; |
} |
int ofw_screen(screen_t *screen) |
{ |
char device_name[BUF_SIZE]; |
uint32_t virtaddr; |
if (ofw_get_property(ofw_aliases, "screen", device_name, sizeof(device_name)) <= 0) |
if (ofw_get_property(ofw_aliases, "screen", device_name, |
sizeof(device_name)) <= 0) |
return false; |
phandle device = ofw_find_device(device_name); |
321,27 → 347,78 |
if (device == -1) |
return false; |
if (ofw_get_property(device, "address", &virtaddr, sizeof(virtaddr)) <= 0) |
if (ofw_get_property(device, "address", &virtaddr, |
sizeof(virtaddr)) <= 0) |
return false; |
screen->addr = (void *) ((uintptr_t) virtaddr); |
if (ofw_get_property(device, "width", &screen->width, sizeof(screen->width)) <= 0) |
if (ofw_get_property(device, "width", &screen->width, |
sizeof(screen->width)) <= 0) |
return false; |
if (ofw_get_property(device, "height", &screen->height, sizeof(screen->height)) <= 0) |
if (ofw_get_property(device, "height", &screen->height, |
sizeof(screen->height)) <= 0) |
return false; |
if (ofw_get_property(device, "depth", &screen->bpp, sizeof(screen->bpp)) <= 0) |
if (ofw_get_property(device, "depth", &screen->bpp, |
sizeof(screen->bpp)) <= 0) |
return false; |
if (ofw_get_property(device, "linebytes", &screen->scanline, sizeof(screen->scanline)) <= 0) |
if (ofw_get_property(device, "linebytes", &screen->scanline, |
sizeof(screen->scanline)) <= 0) |
return false; |
return true; |
} |
#define RED(i) (((i) >> 5) & ((1 << 3) - 1)) |
#define GREEN(i) (((i) >> 3) & ((1 << 2) - 1)) |
#define BLUE(i) ((i) & ((1 << 3) - 1)) |
#define CLIP(i) ((i) <= 255 ? (i) : 255) |
/** |
* Sets up the palette for the 8-bit color depth configuration so that the |
* 3:2:3 color scheme can be used. Checks that setting the palette makes sense |
* (appropriate nodes exist in the OBP tree and the color depth is not greater |
* than 8). |
* |
* @return true if the palette has been set, false otherwise |
* |
*/ |
int ofw_setup_palette(void) |
{ |
char device_name[BUF_SIZE]; |
/* resolve alias */ |
if (ofw_get_property(ofw_aliases, "screen", device_name, |
sizeof(device_name)) <= 0) |
return false; |
/* for depth greater than 8 it makes no sense to set up the palette */ |
uint32_t depth; |
phandle device = ofw_find_device(device_name); |
if (device == -1) |
return false; |
if (ofw_get_property(device, "depth", &depth, sizeof(uint32_t)) <= 0) |
return false; |
if (depth != 8) |
return false; |
/* required in order to be able to make a method call */ |
ihandle screen = ofw_open(device_name); |
if (screen == -1) |
return false; |
/* setup the palette so that the (inverted) 3:2:3 scheme is usable */ |
unsigned int i; |
for (i = 0; i < 256; i++) |
ofw_call("call-method", 6, 1, NULL, "color!", screen, |
255 - i, CLIP(BLUE(i) * 37), GREEN(i) * 85, CLIP(RED(i) * 37)); |
return true; |
} |
void ofw_quiesce(void) |
{ |
ofw_call("quiesce", 0, 0, NULL); |
/branches/dd/boot/generic/align.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
/branches/dd/boot/generic/printf.c |
---|
83,14 → 83,16 |
*/ |
static void print_number(const unative_t num, const unsigned int base) |
{ |
int val = num; |
char d[sizeof(unative_t) * 8 + 1]; /* this is good enough even for base == 2 */ |
int val = num; |
/* This is enough even for base 2. */ |
char d[sizeof(unative_t) * 8 + 1]; |
int i = sizeof(unative_t) * 8 - 1; |
do { |
d[i--] = digits[val % base]; |
} while (val /= base); |
d[sizeof(unative_t) * 8] = 0; |
puts(&d[i + 1]); |
} |
156,89 → 158,89 |
int i = 0; |
va_list ap; |
char c; |
va_start(ap, fmt); |
while ((c = fmt[i++])) { |
switch (c) { |
/* control character */ |
/* control character */ |
case '%': |
switch (c = fmt[i++]) { |
/* percentile itself */ |
case '%': |
break; |
/* |
* String and character conversions. |
*/ |
case 's': |
puts(va_arg(ap, char_ptr)); |
goto loop; |
case 'c': |
c = (char) va_arg(ap, int); |
break; |
/* |
* Hexadecimal conversions with fixed width. |
*/ |
case 'P': |
puts("0x"); |
case 'p': |
print_fixed_hex(va_arg(ap, unative_t), |
sizeof(unative_t)); |
goto loop; |
case 'Q': |
puts("0x"); |
case 'q': |
print_fixed_hex(va_arg(ap, uint64_t), INT64); |
goto loop; |
case 'L': |
puts("0x"); |
case 'l': |
print_fixed_hex(va_arg(ap, unative_t), INT32); |
goto loop; |
case 'W': |
puts("0x"); |
case 'w': |
print_fixed_hex(va_arg(ap, unative_t), INT16); |
goto loop; |
case 'B': |
puts("0x"); |
case 'b': |
print_fixed_hex(va_arg(ap, unative_t), INT8); |
goto loop; |
/* |
* Decimal and hexadecimal conversions. |
*/ |
case 'd': |
print_number(va_arg(ap, unative_t), 10); |
goto loop; |
switch (c = fmt[i++]) { |
/* percentile itself */ |
case '%': |
break; |
/* |
* String and character conversions. |
*/ |
case 's': |
puts(va_arg(ap, char_ptr)); |
goto loop; |
case 'c': |
c = (char) va_arg(ap, int); |
break; |
/* |
* Hexadecimal conversions with fixed width. |
*/ |
case 'P': |
puts("0x"); |
case 'p': |
print_fixed_hex(va_arg(ap, unative_t), sizeof(unative_t)); |
goto loop; |
case 'Q': |
puts("0x"); |
case 'q': |
print_fixed_hex(va_arg(ap, uint64_t), INT64); |
goto loop; |
case 'L': |
puts("0x"); |
case 'l': |
print_fixed_hex(va_arg(ap, unative_t), INT32); |
goto loop; |
case 'W': |
puts("0x"); |
case 'w': |
print_fixed_hex(va_arg(ap, unative_t), INT16); |
goto loop; |
case 'B': |
puts("0x"); |
case 'b': |
print_fixed_hex(va_arg(ap, unative_t), INT8); |
goto loop; |
/* |
* Decimal and hexadecimal conversions. |
*/ |
case 'd': |
print_number(va_arg(ap, unative_t), 10); |
goto loop; |
case 'X': |
puts("0x"); |
case 'x': |
print_number(va_arg(ap, unative_t), 16); |
goto loop; |
/* |
* Bad formatting. |
*/ |
default: |
goto out; |
case 'X': |
puts("0x"); |
case 'x': |
print_number(va_arg(ap, unative_t), 16); |
goto loop; |
/* |
* Bad formatting. |
*/ |
default: |
goto out; |
} |
default: |
write(&c, 1); |
default: |
write(&c, 1); |
} |
loop: |
; |
} |
/branches/dd/boot/generic/string.c |
---|
39,9 → 39,9 |
/** Return number of characters in a string. |
* |
* @param str NULL terminated string. |
* @param str NULL terminated string. |
* |
* @return Number of characters in str. |
* @return Number of characters in str. |
*/ |
size_t strlen(const char *str) |
{ |
53,16 → 53,17 |
return i; |
} |
/** Compare two NULL terminated strings |
/** Compare two NULL terminated strings. |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
* characters on the minimum of their lengths. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param src First string to compare. |
* @param dst Second string to compare. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
int strcmp(const char *src, const char *dst) |
81,7 → 82,7 |
} |
/** Compare two NULL terminated strings |
/** Compare two NULL terminated strings. |
* |
* Do a char-by-char comparison of two NULL terminated strings. |
* The strings are considered equal iff they consist of the same |
88,11 → 89,12 |
* characters on the minimum of their lengths and specified maximal |
* length. |
* |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param len Maximal length for comparison. |
* @param src First string to compare. |
* @param dst Second string to compare. |
* @param len Maximal length for comparison. |
* |
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller. |
* @return 0 if the strings are equal, -1 if first is smaller, |
* 1 if second smaller. |
* |
*/ |
int strncmp(const char *src, const char *dst, size_t len) |
118,9 → 120,9 |
* If 'src' is shorter than 'len', '\0' is inserted behind the |
* last copied character. |
* |
* @param src Source string. |
* @param dest Destination buffer. |
* @param len Size of destination buffer. |
* @param src Source string. |
* @param dest Destination buffer. |
* @param len Size of destination buffer. |
*/ |
void strncpy(char *dest, const char *src, size_t len) |
{ |
132,13 → 134,13 |
dest[i-1] = '\0'; |
} |
/** Convert ascii representation to unative_t |
/** Convert ascii representation to unative_t. |
* |
* Supports 0x for hexa & 0 for octal notation. |
* Does not check for overflows, does not support negative numbers |
* |
* @param text Textual representation of number |
* @return Converted number or 0 if no valid number ofund |
* @param text Textual representation of number. |
* @return Converted number or 0 if no valid number found. |
*/ |
unative_t atoi(const char *text) |
{ |
152,9 → 154,9 |
base = 8; |
while (*text) { |
if (base != 16 && \ |
((*text >= 'A' && *text <= 'F' ) |
|| (*text >='a' && *text <='f'))) |
if (base != 16 && |
((*text >= 'A' && *text <= 'F') || |
(*text >='a' && *text <='f'))) |
break; |
if (base == 8 && *text >='8') |
break; |
176,5 → 178,28 |
return result; |
} |
/** Move piece of memory to another, possibly overlapping, location. |
* |
* @param dst Destination address. |
* @param src Source address. |
* @param len Number of bytes to move. |
* |
* @return Destination address. |
*/ |
void *memmove(void *dst, const void *src, size_t len) |
{ |
char *d = dst; |
const char *s = src; |
if (s < d) { |
while (len--) |
*(d + len) = *(s + len); |
} else { |
while (len--) |
*d++ = *s++; |
} |
return dst; |
} |
/** @} |
*/ |
/branches/dd/boot/generic/macros.h |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef BOOT_MACROS_H_ |
#define BOOT_MACROS_H_ |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define SIZE2KB(size) ((size) >> 10) |
#define SIZE2MB(size) ((size) >> 20) |
#define KB2SIZE(kb) ((kb) << 10) |
#define MB2SIZE(mb) ((mb) << 20) |
#define STRING(arg) STRING_ARG(arg) |
#define STRING_ARG(arg) #arg |
#endif |
/** @} |
*/ |
/branches/dd/boot/generic/string.h |
---|
42,6 → 42,7 |
extern int strncmp(const char *src, const char *dst, size_t len); |
extern void strncpy(char *dest, const char *src, size_t len); |
extern unative_t atoi(const char *text); |
extern void *memmove(void *dst, const void *src, size_t len); |
#endif |
/branches/dd/boot/Makefile |
---|
29,7 → 29,8 |
## Include configuration |
# |
-include Makefile.config |
-include ../Makefile.config |
-include ../config.defs |
## Paths |
# |
38,31 → 39,11 |
KERNELDIR = $(BASE)/kernel |
USPACEDIR = $(BASE)/uspace |
ifeq ($(CONFIG_DEBUG),y) |
DEFS += -DCONFIG_DEBUG |
endif |
.PHONY: all build clean generic_clean |
ifeq ($(CONFIG_BAT),y) |
DEFS += -DCONFIG_BAT |
endif |
all: ../Makefile.config ../config.h ../config.defs build |
ifeq ($(CONFIG_SMP),y) |
DEFS += -DCONFIG_SMP |
endif |
-include arch/$(BARCH)/Makefile.inc |
.PHONY: all build config distclean clean generic_clean |
all: |
../tools/config.py boot.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) $(IMAGE) |
$(MAKE) -C . build |
-include arch/$(ARCH)/Makefile.inc |
config: |
../tools/config.py boot.config |
distclean: clean |
-rm Makefile.config |
generic_clean: |
-rm generic/*.o genarch/*.o |
/branches/dd/boot/arch/ppc64/Makefile.inc |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/main.c |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/asm.h |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/ofwarch.c |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/types.h |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/main.h |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/Makefile |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/ppc64/loader/debug.inc |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/ofwarch.h |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/asm.S |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/regname.h |
---|
File deleted |
/branches/dd/boot/arch/ppc64/loader/boot.S |
---|
File deleted |
/branches/dd/boot/arch/ia32xen/grub/menu.lst |
---|
File deleted |
/branches/dd/boot/arch/ia32xen/grub/stage2_eltorito |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/dd/boot/arch/ia32xen/grub/COPYING |
---|
File deleted |
/branches/dd/boot/arch/ia32xen/grub/xen.gz |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/dd/boot/arch/ia32xen/grub/menu.debug.lst |
---|
File deleted |
/branches/dd/boot/arch/ia32xen/grub/README |
---|
File deleted |
/branches/dd/boot/arch/ia32xen/grub/xen.debug.gz |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/branches/dd/boot/arch/ia32xen/Makefile.inc |
---|
File deleted |
/branches/dd/boot/arch/sparc64/Makefile.inc |
---|
26,25 → 26,40 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
TMP=distroot |
TMP = distroot |
ifeq ($(CONFIG_AOUT_ISOFS_B),y) |
SILO_PACKAGE = silo.tar.gz |
else |
SILO_PACKAGE = silo.patched.tar.gz |
endif |
build: $(BASE)/image.iso |
$(BASE)/image.iso: depend arch/$(ARCH)/loader/image.boot |
$(BASE)/image.iso: depend arch/$(BARCH)/loader/image.boot |
mkdir -p $(TMP)/boot |
mkdir -p $(TMP)/HelenOS |
cat arch/$(ARCH)/silo/silo.tar.gz | (cd $(TMP)/boot; tar xvfz -) |
cp arch/$(ARCH)/silo/README arch/$(ARCH)/silo/COPYING arch/$(ARCH)/silo/silo.conf $(TMP)/boot |
cp arch/$(ARCH)/loader/image.boot $(TMP)/HelenOS/image.boot |
cat arch/$(BARCH)/silo/$(SILO_PACKAGE) | (cd $(TMP)/boot; tar xvfz -) |
cp arch/$(BARCH)/silo/README arch/$(BARCH)/silo/COPYING $(TMP)/boot |
ifeq ($(CONFIG_RD_EXTERNAL),y) |
cp arch/$(BARCH)/silo/silo.conf $(TMP)/boot/silo.conf |
else |
cat arch/$(BARCH)/silo/silo.conf | grep -v initrd > $(TMP)/boot/silo.conf |
endif |
cp arch/$(BARCH)/loader/image.boot $(TMP)/HelenOS/image.boot |
gzip -f $(TMP)/HelenOS/image.boot |
ifeq ($(CONFIG_RD_EXTERNAL),y) |
cp arch/$(BARCH)/loader/initrd.img $(TMP)/HelenOS/initrd.img |
endif |
mkisofs -f -G $(TMP)/boot/isofs.b -B ... -r -o $(BASE)/image.iso $(TMP)/ |
depend: |
-rm arch/$(ARCH)/loader/image.boot |
-rm arch/$(BARCH)/loader/image.boot |
arch/$(ARCH)/loader/image.boot: |
$(MAKE) -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)" |
arch/$(BARCH)/loader/image.boot: |
$(MAKE) -C arch/$(BARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
clean: generic_clean |
$(MAKE) -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
$(MAKE) -C arch/$(BARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
-rm -fr $(TMP) |
-rm -f $(BASE)/image.iso |
/branches/dd/boot/arch/sparc64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/sparc64/loader/_link.ld.in |
---|
0,0 → 1,23 |
OUTPUT_FORMAT("elf64-sparc") |
ENTRY(start) |
SECTIONS { |
.boot 0x4000: AT (0x4000) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); |
[[COMPONENTS]] |
} |
/DISCARD/ : { |
*(.comment); |
*(.note*); |
} |
} |
/branches/dd/boot/arch/sparc64/loader/asm.S |
---|
30,6 → 30,9 |
#include <stack.h> |
#include <register.h> |
.register %g2, #scratch |
.register %g3, #scratch |
.text |
.global halt |
41,8 → 44,7 |
nop |
memcpy: |
.register %g2, #scratch |
.register %g3, #scratch |
mov %o0, %o3 ! save dst |
add %o1, 7, %g1 |
and %g1, -8, %g1 |
cmp %o1, %g1 |
61,7 → 63,7 |
mov %g2, %g3 |
2: |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
3: |
and %g1, -8, %g1 |
cmp %o0, %g1 |
95,9 → 97,38 |
mov %g2, %g3 |
jmp %o7 + 8 ! exit point |
mov %o1, %o0 |
mov %o3, %o0 |
jump_to_kernel: |
/* |
* We have copied code and now we need to guarantee cache coherence. |
* 1. Make sure that the code we have moved has drained to main memory. |
* 2. Invalidate I-cache. |
* 3. Flush instruction pipeline. |
*/ |
/* |
* US3 processors have a write-invalidate cache, so explicitly |
* invalidating it is not required. Whether to invalidate I-cache |
* or not is decided according to the value of the global |
* "subarchitecture" variable (set in the bootstrap). |
*/ |
set subarchitecture, %g2 |
ldub [%g2], %g2 |
cmp %g2, 3 |
be 1f |
nop |
0: |
call icache_flush |
nop |
1: |
membar #StoreStore |
/* |
* Flush the instruction pipeline. |
*/ |
flush %i7 |
mov %o0, %l1 |
mov %o1, %o0 |
mov %o2, %o1 |
105,6 → 136,23 |
jmp %l1 ! jump to kernel |
nop |
#define ICACHE_SIZE 8192 |
#define ICACHE_LINE_SIZE 32 |
#define ICACHE_SET_BIT (1 << 13) |
#define ASI_ICACHE_TAG 0x67 |
# Flush I-cache |
icache_flush: |
set ((ICACHE_SIZE - ICACHE_LINE_SIZE) | ICACHE_SET_BIT), %g1 |
stxa %g0, [%g1] ASI_ICACHE_TAG |
0: membar #Sync |
subcc %g1, ICACHE_LINE_SIZE, %g1 |
bnz,pt %xcc, 0b |
stxa %g0, [%g1] ASI_ICACHE_TAG |
membar #Sync |
retl |
! SF Erratum #51 |
nop |
.global ofw |
ofw: |
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp |
/branches/dd/boot/arch/sparc64/loader/boot.S |
---|
53,6 → 53,15 |
.ascii "HdrS" |
.word 0 |
.half 0 |
.half 0 |
.half 0 |
.half 0 |
.global silo_ramdisk_image |
silo_ramdisk_image: |
.word 0 |
.global silo_ramdisk_size |
silo_ramdisk_size: |
.word 0 |
.align 8 |
1: |
/branches/dd/boot/arch/sparc64/loader/main.c |
---|
36,34 → 36,87 |
#include <ofw_tree.h> |
#include "ofwarch.h" |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
bootinfo_t bootinfo; |
component_t components[COMPONENTS]; |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
/** UltraSPARC subarchitecture - 1 for US, 3 for US3 */ |
uint8_t subarchitecture; |
/** |
* mask of the MID field inside the ICBUS_CONFIG register shifted by |
* MID_SHIFT bits to the right |
*/ |
uint16_t mid_mask; |
/** Print version information. */ |
static void version_print(void) |
{ |
printf("HelenOS SPARC64 Bootloader\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n", release, revision, timestamp); |
printf("HelenOS SPARC64 Bootloader\nRelease %s%s%s\n" |
"Copyright (c) 2006 HelenOS project\n", |
release, revision, timestamp); |
} |
/* the lowest ID (read from the VER register) of some US3 CPU model */ |
#define FIRST_US3_CPU 0x14 |
/* the greatest ID (read from the VER register) of some US3 CPU model */ |
#define LAST_US3_CPU 0x19 |
/* UltraSPARC IIIi processor implementation code */ |
#define US_IIIi_CODE 0x15 |
/** |
* Sets the global variables "subarchitecture" and "mid_mask" to |
* correct values. |
*/ |
static void detect_subarchitecture(void) |
{ |
uint64_t v; |
asm volatile ("rdpr %%ver, %0\n" : "=r" (v)); |
v = (v << 16) >> 48; |
if ((v >= FIRST_US3_CPU) && (v <= LAST_US3_CPU)) { |
subarchitecture = SUBARCH_US3; |
if (v == US_IIIi_CODE) |
mid_mask = (1 << 5) - 1; |
else |
mid_mask = (1 << 10) - 1; |
} else if (v < FIRST_US3_CPU) { |
subarchitecture = SUBARCH_US; |
mid_mask = (1 << 5) - 1; |
} else { |
printf("\nThis CPU is not supported by HelenOS."); |
} |
} |
void bootstrap(void) |
{ |
void *base = (void *) KERNEL_VIRTUAL_ADDRESS; |
void *balloc_base; |
unsigned int top = 0; |
int i, j; |
version_print(); |
detect_subarchitecture(); |
init_components(components); |
if (!ofw_get_physmem_start(&bootinfo.physmem_start)) { |
75,34 → 128,103 |
printf("Error: unable to get memory map, halting.\n"); |
halt(); |
} |
if (bootinfo.memmap.total == 0) { |
printf("Error: no memory detected, halting.\n"); |
halt(); |
} |
/* |
* SILO for some reason adds 0x400000 and subtracts |
* bootinfo.physmem_start to/from silo_ramdisk_image. |
* We just need plain physical address so we fix it up. |
*/ |
if (silo_ramdisk_image) { |
silo_ramdisk_image += bootinfo.physmem_start; |
silo_ramdisk_image -= 0x400000; |
/* Install 1:1 mapping for the ramdisk. */ |
if (ofw_map((void *)((uintptr_t) silo_ramdisk_image), |
(void *)((uintptr_t) silo_ramdisk_image), |
silo_ramdisk_size, -1) != 0) { |
printf("Failed to map ramdisk.\n"); |
halt(); |
} |
} |
printf("\nSystem info\n"); |
printf(" memory: %dM starting at %P\n", |
bootinfo.memmap.total >> 20, bootinfo.physmem_start); |
bootinfo.memmap.total >> 20, bootinfo.physmem_start); |
printf("\nMemory statistics\n"); |
printf(" kernel entry point at %P\n", KERNEL_VIRTUAL_ADDRESS); |
printf(" %P: boot info structure\n", &bootinfo); |
unsigned int i; |
for (i = 0; i < COMPONENTS; i++) |
/* |
* Figure out destination address for each component. |
* In this phase, we don't copy the components yet because we want to |
* to be careful not to overwrite anything, especially the components |
* which haven't been copied yet. |
*/ |
bootinfo.taskmap.count = 0; |
for (i = 0; i < COMPONENTS; i++) { |
printf(" %P: %s image (size %d bytes)\n", components[i].start, |
components[i].name, components[i].size); |
top = ALIGN_UP(top, PAGE_SIZE); |
if (i > 0) { |
if (bootinfo.taskmap.count == TASKMAP_MAX_RECORDS) { |
printf("Skipping superfluous components.\n"); |
break; |
} |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = |
base + top; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = |
components[i].size; |
strncpy(bootinfo.taskmap.tasks[ |
bootinfo.taskmap.count].name, components[i].name, |
BOOTINFO_TASK_NAME_BUFLEN); |
bootinfo.taskmap.count++; |
} |
top += components[i].size; |
} |
void * base = (void *) KERNEL_VIRTUAL_ADDRESS; |
unsigned int top = 0; |
j = bootinfo.taskmap.count - 1; /* do not consider ramdisk */ |
printf("\nCopying components\n"); |
bootinfo.taskmap.count = 0; |
for (i = 0; i < COMPONENTS; i++) { |
printf(" %s...", components[i].name); |
if (silo_ramdisk_image) { |
/* Treat the ramdisk as the last bootinfo task. */ |
if (bootinfo.taskmap.count == TASKMAP_MAX_RECORDS) { |
printf("Skipping ramdisk.\n"); |
goto skip_ramdisk; |
} |
top = ALIGN_UP(top, PAGE_SIZE); |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = |
base + top; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = |
silo_ramdisk_size; |
bootinfo.taskmap.count++; |
printf("\nCopying ramdisk..."); |
/* |
* Claim and map the whole ramdisk as it may exceed the area |
* given to us by SILO. |
*/ |
(void) ofw_claim_phys(base + top, silo_ramdisk_size); |
(void) ofw_map(bootinfo.physmem_start + base + top, base + top, |
silo_ramdisk_size, -1); |
memmove(base + top, (void *)((uintptr_t)silo_ramdisk_image), |
silo_ramdisk_size); |
printf("done.\n"); |
top += silo_ramdisk_size; |
} |
skip_ramdisk: |
/* |
* Now we can proceed to copy the components. We do it in reverse order |
* so that we don't overwrite anything even if the components overlap |
* with base. |
*/ |
printf("\nCopying bootinfo tasks\n"); |
for (i = COMPONENTS - 1; i > 0; i--, j--) { |
printf(" %s...", components[i].name); |
/* |
* At this point, we claim the physical memory that we are |
* going to use. We should be safe in case of the virtual |
110,36 → 232,41 |
* SPARC binding, should restrict its use of virtual memory |
* to addresses from [0xffd00000; 0xffefffff] and |
* [0xfe000000; 0xfeffffff]. |
* |
* XXX We don't map this piece of memory. We simply rely on |
* SILO to have it done for us already in this case. |
*/ |
(void) ofw_claim_phys(bootinfo.physmem_start + base + top, |
(void) ofw_claim_phys(bootinfo.physmem_start + |
bootinfo.taskmap.tasks[j].addr, |
ALIGN_UP(components[i].size, PAGE_SIZE)); |
memcpy(base + top, components[i].start, components[i].size); |
if (i > 0) { |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = |
base + top; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = |
components[i].size; |
bootinfo.taskmap.count++; |
} |
top += components[i].size; |
memcpy((void *)bootinfo.taskmap.tasks[j].addr, |
components[i].start, components[i].size); |
printf("done.\n"); |
} |
printf("\nCopying kernel..."); |
(void) ofw_claim_phys(bootinfo.physmem_start + base, |
ALIGN_UP(components[0].size, PAGE_SIZE)); |
memcpy(base, components[0].start, components[0].size); |
printf("done.\n"); |
/* |
* Claim the physical memory for the boot allocator. |
* Claim and map the physical memory for the boot allocator. |
* Initialize the boot allocator. |
*/ |
(void) ofw_claim_phys(bootinfo.physmem_start + |
base + ALIGN_UP(top, PAGE_SIZE), BALLOC_MAX_SIZE); |
balloc_init(&bootinfo.ballocs, ALIGN_UP(((uintptr_t) base) + top, |
PAGE_SIZE)); |
balloc_base = base + ALIGN_UP(top, PAGE_SIZE); |
(void) ofw_claim_phys(bootinfo.physmem_start + balloc_base, |
BALLOC_MAX_SIZE); |
(void) ofw_map(bootinfo.physmem_start + balloc_base, balloc_base, |
BALLOC_MAX_SIZE, -1); |
balloc_init(&bootinfo.ballocs, (uintptr_t)balloc_base); |
printf("\nCanonizing OpenFirmware device tree..."); |
bootinfo.ofw_root = ofw_tree_build(); |
printf("done.\n"); |
#ifdef CONFIG_SMP |
#ifdef CONFIG_AP |
printf("\nChecking for secondary processors..."); |
if (!ofw_cpu()) |
printf("Error: unable to get CPU properties\n"); |
146,9 → 273,10 |
printf("done.\n"); |
#endif |
ofw_setup_palette(); |
printf("\nBooting the kernel...\n"); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, |
sizeof(bootinfo)); |
} |
/branches/dd/boot/arch/sparc64/loader/main.h |
---|
38,12 → 38,19 |
#define TASKMAP_MAX_RECORDS 32 |
/** Size of buffer for storing task name in task_t. */ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
#define BSP_PROCESSOR 1 |
#define AP_PROCESSOR 0 |
#define SUBARCH_US 1 |
#define SUBARCH_US3 3 |
typedef struct { |
void *addr; |
uint32_t size; |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} task_t; |
typedef struct { |
59,6 → 66,9 |
ofw_tree_node_t *ofw_root; |
} bootinfo_t; |
extern uint32_t silo_ramdisk_image; |
extern uint32_t silo_ramdisk_size; |
extern bootinfo_t bootinfo; |
extern void start(void); |
/branches/dd/boot/arch/sparc64/loader/ofwarch.c |
---|
32,7 → 32,7 |
* @brief Architecture dependent parts of OpenFirmware interface. |
*/ |
#include <ofwarch.h> |
#include <ofwarch.h> |
#include <ofw.h> |
#include <printf.h> |
#include <string.h> |
40,6 → 40,10 |
#include "main.h" |
#include "asm.h" |
/* these tho variables will be set by the detect_subarchitecture function */ |
extern uint8_t subarchitecture; |
extern uint16_t mid_mask; |
void write(const char *str, const int len) |
{ |
int i; |
56,31 → 60,40 |
return flag != -1; |
} |
int ofw_cpu(void) |
/** |
* Starts all CPUs represented by following siblings of the given node, |
* except for the current CPU. |
* |
* @param child The first child of the OFW tree node whose children |
* represent CPUs to be woken up. |
* @param current_mid MID of the current CPU, the current CPU will |
* (of course) not be woken up. |
* @return Number of CPUs which have the same parent node as |
* "child". |
*/ |
static int wake_cpus_in_node(phandle child, uint64_t current_mid) |
{ |
int cpus; |
char type_name[BUF_SIZE]; |
phandle node; |
node = ofw_get_child_node(ofw_root); |
if (node == 0 || node == -1) { |
printf("Could not find any child nodes of the root node.\n"); |
return 0; |
} |
uint64_t current_mid; |
asm volatile ("ldxa [%1] %2, %0\n" : "=r" (current_mid) : "r" (0), "i" (ASI_UPA_CONFIG)); |
current_mid >>= UPA_CONFIG_MID_SHIFT; |
current_mid &= UPA_CONFIG_MID_MASK; |
int cpus; |
for (cpus = 0; node != 0 && node != -1; node = ofw_get_peer_node(node), cpus++) { |
if (ofw_get_property(node, "device_type", type_name, sizeof(type_name)) > 0) { |
for (cpus = 0; child != 0 && child != -1; |
child = ofw_get_peer_node(child), cpus++) { |
if (ofw_get_property(child, "device_type", type_name, |
sizeof(type_name)) > 0) { |
if (strcmp(type_name, "cpu") == 0) { |
uint32_t mid; |
if (ofw_get_property(node, "upa-portid", &mid, sizeof(mid)) <= 0) |
/* |
* "upa-portid" for US, "portid" for US-III, |
* "cpuid" for US-IV |
*/ |
if (ofw_get_property( |
child, "upa-portid", |
&mid, sizeof(mid)) <= 0 |
&& ofw_get_property(child, "portid", |
&mid, sizeof(mid)) <= 0 |
&& ofw_get_property(child, "cpuid", |
&mid, sizeof(mid)) <= 0) |
continue; |
if (current_mid != mid) { |
87,9 → 100,10 |
/* |
* Start secondary processor. |
*/ |
(void) ofw_call("SUNW,start-cpu", 3, 1, NULL, node, |
KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | AP_PROCESSOR); |
(void) ofw_call("SUNW,start-cpu", 3, 1, |
NULL, child, KERNEL_VIRTUAL_ADDRESS, |
bootinfo.physmem_start | |
AP_PROCESSOR); |
} |
} |
} |
98,12 → 112,59 |
return cpus; |
} |
/** |
* Finds out the current CPU's MID and wakes up all AP processors. |
*/ |
int ofw_cpu(void) |
{ |
int cpus; |
phandle node; |
phandle subnode; |
phandle cpus_parent; |
phandle cmp; |
char name[BUF_SIZE]; |
/* get the current CPU MID */ |
uint64_t current_mid; |
asm volatile ("ldxa [%1] %2, %0\n" |
: "=r" (current_mid) |
: "r" (0), "i" (ASI_ICBUS_CONFIG)); |
current_mid >>= ICBUS_CONFIG_MID_SHIFT; |
current_mid &= mid_mask; |
/* wake up CPUs */ |
cpus_parent = ofw_find_device("/ssm@0,0"); |
if (cpus_parent == 0 || cpus_parent == -1) { |
cpus_parent = ofw_find_device("/"); |
} |
node = ofw_get_child_node(cpus_parent); |
cpus = wake_cpus_in_node(node, current_mid); |
while (node != 0 && node != -1) { |
if (ofw_get_property(node, "name", name, |
sizeof(name)) > 0) { |
if (strcmp(name, "cmp") == 0) { |
subnode = ofw_get_child_node(node); |
cpus += wake_cpus_in_node(subnode, |
current_mid); |
} |
} |
node = ofw_get_peer_node(node); |
} |
return cpus; |
} |
/** Get physical memory starting address. |
* |
* @param start Pointer to variable where the physical memory starting |
* address will be stored. |
* @param start Pointer to variable where the physical memory starting |
* address will be stored. |
* |
* @return Non-zero on succes, zero on failure. |
* @return Non-zero on succes, zero on failure. |
*/ |
int ofw_get_physmem_start(uintptr_t *start) |
{ |
/branches/dd/boot/arch/sparc64/loader/register.h |
---|
33,8 → 33,7 |
#define PSTATE_PRIV_BIT 4 |
#define PSTATE_AM_BIT 8 |
#define ASI_UPA_CONFIG 0x4a |
#define UPA_CONFIG_MID_SHIFT 17 |
#define UPA_CONFIG_MID_MASK 0x1f |
#define ASI_ICBUS_CONFIG 0x4a |
#define ICBUS_CONFIG_MID_SHIFT 17 |
#endif |
/branches/dd/boot/arch/sparc64/loader/Makefile |
---|
27,13 → 27,19 |
# |
include ../../../../version |
include ../../../Makefile.config |
-include ../../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = /usr/local/sparc64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 49,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
59,18 → 57,11 |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
endif |
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64 |
CFLAGS = -DRELEASE=$(RELEASE) -I. -I../../../generic -I../../../genarch -imacros ../../../../config.h -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64 -mno-fpu -pipe |
ifdef REVISION |
CFLAGS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
CFLAGS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
SOURCES = \ |
main.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
../../../genarch/balloc.c \ |
80,23 → 71,50 |
asm.S \ |
boot.S |
# |
# All components that go to image.boot without the ramdisk. |
# |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
# |
# Final list of all components that go to image.boot. |
# |
ALL_COMPONENTS = $(COMPONENTS) |
ifeq ($(CONFIG_RD_EXTERNAL),n) |
ALL_COMPONENTS += ./initrd.img |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fhc/fhc \ |
$(USPACEDIR)/srv/obio/obio |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/bdsh/bdsh \ |
$(USPACEDIR)/app/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
ALL_COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(ALL_COMPONENTS)))) |
.PHONY: all clean depend |
104,17 → 122,37 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot boot.disasm Makefile.depend |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(ALL_COMPONENT_OBJECTS) $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(ALL_COMPONENT_OBJECTS): $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(ALL_COMPONENTS) |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
123,4 → 161,4 |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
disasm: image.boot |
$(OBJDUMP) -d image.boot > boot.disasm |
$(OBJDUMP) -d image.boot > image.disasm |
/branches/dd/boot/arch/sparc64/silo/silo.patched.tar.gz |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/dd/boot/arch/sparc64/silo/silo.conf |
---|
1,3 → 1,4 |
timeout = 0 |
image = /HelenOS/image.boot |
image = /HelenOS/image.boot.gz |
label = HelenOS |
initrd = /HelenOS/initrd.img |
/branches/dd/boot/arch/ia64/Makefile.inc |
---|
26,39 → 26,17 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#ifeq ($(MACHINE),ski) |
#VMAXLMA_SRC = tools/ia64/vmaxlma.c |
#build: $(BASE)/kernel.bin |
#echo Building SKI |
#$(BASE)/kernel.bin: $(KERNELDIR)/kernel.bin vmaxlma |
# cp $(KERNELDIR)/kernel.bin $(BASE)/kernel.bin |
# ./vmaxlma $(BASE)/kernel.bin |
#vmaxlma: $(VMAXLMA_SRC) |
# $(CC) $(VMAXLMA_SRC) -o $@ |
#clean: |
# -rm -f $(BASE)/kernel.bin vmaxlma |
#else |
build: $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot |
cp arch/$(ARCH)/loader/image.boot $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(BARCH)/loader/image.boot |
cp arch/$(BARCH)/loader/image.boot $(BASE)/image.boot |
depend: |
-rm arch/$(ARCH)/loader/image.boot |
-rm arch/$(BARCH)/loader/image.boot |
arch/$(ARCH)/loader/image.boot: |
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)" |
arch/$(BARCH)/loader/image.boot: |
make -C arch/$(BARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
clean: generic_clean |
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)" |
make -C arch/$(BARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
-rm -f $(BASE)/image.boot |
#endif |
/branches/dd/boot/arch/ia64/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/ia64/loader/_link.ld.in |
---|
0,0 → 1,29 |
OUTPUT_FORMAT("elf64-ia64-little") |
ENTRY(start) |
SECTIONS { |
.boot 0x4400000: AT (0x4400000) { |
*(BOOTSTRAP); |
[[COMPONENTS]] |
. = ALIGN (16384); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
_got = . ; |
*(.got .got.*); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); |
} |
.sboot : { |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
} |
/DISCARD/ : { |
*(.comment); |
*(.note*); |
} |
} |
/branches/dd/boot/arch/ia64/loader/asm.S |
---|
37,7 → 37,5 |
alloc loc0 = ar.pfs, 1, 1, 0, 0 |
movl r8 = 0x4404000;; |
mov b1 = r8 ;; |
mov r1 = in0; |
mov r1 = in0; #Save bootinfo prt |
br.call.sptk.many b0 = b1;; |
.global ofw |
ofw: |
/branches/dd/boot/arch/ia64/loader/boot.S |
---|
34,6 → 34,7 |
.global start |
start: |
mov ar.rsc = r0 |
# movl r8 = (VRN_KERNEL << VRN_SHIFT) ;; |
movl r1 = 0x4400000 |
57,6 → 58,22 |
mov b1 = r18 ;; |
br.call.sptk.many b0 = b1 |
.align 512 |
ap_start: |
ap_loop: |
movl r18=0x4405000;; |
mov b1 = r18 ;; |
br.call.sptk.many b0 = b1;; |
.align 1024 |
.align 4096 |
.global binfo |
binfo: |
.bss #on this line is ".bss", it cannot be seen in my mcedit :-( |
/branches/dd/boot/arch/ia64/loader/main.c |
---|
1,6 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
33,11 → 33,13 |
#include "_components.h" |
#include <align.h> |
#include <balloc.h> |
#include <macros.h> |
#include <string.h> |
bootinfo_t bootinfo; |
extern bootinfo_t binfo; |
component_t components[COMPONENTS]; |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
void write(const char *str, const int len) |
{ |
44,15 → 46,22 |
return; |
} |
#define DEFAULT_MEMORY_BASE 0x4000000 |
#define DEFAULT_MEMORY_SIZE 0x4000000 |
#define DEFAULT_LEGACY_IO_BASE 0x00000FFFFC000000 |
#define DEFAULT_LEGACY_IO_SIZE 0x4000000 |
#define DEFAULT_FREQ_SCALE 0x0000000100000001 /* 1/1 */ |
#define DEFAULT_SYS_FREQ 100000000 /* 100MHz */ |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
60,26 → 69,18 |
/** Print version information. */ |
static void version_print(void) |
{ |
printf("HelenOS IA64 Bootloader\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n", release, revision, timestamp); |
printf("HelenOS IA64 Bootloader\nRelease %s%s%s\n" |
"Copyright (c) 2006 HelenOS project\n", release, revision, |
timestamp); |
} |
void bootstrap(void) |
{ |
int ii; |
//for(ii=0;ii<KERNEL_SIZE;ii++) ((char *)(0x100000))[ii] = ((char *)KERNEL_START)[ii+1]; |
//((int *)(0x100000))[0]++; |
bootinfo_t *bootinfo = &binfo; |
version_print(); |
init_components(components); |
printf("\nSystem info\n"); |
91,20 → 92,46 |
printf(" %P: %s image (size %d bytes)\n", components[i].start, |
components[i].name, components[i].size); |
if (!bootinfo->hello_configured) { |
/* |
* Load configuration defaults for simulators. |
*/ |
bootinfo->memmap_items = 0; |
bootinfo->memmap[bootinfo->memmap_items].base = |
DEFAULT_MEMORY_BASE; |
bootinfo->memmap[bootinfo->memmap_items].size = |
DEFAULT_MEMORY_SIZE; |
bootinfo->memmap[bootinfo->memmap_items].type = |
EFI_MEMMAP_FREE_MEM; |
bootinfo->memmap_items++; |
bootinfo.taskmap.count = 0; |
bootinfo->memmap[bootinfo->memmap_items].base = |
DEFAULT_LEGACY_IO_BASE; |
bootinfo->memmap[bootinfo->memmap_items].size = |
DEFAULT_LEGACY_IO_SIZE; |
bootinfo->memmap[bootinfo->memmap_items].type = |
EFI_MEMMAP_IO_PORTS; |
bootinfo->memmap_items++; |
bootinfo->freq_scale = DEFAULT_FREQ_SCALE; |
bootinfo->sys_freq = DEFAULT_SYS_FREQ; |
} |
bootinfo->taskmap.count = 0; |
for (i = 0; i < COMPONENTS; i++) { |
if (i > 0) { |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = components[i].start; |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = components[i].size; |
bootinfo.taskmap.count++; |
bootinfo->taskmap.tasks[bootinfo->taskmap.count].addr = |
components[i].start; |
bootinfo->taskmap.tasks[bootinfo->taskmap.count].size = |
components[i].size; |
strncpy(bootinfo->taskmap.tasks[ |
bootinfo->taskmap.count].name, |
components[i].name, BOOTINFO_TASK_NAME_BUFLEN); |
bootinfo->taskmap.count++; |
} |
} |
jump_to_kernel(&bootinfo); |
jump_to_kernel(bootinfo); |
} |
/branches/dd/boot/arch/ia64/loader/gefi/Make.defaults |
---|
27,30 → 27,19 |
# |
INSTALLROOT=/usr/local |
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) |
TOPDIR := $(shell pwd) |
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) |
INCDIR = -I. -I$(CDIR)/inc -I$(CDIR)/inc/$(ARCH) -I$(CDIR)/inc/protocol |
ARCH = ia64 |
INCDIR = -I. -I$(CDIR)/inc -I$(CDIR)/inc/$(ARCH) -I$(CDIR)/inc/protocol |
CPPFLAGS = -DCONFIG_$(ARCH) |
CFLAGS = -O2 -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants |
LDFLAGS = -nostdlib |
INSTALL = install |
CFLAGS = -O2 -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -frename-registers -mfixed-range=f32-f127 |
LDFLAGS = -nostdlib |
INSTALL = install |
GCC_VERSION=$(shell $(CROSS_COMPILE)$(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') |
# prefix = |
CC = $(prefix)gcc |
AS = $(prefix)as |
LD = $(prefix)ld |
AR = $(prefix)ar |
RANLIB = $(prefix)ranlib |
OBJCOPY = $(prefix)objcopy |
OBJDUMP = $(prefix)objdump |
ifneq ($(GCC_VERSION),2) |
CFLAGS += -frename-registers |
endif |
CFLAGS += -mfixed-range=f32-f127 |
CC = $(prefix)gcc |
AS = $(prefix)as |
LD = $(prefix)ld |
AR = $(prefix)ar |
RANLIB = $(prefix)ranlib |
OBJCOPY = $(prefix)objcopy |
OBJDUMP = $(prefix)objdump |
/branches/dd/boot/arch/ia64/loader/gefi/HelenOS/hello.c |
---|
1,9 → 1,29 |
#include <efi.h> |
#include <efilib.h> |
#include <../../../../../../kernel/arch/ia64/include/bootinfo.h> |
#define KERNEL_LOAD_ADDRESS 0x4400000 |
#define MEM_MAP_DESCRIPTOR_OFFSET_TYPE 0 |
#define MEM_MAP_DESCRIPTOR_OFFSET_BASE 8 |
#define MEM_MAP_DESCRIPTOR_OFFSET_PAGES 24 |
//Link image as a data array into hello - usefull with network boot |
//#define IMAGE_LINKED |
bootinfo_t *bootinfo=(bootinfo_t *)BOOTINFO_ADDRESS; |
#ifdef IMAGE_LINKED |
extern char HOSimage[]; |
extern int HOSimagesize; |
#endif |
static CHAR16 * |
a2u (char *str) |
{ |
15,24 → 35,7 |
mem[i] = 0; |
return mem; |
} |
char HEX[256]; |
char hexs[]="0123456789ABCDEF"; |
/* |
void to_hex(unsigned long long num) |
{ |
int a; |
for(a=15;a>=0;a--) |
{ |
char c=num - (num & 0xfffffffffffffff0LL); |
num/=16; |
c=hexs[c]; |
HEX[a]=c; |
} |
} |
*/ |
EFI_STATUS |
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) |
{ |
72,16 → 75,18 |
EFI_FILE *FileHandle; |
BS->HandleProtocol(LoadedImage->DeviceHandle, &FileSystemProtocol, &Vol); |
Vol->OpenVolume (Vol, &CurDir); |
char FileName[1024]; |
char *OsKernelBuffer; |
int i; |
int defaultLoad; |
int imageLoad; |
UINTN Size; |
StrCpy(FileName,DevicePathToStr(LoadedImage->FilePath)); |
for(i=StrLen(FileName);i>=0 && FileName[i]!='\\';i--); |
FileName[i] = 0; |
FileName[0] = 0; |
Print(L"%s\n",LoadedImage->LoadOptions); |
97,11 → 102,13 |
} |
while(LoadOptions[i]==L' ') if(LoadOptions[i++]==0) break; |
if(LoadOptions[i++]==0) |
if(LoadOptions[i++]==0){ |
StrCat(FileName,L"\\image.bin"); |
else{ |
defaultLoad=1; |
} |
/* else{ |
CHAR16 buf[1024]; |
buf[0]='\\'; |
//buf[0]='\\'; |
i--; |
int j; |
for(j=0;LoadOptions[i+j]!=L' '&&LoadOptions[i+j]!=0;j++) |
108,38 → 115,101 |
buf[j+1]=LoadOptions[i+j]; |
buf[j+1]=0; |
StrCat(FileName,buf); |
defaultLoad=0; |
}*/ |
else{ |
CHAR16 buf[1024]; |
//buf[0]='\\'; |
i--; |
int j; |
for(j=0;LoadOptions[i+j]!=L' '&&LoadOptions[i+j]!=0;j++) |
buf[j]=LoadOptions[i+j]; |
buf[j+1]=0; |
StrCat(FileName,buf); |
defaultLoad=0; |
} |
//Print(L"%s\n",FileName); |
EFI_STATUS stat; |
stat=CurDir->Open(CurDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); |
if(EFI_ERROR(stat)){ |
Print(L"Error Opening Image %s\n",FileName); |
return 0; |
imageLoad=1; |
#ifdef IMAGE_LINKED |
if(defaultLoad) { |
Print(L"Using Linked Image\n"); |
imageLoad=0; |
} |
Size = 0x00400000; |
BS->AllocatePool(EfiLoaderData, Size, &OsKernelBuffer); |
FileHandle->Read(FileHandle, &Size, OsKernelBuffer); |
FileHandle->Close(FileHandle); |
#endif |
if(Size<1) return 0; |
char * HOS; |
if(imageLoad) |
{ |
Size = 0x00400000; |
Vol->OpenVolume (Vol, &CurDir); |
char * HOS = OsKernelBuffer; |
EFI_STATUS stat; |
stat=CurDir->Open(CurDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); |
if(EFI_ERROR(stat)){ |
Print(L"Error Opening Image %s\n",FileName); |
return 0; |
} |
BS->AllocatePool(EfiLoaderData, Size, &OsKernelBuffer); |
FileHandle->Read(FileHandle, &Size, OsKernelBuffer); |
FileHandle->Close(FileHandle); |
HOS = OsKernelBuffer; |
if(Size<1) return 0; |
} |
#ifdef IMAGE_LINKED |
else { |
HOS = HOSimage; |
Size = HOSimagesize; |
Print(L"Image start %llX\n",(long long)HOS); |
Print(L"Image size %llX\n",(long long)Size); |
Print(L"Image &size %llX\n",(long long)&Size); |
} |
#endif |
int HOSSize = Size; |
{ |
rArg rSAL; |
rArg rPAL; |
//Setup AP's wake up address |
LibSalProc(0x01000000,2,0x4400200,0,0,0,0,0,&rSAL); |
//Get System Frequency |
UINT64 sys_freq; |
LibSalProc(0x01000012,0,0,0,0,0,0,0,&rSAL); |
sys_freq=rSAL.p1; |
UINT64 freq_scale; |
//Get CPU Frequency to System Frequency ratio |
LibPalProc(14,0,0,0,&rPAL); |
freq_scale=rPAL.p1; |
UINT64 sapic; |
LibGetSalIpiBlock(&sapic); |
Print (L"SAPIC:%X\n", sapic); |
//bootinfo->sapic=sapic; |
UINT64 wakeup_intno; |
LibGetSalWakeupVector(&wakeup_intno); |
Print (L"WAKEUP INTNO:%X\n", wakeup_intno); |
UINTN cookie; |
void *p=(void *)KERNEL_LOAD_ADDRESS; |
UINTN mapsize,descsize; |
UINT32 desver; |
EFI_STATUS status; |
EFI_MEMORY_DESCRIPTOR emd[1024]; |
mapsize=1024*sizeof(emd); |
status=BS->AllocatePages(AllocateAnyPages,EfiLoaderData,/*(HOSSize>>12)+1*/ 1,p); |
if(EFI_ERROR(status)){ |
150,10 → 220,18 |
return EFI_SUCCESS; |
} |
status=BS->GetMemoryMap(&mapsize,emd,&cookie,&descsize,&desver); |
if(EFI_ERROR(status)){ |
Print(L"Error 1\n"); |
return EFI_SUCCESS; |
UINTN no_entryes; |
void * mds; |
mds=LibMemoryMap(&no_entryes,&cookie,&descsize,&desver); |
for(i=0;i<no_entryes;i++) |
{ |
unsigned int type=*((unsigned int *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_TYPE)); |
unsigned long long base=*((unsigned long long *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_BASE)); |
unsigned long long pages=*((unsigned long long *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_PAGES)); |
Print(L"T:%02d %016llX %016llX\n",type,base,pages*EFI_PAGE_SIZE); |
} |
status=BS->ExitBootServices(image,cookie); |
if(EFI_ERROR(status)){ |
161,12 → 239,62 |
return EFI_SUCCESS; |
} |
} |
int a; |
for(a=0;a<HOSSize;a++){ |
((char *)(0x4400000))[a]=HOS[a]; |
} |
bootinfo->sapic=(unsigned long *)sapic; |
bootinfo->wakeup_intno=wakeup_intno; |
bootinfo->sys_freq=sys_freq; |
bootinfo->freq_scale=freq_scale; |
bootinfo->hello_configured=1; |
bootinfo->memmap_items=0; |
for(i=0;i<no_entryes;i++) |
{ |
unsigned int type=*((unsigned int *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_TYPE)); |
unsigned long long base=*((unsigned long long *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_BASE)); |
unsigned long long pages=*((unsigned long long *)(mds+i*descsize+MEM_MAP_DESCRIPTOR_OFFSET_PAGES)); |
switch (type) |
{ |
case EfiConventionalMemory: |
bootinfo->memmap[bootinfo->memmap_items].type=EFI_MEMMAP_FREE_MEM; |
bootinfo->memmap[bootinfo->memmap_items].base=base; |
bootinfo->memmap[bootinfo->memmap_items].size=pages*EFI_PAGE_SIZE; |
bootinfo->memmap_items++; |
break; |
case EfiMemoryMappedIO: |
bootinfo->memmap[bootinfo->memmap_items].type=EFI_MEMMAP_IO; |
bootinfo->memmap[bootinfo->memmap_items].base=base; |
bootinfo->memmap[bootinfo->memmap_items].size=pages*EFI_PAGE_SIZE; |
bootinfo->memmap_items++; |
break; |
case EfiMemoryMappedIOPortSpace: |
bootinfo->memmap[bootinfo->memmap_items].type=EFI_MEMMAP_IO_PORTS; |
bootinfo->memmap[bootinfo->memmap_items].base=base; |
bootinfo->memmap[bootinfo->memmap_items].size=pages*EFI_PAGE_SIZE; |
bootinfo->memmap_items++; |
break; |
default : |
break; |
} |
} |
//Run Kernel |
asm volatile( |
177,8 → 305,6 |
); |
while(1){ |
((volatile int *)(0x80000000000b8000))[0]++; |
} |
//Not reached |
return EFI_SUCCESS; |
} |
/branches/dd/boot/arch/ia64/loader/gefi/HelenOS/division.c |
---|
0,0 → 1,0 |
link ../../../../../../uspace/lib/softint/generic/division.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/dd/boot/arch/ia64/loader/gefi/HelenOS/division.h |
---|
0,0 → 1,0 |
link ../../../../../../uspace/lib/softint/include/division.h |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/dd/boot/arch/ia64/loader/gefi/HelenOS/mkimage.c |
---|
0,0 → 1,17 |
#include<stdio.h> |
#include<stdlib.h> |
int main(int argc,char** argv) |
{ |
FILE *fi,*fo; |
int count=0; |
int ch; |
fi=fopen("image.bin","rb"); |
fo=fopen("image.c","wb"); |
fprintf(fo,"char HOSimage[]={\n"); |
if((ch=getc(fi))!=EOF) {fprintf(fo,"0x%02X",ch);count++;} |
while((ch=getc(fi))!=EOF) {fprintf(fo,",0x%02X",ch);count++;} |
fprintf(fo,"};\nint HOSimagesize=%d;\n",count); |
return EXIT_SUCCESS; |
} |
/branches/dd/boot/arch/ia64/loader/gefi/HelenOS/Makefile |
---|
28,7 → 28,8 |
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o |
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) |
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
#LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) |
LOADLIBES = -lefi -lgnuefi |
FORMAT = efi-app-$(ARCH) |
36,7 → 37,7 |
clean: |
rm -f *.efi *~ *.o *.so |
rm -f *.efi *~ *.o *.so *.map *.disass *.bin |
.PHONY: install |
45,16 → 46,32 |
-j .rela -j .reloc --target=$(FORMAT) hello.so hello.efi |
$(OBJDUMP) -d hello.efi > hello.disass |
hello.so: hello.o image.o |
$(LD) $(LDFLAGS) -Map hello.map hello.o -o hello.so $(LOADLIBES) |
#When selected first lines or second lines, select if image is linked into hello or not - usefull for network boot |
#hello.so: hello.o image.o division.o |
hello.so: hello.o image.bin division.o |
# $(LD) $(LDFLAGS) -Map hello.map hello.o division.o image.o -o hello.so $(LOADLIBES) #link image inside hello |
$(LD) $(LDFLAGS) -Map hello.map hello.o division.o -o hello.so $(LOADLIBES) #dont link image inside hello |
hello.o: hello.c |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c hello.c -o hello.o |
image.o: ../../image.boot |
division.o: division.c |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c division.c -o division.o |
image.bin: ../../image.boot |
$(OBJCOPY) -O binary ../../image.boot image.bin |
$(OBJCOPY) -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
image.o: ../../image.boot mkimage |
$(OBJCOPY) -O binary ../../image.boot image.bin |
./mkimage |
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c image.c -o image.o |
# $(OBJCOPY) -I binary -O elf64-ia64-little -B ia64 image.bin image.o |
mkimage: mkimage.c |
gcc -o mkimage mkimage.c |
gefi: |
make -C .. prefix=$(PREFIX) |
/branches/dd/boot/arch/ia64/loader/gefi/Makefile |
---|
23,9 → 23,9 |
include Make.defaults |
SUBDIRS = lib gnuefi inc apps |
SUBDIRS = lib gnuefi inc |
all: check_gcc $(SUBDIRS) |
all: $(SUBDIRS) |
$(SUBDIRS): |
$(MAKE) -C $@ |
39,13 → 39,4 |
.PHONY: $(SUBDIRS) clean depend |
# |
# on both platforms you must use gcc 3.0 or higher |
# |
check_gcc: |
ifeq ($(GCC_VERSION),2) |
@echo "you need to use a version of gcc >= 3.0, you are using `$(CC) --version`" |
@exit 1 |
endif |
include Make.rules |
/branches/dd/boot/arch/ia64/loader/main.h |
---|
29,29 → 29,14 |
#ifndef BOOT_ia64_MAIN_H_ |
#define BOOT_ia64_MAIN_H_ |
#include <ofw.h> |
#include <ofw_tree.h> |
#include <types.h> |
#include <../../../../kernel/arch/ia64/include/bootinfo.h> |
#define CONFIG_INIT_TASKS 32 |
typedef struct { |
void *addr; |
size_t size; |
} init_task_t; |
typedef struct { |
count_t count; |
init_task_t tasks[CONFIG_INIT_TASKS]; |
} init_t; |
typedef struct { |
init_t taskmap; |
} bootinfo_t; |
extern bootinfo_t bootinfo; |
extern void start(void); |
extern void bootstrap(void); |
/branches/dd/boot/arch/ia64/loader/Makefile |
---|
27,13 → 27,19 |
# |
include ../../../../version |
include ../../../Makefile.config |
-include ../../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-ia64-little |
BFD_ARCH = ia64 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ia64/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
41,7 → 47,7 |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
GEFI_PREXIX = |
GEFI_PREFIX = |
endif |
ifeq ($(COMPILER),icc_native) |
62,40 → 68,48 |
endif |
#-mno-pic means do not use gp + imm22 to address data |
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -I../../../../kernel/generic/include -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic |
CFLAGS = -DRELEASE=$(RELEASE) -I. -I../../../generic -I../../../genarch -I../../../../kernel/generic/include -imacros ../../../../config.h -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic -pipe |
ifdef REVISION |
CFLAGS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
CFLAGS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
SOURCES = \ |
main.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
../../../genarch/balloc.c \ |
_components.c \ |
asm.S \ |
boot.S |
NOCOMPONENTS = \ |
$(KERNELDIR)/kernel.bin |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
105,25 → 119,44 |
-include Makefile.depend |
hello.efi: image.boot |
make -C gefi/HelenOS PREFIX=$(GEFI_PREFIX) |
cp gefi/HelenOS/hello.efi ../../../../ |
# cp gefi/HelenOS/hello.efi /boot/efi/ |
cp gefi/HelenOS/image.bin ../../../../ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -Map boot.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot boot.disasm Makefile.depend |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) image.boot image.map image.disasm initrd.img image.boot Makefile.depend ../../../../image.bin ../../../../hello.efi |
make -C gefi clean |
make -C gefi/HelenOS clean |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned long" $(COMPONENTS) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
132,4 → 165,4 |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
disasm: image.boot |
$(OBJDUMP) -d image.boot > boot.disasm |
$(OBJDUMP) -d image.boot > image.disasm |
/branches/dd/boot/arch/arm32/Makefile.inc |
---|
28,15 → 28,15 |
build: $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot |
cp arch/$(ARCH)/loader/image.boot $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(BARCH)/loader/image.boot |
cp arch/$(BARCH)/loader/image.boot $(BASE)/image.boot |
depend: |
-rm arch/$(ARCH)/loader/image.boot |
-rm arch/$(BARCH)/loader/image.boot |
arch/$(ARCH)/loader/image.boot: |
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) IMAGE=$(IMAGE) |
arch/$(BARCH)/loader/image.boot: |
make -C arch/$(BARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
clean: |
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) IMAGE=$(IMAGE) |
make -C arch/$(BARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
-rm -f $(BASE)/image.boot |
/branches/dd/boot/arch/arm32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/arm32/loader/_link.ld.in |
---|
0,0 → 1,24 |
OUTPUT_FORMAT("elf32-littlearm") |
ENTRY(start) |
SECTIONS { |
.boot 0x0: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
. = 0x4000; |
*(PT); /* page table placed at 0x4000 */ |
[[COMPONENTS]] |
} |
} |
/branches/dd/boot/arch/arm32/loader/asm.S |
---|
35,7 → 35,8 |
add r3, r1, #3 |
bic r3, r3, #3 |
cmp r1, r3 |
stmdb sp!, {r4, lr} |
stmdb sp!, {r4, r5, lr} |
mov r5, r0 |
beq 4f |
1: |
cmp r2, #0 |
48,8 → 49,8 |
cmp ip, r2 |
bne 2b |
3: |
mov r0, r1 |
ldmia sp!, {r4, pc} |
mov r0, r5 |
ldmia sp!, {r4, r5, pc} |
4: |
add r3, r0, #3 |
bic r3, r3, #3 |
/branches/dd/boot/arch/arm32/loader/boot.S |
---|
39,6 → 39,11 |
b bootstrap |
jump_to_kernel: |
# |
# TODO |
# Make sure that the I-cache, D-cache and memory are mutually coherent |
# before passing control to the copied code. |
# |
bx r0 |
48,5 → 53,3 |
# make place for PTL0 page table |
page_table: |
.skip PTL0_ENTRIES * PTL0_ENTRY_SIZE |
/branches/dd/boot/arch/arm32/loader/main.c |
---|
32,13 → 32,16 |
*/ |
/** @file |
* @brief Bootstrap. |
*/ |
*/ |
#include "main.h" |
#include "main.h" |
#include "asm.h" |
#include "_components.h" |
#include <printf.h> |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
#include "mm.h" |
46,16 → 49,16 |
#define KERNEL_VIRTUAL_ADDRESS 0x80200000 |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
76,9 → 79,10 |
version_print(); |
component_t components[COMPONENTS]; |
bootinfo_t bootinfo; |
init_components(components); |
bootinfo_t bootinfo; |
printf("\nMemory statistics\n"); |
printf(" kernel entry point at %L\n", KERNEL_VIRTUAL_ADDRESS); |
printf(" %L: boot info structure\n", &bootinfo); |
100,6 → 104,8 |
if (i > 0) { |
bootinfo.tasks[bootinfo.cnt].addr = ((void *) KERNEL_VIRTUAL_ADDRESS) + top; |
bootinfo.tasks[bootinfo.cnt].size = components[i].size; |
strncpy(bootinfo.tasks[bootinfo.cnt].name, |
components[i].name, BOOTINFO_TASK_NAME_BUFLEN); |
bootinfo.cnt++; |
} |
top += components[i].size; |
107,7 → 113,7 |
} |
printf("\nBooting the kernel...\n"); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo, sizeof(bootinfo)); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo); |
} |
/** @} |
/branches/dd/boot/arch/arm32/loader/asm.h |
---|
32,7 → 32,7 |
*/ |
/** @file |
* @brief Functions implemented in assembly. |
*/ |
*/ |
#ifndef BOOT_arm32_ASM_H |
40,10 → 40,10 |
/** Copies cnt bytes from dst to src. |
* |
* |
* @param dst Destination address. |
* @param src Source address. |
* @param cnt Count of bytes to be copied. |
* @param cnt Count of bytes to be copied. |
*/ |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
58,12 → 58,11 |
/** Jumps to the kernel entry point. |
* |
* @param entry Kernel entry point address. |
* @param bootinfo Structure holding information about loaded tasks. |
* @param bootinfo_size Size of the bootinfo structure. |
* @param entry Kernel entry point address. |
* @param bootinfo Structure holding information about loaded tasks. |
* |
*/ |
extern void jump_to_kernel(void *entry, void *bootinfo, |
unsigned int bootinfo_size) __attribute__((noreturn)); |
extern void jump_to_kernel(void *entry, void *bootinfo) __attribute__((noreturn)); |
#endif |
/branches/dd/boot/arch/arm32/loader/main.h |
---|
32,7 → 32,7 |
*/ |
/** @file |
* @brief Boot related declarations. |
*/ |
*/ |
#ifndef BOOT_arm32_MAIN_H |
39,17 → 39,13 |
#define BOOT_arm32_MAIN_H |
/** Aligns to the nearest higher address. |
* |
* @param addr Address or number to be aligned. |
* @param align Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1)) |
/** Maximum number of tasks in the #bootinfo_t struct. */ |
#define TASKMAP_MAX_RECORDS 32 |
/** Size of buffer for storing task name in task_t. */ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
/** Struct holding information about single loaded task. */ |
typedef struct { |
/** Address where the task was placed. */ |
56,6 → 52,8 |
void *addr; |
/** Size of the task's binary. */ |
unsigned int size; |
/** Task name. */ |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} task_t; |
74,4 → 72,3 |
/** @} |
*/ |
/branches/dd/boot/arch/arm32/loader/Makefile |
---|
27,21 → 27,29 |
# |
include ../../../../version |
include ../../../../Makefile.config |
-include ../../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = /usr/local/arm/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
ifeq ($(COMPILER),native) |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
else |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld |
49,47 → 57,47 |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
endif |
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../.. -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 |
CFLAGS = -DRELEASE=$(RELEASE) -I. -I../../../generic -I../../.. -imacros ../../../../config.h -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -pipe |
ifdef REVISION |
CFLAGS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
CFLAGS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
ifdef MACHINE |
CFLAGS += "-DMACHINE=$(MACHINE)" |
endif |
SOURCES = \ |
main.c \ |
boot.S \ |
asm.S \ |
mm.c \ |
print/gxemul.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
../../../genarch/division.c |
ifeq ($(MACHINE), gxemul_testarm) |
SOURCES += print/gxemul.c |
endif |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/tetris/tetris |
$(USPACEDIR)/app/bdsh/bdsh |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
100,17 → 108,37 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(OBJECTS) $(COMPONENT_OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/boot/arch/ppc32/Makefile.inc |
---|
28,15 → 28,15 |
build: $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot |
cp arch/$(ARCH)/loader/image.boot $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(BARCH)/loader/image.boot |
cp arch/$(BARCH)/loader/image.boot $(BASE)/image.boot |
depend: |
-rm arch/$(ARCH)/loader/image.boot |
-rm arch/$(BARCH)/loader/image.boot |
arch/$(ARCH)/loader/image.boot: |
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)" |
arch/$(BARCH)/loader/image.boot: |
make -C arch/$(BARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
clean: generic_clean |
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)" |
make -C arch/$(BARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
-rm -f $(BASE)/image.boot |
/branches/dd/boot/arch/ppc32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/ppc32/loader/debug.inc |
---|
File deleted |
/branches/dd/boot/arch/ppc32/loader/_link.ld.in |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("elf32-powerpc") |
OUTPUT_ARCH(powerpc:common) |
ENTRY(start) |
SECTIONS { |
.boot 0x01000000: AT (0) { |
*(BOOTSTRAP); |
*(REALMODE); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
[[COMPONENTS]] |
} |
} |
/branches/dd/boot/arch/ppc32/loader/asm.S |
---|
28,8 → 28,26 |
#include "asm.h" |
#include "regname.h" |
#include "debug.inc" |
.macro SMC_COHERENCY addr |
dcbst 0, \addr |
sync |
icbi 0, \addr |
sync |
isync |
.endm |
.macro FLUSH_DCACHE addr |
dcbst 0, \addr |
sync |
isync |
.endm |
.macro TLB_FLUSH reg |
tlbie \reg |
addi \reg, \reg, 0x1000 |
.endm |
.text |
.global halt |
140,9 → 158,6 |
real_mode: |
DEBUG_INIT |
DEBUG_real_mode |
# copy kernel to proper location |
# |
# r5 = trans (pa) |
163,14 → 178,13 |
mtctr r31 |
lwz r29, 0(r5) |
DEBUG_INIT |
DEBUG_copy_loop |
copy_loop: |
lwz r28, 0(r29) |
stw r28, 0(r30) |
SMC_COHERENCY r30 |
addi r29, r29, 4 |
addi r30, r30, 4 |
subi r6, r6, 4 |
180,15 → 194,11 |
bdnz copy_loop |
DEBUG_end_copy_loop |
addi r5, r5, 4 |
b page_copy |
copy_end: |
DEBUG_segments |
# initially fill segment registers |
li r31, 0 |
196,7 → 206,7 |
li r29, 8 |
mtctr r29 |
li r30, 0 # ASID 0 (VSIDs 0 .. 7) |
seg_fill_uspace: |
mtsrin r30, r31 |
220,8 → 230,6 |
# invalidate block address translation registers |
DEBUG_bat |
li r30, 0 |
mtspr ibat0u, r30 |
251,8 → 259,6 |
# create empty Page Hash Table |
# on top of memory, size 64 KB |
DEBUG_pht |
lwz r31, 0(r3) # r31 = memory size |
lis r30, 65536@h |
274,6 → 280,7 |
# write zeroes |
stw r29, 0(r31) |
FLUSH_DCACHE r31 |
addi r31, r31, 4 |
subi r30, r30, 4 |
282,8 → 289,6 |
beq clear_end |
bdnz pht_clear |
DEBUG_end_pht_clear |
clear_end: |
291,8 → 296,6 |
# create BAT identity mapping |
DEBUG_mapping |
lwz r31, 0(r3) # r31 = memory size |
lis r29, 0x0002 |
315,8 → 318,6 |
bdnz bat_mask |
DEBUG_bat_mask |
andi. r31, r31, 0x07ff # mask = mask & 0x07ff (BAT can map up to 256 MB) |
li r29, 2 |
336,16 → 337,90 |
mtspr dbat0l, r30 |
no_bat: |
#endif |
DEBUG_tlb |
# flush TLB |
tlbia |
li r31, 0 |
sync |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
TLB_FLUSH r31 |
eieio |
tlbsync |
sync |
DEBUG_prepare |
# start the kernel |
# |
# pc = KERNEL_START_ADDR |
373,8 → 448,6 |
sync |
isync |
DEBUG_rfi |
rfi |
.align PAGE_WIDTH |
/branches/dd/boot/arch/ppc32/loader/regname.h |
---|
208,11 → 208,13 |
#define hid0 1008 |
/* MSR bits */ |
#define msr_ir (1 << 4) |
#define msr_dr (1 << 5) |
#define msr_dr (1 << 4) |
#define msr_ir (1 << 5) |
#define msr_pr (1 << 14) |
#define msr_ee (1 << 15) |
/* HID0 bits */ |
#define hid0_sten (1 << 24) |
#define hid0_ice (1 << 15) |
#define hid0_dce (1 << 14) |
#define hid0_icfi (1 << 11) |
/branches/dd/boot/arch/ppc32/loader/main.c |
---|
32,6 → 32,8 |
#include "_components.h" |
#include <ofw.h> |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
#define HEAP_GAP 1024000 |
72,16 → 74,16 |
} |
} |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
89,7 → 91,7 |
/** Print version information. */ |
static void version_print(void) |
{ |
printf("HelenOS PPC32 Bootloader\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n", release, revision, timestamp); |
printf("HelenOS PPC32 Bootloader\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n\n", release, revision, timestamp); |
} |
void bootstrap(void) |
96,10 → 98,10 |
{ |
version_print(); |
init_components(); |
component_t components[COMPONENTS]; |
init_components(components); |
unsigned int i; |
for (i = 0; i < COMPONENTS; i++) |
check_align(components[i].start, components[i].name); |
107,29 → 109,29 |
check_align(&trans, "translation table"); |
if (!ofw_memmap(&bootinfo.memmap)) { |
printf("Error: unable to get memory map, halting.\n"); |
printf("Error: Unable to get memory map, halting.\n"); |
halt(); |
} |
if (bootinfo.memmap.total == 0) { |
printf("Error: no memory detected, halting.\n"); |
printf("Error: No memory detected, halting.\n"); |
halt(); |
} |
if (!ofw_screen(&bootinfo.screen)) { |
printf("Error: unable to get screen properties, halting.\n"); |
halt(); |
} |
if (!ofw_screen(&bootinfo.screen)) |
printf("Warning: Unable to get screen properties.\n"); |
if (!ofw_keyboard(&bootinfo.keyboard)) { |
printf("Error: unable to get keyboard properties, halting.\n"); |
halt(); |
} |
if (!ofw_macio(&bootinfo.macio)) |
printf("Warning: Unable to get macio properties.\n"); |
printf("\nDevice statistics\n"); |
printf(" screen at %L, resolution %dx%d, %d bpp (scanline %d bytes)\n", bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.bpp, bootinfo.screen.scanline); |
printf(" keyboard at %L (size %d bytes)\n", bootinfo.keyboard.addr, bootinfo.keyboard.size); |
printf("Device statistics\n"); |
if (bootinfo.screen.addr) |
printf(" screen at %L, resolution %dx%d, %d bpp (scanline %d bytes)\n", bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.bpp, bootinfo.screen.scanline); |
if (bootinfo.macio.addr) |
printf(" macio at %L (size %d bytes)\n", bootinfo.macio.addr, bootinfo.macio.size); |
void *real_mode_pa = ofw_translate(&real_mode); |
void *trans_pa = ofw_translate(&trans); |
void *bootinfo_pa = ofw_translate(&bootinfo); |
165,6 → 167,9 |
if (j == 0) { |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = (void *) (pages << PAGE_WIDTH); |
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = components[i].size; |
strncpy(bootinfo.taskmap.tasks[bootinfo.taskmap.count].name, |
components[i].name, BOOTINFO_TASK_NAME_BUFLEN); |
bootinfo.taskmap.count++; |
} |
} |
176,6 → 181,8 |
fix_overlap(&trans, &trans_pa, "translation table", &top); |
fix_overlap(&bootinfo, &bootinfo_pa, "boot info", &top); |
ofw_setup_palette(); |
printf("\nBooting the kernel...\n"); |
jump_to_kernel(bootinfo_pa, sizeof(bootinfo), trans_pa, pages << PAGE_WIDTH, real_mode_pa, (void *) bootinfo.screen.addr, bootinfo.screen.scanline); |
} |
/branches/dd/boot/arch/ppc32/loader/main.h |
---|
33,9 → 33,17 |
#define TASKMAP_MAX_RECORDS 32 |
/** Size of buffer for storing task name in task_t. */ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
/** Struct holding information about single loaded task. */ |
typedef struct { |
/** Address where the task was placed. */ |
void *addr; |
/** Size of the task's binary. */ |
unsigned int size; |
/** Task name. */ |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} task_t; |
typedef struct { |
47,7 → 55,7 |
memmap_t memmap; |
taskmap_t taskmap; |
screen_t screen; |
keyboard_t keyboard; |
macio_t macio; |
} bootinfo_t; |
extern void start(void); |
/branches/dd/boot/arch/ppc32/loader/ofwarch.c |
---|
39,25 → 39,32 |
void write(const char *str, const int len) |
{ |
ofw_write(str, len); |
int i; |
for (i = 0; i < len; i++) { |
if (str[i] == '\n') |
ofw_write("\r", 1); |
ofw_write(&str[i], 1); |
} |
} |
int ofw_keyboard(keyboard_t *keyboard) |
int ofw_macio(macio_t *macio) |
{ |
char device_name[BUF_SIZE]; |
if (ofw_get_property(ofw_aliases, "macio", device_name, sizeof(device_name)) <= 0) |
return false; |
phandle device = ofw_find_device(device_name); |
if (device == -1) |
return false; |
pci_reg_t macio; |
if (ofw_get_property(device, "assigned-addresses", &macio, sizeof(macio)) <= 0) |
pci_reg_t pci_reg; |
if (ofw_get_property(device, "assigned-addresses", &pci_reg, sizeof(pci_reg)) <= 0) |
return false; |
keyboard->addr = (void *) macio.addr.addr_lo; |
keyboard->size = macio.size_lo; |
macio->addr = (void *) pci_reg.addr.addr_lo; |
macio->size = pci_reg.size_lo; |
return true; |
} |
/branches/dd/boot/arch/ppc32/loader/Makefile |
---|
27,13 → 27,19 |
# |
include ../../../../version |
include ../../../Makefile.config |
-include ../../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = /usr/local/ppc/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 49,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
59,21 → 57,15 |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
endif |
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc -msoft-float -m32 |
CFLAGS = -DRELEASE=$(RELEASE) -I. -I../../../generic -I../../../genarch -imacros ../../../../config.h -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=powerpc -msoft-float -m32 -pipe |
ifdef REVISION |
CFLAGS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
CFLAGS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
SOURCES = \ |
main.c \ |
ofwarch.c \ |
_components.c \ |
../../../genarch/ofw.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
asm.S \ |
boot.S |
80,17 → 72,31 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS)))) |
101,17 → 107,37 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 4096 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/boot/arch/amd64/grub/menu.lst |
---|
2,18 → 2,14 |
timeout 10 |
title=HelenOS |
root (cd) |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/pci |
module /boot/fb |
module /boot/kbd |
module /boot/console |
module /boot/tetris |
module /boot/tester |
module /boot/klog |
module /boot/tmpfs |
module /boot/fat |
module /boot/vfs |
module /boot/devmap |
root (cd) |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/devmap |
module /boot/rd |
module /boot/vfs |
module /boot/tmpfs |
module /boot/fat |
module /boot/loader |
module /boot/initrd.img |
/branches/dd/boot/arch/amd64/Makefile.inc |
---|
26,33 → 26,72 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
TASKS = \ |
INIT_TASKS = \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/pci/pci \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
build: $(BASE)/image.iso |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(TASKS) |
mkdir -p arch/$(ARCH)/iso/boot/grub |
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/ |
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/ |
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/ |
for task in $(TASKS) ; do \ |
cp $$task arch/$(ARCH)/iso/boot/ ; \ |
$(BASE)/image.iso: arch/$(BARCH)/grub/stage2_eltorito arch/$(BARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS) |
mkdir -p arch/$(BARCH)/iso/boot/grub |
cp arch/$(BARCH)/grub/stage2_eltorito arch/$(BARCH)/iso/boot/grub/ |
ifneq ($(RDFMT),tmpfs) |
cat arch/$(BARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(BARCH)/iso/boot/grub/menu.lst |
endif |
ifneq ($(RDFMT),fat) |
cat arch/$(BARCH)/grub/menu.lst | grep -v "fat" >arch/$(BARCH)/iso/boot/grub/menu.lst |
endif |
cp $(KERNELDIR)/kernel.bin arch/$(BARCH)/iso/boot/ |
for task in $(INIT_TASKS) ; do \ |
cp $$task arch/$(BARCH)/iso/boot/ ; \ |
done |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/ |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs |
endif |
$(BASE)/tools/mkhord.py 4096 arch/$(BARCH)/iso/boot/initrd.fs arch/$(BARCH)/iso/boot/initrd.img |
rm arch/$(BARCH)/iso/boot/initrd.fs |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(BARCH)/iso/ |
clean: |
-rm -fr arch/$(ARCH)/iso |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -fr arch/$(BARCH)/iso |
-rm -f $(BASE)/image.iso |
/branches/dd/boot/arch/mips32/Makefile.inc |
---|
28,15 → 28,15 |
build: $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot |
cp arch/$(ARCH)/loader/image.boot $(BASE)/image.boot |
$(BASE)/image.boot: depend arch/$(BARCH)/loader/image.boot |
cp arch/$(BARCH)/loader/image.boot $(BASE)/image.boot |
depend: |
-rm arch/$(ARCH)/loader/image.boot |
-rm arch/$(BARCH)/loader/image.boot |
arch/$(ARCH)/loader/image.boot: |
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) IMAGE=$(IMAGE) |
arch/$(BARCH)/loader/image.boot: |
make -C arch/$(BARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
clean: |
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) IMAGE=$(IMAGE) |
make -C arch/$(BARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) |
-rm -f $(BASE)/image.boot |
/branches/dd/boot/arch/mips32/loader/pack |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/branches/dd/boot/arch/mips32/loader/_link.ld.in.ecoff |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("ecoff-littlemips") |
ENTRY(start) |
SECTIONS { |
.boot 0xbfc00000: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
[[COMPONENTS]] |
} |
} |
/branches/dd/boot/arch/mips32/loader/asm.S |
---|
48,6 → 48,7 |
and $v0,$v0,$v1 |
beq $a1,$v0,3f |
move $t0,$a0 |
move $t2,$a0 # save dst |
0: |
beq $a2,$zero,2f |
63,7 → 64,7 |
2: |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
3: |
addiu $v0,$a0,3 |
103,9 → 104,13 |
sb $a0,0($v1) |
jr $ra |
move $v0,$a1 |
move $v0,$t2 |
jump_to_kernel: |
# .word 0x39 |
# |
# TODO |
# Make sure that the I-cache, D-cache and memory are mutually coherent |
# before passing control to the copied code. |
# |
j $a0 |
nop |
/branches/dd/boot/arch/mips32/loader/_link.ld.in.binary |
---|
0,0 → 1,21 |
OUTPUT_FORMAT("binary") |
ENTRY(start) |
SECTIONS { |
.boot 0xbfc00000: AT (0) { |
*(BOOTSTRAP); |
*(.text); |
*(.rodata); |
*(.rodata.*); |
*(.data); /* initialized data */ |
*(.sdata); |
*(.sdata2); |
*(.sbss); |
*(.scommon); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
*(.reginfo); |
[[COMPONENTS]] |
} |
} |
/branches/dd/boot/arch/mips32/loader/boot.S |
---|
27,9 → 27,8 |
# |
#include "regname.h" |
#include "main.h" |
#define INITIAL_STACK 0x80040000 |
.set noat |
.set noreorder |
.set nomacro |
38,8 → 37,82 |
.global start |
start: |
lui $sp, INITIAL_STACK >> 16 |
ori $sp, $sp, INITIAL_STACK & 0xffff |
j bootstrap |
/* Setup CPU map (on msim this code |
is executed in parallel on all CPUs, |
but it not an issue) */ |
la $a0, CPUMAP |
sw $zero, 0($a0) |
sw $zero, 4($a0) |
sw $zero, 8($a0) |
sw $zero, 12($a0) |
sw $zero, 16($a0) |
sw $zero, 20($a0) |
sw $zero, 24($a0) |
sw $zero, 28($a0) |
sw $zero, 32($a0) |
sw $zero, 36($a0) |
sw $zero, 40($a0) |
sw $zero, 44($a0) |
sw $zero, 48($a0) |
sw $zero, 52($a0) |
sw $zero, 56($a0) |
sw $zero, 60($a0) |
sw $zero, 64($a0) |
sw $zero, 68($a0) |
sw $zero, 72($a0) |
sw $zero, 76($a0) |
sw $zero, 80($a0) |
sw $zero, 84($a0) |
sw $zero, 88($a0) |
sw $zero, 92($a0) |
sw $zero, 96($a0) |
sw $zero, 100($a0) |
sw $zero, 104($a0) |
sw $zero, 108($a0) |
sw $zero, 112($a0) |
sw $zero, 116($a0) |
sw $zero, 120($a0) |
sw $zero, 124($a0) |
lui $a1, 1 |
#ifdef MACHINE_msim |
/* Read dorder value */ |
la $k0, MSIM_DORDER_ADDRESS |
lw $k1, ($k0) |
/* If we are not running on BSP |
then end in an infinite loop */ |
beq $k1, $zero, bsp |
nop |
/* Record CPU presence */ |
sll $a2, $k1, 2 |
addu $a2, $a2, $a0 |
sw $a1, ($a2) |
loop: |
j loop |
nop |
#endif |
bsp: |
/* Record CPU presence */ |
sw $a1, ($a0) |
/* Setup initial stack */ |
la $sp, INITIAL_STACK |
j bootstrap |
nop |
/branches/dd/boot/arch/mips32/loader/main.c |
---|
28,6 → 28,9 |
#include "main.h" |
#include <printf.h> |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
#include "msim.h" |
#include "asm.h" |
#include "_components.h" |
34,16 → 37,16 |
#define KERNEL_VIRTUAL_ADDRESS 0x80100000 |
char *release = RELEASE; |
char *release = STRING(RELEASE); |
#ifdef REVISION |
char *revision = ", revision " REVISION; |
char *revision = ", revision " STRING(REVISION); |
#else |
char *revision = ""; |
#endif |
#ifdef TIMESTAMP |
char *timestamp = "\nBuilt on " TIMESTAMP; |
char *timestamp = "\nBuilt on " STRING(TIMESTAMP); |
#else |
char *timestamp = ""; |
#endif |
59,9 → 62,10 |
version_print(); |
component_t components[COMPONENTS]; |
bootinfo_t bootinfo; |
init_components(components); |
bootinfo_t bootinfo; |
printf("\nMemory statistics\n"); |
printf(" kernel entry point at %L\n", KERNEL_VIRTUAL_ADDRESS); |
printf(" %L: boot info structure\n", &bootinfo); |
71,9 → 75,10 |
printf(" %L: %s image (size %d bytes)\n", components[i].start, components[i].name, components[i].size); |
printf("\nCopying components\n"); |
unsigned int top = 0; |
bootinfo.cnt = 0; |
for (i = 0; i < COMPONENTS; i++) { |
for (i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) { |
printf(" %s...", components[i].name); |
top = ALIGN_UP(top, PAGE_SIZE); |
memcpy(((void *) KERNEL_VIRTUAL_ADDRESS) + top, components[i].start, components[i].size); |
80,6 → 85,8 |
if (i > 0) { |
bootinfo.tasks[bootinfo.cnt].addr = ((void *) KERNEL_VIRTUAL_ADDRESS) + top; |
bootinfo.tasks[bootinfo.cnt].size = components[i].size; |
strncpy(bootinfo.tasks[bootinfo.cnt].name, |
components[i].name, BOOTINFO_TASK_NAME_BUFLEN); |
bootinfo.cnt++; |
} |
top += components[i].size; |
86,6 → 93,13 |
printf("done.\n"); |
} |
unsigned int *cpumap = (unsigned int *) CPUMAP; |
bootinfo.cpumap = 0; |
for (i = 0; i < CPUMAP_MAX_RECORDS; i++) { |
if (cpumap[i] != 0) |
bootinfo.cpumap |= (1 << i); |
} |
printf("\nBooting the kernel...\n"); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo, sizeof(bootinfo)); |
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo); |
} |
/branches/dd/boot/arch/mips32/loader/asm.h |
---|
29,11 → 29,11 |
#ifndef BOOT_mips32_ASM_H_ |
#define BOOT_mips32_ASM_H_ |
#define PAGE_SIZE 16384 |
#define PAGE_WIDTH 14 |
#define PAGE_SIZE 16384 |
#define PAGE_WIDTH 14 |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
#define memcpy(dst, src, cnt) __builtin_memcpy((dst), (src), (cnt)) |
void jump_to_kernel(void *entry, void *bootinfo, unsigned int bootinfo_size) __attribute__((noreturn)); |
void jump_to_kernel(void *entry, void *bootinfo) __attribute__((noreturn)); |
#endif |
/branches/dd/boot/arch/mips32/loader/main.h |
---|
29,21 → 29,30 |
#ifndef BOOT_mips32_MAIN_H_ |
#define BOOT_mips32_MAIN_H_ |
/** Align to the nearest higher address. |
* |
* @param addr Address or size to be aligned. |
* @param align Size of alignment, must be power of 2. |
*/ |
#define ALIGN_UP(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1)) |
#define CPUMAP 0x80001000 |
#define INITIAL_STACK 0x80002000 |
#define MSIM_DORDER_ADDRESS 0xb0000004 |
#define TASKMAP_MAX_RECORDS 32 |
#define TASKMAP_MAX_RECORDS 32 |
#define CPUMAP_MAX_RECORDS 32 |
#ifndef __ASM__ |
/** Size of buffer for storing task name in task_t. */ |
#define BOOTINFO_TASK_NAME_BUFLEN 32 |
/** Struct holding information about single loaded task. */ |
typedef struct { |
/** Address where the task was placed. */ |
void *addr; |
/** Size of the task's binary. */ |
unsigned int size; |
/** Task name. */ |
char name[BOOTINFO_TASK_NAME_BUFLEN]; |
} task_t; |
typedef struct { |
unsigned int cpumap; |
unsigned int cnt; |
task_t tasks[TASKMAP_MAX_RECORDS]; |
} bootinfo_t; |
52,3 → 61,5 |
extern void bootstrap(void); |
#endif |
#endif |
/branches/dd/boot/arch/mips32/loader/Makefile |
---|
27,13 → 27,27 |
# |
include ../../../../version |
include ../../../Makefile.config |
-include ../../../../Makefile.config |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
ifeq ($(IMAGE),binary) |
LD_IN = binary |
endif |
ifeq ($(IMAGE),ecoff) |
LD_IN = ecoff |
endif |
BFD_NAME = elf32-tradlittlemips |
BFD_ARCH = mips |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = /usr/local/mipsel/bin |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
ifeq ($(COMPILER),gcc_native) |
CC = gcc |
43,14 → 57,6 |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),icc_native) |
CC = icc |
AS = as |
LD = ld |
OBJCOPY = objcopy |
OBJDUMP = objdump |
endif |
ifeq ($(COMPILER),gcc_cross) |
CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc |
AS = $(TOOLCHAIN_DIR)/$(TARGET)-as |
59,20 → 65,14 |
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump |
endif |
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mhard-float -mips3 |
CFLAGS = -DRELEASE=$(RELEASE) -I. -I../../../generic -imacros ../../../../config.h -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mhard-float -mips3 -pipe |
ifdef REVISION |
CFLAGS += "-DREVISION=\"$(REVISION)\"" |
endif |
ifdef TIMESTAMP |
CFLAGS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
SOURCES = \ |
main.c \ |
msim.c \ |
_components.c \ |
../../../generic/printf.c \ |
../../../generic/string.c \ |
asm.S \ |
boot.S |
79,16 → 79,30 |
COMPONENTS = \ |
$(KERNELDIR)/kernel.bin \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/bdsh/bdsh \ |
$(USPACEDIR)/app/klog/klog |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
100,18 → 114,41 |
-include Makefile.depend |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@ |
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) |
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@ |
depend: |
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null |
clean: |
-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -f _components.h _components.c _link.ld _link.ld.in $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend |
_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) |
./pack $(IMAGE) $(OBJCOPY) $(COMPONENTS) |
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs |
endif |
../../../../tools/mkhord.py 16384 initrd.fs initrd.img |
rm initrd.fs |
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned int" $(COMPONENTS) ./initrd.img |
_link.ld.in: _link.ld.in.$(LD_IN) |
cp $< $@ |
%.o: %.S |
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/boot/arch/ia32/grub/menu.lst |
---|
2,18 → 2,14 |
timeout 10 |
title=HelenOS |
root (cd) |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/pci |
module /boot/fb |
module /boot/kbd |
module /boot/console |
module /boot/vfs |
module /boot/tmpfs |
module /boot/fat |
module /boot/devmap |
module /boot/tetris |
module /boot/tester |
module /boot/klog |
root (cd) |
kernel /boot/kernel.bin |
module /boot/ns |
module /boot/init |
module /boot/devmap |
module /boot/rd |
module /boot/vfs |
module /boot/tmpfs |
module /boot/fat |
module /boot/loader |
module /boot/initrd.img |
/branches/dd/boot/arch/ia32/Makefile.inc |
---|
26,33 → 26,71 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
TASKS = \ |
INIT_TASKS = \ |
$(USPACEDIR)/srv/ns/ns \ |
$(USPACEDIR)/srv/loader/loader \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/srv/rd/rd \ |
$(USPACEDIR)/srv/vfs/vfs |
ifeq ($(RDFMT),tmpfs) |
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs |
endif |
ifeq ($(RDFMT),fat) |
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat |
endif |
RD_SRVS = \ |
$(USPACEDIR)/srv/pci/pci \ |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/vfs/vfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/devmap/devmap \ |
$(USPACEDIR)/app/init/init \ |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
$(USPACEDIR)/app/tester/tester \ |
$(USPACEDIR)/app/klog/klog |
$(USPACEDIR)/app/trace/trace \ |
$(USPACEDIR)/app/klog/klog \ |
$(USPACEDIR)/app/bdsh/bdsh |
build: $(BASE)/image.iso |
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(TASKS) |
mkdir -p arch/$(ARCH)/iso/boot/grub |
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/ |
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/ |
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/ |
for task in $(TASKS) ; do \ |
cp $$task arch/$(ARCH)/iso/boot/ ; \ |
$(BASE)/image.iso: arch/$(BARCH)/grub/stage2_eltorito arch/$(BARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS) |
mkdir -p arch/$(BARCH)/iso/boot/grub |
cp arch/$(BARCH)/grub/stage2_eltorito arch/$(BARCH)/iso/boot/grub/ |
ifneq ($(RDFMT),tmpfs) |
cat arch/$(BARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(BARCH)/iso/boot/grub/menu.lst |
endif |
ifneq ($(RDFMT),fat) |
cat arch/$(BARCH)/grub/menu.lst | grep -v "fat" >arch/$(BARCH)/iso/boot/grub/menu.lst |
endif |
cp $(KERNELDIR)/kernel.bin arch/$(BARCH)/iso/boot/ |
for task in $(INIT_TASKS) ; do \ |
cp $$task arch/$(BARCH)/iso/boot/ ; \ |
done |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/ |
for file in $(RD_SRVS) ; do \ |
cp $$file $(USPACEDIR)/dist/srv/ ; \ |
done |
for file in $(RD_APPS) ; do \ |
cp $$file $(USPACEDIR)/dist/app/ ; \ |
done |
ifeq ($(RDFMT),tmpfs) |
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs |
endif |
ifeq ($(RDFMT),fat) |
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs |
endif |
$(BASE)/tools/mkhord.py 4096 arch/$(BARCH)/iso/boot/initrd.fs arch/$(BARCH)/iso/boot/initrd.img |
rm arch/$(BARCH)/iso/boot/initrd.fs |
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(BARCH)/iso/ |
clean: |
-rm -fr arch/$(ARCH)/iso |
-for file in $(RD_SRVS) ; do \ |
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \ |
done |
-for file in $(RD_APPS) ; do \ |
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \ |
done |
-rm -fr arch/$(BARCH)/iso |
-rm -f $(BASE)/image.iso |
/branches/dd/version |
---|
1,8 → 1,42 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## This file defines the release information of HelenOS. |
# |
# The release string RELEASE consists of three or four components |
# (version, patch level, sublevel and optionally an extra level). |
# |
# The NAME string is the code name of the given release. |
# |
VERSION = 0 |
PATCHLEVEL = 3 |
PATCHLEVEL = 4 |
SUBLEVEL = 0 |
#EXTRAVERSION = 0 |
NAME = Tartare |
ifdef EXTRAVERSION |
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL).$(EXTRAVERSION) |
9,3 → 43,5 |
else |
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) |
endif |
NAME = Sinister Valentine |
/branches/dd/Makefile |
---|
29,119 → 29,28 |
## Include configuration |
# |
-include Makefile.config |
.PHONY: all config distclean clean cscope |
## Setup platform configuration |
# |
all: Makefile.config config.h config.defs |
$(MAKE) -C kernel |
$(MAKE) -C uspace |
$(MAKE) -C boot |
ifeq ($(PLATFORM),amd64) |
KARCH = amd64 |
MACHINE = opteron |
UARCH = amd64 |
BARCH = amd64 |
endif |
Makefile.config config.h config.defs: HelenOS.config |
tools/config.py HelenOS.config default |
ifeq ($(PLATFORM),arm32) |
KARCH = arm32 |
UARCH = arm32 |
BARCH = arm32 |
endif |
ifeq ($(PLATFORM),ia32) |
KARCH = ia32 |
UARCH = ia32 |
BARCH = ia32 |
endif |
ifeq ($(PLATFORM),ia64) |
KARCH = ia64 |
UARCH = ia64 |
BARCH = ia64 |
endif |
ifeq ($(PLATFORM),mips32) |
KARCH = mips32 |
BARCH = mips32 |
ifeq ($(MACHINE),msim) |
UARCH = mips32 |
IMAGE = binary |
endif |
ifeq ($(MACHINE),simics) |
UARCH = mips32 |
IMAGE = ecoff |
endif |
ifeq ($(MACHINE),bgxemul) |
UARCH = mips32eb |
IMAGE = ecoff |
endif |
ifeq ($(MACHINE),lgxemul) |
UARCH = mips32 |
IMAGE = ecoff |
endif |
ifeq ($(MACHINE),indy) |
UARCH = mips32eb |
IMAGE = ecoff |
endif |
endif |
ifeq ($(PLATFORM),ppc32) |
KARCH = ppc32 |
UARCH = ppc32 |
BARCH = ppc32 |
endif |
ifeq ($(PLATFORM),ppc64) |
KARCH = ppc64 |
UARCH = ppc64 |
BARCH = ppc64 |
endif |
ifeq ($(PLATFORM),sparc64) |
KARCH = sparc64 |
UARCH = sparc64 |
BARCH = sparc64 |
endif |
ifeq ($(PLATFORM),ia32xen) |
KARCH = ia32xen |
UARCH = ia32 |
BARCH = ia32xen |
endif |
.PHONY: all build config distclean clean |
all: |
tools/config.py HelenOS.config default $(PLATFORM) $(COMPILER) $(CONFIG_DEBUG) |
$(MAKE) -C . build |
build: |
ifneq ($(MACHINE),) |
$(MAKE) -C kernel ARCH=$(KARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) MACHINE=$(MACHINE) |
else |
$(MAKE) -C kernel ARCH=$(KARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) |
endif |
$(MAKE) -C uspace ARCH=$(UARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) |
ifneq ($(IMAGE),) |
$(MAKE) -C boot ARCH=$(BARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) IMAGE=$(IMAGE) |
else |
$(MAKE) -C boot ARCH=$(BARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) |
endif |
config: |
tools/config.py HelenOS.config |
distclean: |
-$(MAKE) -C kernel distclean |
-$(MAKE) -C uspace distclean |
-$(MAKE) -C boot distclean |
-rm Makefile.config |
distclean: clean |
rm -f Makefile.config config.h config.defs tools/*.pyc |
clean: |
-$(MAKE) -C kernel clean |
-$(MAKE) -C uspace clean |
-$(MAKE) -C boot clean |
cscope: |
find kernel boot uspace -regex '^.*\.[chsS]$$' -print > srclist |
rm -f cscope.out |
cscope -bi srclist |