Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4077 → Rev 4153

/branches/network/contrib/toolchain/toolchain.ppc32.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.amd64.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.ppc64.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.ia32.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.mipsel32.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.sparc64.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.ia64.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.arm32.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
/branches/network/contrib/toolchain/toolchain.mipseb32.sh
19,8 → 19,8
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
32,7 → 32,7
 
PLATFORM="mips"
WORKDIR=`pwd`
TARGET="${PLATFORM}-sgi-irix5"
TARGET="${PLATFORM}-linux-gnu"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
/branches/network/contrib/conf/gxemul.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/branches/network/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/network/contrib/conf/msim.conf
3,6 → 3,7
#
 
add dcpu cpu0
add dcpu cpu1
 
add rwm mainmem 0x00000000
mainmem generic 16M
10,7 → 11,7
 
add rom bootmem 0x1fc00000
bootmem generic 4096k
bootmem load "image.boot"
bootmem load "image.boot"
 
add dprinter printer 0x10000000
add dkeyboard keyboard 0x10000000 2
/branches/network/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/network/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/network/kernel/kernel.config
File deleted
/branches/network/kernel/test/avltree/avltree1.def
1,6 → 1,6
{
"avltree1",
"Test Avl tree operations",
"Test AVL tree operations",
&test_avltree1,
true
},
/branches/network/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;
}
/branches/network/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;
}
/branches/network/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/network/kernel/test/debug/mips1.def
1,4 → 1,3
#ifdef mips32
{
"mips1",
"MIPS debug test",
5,4 → 4,3
&test_mips1,
false
},
#endif
/branches/network/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/network/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/network/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/network/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/network/kernel/test/fpu/fpu1.c
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/kernel/test/fpu/mips2.def
1,4 → 1,3
#ifdef mips32
{
"mips2",
"MIPS FPU test",
5,4 → 4,3
&test_mips2,
true
},
#endif
/branches/network/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/network/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/network/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"
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"
124,7 → 122,7
if (!quiet)
printf("Creating %u threads... ", 2 * THREADS);
 
for (i = 0; i < THREADS; i++) {
thread_t *t;
162,5 → 160,3
return "Test failed";
}
 
#endif
/branches/network/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,14 → 58,14
 
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) {
92,14 → 90,14
 
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) {
162,5 → 160,3
return "Test failed";
}
 
#endif
/branches/network/kernel/genarch/include/kbd/scanc_sun.h
File deleted
/branches/network/kernel/genarch/include/kbd/ns16550.h
File deleted
/branches/network/kernel/genarch/include/kbd/i8042.h
File deleted
/branches/network/kernel/genarch/include/kbd/scanc.h
File deleted
/branches/network/kernel/genarch/include/kbd/key.h
File deleted
/branches/network/kernel/genarch/include/kbd/scanc_pc.h
File deleted
/branches/network/kernel/genarch/include/kbd/z8530.h
File deleted
/branches/network/kernel/genarch/include/kbrd/kbrd.h
0,0 → 1,46
/*
* 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 void kbrd_init(indev_t *devin);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/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/network/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/network/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/network/kernel/genarch/include/kbrd
Property changes:
Added: svn:mergeinfo
/branches/network/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/network/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/network/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/network/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/network/kernel/genarch/include/ofw/ofw_tree.h
30,6 → 30,7
#define KERN_OFW_TREE_H_
 
#include <arch/types.h>
#include <ddi/irq.h>
#include <typedefs.h>
 
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32
43,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;
/**
105,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;
127,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;
135,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));
160,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/network/kernel/genarch/include/drivers/ns16550/ns16550.h
0,0 → 1,75
/*
* 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. */
typedef struct {
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)) ns16550_t;
 
/** Structure representing the ns16550 device. */
typedef struct {
ns16550_t *ns16550;
irq_t irq;
indev_t kbrdin;
} ns16550_instance_t;
 
extern indev_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/kernel/genarch/include/drivers/dsrln/dsrlnin.h
0,0 → 1,60
/*
* 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 genarch
* @{
*/
/**
* @file
* @brief Dummy serial line input.
*/
 
#ifndef KERN_DSRLNIN_H_
#define KERN_DSRLNIN_H_
 
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
#include <typedefs.h>
 
typedef struct {
ioport8_t data;
} __attribute__ ((packed)) dsrlnin_t;
 
typedef struct {
irq_t irq;
dsrlnin_t *dsrlnin;
indev_t kbrdin;
} dsrlnin_instance_t;
 
extern indev_t *dsrlnin_init(dsrlnin_t *, inr_t);
 
#endif
 
/** @}
*/
/branches/network/kernel/genarch/include/drivers/dsrln/dsrlnout.h
0,0 → 1,48
/*
* 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 genarch
* @{
*/
/**
* @file
* @brief Dummy serial line output.
*/
 
#ifndef KERN_DSRLNOUT_H_
#define KERN_DSRLNOUT_H_
 
#include <arch/types.h>
#include <typedefs.h>
 
extern void dsrlnout_init(ioport8_t *);
 
#endif
 
/** @}
*/
/branches/network/kernel/genarch/include/drivers/i8042/i8042.h
0,0 → 1,60
/*
* 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>
 
typedef struct {
ioport8_t data;
uint8_t pad[3];
ioport8_t status;
} __attribute__ ((packed)) i8042_t;
 
typedef struct {
irq_t irq;
i8042_t *i8042;
indev_t kbrdin;
} i8042_instance_t;
 
extern indev_t *i8042_init(i8042_t *, inr_t);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/kernel/genarch/include/drivers/z8530/z8530.h
0,0 → 1,127
/*
* 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. */
typedef struct {
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)) z8530_t;
 
/** Structure representing the z8530 device. */
typedef struct {
irq_t irq;
z8530_t *z8530;
indev_t kbrdin;
} z8530_instance_t;
 
extern indev_t *z8530_init(z8530_t *, inr_t, cir_t, void *);
 
#endif
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/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/network/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/network/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/network/kernel/genarch/include/srln/srln.h
0,0 → 1,46
/*
* 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 void srln_init(indev_t *devin);
 
#endif
 
/** @}
*/
/branches/network/kernel/genarch/Makefile.inc
33,68 → 33,85
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_DSRLNIN),y)
GENARCH_SOURCES += \
genarch/src/drivers/dsrln/dsrlnin.c
endif
 
ifeq ($(CONFIG_DSRLNOUT),y)
GENARCH_SOURCES += \
genarch/src/drivers/dsrln/dsrlnout.c
endif
 
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 → 119,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/network/kernel/genarch/src/kbd/key.c
File deleted
/branches/network/kernel/genarch/src/kbd/z8530.c
File deleted
/branches/network/kernel/genarch/src/kbd/scanc_pc.c
File deleted
/branches/network/kernel/genarch/src/kbd/scanc_sun.c
File deleted
/branches/network/kernel/genarch/src/kbd/ns16550.c
File deleted
/branches/network/kernel/genarch/src/kbd/i8042.c
File deleted
/branches/network/kernel/genarch/src/kbrd/kbrd.c
0,0 → 1,208
/*
* 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)
 
static indev_t kbrdout;
 
indev_operations_t kbrdout_ops = {
.poll = NULL
};
 
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)
{
indev_t *in = (indev_t *) arg;
while (true) {
uint8_t 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(indev_t *devin)
{
indev_initialize("kbrd", &kbrdout, &kbrdout_ops);
thread_t *thread
= thread_create(kkbrd, devin, TASK, 0, "kkbrd", false);
if (thread) {
stdin = &kbrdout;
thread_ready(thread);
}
}
 
/** 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:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x5b);
indev_push_character(stdin, 0x44);
break;
case SC_RIGHTARR:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x5b);
indev_push_character(stdin, 0x43);
break;
case SC_UPARR:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x5b);
indev_push_character(stdin, 0x41);
break;
case SC_DOWNARR:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x5b);
indev_push_character(stdin, 0x42);
break;
case SC_HOME:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x4f);
indev_push_character(stdin, 0x48);
break;
case SC_END:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x4f);
indev_push_character(stdin, 0x46);
break;
case SC_DELETE:
indev_push_character(stdin, 0x1b);
indev_push_character(stdin, 0x5b);
indev_push_character(stdin, 0x33);
indev_push_character(stdin, 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;
indev_push_character(stdin, map[sc]);
break;
}
spinlock_unlock(&keylock);
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/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/network/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/network/kernel/genarch/src/kbrd
Property changes:
Added: svn:mergeinfo
/branches/network/kernel/genarch/src/fb/helenos.xbm
File deleted
/branches/network/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/network/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,258 → 166,265
* 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(outdev_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);
}
 
static chardev_t framebuffer;
static chardev_operations_t fb_ops = {
.write = fb_putchar,
static outdev_t fb_console;
static outdev_operations_t fb_ops = {
.write = fb_putchar
};
 
 
/** Initialize framebuffer as a chardev output device
/** 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 output character device
*
* @param addr Physical address of the framebuffer
* @param x Screen width in pixels
* @param y Screen height in pixels
443,101 → 432,102
* @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();
 
chardev_initialize("fb", &framebuffer, &fb_ops);
stdout = &framebuffer;
fb_redraw();
outdev_initialize("fb", &fb_console, &fb_ops);
stdout = &fb_console;
}
 
/** @}
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/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("%p: 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("%p: 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("%p: 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);
/branches/network/kernel/genarch/src/drivers/ns16550/ns16550.c
0,0 → 1,115
/*
* 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>
#include <ddi/device.h>
 
#define LSR_DATA_READY 0x01
 
static indev_operations_t kbrdin_ops = {
.poll = NULL
};
 
static 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;
}
 
static 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 = pio_read_8(&dev->rbr);
indev_push_character(&instance->kbrdin, x);
}
}
 
/** 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.
*
* @return Keyboard device pointer or NULL on failure.
*
*/
indev_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg)
{
ns16550_instance_t *instance
= malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
if (!instance)
return NULL;
indev_initialize("ns16550", &instance->kbrdin, &kbrdin_ops);
instance->ns16550 = dev;
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_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 &instance->kbrdin;
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/kernel/genarch/src/drivers/dsrln/dsrlnin.c
0,0 → 1,83
/*
* 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 genarch
* @{
*/
/**
* @file
* @brief Dummy serial line input.
*/
 
#include <genarch/drivers/dsrln/dsrlnin.h>
#include <console/chardev.h>
#include <mm/slab.h>
#include <arch/asm.h>
#include <ddi/device.h>
 
static indev_operations_t kbrdin_ops = {
.poll = NULL
};
 
static irq_ownership_t dsrlnin_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void dsrlnin_irq_handler(irq_t *irq)
{
dsrlnin_instance_t *instance = irq->instance;
dsrlnin_t *dev = instance->dsrlnin;
indev_push_character(&instance->kbrdin, pio_read_8(&dev->data));
}
 
indev_t *dsrlnin_init(dsrlnin_t *dev, inr_t inr)
{
dsrlnin_instance_t *instance
= malloc(sizeof(dsrlnin_instance_t), FRAME_ATOMIC);
if (!instance)
return NULL;
indev_initialize("dsrlnin", &instance->kbrdin, &kbrdin_ops);
instance->dsrlnin = dev;
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_devno();
instance->irq.inr = inr;
instance->irq.claim = dsrlnin_claim;
instance->irq.handler = dsrlnin_irq_handler;
instance->irq.instance = instance;
irq_register(&instance->irq);
return &instance->kbrdin;
}
 
/** @}
*/
/branches/network/kernel/genarch/src/drivers/dsrln/dsrlnout.c
0,0 → 1,71
/*
* 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 genarch
* @{
*/
/**
* @file
* @brief Dummy serial line output.
*/
 
 
#include <genarch/drivers/dsrln/dsrlnout.h>
#include <console/chardev.h>
#include <arch/asm.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
 
static ioport8_t *dsrlnout_base;
 
static void dsrlnout_putchar(outdev_t *dev __attribute__((unused)), const char ch, bool silent)
{
if (!silent)
pio_write_8(dsrlnout_base, ch);
}
 
static outdev_t dsrlnout_console;
static outdev_operations_t dsrlnout_ops = {
.write = dsrlnout_putchar
};
 
void dsrlnout_init(ioport8_t *base)
{
/* Initialize the software structure. */
dsrlnout_base = base;
outdev_initialize("dsrlnout", &dsrlnout_console, &dsrlnout_ops);
stdout = &dsrlnout_console;
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 3);
sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(base));
}
 
/** @}
*/
/branches/network/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>
#include <ddi/device.h>
 
static indev_operations_t kbrdin_ops = {
.poll = NULL
};
 
#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 status;
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) {
uint8_t data = pio_read_8(&dev->data);
indev_push_character(&instance->kbrdin, data);
}
}
 
/** Initialize i8042. */
indev_t *i8042_init(i8042_t *dev, inr_t inr)
{
i8042_instance_t *instance
= malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
if (!instance)
return NULL;
indev_initialize("i8042", &instance->kbrdin, &kbrdin_ops);
instance->i8042 = dev;
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_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 &instance->kbrdin;
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/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>
#include <ddi/device.h>
 
static indev_operations_t kbrdin_ops = {
.poll = NULL
};
 
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);
}
 
static 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;
}
 
static void z8530_irq_handler(irq_t *irq)
{
z8530_instance_t *instance = irq->instance;
z8530_t *dev = instance->z8530;
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
uint8_t x = z8530_read(&dev->ctl_a, RR8);
indev_push_character(&instance->kbrdin, x);
}
}
 
/** Initialize z8530. */
indev_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg)
{
z8530_instance_t *instance
= malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
indev_initialize("z8530", &instance->kbrdin, &kbrdin_ops);
instance->z8530 = dev;
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_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 &instance->kbrdin;
}
 
/** @}
*/
Property changes:
Added: svn:mergeinfo
/branches/network/kernel/genarch/src/drivers/ega/ega.c
0,0 → 1,206
/*
* 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 SPACE 0x20
#define STYLE 0x07
 
#define EMPTY_CHAR (STYLE << 8 | SPACE)
 
/*
* 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;
backbuf[ega_cursor * 2 + 1] = STYLE;
if (!silent) {
videoram[ega_cursor * 2] = ch;
videoram[ega_cursor * 2 + 1] = STYLE;
}
}
 
static void ega_putchar(outdev_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 outdev_t ega_console;
static outdev_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();
outdev_initialize("ega", &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/network/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/network/kernel/genarch/src/srln/srln.c
0,0 → 1,88
/*
* 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>
 
static indev_t srlnout;
 
indev_operations_t srlnout_ops = {
.poll = NULL
};
 
static void ksrln(void *arg)
{
indev_t *in = (indev_t *) arg;
bool cr = false;
while (true) {
uint8_t ch = _getc(in);
if ((ch == '\n') && (cr)) {
cr = false;
continue;
}
if (ch == '\r') {
ch = '\n';
cr = true;
} else
cr = false;
if (ch == 0x7f)
ch = '\b';
indev_push_character(stdin, ch);
}
}
 
void srln_init(indev_t *devin)
{
indev_initialize("srln", &srlnout, &srlnout_ops);
thread_t *thread
= thread_create(ksrln, devin, TASK, 0, "ksrln", false);
if (thread) {
stdin = &srlnout;
thread_ready(thread);
}
}
 
/** @}
*/
/branches/network/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/network/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/network/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/network/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/network/kernel/generic/include/symtab.h
44,15 → 44,20
char symbol_name[MAX_SYMBOL_NAME];
};
 
extern char * get_symtab_entry(unative_t addr);
extern uintptr_t get_symbol_addr(const char *name);
extern int symtab_name_lookup(unative_t addr, char **name);
extern char *symtab_fmt_name_lookup(unative_t addr);
extern int symtab_addr_lookup(const char *name, uintptr_t *addr);
extern void symtab_print_search(const char *name);
extern int symtab_compl(char *name);
 
#ifdef CONFIG_SYMTAB
 
/* Symtable linked together by build process */
extern struct symtab_entry symbol_table[];
 
#endif
 
#endif
 
/** @}
*/
/branches/network/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,13 → 38,16
#include <arch/types.h>
#include <arch/mm/page.h>
 
#define STACK_SIZE PAGE_SIZE
#define STACK_SIZE PAGE_SIZE
 
#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 {
63,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/network/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/network/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;
132,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/network/kernel/generic/include/proc/program.h
52,12 → 52,14
 
extern void *program_loader;
 
extern void program_create(as_t *as, uintptr_t entry_addr, program_t *p);
extern int program_create_from_image(void *image_addr, program_t *p);
extern int program_create_loader(program_t *p);
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(int *uspace_phone_id);
extern unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len);
 
#endif
 
/branches/network/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/network/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/network/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/network/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/network/kernel/generic/include/debug.h
57,21 → 57,21
#ifdef CONFIG_DEBUG
# define ASSERT(expr) \
if (!(expr)) { \
panic("assertion failed (%s), caller=%p\n", #expr, CALLER); \
panic("Assertion failed (%s), caller=%p.", #expr, CALLER); \
}
#else
# define ASSERT(expr)
#endif
 
/** Extensive debugging output macro
/** Extensive logging output macro
*
* If CONFIG_EDEBUG is set, the LOG() macro
* If CONFIG_LOG is set, the LOG() macro
* will print whatever message is indicated plus
* an information about the location.
*
*/
 
#ifdef CONFIG_EDEBUG
#ifdef CONFIG_LOG
# define LOG(format, ...) \
printf("%s() at %s:%u: " format "\n", __func__, __FILE__, \
__LINE__, ##__VA_ARGS__);
79,15 → 79,15
# define LOG(format, ...)
#endif
 
/** Extensive debugging execute macro
/** Extensive logging execute macro
*
* If CONFIG_EDEBUG is set, the LOG_EXEC() macro
* If CONFIG_LOG is set, the LOG_EXEC() macro
* will print an information about calling a given
* function and call it.
*
*/
 
#ifdef CONFIG_EDEBUG
#ifdef CONFIG_LOG
# define LOG_EXEC(fnc) \
{ \
printf("%s() at %s:%u: " #fnc "\n", __func__, __FILE__, \
/branches/network/kernel/generic/include/panic.h
37,11 → 37,11
 
#ifdef CONFIG_DEBUG
# define panic(format, ...) \
panic_printf("Kernel panic in %s() at %s:%u: " format, __func__, \
__FILE__, __LINE__, ##__VA_ARGS__);
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__);
panic_printf("Kernel panic: " format "\n", ##__VA_ARGS__);
#endif
 
extern void panic_printf(char *fmt, ...) __attribute__((noreturn));
/branches/network/kernel/generic/include/interrupt.h
44,12 → 44,12
 
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; \
printf("Task %" PRIu64 " killed due to an exception at %p.", task->taskid, istate_get_pc(istate)); \
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/network/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/network/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>
/branches/network/kernel/generic/include/memstr.h
44,7 → 44,7
extern void *_memcpy(void *dst, const void *src, size_t cnt);
extern void _memsetb(void *dst, size_t cnt, uint8_t x);
extern void _memsetw(void *dst, size_t cnt, uint16_t x);
extern char *strcpy(char *dest, const char *src);
extern void *memmove(void *dst, const void *src, size_t cnt);
 
#endif
 
/branches/network/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/network/kernel/generic/include/ddi/device.h
39,6 → 39,7
#include <typedefs.h>
 
extern devno_t device_assign_devno(void);
extern unative_t sys_device_assign_devno(void);
 
#endif
 
/branches/network/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/network/kernel/generic/include/console/chardev.h
39,41 → 39,60
#include <synch/waitq.h>
#include <synch/spinlock.h>
 
#define CHARDEV_BUFLEN 512
#define INDEV_BUFLEN 512
 
struct chardev;
struct indev;
 
/* Character device operations interface. */
/* Input character device operations interface. */
typedef struct {
/** Suspend pushing characters. */
void (* suspend)(struct chardev *);
/** Resume pushing characters. */
void (* resume)(struct chardev *);
/** Write character to stream. */
void (* write)(struct chardev *, char c);
/** Read character directly from device, assume interrupts disabled. */
char (* read)(struct chardev *);
} chardev_operations_t;
char (* poll)(struct indev *);
} indev_operations_t;
 
/** Character input device. */
typedef struct chardev {
typedef struct indev {
char *name;
waitq_t wq;
waitq_t wq;
/** Protects everything below. */
SPINLOCK_DECLARE(lock);
uint8_t buffer[CHARDEV_BUFLEN];
SPINLOCK_DECLARE(lock);
uint8_t buffer[INDEV_BUFLEN];
count_t counter;
/** Implementation of chardev operations. */
chardev_operations_t *op;
/** Implementation of indev operations. */
indev_operations_t *op;
index_t index;
void *data;
} chardev_t;
} indev_t;
 
extern void chardev_initialize(char *name, chardev_t *chardev,
chardev_operations_t *op);
extern void chardev_push_character(chardev_t *chardev, uint8_t ch);
 
struct outdev;
 
/* Output character device operations interface. */
typedef struct {
/** Write character to output. */
void (* write)(struct outdev *, char c, bool silent);
} outdev_operations_t;
 
/** Character input device. */
typedef struct outdev {
char *name;
/** Protects everything below. */
SPINLOCK_DECLARE(lock);
/** Implementation of outdev operations. */
outdev_operations_t *op;
void *data;
} outdev_t;
 
extern void indev_initialize(char *name, indev_t *indev,
indev_operations_t *op);
extern void indev_push_character(indev_t *indev, uint8_t ch);
 
extern void outdev_initialize(char *name, outdev_t *outdev,
outdev_operations_t *op);
 
#endif /* KERN_CHARDEV_H_ */
 
/** @}
/branches/network/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,17
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 bool kconsole_check_poll(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/network/kernel/generic/include/console/console.h
38,17 → 38,29
#include <arch/types.h>
#include <console/chardev.h>
 
extern chardev_t *stdin;
extern chardev_t *stdout;
extern indev_t *stdin;
extern outdev_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 count_t gets(chardev_t *chardev, char *buf, size_t buflen);
extern bool check_poll(indev_t *indev);
extern uint8_t getc(indev_t *indev);
extern uint8_t _getc(indev_t *indev);
extern count_t gets(indev_t *indev, char *buf, size_t buflen);
extern void putchar(char c);
extern unative_t sys_klog(int fd, const void * buf, size_t count);
 
extern void grab_console(void);
extern void release_console(void);
 
extern unative_t sys_debug_enable_console(void);
extern unative_t sys_debug_disable_console(void);
 
extern void arch_grab_console(void);
extern void arch_release_console(void);
 
/branches/network/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/network/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/network/kernel/generic/include/mm/frame.h
38,34 → 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
 
/** Convert the frame address to kernel va. */
#define FRAME_KA 0x1
typedef uint8_t frame_flags_t;
 
/** 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
/** Do not allocate above 4 GiB. */
#define FRAME_LOW_4_GiB 0x8
#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);
88,31 → 136,37
return (size_t) (frames << FRAME_WIDTH);
}
 
#define IS_BUDDY_ORDER_OK(index, order) \
static inline bool zone_flags_available(zone_flags_t flags)
{
return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
}
 
#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)
#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) \
#define frame_alloc(order, flags) \
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t, int, unsigned int *);
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, count_t, pfn_t, int);
extern void *frame_get_parent(pfn_t, unsigned int);
extern void frame_set_parent(pfn_t, void *, unsigned int);
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 void zone_merge(unsigned int, unsigned int);
extern bool zone_merge(count_t, count_t);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
120,7 → 174,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(unsigned int);
extern void zone_print_one(count_t);
 
#endif
 
/branches/network/kernel/generic/include/mm/page.h
42,7 → 42,7
/** 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;
59,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/network/kernel/generic/include/mm/slab.h
59,7 → 59,7
/* 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 */
 
/branches/network/kernel/generic/include/mm/buddy.h
82,7 → 82,7
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(int);
extern size_t buddy_conf_size(size_t);
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
 
#endif
/branches/network/kernel/generic/include/typedefs.h
51,6 → 51,10
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/network/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
35,47 → 35,66
#ifndef KERN_MACROS_H_
#define KERN_MACROS_H_
 
#ifndef __ASM__
 
#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 min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
 
/** Return true if the intervals overlap.
*
* @param s1 Start address of the first interval.
* @param sz1 Size of the first interval.
* @param s2 Start address of the second interval.
* @param sz2 Size of the second 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 sz2 Size of the second interval.
*/
static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2)
{
uintptr_t e1 = s1 + sz1;
uintptr_t e2 = s2 + sz2;
 
return (s1 < e2) && (s2 < e1);
return ((s1 < e2) && (s2 < e1));
}
 
#endif /* __ASM__ */
 
#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 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)))
 
/* Compute overlapping of physical addresses */
#define PA_overlaps(x, szx, 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 KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
#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/network/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/network/kernel/generic/include/syscall/syscall.h
44,6 → 44,7
SYS_THREAD_GET_ID,
SYS_TASK_GET_ID,
SYS_TASK_SET_NAME,
SYS_PROGRAM_SPAWN_LOADER,
SYS_FUTEX_SLEEP,
62,6 → 63,7
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,
70,6 → 72,7
SYS_CAP_GRANT,
SYS_CAP_REVOKE,
SYS_DEVICE_ASSIGN_DEVNO,
SYS_PHYSMEM_MAP,
SYS_IOSPACE_ENABLE,
SYS_PREEMPT_CONTROL,
78,6 → 81,8
SYS_SYSINFO_VALUE,
SYS_DEBUG_ENABLE_CONSOLE,
SYS_DEBUG_DISABLE_CONSOLE,
SYS_IPC_CONNECT_KBOX,
SYSCALL_END
} syscall_t;
 
/branches/network/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/network/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
260,12 → 266,6
typedef struct {
unative_t args[IPC_CALL_LEN];
phone_t *phone;
/*
* 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;
} ipc_data_t;
 
typedef struct {
287,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);
306,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/network/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/network/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/network/kernel/generic/include/errno.h
48,15 → 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 EINTR -16 /* Operation was interrupted. */
#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/network/kernel/generic/src/synch/rwlock.c
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/network/kernel/generic/src/synch/spinlock.c
76,7 → 76,6
void spinlock_lock_debug(spinlock_t *sl)
{
count_t i = 0;
char *symbol;
bool deadlock_reported = false;
 
preemption_disable();
106,12 → 105,10
continue;
#endif
if (i++ > DEADLOCK_THRESHOLD) {
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);
printf("\n");
printf("cpu%u: looping on spinlock %" PRIp ":%s, "
"caller=%" PRIp "(%s)", CPU->id, sl, sl->name,
CALLER, symtab_fmt_name_lookup(CALLER));
 
i = 0;
deadlock_reported = true;
}
/branches/network/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/network/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.
64,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>
72,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
82,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);
/*
100,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;
125,35 → 133,36
* 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();
 
/*
* Create kernel console.
*/
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole",
false);
if (t)
thread_ready(t);
else
panic("thread_create/kconsole\n");
 
#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();
/*
164,14 → 173,31
for (i = 0; i < init.cnt; i++) {
if (init.tasks[i].addr % FRAME_SIZE) {
printf("init[%" PRIc "].addr is not frame aligned", i);
printf("init[%" PRIc "].addr is not frame aligned\n", i);
continue;
}
 
/*
* 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,
&programs[i]);
 
if (rc == 0 && programs[i].task != NULL) {
namebuf, &programs[i]);
if ((rc == 0) && (programs[i].task != NULL)) {
/*
* Set capabilities to init userspace tasks.
*/
184,31 → 210,42
/* It was the program loader and was registered */
} else {
/* RAM disk image */
int rd = init_rd((rd_header_t *) init.tasks[i].addr,
init.tasks[i].size);
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %" PRIc " not used, error "
"code %d.\n", i, rd);
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
}
}
/*
* Run user tasks with reasonable delays
* 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) {
thread_usleep(50000);
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/network/kernel/generic/src/main/main.c
81,8 → 81,8
#include <adt/btree.h>
#include <smp/smp.h>
#include <ddi/ddi.h>
#include <main/main.h>
 
 
/** Global configuration structure. */
config_t config;
 
105,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
191,8 → 188,6
{
/* Keep this the first thing. */
the_initialize(THE);
 
LOG();
version_print();
201,7 → 196,7
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
208,6 → 203,7
* commands.
*/
LOG_EXEC(kconsole_init());
#endif
/*
* Exception handler initialization, before architecture
214,7 → 210,7
* starts adding its own handlers
*/
LOG_EXEC(exc_init());
 
/*
* Memory management subsystems initialization.
*/
252,7 → 248,7
if (init.cnt > 0) {
count_t i;
for (i = 0; i < init.cnt; i++)
printf("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
260,21 → 256,25
LOG_EXEC(ipc_init());
LOG_EXEC(klog_init());
 
#ifdef CONFIG_KCONSOLE
LOG_EXEC(kconsole_notify_init());
#endif
/*
* Create kernel task.
*/
task_t *kernel = task_create(AS_KERNEL, "kernel");
if (!kernel)
panic("Can't create kernel task\n");
panic("Cannot create kernel task.");
/*
* Create the first thread.
*/
thread_t *kinit_thread = thread_create(kinit, NULL, kernel, 0, "kinit",
true);
thread_t *kinit_thread
= thread_create(kinit, NULL, kernel, 0, "kinit", true);
if (!kinit_thread)
panic("Can't create kinit thread\n");
panic("Cannot create kinit thread.");
LOG_EXEC(thread_ready(kinit_thread));
/*
328,6 → 328,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/network/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/network/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/network/kernel/generic/src/debug/symtab.c
37,22 → 37,23
 
#include <symtab.h>
#include <byteorder.h>
#include <func.h>
#include <string.h>
#include <print.h>
#include <arch/types.h>
#include <typedefs.h>
#include <errno.h>
 
/** Return entry that seems most likely to correspond to argument.
/** Get name of symbol that seems most likely to correspond to address.
*
* Return entry that seems most likely to correspond
* to address passed in the argument.
* @param addr Address.
* @param name Place to store pointer to the symbol name.
*
* @param addr Address.
*
* @return Pointer to respective symbol string on success, NULL otherwise.
* @return Zero on success or negative error code, ENOENT if not found,
* ENOTSUP if symbol table not available.
*/
char * get_symtab_entry(unative_t addr)
int symtab_name_lookup(unative_t addr, char **name)
{
#ifdef CONFIG_SYMTAB
count_t i;
 
for (i = 1; symbol_table[i].address_le; ++i) {
59,11 → 60,44
if (addr < uint64_t_le2host(symbol_table[i].address_le))
break;
}
if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le))
return symbol_table[i - 1].symbol_name;
return NULL;
if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) {
*name = symbol_table[i - 1].symbol_name;
return EOK;
}
 
*name = NULL;
return ENOENT;
#else
*name = NULL;
return ENOTSUP;
#endif
}
 
/** Lookup symbol by address and format for display.
*
* Returns name of closest corresponding symbol, "Not found" if none exists
* or "N/A" if no symbol information is available.
*
* @param addr Address.
* @param name Place to store pointer to the symbol name.
*
* @return Pointer to a human-readable string.
*/
char *symtab_fmt_name_lookup(unative_t addr)
{
int rc;
char *name;
 
rc = symtab_name_lookup(addr, &name);
switch (rc) {
case EOK: return name;
case ENOENT: return "Not found";
default: return "N/A";
}
}
 
#ifdef CONFIG_SYMTAB
 
/** Find symbols that match the parameter forward and print them.
*
* @param name - search string
102,17 → 136,22
return NULL;
}
 
#endif
 
/** Return address that corresponds to the entry
*
* Search symbol table, and if there is one match, return it
*
* @param name Name of the symbol
* @return 0 - Not found, -1 - Duplicate symbol, other - address of symbol
* @param name Name of the symbol
* @param addr Place to store symbol address
*
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate
* symbol, ENOTSUP - no symbol information available.
*/
uintptr_t get_symbol_addr(const char *name)
int symtab_addr_lookup(const char *name, uintptr_t *addr)
{
#ifdef CONFIG_SYMTAB
count_t found = 0;
uintptr_t addr = NULL;
char *hint;
int i;
 
119,19 → 158,25
i = 0;
while ((hint = symtab_search_one(name, &i))) {
if (!strlen(hint)) {
addr = uint64_t_le2host(symbol_table[i].address_le);
*addr = uint64_t_le2host(symbol_table[i].address_le);
found++;
}
i++;
}
if (found > 1)
return ((uintptr_t) -1);
return addr;
return EOVERFLOW;
if (found < 1)
return ENOENT;
return EOK;
#else
return ENOTSUP;
#endif
}
 
/** Find symbols that match parameter and prints them */
void symtab_print_search(const char *name)
{
#ifdef CONFIG_SYMTAB
int i;
uintptr_t addr;
char *realname;
144,6 → 189,9
printf("%p: %s\n", addr, realname);
i++;
}
#else
printf("No symbol information available.\n");
#endif
}
 
/** Symtab completion
153,6 → 201,7
*/
int symtab_compl(char *input)
{
#ifdef CONFIG_SYMTAB
char output[MAX_SYMBOL_NAME + 1];
int startpos = 0;
char *foundtxt;
196,7 → 245,9
}
strncpy(input, output, MAX_SYMBOL_NAME);
return found;
#else
return 0;
#endif
}
 
/** @}
/branches/network/kernel/generic/src/cpu/cpu.c
64,7 → 64,7
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(cpus, sizeof(cpu_t) * config.cpu_count, 0);
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;
/branches/network/kernel/generic/src/sysinfo/sysinfo.c
163,7 → 163,8
i = 0;
}
}
panic("Not reached\n");
 
panic("Not reached.");
return NULL;
}
 
/branches/network/kernel/generic/src/interrupt/interrupt.c
42,7 → 42,6
#include <debug.h>
#include <console/kconsole.h>
#include <console/console.h>
#include <console/chardev.h>
#include <console/cmd.h>
#include <panic.h>
#include <print.h>
68,13 → 67,13
iroutine old;
spinlock_lock(&exctbl_lock);
 
old = exc_table[n].f;
exc_table[n].f = f;
exc_table[n].name = name;
 
spinlock_unlock(&exctbl_lock);
 
spinlock_unlock(&exctbl_lock);
return old;
}
 
86,8 → 85,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 → 108,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;
120,9 → 130,7
#endif
for (i = 0; i < IVT_ITEMS; i++) {
symbol = get_symtab_entry((unative_t) exc_table[i].f);
if (!symbol)
symbol = "not found";
symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f);
 
#ifdef __32_BITS__
printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
137,7 → 145,7
if (((i + 1) % 20) == 0) {
printf(" -- Press any key to continue -- ");
spinlock_unlock(&exctbl_lock);
getc(stdin);
_getc(stdin);
spinlock_lock(&exctbl_lock);
printf("\n");
}
149,15 → 157,18
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)
{
166,9 → 177,11
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/network/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/network/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/network/kernel/generic/src/ddi/device.c
31,7 → 31,7
*/
/**
* @file
* @brief Device numbers.
* @brief Device numbers.
*/
 
#include <arch/types.h>
47,13 → 47,16
*/
devno_t device_assign_devno(void)
{
devno_t devno;
 
devno = (devno_t) atomic_postinc(&last);
devno_t devno = (devno_t) atomic_postinc(&last);
ASSERT(devno >= 0);
 
return devno;
}
 
unative_t sys_device_assign_devno(void)
{
return (unative_t) device_assign_devno();
}
 
/** @}
*/
/branches/network/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/network/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/network/kernel/generic/src/printf/vprintf.c
62,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/network/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 */
/branches/network/kernel/generic/src/console/console.c
39,7 → 39,6
#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>
47,71 → 46,45
#include <func.h>
#include <print.h>
#include <atomic.h>
#include <syscall/copy.h>
#include <errno.h>
 
#define KLOG_SIZE PAGE_SIZE
#define KLOG_LATENCY 8
 
/**< Kernel log cyclic buffer */
/** Kernel log cyclic buffer */
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 
/**< Kernel log initialized */
/** Kernel log initialized */
static bool klog_inited = false;
/**< First kernel log characters */
/** First kernel log characters */
static index_t klog_start = 0;
/**< Number of valid kernel log characters */
/** Number of valid kernel log characters */
static size_t klog_len = 0;
/**< Number of stored (not printed) kernel log characters */
/** Number of stored (not printed) kernel log characters */
static size_t klog_stored = 0;
/**< Number of stored kernel log characters for uspace */
/** Number of stored kernel log characters for uspace */
static size_t klog_uspace = 0;
 
/**< Kernel log spinlock */
/** 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.
*/
#define KLOG_VIRT_INR 0
 
static irq_t klog_irq;
/** Standard input and output character devices */
indev_t *stdin = NULL;
outdev_t *stdout = NULL;
 
static chardev_operations_t null_stdout_ops = {
.suspend = NULL,
.resume = NULL,
.write = NULL,
.read = NULL
};
 
chardev_t null_stdout = {
.name = "null",
.op = &null_stdout_ops
};
 
/** 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(void)
{
return IRQ_DECLINE;
}
 
/** Standard input character device */
chardev_t *stdin = NULL;
chardev_t *stdout = &null_stdout;
 
/** 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)
{
119,89 → 92,122
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.vbase = (uintptr_t) klog;
klog_parea.frames = SIZE2FRAMES(KLOG_SIZE);
klog_parea.cacheable = true;
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);
//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);
}
 
/** Get character from character device. Do not echo character.
void grab_console(void)
{
silent = false;
arch_grab_console();
}
 
void release_console(void)
{
silent = true;
arch_release_console();
}
 
/** Tell kernel to get keyboard/console access again */
unative_t sys_debug_enable_console(void)
{
#ifdef CONFIG_KCONSOLE
grab_console();
return true;
#else
return false;
#endif
}
 
/** Tell kernel to relinquish keyboard/console access */
unative_t sys_debug_disable_console(void)
{
release_console();
return true;
}
 
bool check_poll(indev_t *indev)
{
if (indev == NULL)
return false;
if (indev->op == NULL)
return false;
return (indev->op->poll != NULL);
}
 
/** Get character from input character device. Do not echo character.
*
* @param chardev Character device.
* @param indev Input character device.
* @return Character read.
*
* @return Character read.
*/
uint8_t _getc(chardev_t *chardev)
uint8_t _getc(indev_t *indev)
{
uint8_t ch;
ipl_t ipl;
 
if (atomic_get(&haltstate)) {
/* If we are here, we are hopefully on the processor, that
/* If we are here, we are hopefully on the processor that
* issued the 'halt' command, so proceed to read the character
* directly from input
*/
if (chardev->op->read)
return chardev->op->read(chardev);
/* no other way of interacting with user, halt */
if (check_poll(indev))
return indev->op->poll(indev);
/* No other way of interacting with user */
interrupts_disable();
if (CPU)
printf("cpu%u: ", CPU->id);
else
printf("cpu: ");
printf("halted - no kconsole\n");
printf("halted (no polling input)\n");
cpu_halt();
}
 
waitq_sleep(&chardev->wq);
ipl = interrupts_disable();
spinlock_lock(&chardev->lock);
ch = chardev->buffer[(chardev->index - chardev->counter) % CHARDEV_BUFLEN];
chardev->counter--;
spinlock_unlock(&chardev->lock);
waitq_sleep(&indev->wq);
ipl_t ipl = interrupts_disable();
spinlock_lock(&indev->lock);
uint8_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN];
indev->counter--;
spinlock_unlock(&indev->lock);
interrupts_restore(ipl);
 
chardev->op->resume(chardev);
 
return ch;
}
 
/** Get string from character device.
/** Get string from input character device.
*
* Read characters from character device until first occurrence
* Read characters from input character device until first occurrence
* of newline character.
*
* @param chardev Character device.
* @param buf Buffer where to store string terminated by '\0'.
* @param indev Input character device.
* @param buf Buffer where to store string terminated by '\0'.
* @param buflen Size of the buffer.
*
* @return Number of characters read.
*
*/
count_t gets(chardev_t *chardev, char *buf, size_t buflen)
count_t gets(indev_t *indev, char *buf, size_t buflen)
{
index_t index = 0;
char ch;
 
while (index < buflen) {
ch = _getc(chardev);
char ch = _getc(indev);
if (ch == '\b') {
if (index > 0) {
index--;
213,7 → 219,7
continue;
}
putchar(ch);
 
if (ch == '\n') { /* end of string => write 0, return */
buf[index] = '\0';
return (count_t) index;
220,15 → 226,14
}
buf[index++] = ch;
}
return (count_t) index;
}
 
/** Get character from device & echo it to screen */
uint8_t getc(chardev_t *chardev)
/** Get character from input device & echo it to screen */
uint8_t getc(indev_t *indev)
{
uint8_t ch;
 
ch = _getc(chardev);
uint8_t ch = _getc(indev);
putchar(ch);
return ch;
}
237,10 → 242,10
{
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;
}
// 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);
}
249,11 → 254,11
{
spinlock_lock(&klog_lock);
if ((klog_stored > 0) && (stdout->op->write)) {
if ((klog_stored > 0) && (stdout) && (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]);
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent);
klog_stored = 0;
}
264,8 → 269,8
else
klog_start = (klog_start + 1) % KLOG_SIZE;
if (stdout->op->write)
stdout->op->write(stdout, c);
if ((stdout) && (stdout->op->write))
stdout->op->write(stdout, c, silent);
else {
/* The character is just in the kernel log */
if (klog_stored < klog_len)
289,5 → 294,38
klog_update();
}
 
/** Print using kernel facility
*
* Print to kernel log.
*
*/
unative_t sys_klog(int fd, const void * buf, size_t count)
{
char *data;
int rc;
 
if (count > PAGE_SIZE)
return ELIMIT;
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);
} else
klog_update();
return count;
}
 
/** @}
*/
/branches/network/kernel/generic/src/console/cmd.c
50,9 → 50,9
#include <arch.h>
#include <config.h>
#include <func.h>
#include <string.h>
#include <macros.h>
#include <debug.h>
#include <symtab.h>
#include <cpu.h>
#include <mm/tlb.h>
#include <arch/mm/tlb.h>
64,6 → 64,8
#include <proc/task.h>
#include <ipc/ipc.h>
#include <ipc/irq.h>
#include <symtab.h>
#include <errno.h>
 
#ifdef CONFIG_TEST
#include <test.h>
78,12 → 80,6
.argc = 0
};
 
static cmd_info_t exit_info = {
.name = "exit",
.description = "Exit kconsole.",
.argc = 0
};
 
static int cmd_reboot(cmd_arg_t *argv);
static cmd_info_t reboot_info = {
.name = "reboot",
398,17 → 394,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 */
456,12 → 452,11
&continue_info,
&cpus_info,
&desc_info,
&exit_info,
&reboot_info,
&uptime_info,
&halt_info,
&help_info,
&ipc_task_info,
&ipc_info,
&set4_info,
&slabs_info,
&symaddr_info,
501,7 → 496,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 → 509,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;
}
 
616,33 → 619,26
{
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;
int rc;
 
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
else if (symaddr == (uintptr_t) -1) {
symtab_print_search((char *) argv->buffer);
symbol = (char *) argv->buffer;
rc = symtab_addr_lookup(symbol, &symaddr);
 
if (rc == ENOENT)
printf("Symbol %s not found.\n", symbol);
else if (rc == EOVERFLOW) {
symtab_print_search(symbol);
printf("Duplicate symbol, be more specific.\n");
} else if (rc == EOK) {
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());
} else {
symbol = get_symtab_entry(symaddr);
printf("Calling %s() (%p)\n", symbol, 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: %#" PRIxn "\n", f());
printf("No symbol information available.\n");
}
return 1;
}
 
680,35 → 676,27
{
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;
int rc;
 
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
else if (symaddr == (uintptr_t) -1) {
symtab_print_search((char *) argv->buffer);
symbol = (char *) argv->buffer;
rc = symtab_addr_lookup(symbol, &symaddr);
 
if (rc == ENOENT) {
printf("Symbol %s not found.\n", symbol);
} else if (rc == EOVERFLOW) {
symtab_print_search(symbol);
printf("Duplicate symbol, be more specific.\n");
} else if (rc == EOK) {
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));
} else {
symbol = get_symtab_entry(symaddr);
printf("No symbol information available.\n");
}
 
printf("Calling f(%#" PRIxn "): %p: %s\n", arg1, 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: %#" PRIxn "\n", f(arg1));
}
return 1;
}
 
717,36 → 705,28
{
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;
int rc;
 
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
else if (symaddr == (uintptr_t) -1) {
symtab_print_search((char *) argv->buffer);
symbol = (char *) argv->buffer;
rc = symtab_addr_lookup(symbol, &symaddr);
 
if (rc == ENOENT) {
printf("Symbol %s not found.\n", symbol);
} else if (rc == EOVERFLOW) {
symtab_print_search(symbol);
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
} else if (rc == EOK) {
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);
#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: %#" PRIxn "\n", f(arg1, arg2));
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2));
} else {
printf("No symbol information available.\n");
}
return 1;
}
 
755,37 → 735,29
{
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;
int rc;
symbol = (char *) argv->buffer;
rc = symtab_addr_lookup(symbol, &symaddr);
 
symaddr = get_symbol_addr((char *) argv->buffer);
if (!symaddr)
printf("Symbol %s not found.\n", argv->buffer);
else if (symaddr == (uintptr_t) -1) {
symtab_print_search((char *) argv->buffer);
if (rc == ENOENT) {
printf("Symbol %s not found.\n", symbol);
} else if (rc == EOVERFLOW) {
symtab_print_search(symbol);
printf("Duplicate symbol, be more specific.\n");
} else {
symbol = get_symtab_entry(symaddr);
} else if (rc == EOK) {
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);
#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: %#" PRIxn "\n", f(arg1, arg2, arg3));
printf("Result: %#" PRIxn "\n", fnc(arg1, arg2, arg3));
} else {
printf("No symbol information available.\n");
}
return 1;
}
 
835,30 → 807,34
/** Write 4 byte value to address */
int cmd_set4(cmd_arg_t *argv)
{
uint32_t *addr;
uintptr_t addr;
uint32_t arg1 = argv[1].intval;
bool pointer = false;
int rc;
 
if (((char *)argv->buffer)[0] == '*') {
addr = (uint32_t *) get_symbol_addr((char *) argv->buffer + 1);
rc = symtab_addr_lookup((char *) argv->buffer + 1, &addr);
pointer = true;
} else if (((char *) argv->buffer)[0] >= '0' &&
((char *)argv->buffer)[0] <= '9')
addr = (uint32_t *)atoi((char *)argv->buffer);
else
addr = (uint32_t *)get_symbol_addr((char *) argv->buffer);
((char *)argv->buffer)[0] <= '9') {
rc = EOK;
addr = atoi((char *)argv->buffer);
} else {
rc = symtab_addr_lookup((char *) argv->buffer, &addr);
}
 
if (!addr)
if (rc == ENOENT)
printf("Symbol %s not found.\n", argv->buffer);
else if (addr == (uint32_t *) -1) {
else if (rc == EOVERFLOW) {
symtab_print_search((char *) argv->buffer);
printf("Duplicate symbol, be more specific.\n");
} else {
} else if (rc == EOK) {
if (pointer)
addr = (uint32_t *)(*(unative_t *)addr);
addr = *(uintptr_t *) addr;
printf("Writing %#" PRIx64 " -> %p\n", arg1, addr);
*addr = arg1;
*(uint32_t *) addr = arg1;
} else {
printf("No symbol information available.\n");
}
return 1;
937,7 → 913,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 → 952,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 → 969,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 */
/branches/network/kernel/generic/src/console/chardev.c
37,42 → 37,62
#include <synch/waitq.h>
#include <synch/spinlock.h>
 
/** Initialize character device.
/** Initialize input character device.
*
* @param chardev Character device.
* @param op Implementation of character device operations.
* @param indev Input character device.
* @param op Implementation of input character device operations.
*
*/
void chardev_initialize(char *name, chardev_t *chardev,
chardev_operations_t *op)
void indev_initialize(char *name, indev_t *indev,
indev_operations_t *op)
{
chardev->name = name;
 
waitq_initialize(&chardev->wq);
spinlock_initialize(&chardev->lock, "chardev");
chardev->counter = 0;
chardev->index = 0;
chardev->op = op;
indev->name = name;
waitq_initialize(&indev->wq);
spinlock_initialize(&indev->lock, "indev");
indev->counter = 0;
indev->index = 0;
indev->op = op;
}
 
/** Push character read from input character device.
*
* @param chardev Character device.
* @param ch Character being pushed.
* @param indev Input character device.
* @param ch Character being pushed.
*
*/
void chardev_push_character(chardev_t *chardev, uint8_t ch)
void indev_push_character(indev_t *indev, uint8_t ch)
{
spinlock_lock(&chardev->lock);
chardev->counter++;
if (chardev->counter == CHARDEV_BUFLEN - 1) {
/* buffer full => disable device interrupt */
chardev->op->suspend(chardev);
ASSERT(indev);
spinlock_lock(&indev->lock);
if (indev->counter == INDEV_BUFLEN - 1) {
/* Buffer full */
spinlock_unlock(&indev->lock);
return;
}
chardev->buffer[chardev->index++] = ch;
chardev->index = chardev->index % CHARDEV_BUFLEN; /* index modulo size of buffer */
waitq_wakeup(&chardev->wq, WAKEUP_FIRST);
spinlock_unlock(&chardev->lock);
indev->counter++;
indev->buffer[indev->index++] = ch;
/* Index modulo size of buffer */
indev->index = indev->index % INDEV_BUFLEN;
waitq_wakeup(&indev->wq, WAKEUP_FIRST);
spinlock_unlock(&indev->lock);
}
 
/** Initialize output character device.
*
* @param outdev Output character device.
* @param op Implementation of output character device operations.
*
*/
void outdev_initialize(char *name, outdev_t *outdev,
outdev_operations_t *op)
{
outdev->name = name;
spinlock_initialize(&outdev->lock, "outdev");
outdev->op = op;
}
 
/** @}
*/
/branches/network/kernel/generic/src/console/kconsole.c
49,8 → 49,12
#include <macros.h>
#include <debug.h>
#include <func.h>
#include <string.h>
#include <macros.h>
#include <sysinfo/sysinfo.h>
#include <ddi/device.h>
#include <symtab.h>
#include <macros.h>
#include <errno.h>
 
/** Simple kernel console.
*
83,10 → 87,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 → 127,26
}
 
 
/** Initialize kconsole notification mechanism
*
* Initialize the virtual IRQ notification mechanism.
*
*/
void kconsole_notify_init(void)
{
sysinfo_set_item_val("kconsole.present", NULL, true);
sysinfo_set_item_val("kconsole.inr", NULL, KCONSOLE_VIRT_INR);
irq_initialize(&kconsole_irq);
kconsole_irq.devno = device_assign_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.
203,7 → 256,7
*/
static int cmdtab_compl(char *name)
{
static char output[MAX_SYMBOL_NAME + 1];
static char output[/*MAX_SYMBOL_NAME*/128 + 1];
link_t *startpos = NULL;
const char *foundtxt;
int found = 0;
235,12 → 288,11
startpos = startpos->next;
}
}
strncpy(name, output, MAX_SYMBOL_NAME);
strncpy(name, output, 128/*MAX_SYMBOL_NAME*/);
return found;
}
 
static char *clever_readline(const char *prompt, chardev_t *input)
static char *clever_readline(const char *prompt, indev_t *input)
{
static int histposition = 0;
 
401,42 → 453,71
return current;
}
 
/** Kernel console managing thread.
bool kconsole_check_poll(void)
{
return check_poll(stdin);
}
 
/** 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;
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);
else
printf("Type \"exit\" to leave the console.\n");
while (true) {
cmdline = clever_readline((char *) prompt, stdin);
len = strlen(cmdline);
if (!len)
continue;
if ((!kcon) && (len == 4) && (strncmp(cmdline, "exit", 4) == 0))
break;
cmd_info = parse_cmdline(cmdline, len);
if (!cmd_info)
continue;
if (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];
uintptr_t symaddr;
bool isaddr = false;
bool isptr = false;
int rc;
 
static char symname[MAX_SYMBOL_NAME];
/* If we get a name, try to find it in symbol table */
if (text[0] == '&') {
450,16 → 531,20
}
if (text[0] < '0' || text[0] > '9') {
strncpy(symname, text, min(len + 1, MAX_SYMBOL_NAME));
symaddr = get_symbol_addr(symname);
if (!symaddr) {
rc = symtab_addr_lookup(symname, &symaddr);
switch (rc) {
case ENOENT:
printf("Symbol %s not found.\n", symname);
return -1;
}
if (symaddr == (uintptr_t) -1) {
case EOVERFLOW:
printf("Duplicate symbol %s.\n", symname);
symtab_print_search(symname);
return -1;
default:
printf("No symbol information available.\n");
return -1;
}
 
if (isaddr)
*result = (unative_t)symaddr;
else if (isptr)
/branches/network/kernel/generic/src/proc/scheduler.c
451,7 → 451,7
/*
* Entering state is unexpected.
*/
panic("tid%" PRIu64 ": unexpected state %s\n",
panic("tid%" PRIu64 ": unexpected state %s.",
THREAD->tid, thread_states[THREAD->state]);
break;
}
/branches/network/kernel/generic/src/proc/task.c
52,6 → 52,7
#include <print.h>
#include <errno.h>
#include <func.h>
#include <string.h>
#include <syscall/copy.h>
 
/** Spinlock protecting the tasks_tree AVL tree. */
130,7 → 131,7
/** Create new task with no threads.
*
* @param as Task's address space.
* @param name Symbolic name.
* @param name Symbolic name (a copy is made).
*
* @return New task's structure.
*
148,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;
155,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]);
235,6 → 250,35
sizeof(TASK->taskid));
}
 
/** Syscall for setting the task name.
*
* 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_set_name(const char *uspace_name, size_t name_len)
{
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
325,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)
353,13 → 397,13
order(task_get_accounting(t), &cycles, &suffix);
 
#ifdef __32_BITS__
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %10p %10p %9" PRIu64
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 " %-10s %-3" PRIu32 " %18p %18p %9" PRIu64
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
384,16 → 428,16
spinlock_lock(&tasks_lock);
 
#ifdef __32_BITS__
printf("taskid name ctx address as "
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ---------- ---------- "
printf("------ ------------ --- ---------- ---------- "
"---------- ------- ------ ------>\n");
#endif
 
#ifdef __64_BITS__
printf("taskid name ctx address as "
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ------------------ ------------------ "
printf("------ ------------ --- ------------------ ------------------ "
"---------- ------- ------ ------>\n");
#endif
 
/branches/network/kernel/generic/src/proc/program.c
67,9 → 67,10
*
* @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, program_t *p)
void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p)
{
as_area_t *a;
uspace_arg_t *kernel_uarg;
81,7 → 82,7
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
p->task = task_create(as, "app");
p->task = task_create(as, name);
ASSERT(p->task);
 
/*
106,6 → 107,7
* 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.
112,7 → 114,7
*
* @return EOK on success or negative error code.
*/
int program_create_from_image(void *image_addr, program_t *p)
int program_create_from_image(void *image_addr, char *name, program_t *p)
{
as_t *as;
unsigned int rc;
136,7 → 138,7
return EOK;
}
 
program_create(as, ((elf_header_t *) image_addr)->e_entry, p);
program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p);
 
return EOK;
}
143,10 → 145,12
 
/** Create a task from the program loader image.
*
* @param p Buffer for storing program info.
* @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)
int program_create_loader(program_t *p, char *name)
{
as_t *as;
unsigned int rc;
167,7 → 171,8
return ENOENT;
}
 
program_create(as, ((elf_header_t *) program_loader)->e_entry, p);
program_create(as, ((elf_header_t *) program_loader)->e_entry,
name, p);
 
return EOK;
}
185,48 → 190,37
 
/** Syscall for creating a new loader instance from userspace.
*
* Creates a new task from the program loader image, connects a phone
* to it and stores the phone id into the provided buffer.
* Creates a new task from the program loader image and sets
* the task name.
*
* @param uspace_phone_id Userspace address where to store the phone id.
* @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(int *uspace_phone_id)
unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len)
{
program_t p;
int fake_id;
int rc;
int phone_id;
char namebuf[TASK_NAME_BUFLEN];
 
fake_id = 0;
/* Cap length of name and copy it from userspace. */
 
/* Before we even try creating the task, see if we can write the id */
rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id,
sizeof(fake_id));
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 rc;
return (unative_t) rc;
 
phone_id = phone_alloc();
if (phone_id < 0)
return ELIMIT;
namebuf[name_len] = '\0';
 
rc = program_create_loader(&p);
/* Spawn the new task. */
 
rc = program_create_loader(&p, namebuf);
if (rc != 0)
return rc;
 
phone_connect(phone_id, &p.task->answerbox);
 
/* No need to aquire lock before task_ready() */
rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id,
sizeof(phone_id));
if (rc != 0) {
/* Ooops */
ipc_phone_hangup(&TASK->phones[phone_id]);
task_kill(p.task->taskid);
return rc;
}
 
// FIXME: control the capabilities
cap_set(p.task, cap_get(TASK));
 
/branches/network/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/network/kernel/generic/src/proc/thread.c
102,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
 
161,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
169,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
180,6 → 180,10
return -1;
}
 
#ifdef CONFIG_UDEBUG
mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE);
#endif
 
return 0;
}
 
192,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
207,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
275,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.
*
312,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;
347,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);
 
409,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);
 
437,14 → 452,19
{
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();
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid);
689,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];
696,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().
738,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/network/kernel/generic/src/lib/rd.c
88,9 → 88,7
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize),
FRAME_SIZE);
rd_parea.vbase = (uintptr_t) ((void *) header + hsize);
rd_parea.frames = SIZE2FRAMES(dsize);
rd_parea.cacheable = true;
ddi_parea_register(&rd_parea);
 
sysinfo_set_item_val("rd", NULL, true);
/branches/network/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/network/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,45 → 45,91
#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++)
((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];
((uint8_t *)(((unative_t *) dst) + i))[j] =
((uint8_t *)(((unative_t *) src) + i))[j];
}
return (char *) dst;
}
 
/** Move memory block with possible overlapping.
*
* Copy cnt bytes from src address to dst address. The source and destination
* memory areas may overlap.
*
* @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 *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;
}
 
/** Fill block of memory
*
* Fill cnt bytes at dst address with the value x.
* The filling is done byte-by-byte.
* 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 bytes 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 _memsetb(void *dst, size_t cnt, uint8_t x)
96,14 → 141,14
p[i] = x;
}
 
/** Fill block of memory
/** Fill block of memory.
*
* Fill cnt words at dst address with the value x.
* The filling is done word-by-word.
* Fill cnt words at dst address with the value x. The filling is done
* word-by-word.
*
* @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 words to fill.
* @param x Value to fill.
*
*/
void _memsetw(void *dst, size_t cnt, uint16_t x)
115,25 → 160,5
p[i] = x;
}
 
/** Copy string
*
* 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.
*
* @param src Origin string to copy from.
* @param dst Origin string to copy to.
*
*/
char *strcpy(char *dest, const char *src)
{
char *orig = dest;
while ((*(dest++) = *(src++)))
;
return orig;
}
 
/** @}
*/
/branches/network/kernel/generic/src/lib/func.c
47,7 → 47,7
 
/** Halt wrapper
*
* Set halt flag and halt the cpu.
* Set halt flag and halt the CPU.
*
*/
void halt()
54,9 → 54,7
{
#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;
64,118 → 62,22
#else
atomic_set(&haltstate, 1);
#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_check_poll()))
kconsole("panic", "\nLast resort kernel console ready.\n", false);
#endif
if (CPU)
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/network/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 %" PRIu64 "\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 %" PRIu64 "\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 %" PRIu64 "\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 %" PRIu64 "\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.
/branches/network/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/network/kernel/generic/src/adt/hash_table.c
61,7 → 61,7
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(h->entry, m * sizeof(link_t), 0);
/branches/network/kernel/generic/src/mm/slab.c
173,7 → 173,7
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) {
/branches/network/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/network/kernel/generic/src/mm/backend_anon.c
152,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/network/kernel/generic/src/mm/as.c
122,7 → 122,7
int rc;
 
link_initialize(&as->inactive_as_with_asid_link);
mutex_initialize(&as->lock, MUTEX_PASSIVE);
mutex_initialize(&as->lock, MUTEX_PASSIVE);
rc = as_constructor_arch(as, flags);
146,8 → 146,12
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.
176,7 → 180,7
#else
page_table_create(flags);
#endif
 
return as;
}
 
385,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.
395,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);
 
/*
440,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
448,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++) {
769,11 → 773,12
* 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 withing the area to be changed.
* @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.
* @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)
{
785,7 → 790,7
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);
 
799,7 → 804,7
return ENOENT;
}
 
if (area->sh_info || area->backend != &anon_backend) {
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);
870,6 → 875,7
*/
 
tlb_invalidate_pages(as->asid, area->base, area->pages);
/*
* Invalidate potential software translation caches (e.g. TSB on
* sparc64).
1660,7 → 1666,7
}
 
panic("Inconsistency detected while adding %" PRIc " pages of used "
"space at %p.\n", count, page);
"space at %p.", count, page);
}
 
/** Mark portion of address space area as unused.
1839,7 → 1845,7
 
error:
panic("Inconsistency detected while removing %" PRIc " pages of used "
"space from %p.\n", count, page);
"space from %p.", count, page);
}
 
/** Remove reference to address space area share info.
/branches/network/kernel/generic/src/mm/buddy.c
46,7 → 46,7
#include <macros.h>
 
/** Return size needed for the buddy configuration data. */
size_t buddy_conf_size(int max_order)
size_t buddy_conf_size(size_t max_order)
{
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
}
/branches/network/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/network/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,6
#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>
69,50 → 59,16
#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'
*/
 
typedef struct {
SPINLOCK_DECLARE(lock);
unsigned int count;
zone_t *info[ZONES_MAX];
} zones_t;
 
static zones_t zones;
 
/*
* Synchronization primitives used to sleep when there is no memory
* available.
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
unsigned long mem_avail_frames = 0; /**< Number of available frames. */
unsigned long mem_avail_gen = 0; /**< Generation counter. */
count_t mem_avail_req = 0; /**< Number of frames requested. */
count_t mem_avail_gen = 0; /**< Generation counter. */
 
/********************/
/* Helper functions */
128,13 → 84,12
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);
}
141,7 → 96,8
 
/** Initialize frame structure.
*
* @param frame Frame structure to be initialized.
* @param frame Frame structure to be initialized.
*
*/
static void frame_initialize(frame_t *frame)
{
149,153 → 105,145
frame->buddy_order = 0;
}
 
/**********************/
/* Zoneinfo functions */
/**********************/
/*******************/
/* Zones functions */
/*******************/
 
/** 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;
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 flags Required flags of the target zone.
* @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, int flags, 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;
/* Mask off flags that are not applicable. */
flags &= FRAME_LOW_4_GiB;
 
spinlock_lock(&zones.lock);
if (hint >= zones.count)
hint = 0;
i = hint;
count_t i = hint;
do {
z = zones.info[i];
spinlock_lock(&z->lock);
 
/*
* Check whether the zone meets the search criteria.
*/
if ((z->flags & flags) == flags) {
if ((zones.info[i].flags & flags) == flags) {
/*
* 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;
}
if (zone_can_alloc(&zones.info[i], order))
return i;
}
spinlock_unlock(&z->lock);
if (++i >= zones.count)
i++;
if (i >= zones.count)
i = 0;
} while (i != hint);
spinlock_unlock(&zones.lock);
return NULL;
return (count_t) -1;
}
 
/**************************/
307,82 → 255,73
* 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;
}
 
/** 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) */
} 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.
*
* @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)
static link_t *zone_buddy_bisect(buddy_system_t *buddy, 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)));
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;
}
389,75 → 328,68
 
/** 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.
*
* @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,
static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
uint8_t order)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
}
 
/** 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)
static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
return list_get_instance(block, frame_t, buddy_link)->buddy_order;
}
 
/** 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)
static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block)
{
frame_t * frame;
 
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 1;
list_get_instance(block, frame_t, buddy_link)->refcount = 1;
}
 
/** 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)
static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 0;
list_get_instance(block, frame_t, buddy_link)->refcount = 0;
}
 
static buddy_system_operations_t zone_buddy_system_operations = {
477,60 → 409,57
 
/** 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.
* @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.
*
* 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);
547,567 → 476,633
/** 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--;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames--;
mutex_unlock(&mem_avail_mtx);
}
 
/** Join two 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.
*
* 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.
*
* 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.
*
* - 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 new frame zone.
*
* @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 flags Zone flags.
* @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 flags Zone flags.
*
* @return Initialized zone.
* @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;
 
/* Mask off flags that are calculated automatically. */
flags &= ~FRAME_LOW_4_GiB;
/* Determine calculated flags. */
if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */
flags |= FRAME_LOW_4_GiB;
 
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.
*
* @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.
*
* @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.
* @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.
*
* @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;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames += count;
mutex_unlock(&mem_avail_mtx);
 
/* 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)
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.
* @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;
unsigned long gen = 0;
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, flags, 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, flags, 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, flags,
pzone);
if (freed > 0)
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
}
}
if (!zone) {
/*
* Sleep until some frames are available again.
*/
if (znum == (count_t) -1) {
if (flags & FRAME_ATOMIC) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return 0;
return NULL;
}
#ifdef CONFIG_DEBUG
unsigned long avail;
 
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " waiting for %u frames, "
"%u available.\n", THREAD->tid, 1ULL << order, avail);
count_t avail = total_frames_free();
#endif
 
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
/*
* Sleep until some frames are available again.
*/
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
"%" PRIc " available.\n", THREAD->tid, size, avail);
#endif
mutex_lock(&mem_avail_mtx);
while ((mem_avail_frames < (1ULL << order)) ||
gen == mem_avail_gen)
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);
gen = mem_avail_gen;
mutex_unlock(&mem_avail_mtx);
 
#ifdef CONFIG_DEBUG
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " woken up, %u frames available.\n",
THREAD->tid, avail);
printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
#endif
 
interrupts_restore(ipl);
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;
mutex_lock(&mem_avail_mtx);
mem_avail_frames -= (1ULL << order);
mutex_unlock(&mem_avail_mtx);
 
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);
mem_avail_frames++;
mem_avail_gen++;
condvar_broadcast(&mem_avail_cv);
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);
 
interrupts_restore(ipl);
}
 
/** Add reference to frame.
1115,26 → 1110,24
* Find respective frame structure for supplied PFN and
* increment frame reference count.
*
* @param pfn Frame number of the frame to be freed.
* @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);
}
 
1141,18 → 1134,21
/** 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. */
1164,6 → 1160,7
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) {
1178,35 → 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();
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);
1217,18 → 1207,14
/** Prints list of zones. */
void zone_print_list(void)
{
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
 
#ifdef __32_BITS__
printf("# base address free frames busy frames\n");
printf("-- ------------ ------------ ------------\n");
#ifdef __32_BITS__
printf("# base address frames flags free frames busy frames\n");
printf("-- ------------ ------------ -------- ------------ ------------\n");
#endif
 
#ifdef __64_BITS__
printf("# base address free frames busy frames\n");
printf("-- -------------------- ------------ ------------\n");
printf("# base address frames flags free frames busy frames\n");
printf("-- -------------------- ------------ -------- ------------ ------------\n");
#endif
/*
1241,13 → 1227,10
* we may end up with inaccurate output (e.g. a zone being skipped from
* the listing).
*/
 
for (i = 0; ; i++) {
uintptr_t base;
count_t free_count;
count_t busy_count;
 
ipl = interrupts_disable();
count_t i;
for (i = 0;; i++) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (i >= zones.count) {
1255,56 → 1238,61
interrupts_restore(ipl);
break;
}
 
zone = zones.info[i];
spinlock_lock(&zone->lock);
 
base = PFN2ADDR(zone->base);
free_count = zone->free_count;
busy_count = zone->busy_count;
 
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("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
printf(" %10p", base);
#endif
 
#ifdef __64_BITS__
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
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");
}
}
 
/** Prints zone details.
*
* @param num Zone base address or zone number.
* @param num Zone base address or zone number.
*
*/
void zone_print_one(unsigned int num)
void zone_print_one(count_t num)
{
zone_t *zone = NULL;
ipl_t ipl;
unsigned int i;
uintptr_t base;
count_t count;
count_t busy_count;
count_t free_count;
 
ipl = interrupts_disable();
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");
1311,24 → 1299,33
return;
}
spinlock_lock(&zone->lock);
base = PFN2ADDR(zone->base);
count = zone->count;
busy_count = zone->busy_count;
free_count = zone->free_count;
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;
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,
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
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)));
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/network/kernel/generic/src/mm/backend_elf.c
129,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;
}
214,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;
}
/branches/network/kernel/generic/src/syscall/syscall.c
32,9 → 32,9
 
/**
* @file
* @brief Syscall table and syscall wrappers.
* @brief Syscall table and syscall wrappers.
*/
 
#include <syscall/syscall.h>
#include <proc/thread.h>
#include <proc/task.h>
42,76 → 42,50
#include <mm/as.h>
#include <print.h>
#include <putchar.h>
#include <errno.h>
#include <arch.h>
#include <debug.h>
#include <ddi/device.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 <udebug/udebug.h>
 
/** Print using kernel facility
*
* Print to kernel log.
*
*/
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;
if (count > 0) {
data = (char *) malloc(count, 0);
if (!data)
return ENOMEM;
rc = copy_from_uspace(data, buf, count);
if (rc) {
free(data);
return rc;
}
for (i = 0; i < count; i++)
putchar(data[i]);
free(data);
} else
klog_update();
return count;
}
 
/** Tell kernel to get keyboard/console access again */
static unative_t sys_debug_enable_console(void)
{
arch_grab_console();
return 0;
}
 
/** 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)
{
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 {
} else {
printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
task_kill(TASK->taskid);
thread_exit();
}
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;
}
 
125,6 → 99,7
(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. */
146,6 → 121,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,
156,6 → 132,7
(syshandler_t) sys_cap_revoke,
/* DDI related syscalls. */
(syshandler_t) sys_device_assign_devno,
(syshandler_t) sys_physmem_map,
(syshandler_t) sys_iospace_enable,
(syshandler_t) sys_preempt_control,
165,7 → 142,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/network/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/network/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>
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;
}
 
441,11 → 454,18
IPC_SET_ARG4(call.data, 0);
IPC_SET_ARG5(call.data, 0);
 
if (!(res = request_preprocess(&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);
}
481,8 → 501,14
 
GET_CHECK_PHONE(phone, phoneid, return ENOENT);
 
if (!(res = request_preprocess(&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);
550,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);
584,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);
592,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.
599,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;
623,7 → 648,7
call = get_call(callid);
if (!call)
return ENOENT;
 
call->flags |= IPC_CALL_FORWARDED;
 
GET_CHECK_PHONE(phone, phoneid, {
640,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))) {
652,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);
}
}
}
 
662,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
785,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;
 
809,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);
828,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;
868,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/network/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>
201,9 → 203,9
call->flags |= IPC_CALL_ANSWERED;
 
if (call->flags & IPC_CALL_FORWARDED) {
if (call->data.caller_phone) {
if (call->caller_phone) {
/* Demasquerade the caller phone. */
call->data.phone = call->data.caller_phone;
call->data.phone = call->caller_phone;
}
}
 
360,8 → 362,8
spinlock_unlock(&oldbox->lock);
 
if (mode & IPC_FF_ROUTE_FROM_ME) {
if (!call->data.caller_phone)
call->data.caller_phone = call->data.phone;
if (!call->caller_phone)
call->caller_phone = call->data.phone;
call->data.phone = newphone;
}
 
427,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;
 
442,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;
}
475,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);
517,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);
}
}
592,8 → 655,9
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid,
" 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),
606,8 → 670,9
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid,
" 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),
615,11 → 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:%" PRIun " A1:%" PRIun " A2:%" PRIun
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
" 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/network/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/network/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/network/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/network/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/network/kernel/Makefile
30,23 → 30,27
## 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) \
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \
-nostdlib -nostdinc
-nostdlib -nostdinc -pipe
 
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \
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,72 → 80,6
#
SYMTAB_SECTION=".section symtab.data, \"a\", $(ATSIGN)progbits;"
 
## Setup kernel configuration
#
ifeq ($(CONFIG_DEBUG),y)
DEFS += -DCONFIG_DEBUG
endif
 
ifeq ($(CONFIG_EDEBUG),y)
DEFS += -DCONFIG_EDEBUG
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)
174,6 → 104,7
OBJDUMP = $(BINUTILS_PREFIX)objdump
LIBDIR = /usr/lib
CFLAGS = $(GCC_CFLAGS)
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),icc_native)
185,6 → 116,7
OBJDUMP = objdump
LIBDIR = /usr/lib
CFLAGS = $(ICC_CFLAGS)
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),suncc_native)
196,6 → 128,8
OBJDUMP = $(BINUTILS_PREFIX)objdump
LIBDIR = /usr/lib
CFLAGS = $(SUNCC_CFLAGS)
DEFS += $(CONFIG_DEFS)
DEPEND_DEFS = $(DEFS)
endif
 
ifeq ($(COMPILER),gcc_cross)
207,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
220,12 → 155,11
generic/src/adt/list.c \
generic/src/console/chardev.c \
generic/src/console/console.c \
generic/src/console/kconsole.c \
generic/src/console/cmd.c \
generic/src/cpu/cpu.c \
generic/src/ddi/ddi.c \
generic/src/ddi/irq.c \
generic/src/ddi/device.c \
generic/src/debug/symtab.c \
generic/src/interrupt/interrupt.c \
generic/src/main/main.c \
generic/src/main/kinit.c \
252,6 → 186,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 \
261,7 → 196,6
generic/src/printf/vprintf.c \
generic/src/printf/vsprintf.c \
generic/src/printf/vsnprintf.c \
generic/src/debug/symtab.c \
generic/src/time/clock.c \
generic/src/time/timeout.c \
generic/src/time/delay.c \
283,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 \
294,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 \
315,6 → 263,58
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
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
321,25 → 321,24
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES)))
 
.PHONY: all build config distclean clean archlinks depend disasm
ifeq ($(CONFIG_SYMTAB),y)
SYMTAB_OBJECTS := generic/src/debug/real_map.o
else
SYMTAB_OBJECTS :=
endif
 
all:
../tools/config.py kernel.config default $(ARCH) $(COMPILER) $(CONFIG_DEBUG) $(MACHINE)
.PHONY: all build clean archlinks depend disasm
 
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 ; \
346,24 → 345,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
 
370,8 → 369,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) $(SYMTAB_OBJECTS)
$(LD) -T arch/$(KARCH)/_link.ld $(LFLAGS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) $(SYMTAB_OBJECTS) -o $@ -Map kernel.map
 
kernel.bin: kernel.raw
$(OBJCOPY) -O $(BFD) kernel.raw kernel.bin
/branches/network/kernel/arch/ppc64/_link.ld.in
File deleted
/branches/network/kernel/arch/ppc64/include/arg.h
File deleted
/branches/network/kernel/arch/ppc64/include/atomic.h
File deleted
/branches/network/kernel/arch/ppc64/include/arch.h
File deleted
/branches/network/kernel/arch/ppc64/include/proc/thread.h
File deleted
/branches/network/kernel/arch/ppc64/include/proc/task.h
File deleted
/branches/network/kernel/arch/ppc64/include/boot/boot.h
File deleted
/branches/network/kernel/arch/ppc64/include/faddr.h
File deleted
/branches/network/kernel/arch/ppc64/include/asm.h
File deleted
/branches/network/kernel/arch/ppc64/include/mm/frame.h
File deleted
/branches/network/kernel/arch/ppc64/include/mm/page.h
File deleted
/branches/network/kernel/arch/ppc64/include/mm/asid.h
File deleted
/branches/network/kernel/arch/ppc64/include/mm/tlb.h
File deleted
/branches/network/kernel/arch/ppc64/include/mm/as.h
File deleted
/branches/network/kernel/arch/ppc64/include/context.h
File deleted
/branches/network/kernel/arch/ppc64/include/debug.h
File deleted
/branches/network/kernel/arch/ppc64/include/barrier.h
File deleted
/branches/network/kernel/arch/ppc64/include/cpu.h
File deleted
/branches/network/kernel/arch/ppc64/include/drivers/pic.h
File deleted
/branches/network/kernel/arch/ppc64/include/asm/regname.h
File deleted
/branches/network/kernel/arch/ppc64/include/context_offset.h
File deleted
/branches/network/kernel/arch/ppc64/include/interrupt.h
File deleted
/branches/network/kernel/arch/ppc64/include/fpu_context.h
File deleted
/branches/network/kernel/arch/ppc64/include/exception.h
File deleted
/branches/network/kernel/arch/ppc64/include/cycle.h
File deleted
/branches/network/kernel/arch/ppc64/include/byteorder.h
File deleted
/branches/network/kernel/arch/ppc64/include/cpuid.h
File deleted
/branches/network/kernel/arch/ppc64/include/types.h
File deleted
/branches/network/kernel/arch/ppc64/include/elf.h
File deleted
/branches/network/kernel/arch/ppc64/include/memstr.h
File deleted
/branches/network/kernel/arch/ppc64/Makefile.inc
File deleted
/branches/network/kernel/arch/ppc64/src/mm/frame.c
File deleted
/branches/network/kernel/arch/ppc64/src/mm/page.c
File deleted
/branches/network/kernel/arch/ppc64/src/mm/tlb.c
File deleted
/branches/network/kernel/arch/ppc64/src/mm/as.c
File deleted
/branches/network/kernel/arch/ppc64/src/dummy.s
File deleted
/branches/network/kernel/arch/ppc64/src/interrupt.c
File deleted
/branches/network/kernel/arch/ppc64/src/ppc64.c
File deleted
/branches/network/kernel/arch/ppc64/src/drivers/pic.c
File deleted
/branches/network/kernel/arch/ppc64/src/exception.S
File deleted
/branches/network/kernel/arch/ppc64/src/fpu_context.S
File deleted
/branches/network/kernel/arch/ppc64/src/ddi/ddi.c
File deleted
/branches/network/kernel/arch/ppc64/src/asm.S
File deleted
/branches/network/kernel/arch/ppc64/src/proc/scheduler.c
File deleted
/branches/network/kernel/arch/ppc64/src/boot/boot.S
File deleted
/branches/network/kernel/arch/ppc64/src/context.S
File deleted
/branches/network/kernel/arch/ppc64/src/debug/panic.s
File deleted
/branches/network/kernel/arch/ppc64/src/cpu/cpu.c
File deleted
/branches/network/kernel/arch/ia32xen/_link.ld.in
File deleted
/branches/network/kernel/arch/ia32xen/include/hypercall.h
File deleted
/branches/network/kernel/arch/ia32xen/include/mm/frame.h
File deleted
/branches/network/kernel/arch/ia32xen/include/mm/page.h
File deleted
/branches/network/kernel/arch/ia32xen/include/mm/asid.h
File deleted
/branches/network/kernel/arch/ia32xen/include/mm/tlb.h
File deleted
/branches/network/kernel/arch/ia32xen/include/mm/as.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/ia32xen/include/drivers/xconsole.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/ia32xen/include/types.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/ia32xen/include/pm.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/kernel/arch/ia32xen/include/asm.h
File deleted
/branches/network/kernel/arch/ia32xen/Makefile.inc
File deleted
/branches/network/kernel/arch/ia32xen/src/ia32xen.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/pm.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/smp/apic.c
File deleted
/branches/network/kernel/arch/ia32xen/src/smp/mps.c
File deleted
/branches/network/kernel/arch/ia32xen/src/smp/smp.c
File deleted
/branches/network/kernel/arch/ia32xen/src/smp/ipi.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/boot/boot.S
File deleted
/branches/network/kernel/arch/ia32xen/src/proc/scheduler.c
File deleted
/branches/network/kernel/arch/ia32xen/src/proc/task.c
File deleted
/branches/network/kernel/arch/ia32xen/src/proc/thread.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/mm/page.c
File deleted
/branches/network/kernel/arch/ia32xen/src/mm/tlb.c
File deleted
/branches/network/kernel/arch/ia32xen/src/mm/as.c
File deleted
/branches/network/kernel/arch/ia32xen/src/mm/frame.c
File deleted
/branches/network/kernel/arch/ia32xen/src/userspace.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/interrupt.c
File deleted
/branches/network/kernel/arch/ia32xen/src/drivers/xconsole.c
File deleted
/branches/network/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/network/kernel/arch/ia32xen/src/asm.S
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/sparc64/include/types.h
57,6 → 57,9
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
/branches/network/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/network/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/network/kernel/arch/sparc64/include/asm.h
42,7 → 42,56
#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.
87,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.
358,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/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/sparc64/include/mm/cache_spec.h
38,19 → 38,20
/*
* The following macros are valid for the following processors:
*
* UltraSPARC, UltraSPARC II, UltraSPARC IIi
* 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
 
#define ICACHE_SIZE (16 * 1024)
#define ICACHE_WAYS 2
#define ICACHE_LINE_SIZE 32
 
#endif
 
/** @}
/branches/network/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/network/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,7 → 286,7
 
/** 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)
{
165,7 → 296,7
 
/** 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,7 → 305,7
 
/** 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)
{
182,15 → 313,18
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,12 → 333,12
 
/** 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;
214,13 → 348,14
 
/** 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,9 → 407,120
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)
{
284,7 → 530,7
 
/** 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,7 → 559,7
 
/** 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)
{
323,7 → 569,7
 
/** 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,7 → 588,7
 
/** 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)
{
352,7 → 598,7
 
/** 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 */
/* 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/network/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/network/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/network/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/network/kernel/arch/sparc64/include/barrier.h
82,6 → 82,8
asm volatile ("membar #Sync\n");
}
 
#if defined (US)
 
#define smc_coherence(a) \
{ \
write_barrier(); \
97,6 → 99,22
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/network/kernel/arch/sparc64/include/cpu.h
35,15 → 35,6
#ifndef KERN_sparc64_CPU_H_
#define KERN_sparc64_CPU_H_
 
#include <arch/types.h>
#include <typedefs.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
52,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
66,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/network/kernel/arch/sparc64/include/drivers/z8530.h
File deleted
/branches/network/kernel/arch/sparc64/include/drivers/ns16550.h
File deleted
/branches/network/kernel/arch/sparc64/include/drivers/sgcn.h
0,0 → 1,127
/*
* 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>
#include <console/chardev.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);
indev_t *sgcnin_init(void);
void sgcnout_init(void);
 
#endif
 
/** @}
*/
/branches/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/sparc64/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-sparc
BFD_ARCH = sparc
BFD = binary
46,80 → 42,55
 
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 \
arch/$(KARCH)/src/drivers/fhc.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
endif
/branches/network/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 = %" PRIu32 ") timed out\n",
__func__, mid);
}
}
 
/branches/network/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/network/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/network/kernel/arch/sparc64/src/console.c
37,14 → 37,8
 
#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 <genarch/srln/srln.h>
#include <console/chardev.h>
#include <console/console.h>
#include <arch/asm.h>
54,89 → 48,98
#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;
ofw_tree_property_t *prop;
ofw_tree_node_t *screen;
ofw_tree_node_t *keyboard;
#ifdef CONFIG_FB
ofw_tree_property_t *prop_scr = ofw_tree_getprop(aliases, "screen");
if (!prop_scr)
panic("Cannot find property 'screen'.");
if (!prop_scr->value)
panic("Cannot find screen alias.");
ofw_tree_node_t *screen = ofw_tree_lookup(prop_scr->value);
if (!screen)
panic("Cannot find %s.", prop_scr->value);
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");
if (!prop->value)
panic("Can't find screen alias.\n");
screen = ofw_tree_lookup(prop->value);
if (!screen)
panic("Can't find %s\n", prop->value);
 
scr_init(screen);
#endif
 
prop = ofw_tree_getprop(aliases, "keyboard");
if (!prop)
panic("Can't find property \"keyboard\".\n");
if (!prop->value)
panic("Can't find keyboard alias.\n");
keyboard = ofw_tree_lookup(prop->value);
#ifdef CONFIG_SUN_KBD
ofw_tree_property_t *prop_kbd = ofw_tree_getprop(aliases, "keyboard");
if (!prop_kbd)
panic("Cannot find property 'keyboard'.");
if (!prop_kbd->value)
panic("Cannot find keyboard alias.");
ofw_tree_node_t *keyboard = ofw_tree_lookup(prop_kbd->value);
if (!keyboard)
panic("Can't find %s\n", prop->value);
 
panic("Cannot find %s.", prop_kbd->value);
kbd_init(keyboard);
#endif
}
 
/** Kernel thread for polling keyboard.
*
* @param arg Ignored.
*/
void kkbdpoll(void *arg)
/** Initilize I/O on the Serengeti machine. */
static void serengeti_init(void)
{
thread_detach(THREAD);
 
#ifdef CONFIG_Z8530
if (kbd_type == KBD_Z8530) {
/*
* The z8530 driver is interrupt-driven.
*/
return;
}
#ifdef CONFIG_SGCN_KBD
indev_t *kbrdin;
kbrdin = sgcnin_init();
if (kbrdin)
srlnin_init(kbrdin);
#endif
#ifdef CONFIG_SGCN_PRN
sgcnout_init();
#endif
}
 
while (1) {
#ifdef CONFIG_NS16550
if (kbd_type == KBD_NS16550)
ns16550_poll();
#endif
thread_usleep(KEYBOARD_POLL_PAUSE);
/**
* 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();
}
}
 
 
/** Acquire console back for kernel
*
*/
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 → 151,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/network/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/network/kernel/arch/sparc64/src/sparc64.c
37,7 → 37,6
#include <config.h>
#include <arch/trap/trap.h>
#include <arch/console.h>
#include <proc/thread.h>
#include <console/console.h>
#include <arch/boot/boot.h>
#include <arch/arch.h>
47,10 → 46,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 → 61,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 → 88,6
* But we only create 128 buckets.
*/
irq_init(1 << 11, 128);
standalone_sparc64_console_init();
}
}
 
101,18 → 101,7
 
void arch_post_smp_init(void)
{
static thread_t *t = NULL;
 
 
if (!t) {
/*
* Create thread that polls keyboard.
*/
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
}
standalone_sparc64_console_init();
}
 
/** Calibrate delay loop.
161,5 → 150,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/network/kernel/arch/sparc64/src/trap/exception.c
40,62 → 40,67
#include <arch/asm.h>
#include <arch/register.h>
#include <debug.h>
#include <print.h>
#include <symtab.h>
#include <print.h>
 
void dump_istate(istate_t *istate)
{
char *tpcs, *tnpcs;
 
tpcs = symtab_fmt_name_lookup(istate->tpc);
tnpcs = symtab_fmt_name_lookup(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));
printf("TPC=%#" PRIx64 " (%s)\n", istate->tpc, tpcs);
printf("TNPC=%#" PRIx64 " (%s)\n", istate->tnpc, tnpcs);
}
 
/** 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 → 118,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 → 127,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/network/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) {
/*
98,7 → 112,7
*/
#ifdef CONFIG_DEBUG
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
#endif
}
 
/branches/network/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/network/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;
/branches/network/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/network/kernel/arch/sparc64/src/mm/as.c
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/network/kernel/arch/sparc64/src/mm/cache.S
47,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/network/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/network/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/network/kernel/arch/sparc64/src/mm/page.c
1,5 → 1,5
/*
* Copyright (c) 2005 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* 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 sparc64mm
/** @addtogroup sparc64mm
* @{
*/
/** @file
42,126 → 42,27
#include <align.h>
#include <config.h>
 
#ifdef CONFIG_SMP
/** Entries locked in DTLB of BSP.
*
* Application processors need to have the same locked entries in their DTLBs as
* the bootstrap processor.
*/
static struct {
uintptr_t virt_page;
uintptr_t phys_page;
int pagesize_code;
} bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT];
 
/** Number of entries in bsp_locked_dtlb_entry array. */
static count_t bsp_locked_dtlb_entries = 0;
#endif /* CONFIG_SMP */
 
/** Perform sparc64 specific initialization of paging. */
void page_arch_init(void)
{
if (config.cpu_active == 1) {
if (config.cpu_active == 1)
page_mapping_operations = &ht_mapping_operations;
} else {
 
#ifdef CONFIG_SMP
unsigned int i;
 
/*
* Copy locked DTLB entries from the BSP.
*/
for (i = 0; i < bsp_locked_dtlb_entries; i++) {
dtlb_insert_mapping(bsp_locked_dtlb_entry[i].virt_page,
bsp_locked_dtlb_entry[i].phys_page,
bsp_locked_dtlb_entry[i].pagesize_code, true,
false);
}
#endif
 
}
}
 
/** Map memory-mapped device into virtual memory.
*
* So far, only DTLB is used to map devices into memory. Chances are that there
* will be only a limited amount of devices that the kernel itself needs to
* lock in DTLB.
* We are currently using identity mapping for mapping device registers.
*
* @param physaddr Physical address of the page where the device is located.
* Must be at least page-aligned.
* @param size Size of the device's registers. Must not exceed 4M and must
* include extra space caused by the alignment.
* @param physaddr Physical address of the page where the device is
* located.
* @param size Size of the device's registers. This argument is
* ignored.
*
* @return Virtual address of the page where the device is mapped.
* @return Virtual address of the page where the device is mapped.
*/
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
unsigned int order;
unsigned int i;
 
ASSERT(config.cpu_active == 1);
 
struct {
int pagesize_code;
size_t increment;
count_t count;
} sizemap[] = {
{ PAGESIZE_8K, 0, 1 }, /* 8K */
{ PAGESIZE_8K, MMU_PAGE_SIZE, 2 }, /* 16K */
{ PAGESIZE_8K, MMU_PAGE_SIZE, 4 }, /* 32K */
{ PAGESIZE_64K, 0, 1}, /* 64K */
{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 2 }, /* 128K */
{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 4 }, /* 256K */
{ PAGESIZE_512K, 0, 1 }, /* 512K */
{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 2 }, /* 1M */
{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 4 }, /* 2M */
{ PAGESIZE_4M, 0, 1 }, /* 4M */
{ PAGESIZE_4M, 512 * MMU_PAGE_SIZE, 2 } /* 8M */
};
ASSERT(ALIGN_UP(physaddr, MMU_PAGE_SIZE) == physaddr);
ASSERT(size <= 8 * 1024 * 1024);
if (size <= MMU_FRAME_SIZE)
order = 0;
else
order = (fnzb64(size - 1) + 1) - MMU_FRAME_WIDTH;
 
/*
* Use virtual addresses that are beyond the limit of physical memory.
* Thus, the physical address space will not be wasted by holes created
* by frame_alloc().
*/
ASSERT(PA2KA(last_frame));
uintptr_t virtaddr = ALIGN_UP(PA2KA(last_frame),
1 << (order + FRAME_WIDTH));
last_frame = ALIGN_UP(KA2PA(virtaddr) + size,
1 << (order + FRAME_WIDTH));
for (i = 0; i < sizemap[order].count; i++) {
/*
* First, insert the mapping into DTLB.
*/
dtlb_insert_mapping(virtaddr + i * sizemap[order].increment,
physaddr + i * sizemap[order].increment,
sizemap[order].pagesize_code, true, false);
#ifdef CONFIG_SMP
/*
* Second, save the information about the mapping for APs.
*/
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].virt_page =
virtaddr + i * sizemap[order].increment;
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].phys_page =
physaddr + i * sizemap[order].increment;
bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].pagesize_code =
sizemap[order].pagesize_code;
bsp_locked_dtlb_entries++;
#endif
}
return virtaddr;
return PA2KA(physaddr);
}
 
/** @}
/branches/network/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/network/kernel/arch/sparc64/src/drivers/kbd.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
/** @addtogroup sparc64
* @{
*/
/** @file
34,22 → 34,30
 
#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 <ddi/device.h>
 
#include <console/console.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;
 
#ifdef CONFIG_SUN_KBD
 
/** Initialize keyboard.
*
* Traverse OpenFirmware device tree in order to find necessary
63,7 → 71,16
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 → 101,32
*/
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;
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,23 → 158,57
*/
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);
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) +
offset;
indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg);
if (kbrdin_z8530)
kbrd_init(kbrdin_z8530);
/*
* 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.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);
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) +
offset;
indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg);
if (kbrdin_ns16550)
kbrd_init(kbrdin_ns16550);
/*
* 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.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");
}
}
 
#endif
 
/** @}
*/
/branches/network/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/network/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/network/kernel/arch/sparc64/src/drivers/sgcn.c
0,0 → 1,383
/*
* 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.h>
#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 <proc/thread.h>
#include <console/chardev.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <synch/spinlock.h>
 
#define POLL_INTERVAL 10000
 
/*
* 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 necessary arrangements 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"
 
/*
* 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;
 
/* true iff the kernel driver should ignore pressed keys */
static bool kbd_disabled;
 
/*
* 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_putchar(outdev_t *, const char, bool);
 
/** SGCN output device operations */
static outdev_operations_t sgcnout_ops = {
.write = sgcn_putchar
};
 
/** SGCN input device operations */
static indev_operations_t sgcnin_ops = {
.poll = NULL
};
 
static indev_t sgcnin; /**< SGCN input device. */
static outdev_t sgcnout; /**< SGCN output device. */
 
/**
* 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.
*/
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)
{
static bool initialized;
if (initialized)
return;
 
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);
initialized = true;
}
 
/**
* 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(outdev_t *od, 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);
}
}
 
/**
* Grabs the input for kernel.
*/
void sgcn_grab(void)
{
kbd_disabled = true;
}
 
/**
* Releases the input so that userspace can use it.
*/
void sgcn_release(void)
{
kbd_disabled = true;
}
 
/**
* 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.
*/
static void sgcn_poll()
{
uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
uint32_t end = SGCN_BUFFER_HEADER->in_end;
uint32_t size = end - begin;
 
if (kbd_disabled)
return;
 
spinlock_lock(&sgcn_input_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);
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;
indev_push_character(&sgcnin, c);
}
 
spinlock_unlock(&sgcn_input_lock);
}
 
/**
* Polling thread function.
*/
static void kkbdpoll(void *arg) {
while (1) {
if (!silent) {
sgcn_poll();
}
thread_usleep(POLL_INTERVAL);
}
}
 
/**
* A public function which initializes input from the Serengeti console.
*/
indev_t *sgcnin_init(void)
{
sgcn_buffer_begin_init();
 
kbd_type = KBD_SGCN;
 
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
 
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("Cannot create kkbdpoll.");
thread_ready(t);
indev_initialize("sgcnin", &sgcnin, &sgcnin_ops);
 
return &sgcnin;
}
 
/**
* A public function which initializes output to the Serengeti console.
*/
void sgcnout_init(void)
{
sgcn_buffer_begin_init();
 
sysinfo_set_item_val("fb.kind", NULL, 4);
 
outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);
stdout = &sgcnout;
}
 
/** @}
*/
/branches/network/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, &reg[PCI_SABRE_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[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, &reg[PCI_PSYCHO_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[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/network/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/network/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/network/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/network/kernel/arch/ia64/include/ski/ski.h
35,22 → 35,17
#ifndef KERN_ia64_SKI_H_
#define KERN_ia64_SKI_H_
 
#include <arch/types.h>
#include <console/console.h>
#include <console/chardev.h>
 
#define SKI_INIT_CONSOLE 20
#define SKI_GETCHAR 21
#define SKI_PUTCHAR 31
 
extern chardev_t ski_uconsole;
 
extern void ski_init_console(void);
 
extern indev_t *skiin_init(void);
extern void skiout_init(void);
extern void ski_kbd_grab(void);
extern void ski_kbd_release(void);
 
extern void kkbdpoll(void *arg);
 
#endif
 
/** @}
/branches/network/kernel/arch/ia64/include/types.h
65,6 → 65,11
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef struct {
unative_t fnc;
unative_t gp;
} fncptr_t;
 
#define PRIp "lx" /**< Format for uintptr_t. */
#define PRIs "lu" /**< Format for size_t. */
#define PRIc "lu" /**< Format for count_t. */
/branches/network/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/network/kernel/arch/ia64/include/arch.h
39,6 → 39,8
 
#include <arch/ski/ski.h>
 
extern void arch_pre_main(void);
 
#endif
 
/** @}
/branches/network/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/network/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/network/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/network/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/network/kernel/arch/ia64/include/mm/page.h
46,8 → 46,25
/** 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
62,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/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/ia64/include/drivers/i8042.h
File deleted
/branches/network/kernel/arch/ia64/include/drivers/ega.h
File deleted
/branches/network/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/network/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/network/kernel/arch/ia64/Makefile.inc
29,18 → 29,11
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-little
BFD_ARCH = ia64-elf64
TARGET = ia64-pc-linux-gnu
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)
48,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/network/kernel/arch/ia64/src/putchar.c
File deleted
/branches/network/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/network/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/network/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/network/kernel/arch/ia64/src/asm.S
51,7 → 51,7
 
adds r14 = 7, in1
mov r2 = ar.lc
mov r8 = in0
mov r8 = in0 ;;
and r14 = -8, r14 ;;
cmp.ne p6, p7 = r14, in1
(p7) br.cond.dpnt 3f ;;
128,6 → 128,10
memsetb:
br _memsetb
 
.global memsetw
memsetw:
br _memsetw
 
.global cpu_halt
cpu_halt:
br cpu_halt
/branches/network/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/network/kernel/arch/ia64/src/ia64.c
50,64 → 50,91
#include <proc/uarg.h>
#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);
#ifdef SKI
ski_init_console();
#else
ega_init();
#endif
if (config.cpu_active == 1) {
iosapic_init();
irq_init(INR_COUNT, INR_COUNT);
}
it_init();
}
 
119,51 → 146,55
{
}
 
 
#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.
*/
#ifdef SKI
thread_t *t;
t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("cannot create kkbdpoll\n");
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);
 
thread_t *t;
t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("cannot create kkbdpoll\n");
thread_ready(t);
 
indev_t *in;
in = skiin_init();
if (in)
srln_init(in);
skiout_init();
#endif
 
}
#ifdef CONFIG_EGA
ega_init(EGA_BASE, EGA_VIDEORAM);
#endif
#ifdef CONFIG_NS16550
indev_t *kbrdin_ns16550
= ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL);
if (kbrdin_ns16550)
srln_init(kbrdin_ns16550);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ);
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);
#endif
#ifdef CONFIG_I8042
indev_t *kbrdin_i8042 = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
if (kbrdin_i8042)
kbrd_init(kbrdin_i8042);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
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("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 → 203,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 → 240,9
{
#ifdef SKI
ski_kbd_grab();
#endif
#endif
}
 
/** Return console to userspace
*
*/
224,9 → 255,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/network/kernel/arch/ia64/src/ski/ski.c
35,29 → 35,19
#include <arch/ski/ski.h>
#include <console/console.h>
#include <console/chardev.h>
#include <arch/interrupt.h>
#include <sysinfo/sysinfo.h>
#include <arch/types.h>
#include <ddi/device.h>
#include <ddi/irq.h>
#include <ipc/irq.h>
#include <proc/thread.h>
#include <synch/spinlock.h>
#include <arch/asm.h>
#include <arch/drivers/kbd.h>
#include <arch.h>
 
#define SKI_KBD_INR 0
static indev_t skiin; /**< Ski input device. */
static outdev_t skiout; /**< Ski output device. */
 
static irq_t ski_kbd_irq;
static devno_t ski_kbd_devno;
 
chardev_t ski_console;
chardev_t ski_uconsole;
 
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,21 → 56,31
* @param d Character device.
* @param ch Character to be printed.
*/
void ski_putchar(chardev_t *d, const char ch)
static void ski_putchar(outdev_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);
}
}
 
static indev_operations_t skiin_ops = {
.poll = NULL
};
 
static outdev_operations_t skiout_ops = {
.write = ski_putchar
};
 
/** Ask debug console if a key was pressed.
*
* Use SSC (Simulator System Call) to
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;
107,102 → 107,47
return (int32_t) ch;
}
 
/**
* This is a blocking wrapper for ski_getchar().
* To be used when the kernel crashes.
*/
static char ski_getchar_blocking(chardev_t *d)
{
int ch;
 
while(!(ch = ski_getchar()))
;
if(ch == '\r')
ch = '\n';
return (char) ch;
}
 
/** Ask keyboard if a key was pressed. */
static void poll_keyboard(void)
{
char ch;
static char last;
ipl_t ipl;
 
ipl = interrupts_disable();
 
if (kbd_disabled) {
interrupts_restore(ipl);
if (kbd_disabled)
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) {
chardev_push_character(&ski_uconsole, ch);
ipc_irq_send_notif(&ski_kbd_irq);
} else {
chardev_push_character(&ski_console, ch);
}
last = ch;
spinlock_unlock(&ski_kbd_irq.lock);
interrupts_restore(ipl);
indev_push_character(&skiin, ch);
return;
}
 
if (last) {
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);
}
last = 0;
}
 
spinlock_unlock(&ski_kbd_irq.lock);
interrupts_restore(ipl);
}
 
/* Called from getc(). */
static void ski_kbd_enable(chardev_t *d)
{
kbd_disabled = false;
}
#define POLL_INTERVAL 10000 /* 10 ms */
 
/* Called from getc(). */
static void ski_kbd_disable(chardev_t *d)
/** Kernel thread for polling keyboard. */
static void kkbdpoll(void *arg)
{
kbd_disabled = true;
while (1) {
if (!silent) {
poll_keyboard();
}
thread_usleep(POLL_INTERVAL);
}
}
 
/** Decline to service hardware IRQ.
*
* This is only a virtual IRQ, so always decline.
*
* @return Always IRQ_DECLINE.
*/
static irq_ownership_t ski_kbd_claim(void)
{
return IRQ_DECLINE;
}
 
static chardev_operations_t ski_ops = {
.resume = ski_kbd_enable,
.suspend = ski_kbd_disable,
.write = ski_putchar,
.read = ski_getchar_blocking
};
 
/** Initialize debug console
*
* Issue SSC (Simulator System Call) to
* to open debug console.
*/
void ski_init_console(void)
static void ski_init(void)
{
static bool initialized;
 
if (initialized)
return;
asm volatile (
"mov r15 = %0\n"
"break 0x80000\n"
210,54 → 155,46
: "i" (SKI_INIT_CONSOLE)
: "r15", "r8"
);
initialized = true;
}
 
chardev_initialize("ski_console", &ski_console, &ski_ops);
chardev_initialize("ski_uconsole", &ski_uconsole, &ski_ops);
stdin = &ski_console;
stdout = &ski_console;
indev_t *skiin_init(void)
{
ski_init();
 
ski_kbd_devno = device_assign_devno();
irq_initialize(&ski_kbd_irq);
ski_kbd_irq.inr = SKI_KBD_INR;
ski_kbd_irq.devno = ski_kbd_devno;
ski_kbd_irq.claim = ski_kbd_claim;
irq_register(&ski_kbd_irq);
indev_initialize("skiin", &skiin, &skiin_ops);
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (t)
thread_ready(t);
else
return NULL;
 
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);
 
return &skiin;
}
 
void ski_kbd_grab(void)
 
void skiout_init(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&ski_kbd_irq.lock);
ski_kbd_irq.notif_cfg.notify = false;
spinlock_unlock(&ski_kbd_irq.lock);
interrupts_restore(ipl);
ski_init();
 
outdev_initialize("skiout", &skiout, &skiout_ops);
stdout = &skiout;
 
sysinfo_set_item_val("fb", NULL, false);
}
 
void ski_kbd_release(void)
void ski_kbd_grab(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&ski_kbd_irq.lock);
if (ski_kbd_irq.notif_cfg.answerbox)
ski_kbd_irq.notif_cfg.notify = true;
spinlock_unlock(&ski_kbd_irq.lock);
interrupts_restore(ipl);
kbd_disabled = true;
}
 
 
#define POLL_INTERVAL 50000 /* 50 ms */
 
/** Kernel thread for polling keyboard. */
void kkbdpoll(void *arg)
void ski_kbd_release(void)
{
while (1) {
poll_keyboard();
thread_usleep(POLL_INTERVAL);
}
kbd_disabled = false;
}
 
/** @}
/branches/network/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/network/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/network/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();
/branches/network/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/network/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/network/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/network/kernel/arch/ia64/src/interrupt.c
38,7 → 38,6
#include <ddi/irq.h>
#include <panic.h>
#include <print.h>
#include <symtab.h>
#include <debug.h>
#include <console/console.h>
#include <arch/types.h>
53,6 → 52,8
#include <ipc/irq.h>
#include <ipc/ipc.h>
#include <synch/spinlock.h>
#include <mm/tlb.h>
#include <symtab.h>
 
#define VECTORS_64_BUNDLE 20
#define VECTORS_16_BUNDLE 48
136,9 → 137,9
{
char *ifa, *iipa, *iip;
 
ifa = get_symtab_entry(istate->cr_ifa);
iipa = get_symtab_entry(istate->cr_iipa);
iip = get_symtab_entry(istate->cr_iip);
ifa = symtab_fmt_name_lookup(istate->cr_ifa);
iipa = symtab_fmt_name_lookup(istate->cr_iipa);
iip = symtab_fmt_name_lookup(istate->cr_iip);
 
putchar('\n');
printf("Interrupted context dump:\n");
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/network/kernel/arch/ia64/src/drivers/ega.c
File deleted
/branches/network/kernel/arch/ia64/src/drivers/it.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64
/** @addtogroup ia64
* @{
*/
/** @file
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/network/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/network/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/network/kernel/arch/arm32/include/machine.h
File deleted
/branches/network/kernel/arch/arm32/include/boot.h
File deleted
/branches/network/kernel/arch/arm32/include/debug/print.h
File deleted
/branches/network/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
37,26 → 37,9
#define KERN_arm32_ASM_BOOT_H_
 
/** Size of a temporary stack used for initial kernel start. */
#define TEMP_STACK_SIZE 0x100
#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/network/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/network/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/network/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/network/kernel/arch/arm32/include/types.h
64,6 → 64,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef struct {
} fncptr_t;
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
/branches/network/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/network/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/network/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/network/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/network/kernel/arch/arm32/include/mm/page.h
193,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/network/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/network/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,12 → 39,12
/*
* 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)
/branches/network/kernel/arch/arm32/include/drivers/gxemul.h
38,41 → 38,33
#ifndef KERN_arm32_GXEMUL_H_
#define KERN_arm32_GXEMUL_H_
 
#include <console/chardev.h>
 
/** Last interrupt number (beginning from 0) whose status is probed
/** Last interrupt number (beginning from 0) whose status is probed
* from interrupt controller
*/
#define GXEMUL_IRQC_MAX_IRQ 8
#define GXEMUL_IRQC_MAX_IRQ 8
#define GXEMUL_KBD_IRQ 2
#define GXEMUL_TIMER_IRQ 4
 
/** Timer frequency */
#define GXEMUL_TIMER_FREQ 100
#define GXEMUL_TIMER_FREQ 100
 
/** Struct containing mappings of gxemul HW devices into kernel part
* of virtual address space.
*/
typedef struct {
uintptr_t videoram;
uintptr_t kbd;
uintptr_t rtc;
uintptr_t rtc_freq;
uintptr_t rtc_ack;
uintptr_t irqc;
uintptr_t irqc_mask;
uintptr_t irqc_unmask;
} gxemul_hw_map_t;
#define GXEMUL_KBD_ADDRESS 0x10000000
#define GXEMUL_MP_ADDRESS 0x11000000
#define GXEMUL_FB_ADDRESS 0x12000000
#define GXEMUL_RTC_ADDRESS 0x15000000
#define GXEMUL_IRQC_ADDRESS 0x16000000
 
extern void gxemul_hw_map_init(void);
extern void gxemul_console_init(devno_t devno);
extern void gxemul_release_console(void);
extern void gxemul_grab_console(void);
extern void gxemul_timer_irq_start(void);
extern void gxemul_debug_putc(char ch);
extern void gxemul_cpu_halt(void);
extern void gxemul_irq_exception(int exc_no, istate_t *istate);
extern size_t gxemul_get_memory_size(void);
extern uintptr_t gxemul_get_fb_address(void);
extern void *gxemul_kbd;
extern void *gxemul_rtc;
extern void *gxemul_irqc;
 
#define GXEMUL_HALT_OFFSET 0x010
#define GXEMUL_RTC_FREQ_OFFSET 0x100
#define GXEMUL_MP_MEMSIZE_OFFSET 0x090
#define GXEMUL_RTC_ACK_OFFSET 0x110
 
extern void gxemul_init(void);
 
#endif
 
/** @}
/branches/network/kernel/arch/arm32/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
BFD = binary
39,62 → 35,28
TARGET = arm-linux-gnu
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/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/network/kernel/arch/arm32/src/debug/print.c
File deleted
/branches/network/kernel/arch/arm32/src/exception.c
34,13 → 34,12
*/
 
#include <arch/exception.h>
#include <arch/debug/print.h>
#include <arch/memstr.h>
#include <arch/regutils.h>
#include <interrupt.h>
#include <arch/machine.h>
#include <arch/mm/page_fault.h>
#include <arch/barrier.h>
#include <arch/drivers/gxemul.h>
#include <print.h>
#include <syscall/syscall.h>
 
63,57 → 62,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"
);
}
 
189,10 → 191,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.
*
201,9 → 206,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.
254,7 → 259,10
/** Low-level Prefetch Abort Exception handler. */
static void prefetch_abort_exception_entry(void)
{
asm("sub lr, lr, #4");
asm volatile (
"sub lr, lr, #4"
);
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);
}
 
261,7 → 269,10
/** Low-level Data Abort Exception handler. */
static void data_abort_exception_entry(void)
{
asm("sub lr, lr, #8");
asm volatile (
"sub lr, lr, #8"
);
PROCESS_EXCEPTION(EXC_DATA_ABORT);
}
 
273,7 → 284,10
*/
static void irq_exception_entry(void)
{
asm("sub lr, lr, #4");
asm volatile (
"sub lr, lr, #4"
);
setup_stack_and_save_regs();
switch_to_irq_servicing_mode();
293,6 → 307,12
istate->r3, istate->r4, istate->r5, istate->r6);
}
 
/** Returns the mask of active interrupts. */
static inline uint32_t gxemul_irqc_get_sources(void)
{
return *((uint32_t *) gxemul_irqc);
}
 
/** Interrupt Exception handler.
*
* Determines the sources of interrupt and calls their handlers.
299,7 → 319,23
*/
static void irq_exception(int exc_no, istate_t *istate)
{
machine_irq_exception(exc_no, istate);
uint32_t sources = gxemul_irqc_get_sources();
unsigned int i;
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
if (sources & (1 << i)) {
irq_t *irq = irq_dispatch_and_lock(i);
if (irq) {
/* The IRQ handler was found. */
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/* Spurious interrupt.*/
printf("cpu%d: spurious interrupt (inum=%d)\n",
CPU->id, i);
}
}
}
}
 
/** Fills exception vectors with appropriate exception handlers. */
323,7 → 359,7
install_handler((unsigned) irq_exception_entry,
(unsigned *) EXC_IRQ_VEC);
install_handler((unsigned)fiq_exception_entry,
install_handler((unsigned) fiq_exception_entry,
(unsigned *) EXC_FIQ_VEC);
}
 
333,17 → 369,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.
*/
367,18 → 409,18
*/
void print_istate(istate_t *istate)
{
dprintf("istate dump:\n");
 
dprintf(" r0: %x r1: %x r2: %x r3: %x\n",
printf("istate dump:\n");
printf(" r0: %x r1: %x r2: %x r3: %x\n",
istate->r0, istate->r1, istate->r2, istate->r3);
dprintf(" r4: %x r5: %x r6: %x r7: %x\n",
printf(" r4: %x r5: %x r6: %x r7: %x\n",
istate->r4, istate->r5, istate->r6, istate->r7);
dprintf(" r8: %x r8: %x r10: %x r11: %x\n",
printf(" r8: %x r8: %x r10: %x r11: %x\n",
istate->r8, istate->r9, istate->r10, istate->r11);
dprintf(" r12: %x sp: %x lr: %x spsr: %x\n",
printf(" r12: %x sp: %x lr: %x spsr: %x\n",
istate->r12, istate->sp, istate->lr, istate->spsr);
 
dprintf(" pc: %x\n", istate->pc);
printf(" pc: %x\n", istate->pc);
}
 
/** @}
/branches/network/kernel/arch/arm32/src/console.c
26,32 → 26,28
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32
/** @addtogroup arm32
* @{
*/
/** @file
/** @file
* @brief Console.
*/
 
#include <console/console.h>
#include <arch/console.h>
#include <arch/machine.h>
#include <genarch/fb/fb.h>
 
void console_init(devno_t devno)
{
machine_console_init(devno);
}
 
/** 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/network/kernel/arch/arm32/src/arm32.c
34,36 → 34,37
*/
 
#include <arch.h>
#include <arch/boot.h>
#include <config.h>
#include <arch/console.h>
#include <ddi/device.h>
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <genarch/drivers/dsrln/dsrlnin.h>
#include <genarch/drivers/dsrln/dsrlnout.h>
#include <genarch/srln/srln.h>
#include <sysinfo/sysinfo.h>
#include <ddi/irq.h>
#include <arch/debug/print.h>
#include <arch/drivers/gxemul.h>
#include <print.h>
#include <config.h>
#include <interrupt.h>
#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. */
76,18 → 77,27
/** Performs arm32 specific initialization afterr mm is initialized. */
void arch_post_mm_init(void)
{
machine_hw_map_init();
 
gxemul_init();
/* Initialize exception dispatch table */
exception_init();
 
interrupt_init();
console_init(device_assign_devno());
 
#ifdef CONFIG_FB
fb_init(machine_get_fb_address(), 640, 480, 1920, VISUAL_RGB_8_8_8);
#endif
fb_properties_t prop = {
.addr = GXEMUL_FB_ADDRESS,
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_BGR_8_8_8,
};
fb_init(&prop);
#else
#ifdef CONFIG_ARM_PRN
dsrlnout_init((ioport8_t *) gxemul_kbd);
#endif /* CONFIG_ARM_PRN */
#endif /* CONFIG_FB */
}
 
/** Performs arm32 specific tasks needed after cpu is initialized.
116,6 → 126,23
*/
void arch_post_smp_init(void)
{
#ifdef CONFIG_ARM_KBD
/*
* Initialize the msim/GXemul keyboard port. Then initialize the serial line
* module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts.
*/
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ);
if (kbrdin)
srln_init(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.inr", NULL, GXEMUL_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, (unative_t) gxemul_kbd);
#endif
}
 
 
149,7 → 176,8
/** Halts CPU. */
void cpu_halt(void)
{
machine_cpu_halt();
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET))
= 0;
}
 
/** Reboot. */
156,9 → 184,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/network/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/network/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/network/kernel/arch/arm32/src/mm/page_fault.c
34,7 → 34,6
*/
#include <panic.h>
#include <arch/exception.h>
#include <arch/debug/print.h>
#include <arch/mm/page_fault.h>
#include <mm/as.h>
#include <genarch/mm/page_pt.h>
49,12 → 48,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;
}
 
61,17 → 61,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;
}
 
80,29 → 81,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;
}
 
115,12 → 113,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;
}
 
142,8 → 139,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;
}
 
162,7 → 159,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;
}
184,12 → 181,12
 
if (ret == AS_PF_FAULT) {
print_istate(istate);
dprintf("page fault - pc: %x, va: %x, status: %x(%x), "
printf("page fault - pc: %x, va: %x, status: %x(%x), "
"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.");
}
}
 
203,9 → 200,9
int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate);
 
if (ret == AS_PF_FAULT) {
dprintf("prefetch_abort\n");
printf("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/network/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
35,9 → 35,8
 
#include <mm/frame.h>
#include <arch/mm/frame.h>
#include <arch/machine.h>
#include <arch/drivers/gxemul.h>
#include <config.h>
#include <arch/debug/print.h>
 
/** Address of the last frame in the memory. */
uintptr_t last_frame = 0;
45,11 → 44,12
/** Creates memory zones. */
void frame_arch_init(void)
{
/* all memory as one zone */
zone_create(0, ADDR2PFN(machine_get_memory_size()),
last_frame = *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
/* All memory as one zone */
zone_create(0, ADDR2PFN(last_frame),
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);
58,10 → 58,9
/** Frees the boot page table. */
void boot_page_table_free(void)
{
int i;
for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; i++) {
unsigned int i;
for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; i++)
frame_free(i * FRAME_SIZE + BOOT_PAGE_TABLE_ADDRESS);
}
}
 
/** @}
/branches/network/kernel/arch/arm32/src/mm/page.c
51,19 → 51,15
*/
void page_arch_init(void)
{
int flags = PAGE_CACHEABLE;
page_mapping_operations = &pt_mapping_operations;
uintptr_t cur;
int flags;
 
page_mapping_operations = &pt_mapping_operations;
 
flags = PAGE_CACHEABLE;
 
/* PA2KA(identity) mapping for all frames until last_frame */
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
/* Kernel identity mapping */
for (cur = 0; cur < last_frame; cur += FRAME_SIZE)
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
}
/* create mapping for exception table at high offset */
/* Create mapping for exception table at high offset */
#ifdef HIGH_EXCEPTION_VECTORS
void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA);
page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr), flags);
70,9 → 66,9
#else
#error "Only high exception vector supported now"
#endif
 
as_switch(NULL, AS_KERNEL);
 
boot_page_table_free();
}
 
90,10 → 86,10
{
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)
}
 
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) {
101,7 → 97,7
physaddr + PFN2ADDR(i),
PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL);
}
 
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
return virtaddr;
}
/branches/network/kernel/arch/arm32/src/panic.S
31,5 → 31,5
.global panic_printf
 
panic_printf:
bl debug_printf
bl printf
bl cpu_halt
/branches/network/kernel/arch/arm32/src/userspace.c
90,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/network/kernel/arch/arm32/src/interrupt.c
35,13 → 35,16
 
#include <arch/asm.h>
#include <arch/regutils.h>
#include <arch/drivers/gxemul.h>
#include <ddi/irq.h>
#include <arch/machine.h>
#include <ddi/device.h>
#include <interrupt.h>
 
/** Initial size of a table holding interrupt handlers. */
#define IRQ_COUNT 8
 
static irq_t gxemul_timer_irq;
 
/** Disable interrupts.
*
* @return Old interrupt priority level.
49,7 → 52,7
ipl_t interrupts_disable(void)
{
ipl_t ipl = current_status_reg_read();
 
current_status_reg_control_write(STATUS_REG_IRQ_DISABLED_BIT | ipl);
return ipl;
62,9 → 65,9
ipl_t interrupts_enable(void)
{
ipl_t ipl = current_status_reg_read();
 
current_status_reg_control_write(ipl & ~STATUS_REG_IRQ_DISABLED_BIT);
 
return ipl;
}
 
88,6 → 91,41
return current_status_reg_read();
}
 
/** Starts gxemul Real Time Clock device, which asserts regular interrupts.
*
* @param frequency Interrupts frequency (0 disables RTC).
*/
static void gxemul_timer_start(uint32_t frequency)
{
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET))
= frequency;
}
 
static irq_ownership_t gxemul_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
/** Timer interrupt handler.
*
* @param irq Interrupt information.
* @param arg Not used.
*/
static void gxemul_timer_irq_handler(irq_t *irq)
{
/*
* We are holding a lock which prevents preemption.
* Release the lock, call clock() and reacquire the lock again.
*/
spinlock_unlock(&irq->lock);
clock();
spinlock_lock(&irq->lock);
/* acknowledge tick */
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET))
= 0;
}
 
/** Initialize basic tables for exception dispatching
* and starts the timer.
*/
94,7 → 132,16
void interrupt_init(void)
{
irq_init(IRQ_COUNT, IRQ_COUNT);
machine_timer_irq_start();
irq_initialize(&gxemul_timer_irq);
gxemul_timer_irq.devno = device_assign_devno();
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ;
gxemul_timer_irq.claim = gxemul_timer_claim;
gxemul_timer_irq.handler = gxemul_timer_irq_handler;
irq_register(&gxemul_timer_irq);
gxemul_timer_start(GXEMUL_TIMER_FREQ);
}
 
/** @}
/branches/network/kernel/arch/arm32/src/drivers/gxemul.c
33,361 → 33,19
* @brief GXemul drivers.
*/
 
#include <interrupt.h>
#include <ipc/irq.h>
#include <console/chardev.h>
#include <arch/drivers/gxemul.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <print.h>
#include <ddi/device.h>
#include <mm/page.h>
#include <arch/machine.h>
#include <arch/debug/print.h>
 
/* Addresses of devices. */
#define GXEMUL_VIDEORAM 0x10000000
#define GXEMUL_KBD 0x10000000
#define GXEMUL_HALT_OFFSET 0x10
#define GXEMUL_RTC 0x15000000
#define GXEMUL_RTC_FREQ_OFFSET 0x100
#define GXEMUL_RTC_ACK_OFFSET 0x110
#define GXEMUL_IRQC 0x16000000
#define GXEMUL_IRQC_MASK_OFFSET 0x4
#define GXEMUL_IRQC_UNMASK_OFFSET 0x8
#define GXEMUL_MP 0x11000000
#define GXEMUL_MP_MEMSIZE_OFFSET 0x0090
#define GXEMUL_FB 0x12000000
void *gxemul_kbd;
void *gxemul_rtc;
void *gxemul_irqc;
 
/* IRQs */
#define GXEMUL_KBD_IRQ 2
#define GXEMUL_TIMER_IRQ 4
 
static gxemul_hw_map_t gxemul_hw_map;
static chardev_t console;
static irq_t gxemul_console_irq;
static irq_t gxemul_timer_irq;
 
static bool hw_map_init_called = false;
 
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 char gxemul_do_read(chardev_t *dev);
 
static chardev_operations_t gxemul_ops = {
.resume = gxemul_kbd_enable,
.suspend = gxemul_kbd_disable,
.write = gxemul_write,
.read = gxemul_do_read,
};
 
 
/** Returns the mask of active interrupts. */
static inline uint32_t gxemul_irqc_get_sources(void)
void gxemul_init(void)
{
return *((uint32_t *) gxemul_hw_map.irqc);
gxemul_kbd = (void *) hw_map(GXEMUL_KBD_ADDRESS, PAGE_SIZE);
gxemul_rtc = (void *) hw_map(GXEMUL_RTC_ADDRESS, PAGE_SIZE);
gxemul_irqc = (void *) hw_map(GXEMUL_IRQC_ADDRESS, PAGE_SIZE);
}
 
 
/** Masks interrupt.
*
* @param irq interrupt number
*/
static inline void gxemul_irqc_mask(uint32_t irq)
{
*((uint32_t *) gxemul_hw_map.irqc_mask) = irq;
}
 
 
/** Unmasks interrupt.
*
* @param irq interrupt number
*/
static inline void gxemul_irqc_unmask(uint32_t irq)
{
*((uint32_t *) gxemul_hw_map.irqc_unmask) = irq;
}
 
 
/** Initializes #gxemul_hw_map. */
void gxemul_hw_map_init(void)
{
gxemul_hw_map.videoram = hw_map(GXEMUL_VIDEORAM, PAGE_SIZE);
gxemul_hw_map.kbd = hw_map(GXEMUL_KBD, PAGE_SIZE);
gxemul_hw_map.rtc = hw_map(GXEMUL_RTC, PAGE_SIZE);
gxemul_hw_map.irqc = hw_map(GXEMUL_IRQC, PAGE_SIZE);
 
gxemul_hw_map.rtc_freq = gxemul_hw_map.rtc + GXEMUL_RTC_FREQ_OFFSET;
gxemul_hw_map.rtc_ack = gxemul_hw_map.rtc + GXEMUL_RTC_ACK_OFFSET;
gxemul_hw_map.irqc_mask = gxemul_hw_map.irqc + GXEMUL_IRQC_MASK_OFFSET;
gxemul_hw_map.irqc_unmask = gxemul_hw_map.irqc +
GXEMUL_IRQC_UNMASK_OFFSET;
 
hw_map_init_called = true;
}
 
 
/** Putchar that works with gxemul.
*
* @param dev Not used.
* @param ch Characted to be printed.
*/
static void gxemul_write(chardev_t *dev, const char ch)
{
*((char *) gxemul_hw_map.videoram) = ch;
}
 
/** Enables gxemul keyboard (interrupt unmasked).
*
* @param dev Not used.
*
* Called from getc().
*/
static void gxemul_kbd_enable(chardev_t *dev)
{
gxemul_irqc_unmask(GXEMUL_KBD_IRQ);
}
 
/** Disables gxemul keyboard (interrupt masked).
*
* @param dev not used
*
* Called from getc().
*/
static void gxemul_kbd_disable(chardev_t *dev)
{
gxemul_irqc_mask(GXEMUL_KBD_IRQ);
}
 
/** Read character using polling, assume interrupts disabled.
*
* @param dev Not used.
*/
static char gxemul_do_read(chardev_t *dev)
{
char ch;
 
while (1) {
ch = *((volatile char *) gxemul_hw_map.kbd);
if (ch) {
if (ch == '\r')
return '\n';
if (ch == 0x7f)
return '\b';
return ch;
}
}
}
 
/** Process keyboard interrupt.
*
* @param irq IRQ information.
* @param arg Not used.
*/
static void gxemul_irq_handler(irq_t *irq, void *arg, ...)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
ipc_irq_send_notif(irq);
} else {
char ch = 0;
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)
{
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.
*/
void gxemul_console_init(devno_t devno)
{
chardev_initialize("gxemul_console", &console, &gxemul_ops);
stdin = &console;
stdout = &console;
irq_initialize(&gxemul_console_irq);
gxemul_console_irq.devno = devno;
gxemul_console_irq.inr = GXEMUL_KBD_IRQ;
gxemul_console_irq.claim = gxemul_claim;
gxemul_console_irq.handler = gxemul_irq_handler;
irq_register(&gxemul_console_irq);
gxemul_irqc_unmask(GXEMUL_KBD_IRQ);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, gxemul_hw_map.kbd);
}
 
/** Starts gxemul Real Time Clock device, which asserts regular interrupts.
*
* @param frequency Interrupts frequency (0 disables RTC).
*/
static void gxemul_timer_start(uint32_t frequency)
{
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency;
}
 
static irq_ownership_t gxemul_timer_claim(void)
{
return IRQ_ACCEPT;
}
 
/** Timer interrupt handler.
*
* @param irq Interrupt information.
* @param arg Not used.
*/
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...)
{
/*
* We are holding a lock which prevents preemption.
* Release the lock, call clock() and reacquire the lock again.
*/
spinlock_unlock(&irq->lock);
clock();
spinlock_lock(&irq->lock);
 
/* acknowledge tick */
*((uint32_t*) gxemul_hw_map.rtc_ack) = 0;
}
 
/** Initializes and registers timer interrupt handler. */
static void gxemul_timer_irq_init(void)
{
irq_initialize(&gxemul_timer_irq);
gxemul_timer_irq.devno = device_assign_devno();
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ;
gxemul_timer_irq.claim = gxemul_timer_claim;
gxemul_timer_irq.handler = gxemul_timer_irq_handler;
 
irq_register(&gxemul_timer_irq);
}
 
 
/** Starts timer.
*
* Initiates regular timer interrupts after initializing
* corresponding interrupt handler.
*/
void gxemul_timer_irq_start(void)
{
gxemul_timer_irq_init();
gxemul_timer_start(GXEMUL_TIMER_FREQ);
}
 
/** Returns the size of emulated memory.
*
* @return Size in bytes.
*/
size_t gxemul_get_memory_size(void)
{
return *((int *) (GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET));
}
 
/** Prints a character.
*
* @param ch Character to be printed.
*/
void gxemul_debug_putc(char ch)
{
char *addr = 0;
if (!hw_map_init_called) {
addr = (char *) GXEMUL_KBD;
} else {
addr = (char *) gxemul_hw_map.videoram;
}
 
*(addr) = ch;
}
 
/** Stops gxemul. */
void gxemul_cpu_halt(void)
{
char * addr = 0;
if (!hw_map_init_called) {
addr = (char *) GXEMUL_KBD;
} else {
addr = (char *) gxemul_hw_map.videoram;
}
*(addr + GXEMUL_HALT_OFFSET) = '\0';
}
 
/** Gxemul specific interrupt exception handler.
*
* Determines sources of the interrupt from interrupt controller and
* calls high-level handlers for them.
*
* @param exc_no Interrupt exception number.
* @param istate Saved processor state.
*/
void gxemul_irq_exception(int exc_no, istate_t *istate)
{
uint32_t sources = gxemul_irqc_get_sources();
int i;
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
if (sources & (1 << i)) {
irq_t *irq = irq_dispatch_and_lock(i);
if (irq) {
/* The IRQ handler was found. */
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
/* Spurious interrupt.*/
dprintf("cpu%d: spurious interrupt (inum=%d)\n",
CPU->id, i);
}
}
}
}
 
/** Returns address of framebuffer device.
*
* @return Address of framebuffer device.
*/
uintptr_t gxemul_get_fb_address(void)
{
return (uintptr_t) GXEMUL_FB;
}
 
/** @}
*/
/branches/network/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/network/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/network/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/network/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;
84,11 → 86,10
}
 
/** 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)
/branches/network/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/network/kernel/arch/ppc32/include/types.h
57,6 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "x"
#define PRIs "u"
84,11 → 87,13
 
/** 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/network/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 0x1000
#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/network/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/network/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/network/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/network/kernel/arch/ppc32/include/mm/page.h
120,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
134,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)
147,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/network/kernel/arch/ppc32/include/mm/tlb.h
39,6 → 39,11
#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 */
53,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/network/kernel/arch/ppc32/include/barrier.h
55,6 → 55,7
"dcbst 0, %0\n"
"sync\n"
"icbi 0, %0\n"
"sync\n"
"isync\n"
:: "r" (addr)
);
76,7 → 77,10
asm volatile ("icbi 0, %0\n" :: "r" (addr + i));
}
 
asm volatile ("isync");
asm volatile (
"sync\n"
"isync\n"
);
}
 
#endif
/branches/network/kernel/arch/ppc32/include/drivers/cuda.h
38,10 → 38,8
#include <arch/types.h>
#include <typedefs.h>
 
extern void cuda_init(devno_t devno, uintptr_t base, size_t size);
extern void cuda_init(uintptr_t base, size_t size);
extern int cuda_get_scancode(void);
extern void cuda_grab(void);
extern void cuda_release(void);
 
#endif
 
/branches/network/kernel/arch/ppc32/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
BFD = binary
45,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/network/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/network/kernel/arch/ppc32/src/asm.S
66,9 → 66,9
mr sp, r4
 
# %r3 is defined to hold pcb_ptr - set it to 0
# %r6 is defined to hold pcb_ptr - set it to 0
 
xor r3, r3, r3
xor r6, r6, r6
# jump to userspace
131,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
 
197,8 → 197,8
lwz r12, 148(sp)
mtxer r12
lwz r12, 152(sp)
lwz sp, 156(sp)
lwz r12, 156(sp)
lwz sp, 160(sp)
 
rfi
/branches/network/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/network/kernel/arch/ppc32/src/ppc32.c
42,24 → 42,27
#include <userspace.h>
#include <proc/uarg.h>
#include <console/console.h>
#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);
}
}
 
75,35 → 78,50
void arch_post_mm_init(void)
{
if (config.cpu_active == 1) {
 
#ifdef CONFIG_FB
/* 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);
#endif
/* 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(bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE);
}
/* Merge all zones to 1 big zone */
zone_merge_all();
128,11 → 146,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 → 160,9
*/
void arch_grab_console(void)
{
cuda_grab();
#ifdef CONFIG_FB
fb_redraw();
#endif
}
 
/** Return console to userspace
148,8 → 170,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/network/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,22
#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 <macros.h>
#include <symtab.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.
65,7 → 75,7
* 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.
87,7 → 97,7
*/
page_table_lock(as, lock);
pte = page_mapping_find(as, badvaddr);
ASSERT((pte) && (pte->p));
ASSERT((pte) && (pte->present));
*pfrc = 0;
return pte;
case AS_PF_DEFER:
96,11 → 106,10
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);
panic("Unexpected rc (%d).", rc);
}
}
}
108,21 → 117,20
 
static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
{
char *symbol = "";
char *sym2 = "";
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,
symbol = symtab_fmt_name_lookup(istate->pc);
sym2 = symtab_fmt_name_lookup(istate->lr);
 
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;
148,11 → 156,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;
}
159,86 → 168,25
}
if (!found) {
/* Secondary hash (not) */
uint32_t base2 = (~hash & 0x3ff) << 3;
/* Find unused or colliding
PTE in PTEG */
/* Find unused 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[base + i].v) {
found = true;
base = base2;
h = 1;
break;
}
}
if (!found) {
// TODO: A/C precedence groups
i = page % 8;
}
}
phte[base + i].v = 1;
phte[base + i].vsid = vsid;
phte[base + i].h = h;
phte[base + i].api = api;
phte[base + i].rpn = pfn;
phte[base + i].r = 0;
phte[base + i].c = 0;
phte[base + i].pp = 2; // FIXME
}
 
 
static void pht_real_insert(const uintptr_t vaddr, const pfn_t pfn)
{
uint32_t page = (vaddr >> 12) & 0xffff;
uint32_t api = (vaddr >> 22) & 0x3f;
uint32_t vsid;
asm volatile (
"mfsrin %0, %1\n"
: "=r" (vsid)
: "r" (vaddr)
);
uint32_t sdr1;
asm volatile (
"mfsdr1 %0\n"
: "=r" (sdr1)
);
phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000);
/* Primary hash (xor) */
uint32_t h = 0;
uint32_t hash = vsid ^ page;
uint32_t base = (hash & 0x3ff) << 3;
uint32_t i;
bool found = false;
/* Find unused or 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))) {
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[base2 + i].v)
&& (phte[base2 + i].vsid == vsid)
&& (phte[base2 + i].api == api)
&& (phte[base2 + i].h == 1)) {
found = true;
base = base2;
h = 1;
247,26 → 195,37
}
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_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
phte[base + i].v = 1;
phte[base + i].vsid = vsid;
phte[base + i].h = h;
phte[base + i].api = api;
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
}
 
 
/** Process Instruction/Data Storage Interrupt
/** Process Instruction/Data Storage Exception
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
* @param n Exception vector number.
* @param istate Interrupted register context.
*
*/
void pht_refill(int n, istate_t *istate)
285,12 → 244,9
lock = true;
}
if (n == VECTOR_DATA_STORAGE) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
if (n == VECTOR_DATA_STORAGE)
badvaddr = istate->dar;
else
badvaddr = istate->pc;
page_table_lock(as, lock);
310,12 → 266,12
page_table_unlock(as, lock);
return;
default:
panic("Unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
pte->a = 1; /* Record access to PTE */
pht_insert(badvaddr, pte->pfn);
pte->accessed = 1; /* Record access to PTE */
pht_insert(badvaddr, pte);
page_table_unlock(as, lock);
return;
326,22 → 282,19
}
 
 
/** Process Instruction/Data Storage Interrupt in Real Mode
/** Process Instruction/Data Storage Exception in Real Mode
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
* @param n Exception vector number.
* @param istate Interrupted register context.
*
*/
bool pht_real_refill(int n, istate_t *istate)
bool pht_refill_real(int n, istate_t *istate)
{
uintptr_t badvaddr;
if (n == VECTOR_DATA_STORAGE) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
if (n == VECTOR_DATA_STORAGE)
badvaddr = istate->dar;
else
badvaddr = istate->pc;
uint32_t physmem;
350,15 → 303,140
: "=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 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" (badvaddr)
);
uint32_t sdr1;
asm volatile (
"mfsdr1 %0\n"
: "=r" (sdr1)
);
phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
/* Primary hash (xor) */
uint32_t h = 0;
uint32_t hash = vsid ^ page;
uint32_t base = (hash & 0x3ff) << 3;
uint32_t i;
bool found = false;
/* Find colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
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;
}
}
return false;
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 colliding PTE in PTEG */
for (i = 0; i < 8; i++) {
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;
break;
}
}
if (!found) {
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte_real[base2 + i].v) {
found = true;
base = base2;
h = 1;
break;
}
}
}
if (!found) {
/* Use secondary hash to avoid collisions
with usual PHT refill handler. */
i = RANDI(seed_real) % 8;
base = base2;
h = 1;
}
}
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
return true;
}
 
 
/** Process ITLB/DTLB Miss Exception in Real Mode
*
*
*/
void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
{
uint32_t badvaddr = tlbmiss & 0xfffffffc;
uint32_t physmem;
asm volatile (
"mfsprg3 %0\n"
: "=r" (physmem)
);
if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
return; // FIXME
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)
);
}
 
 
void tlb_arch_init(void)
{
tlb_invalidate_all();
367,9 → 445,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)
);
}
 
438,7 → 594,7
: "=r" (vsid)
: "r" (sr << 28)
);
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr,
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" : "");
/branches/network/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/network/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
49,7 → 49,7
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%" PRIs " bytes)",
panic("Unable to map physical memory %p (%" PRIs " bytes).",
physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
/branches/network/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 {
/*
92,8 → 92,8
 
static void exception_decrementer(int n, istate_t *istate)
{
start_decrementer();
clock();
start_decrementer();
}
 
 
/branches/network/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/network/kernel/arch/ppc32/src/drivers/cuda.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32
/** @addtogroup ppc32
* @{
*/
/** @file
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>
41,6 → 40,7
#include <sysinfo/sysinfo.h>
#include <interrupt.h>
#include <stdarg.h>
#include <ddi/device.h>
 
#define CUDA_IRQ 10
#define SPECIAL '?'
205,101 → 205,52
}
 
 
/* Called from getc(). */
static void cuda_resume(chardev_t *d)
{
}
 
 
/* Called from getc(). */
static void cuda_suspend(chardev_t *d)
{
}
 
 
static char key_read(chardev_t *d)
{
char ch;
ch = 0;
return ch;
}
 
 
static chardev_t kbrd;
static chardev_operations_t ops = {
.suspend = cuda_suspend,
.resume = cuda_resume,
.read = key_read
static indev_t kbrd;
static indev_operations_t ops = {
.poll = NULL
};
 
 
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();
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
}
int scan_code = cuda_get_scancode();
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
indev_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)
void cuda_init(uintptr_t base, size_t size)
{
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);
indev_initialize("cuda_kbd", &kbrd, &ops);
stdin = &kbrd;
irq_initialize(&cuda_irq);
cuda_irq.devno = devno;
cuda_irq.devno = device_assign_devno();
cuda_irq.inr = CUDA_IRQ;
cuda_irq.claim = cuda_claim;
cuda_irq.handler = cuda_irq_handler;
306,9 → 257,8
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);
sysinfo_set_item_val("kbd.address.virtual", NULL, base);
}
345,7 → 295,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/network/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/network/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/network/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/network/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/network/kernel/arch/amd64/include/drivers/vesa.h
File deleted
/branches/network/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/network/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
57,6 → 57,9
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
/branches/network/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/network/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,7 → 111,7
static inline void atomic_lock_arch(atomic_t *val)
{
uint64_t tmp;
 
preemption_disable();
asm volatile (
"0:\n"
106,15 → 118,15
#ifdef CONFIG_HT
"pause\n"
#endif
"mov %0, %1\n"
"testq %1, %1\n"
"mov %[count], %[tmp]\n"
"testq %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
"incq %1\n" /* now use the atomic operation */
"xchgq %0, %1\n"
"testq %1, %1\n"
"incq %[tmp]\n" /* now use the atomic operation */
"xchgq %[count], %[tmp]\n"
"testq %[tmp], %[tmp]\n"
"jnz 0b\n"
: "+m" (val->count), "=&r" (tmp)
: [count] "+m" (val->count), [tmp] "=&r" (tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
/branches/network/kernel/arch/amd64/include/pm.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64
/** @addtogroup amd64
* @{
*/
/** @file
36,63 → 36,60
#define KERN_amd64_PM_H_
 
#ifndef __ASM__
# include <arch/types.h>
# include <arch/context.h>
#include <arch/types.h>
#include <arch/context.h>
#endif
 
#define IDT_ITEMS 64
#define GDT_ITEMS 8
#define IDT_ITEMS 64
#define GDT_ITEMS 8
 
 
#define NULL_DES 0
/* Warning: Do not reorder next items, unless you look into syscall.c!!! */
#define KTEXT_DES 1
#define KDATA_DES 2
#define UDATA_DES 3
#define UTEXT_DES 4
#define KTEXT32_DES 5
/* EndOfWarning */
#define TSS_DES 6
#define NULL_DES 0
/* Warning: Do not reorder the following items, unless you look into syscall.c! */
#define KTEXT_DES 1
#define KDATA_DES 2
#define UDATA_DES 3
#define UTEXT_DES 4
#define KTEXT32_DES 5
/* End of warning */
#define TSS_DES 6
 
 
 
#ifdef CONFIG_FB
 
#define VESA_INIT_DES 8
#define VESA_INIT_SEGMENT 0x8000
#undef GDT_ITEMS
#define GDT_ITEMS 9
#define VESA_INIT_DES 8
#define VESA_INIT_SEGMENT 0x8000
 
#endif /*CONFIG_FB*/
#undef GDT_ITEMS
#define GDT_ITEMS 9
 
#endif /* CONFIG_FB */
 
#define gdtselector(des) ((des) << 3)
#define idtselector(des) ((des) << 4)
 
#define gdtselector(des) ((des) << 3)
#define idtselector(des) ((des) << 4)
#define PL_KERNEL 0
#define PL_USER 3
 
#define PL_KERNEL 0
#define PL_USER 3
#define AR_PRESENT ( 1 << 7)
#define AR_DATA (2 << 3)
#define AR_CODE (3 << 3)
#define AR_WRITABLE (1 << 1)
#define AR_READABLE (1 << 1)
#define AR_TSS (0x09)
#define AR_INTERRUPT (0x0e)
#define AR_TRAP (0x0f)
 
#define AR_PRESENT (1<<7)
#define AR_DATA (2<<3)
#define AR_CODE (3<<3)
#define AR_WRITABLE (1<<1)
#define AR_READABLE (1<<1)
#define AR_TSS (0x9)
#define AR_INTERRUPT (0xe)
#define AR_TRAP (0xf)
#define DPL_KERNEL (PL_KERNEL << 5)
#define DPL_USER (PL_USER << 5)
 
#define DPL_KERNEL (PL_KERNEL<<5)
#define DPL_USER (PL_USER<<5)
#define TSS_BASIC_SIZE 104
#define TSS_IOMAP_SIZE (16 * 1024 + 1) /* 16K for bitmap + 1 terminating byte for convenience */
 
#define TSS_BASIC_SIZE 104
#define TSS_IOMAP_SIZE (16*1024+1) /* 16K for bitmap + 1 terminating byte for convenience */
#define IO_PORTS (64 * 1024)
 
#define IO_PORTS (64*1024)
 
#ifndef __ASM__
 
struct descriptor {
typedef struct {
unsigned limit_0_15: 16;
unsigned base_0_15: 16;
unsigned base_16_23: 8;
103,10 → 100,9
unsigned special: 1;
unsigned granularity : 1;
unsigned base_24_31: 8;
} __attribute__ ((packed));
typedef struct descriptor descriptor_t;
} __attribute__ ((packed)) descriptor_t;
 
struct tss_descriptor {
typedef struct {
unsigned limit_0_15: 16;
unsigned base_0_15: 16;
unsigned base_16_23: 8;
121,10 → 117,9
unsigned base_24_31: 8;
unsigned base_32_63 : 32;
unsigned : 32;
} __attribute__ ((packed));
typedef struct tss_descriptor tss_descriptor_t;
} __attribute__ ((packed)) tss_descriptor_t;
 
struct idescriptor {
typedef struct {
unsigned offset_0_15: 16;
unsigned selector: 16;
unsigned ist:3;
135,22 → 130,19
unsigned offset_16_31: 16;
unsigned offset_32_63: 32;
unsigned : 32;
} __attribute__ ((packed));
typedef struct idescriptor idescriptor_t;
} __attribute__ ((packed)) idescriptor_t;
 
struct ptr_16_64 {
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__ ((packed));
typedef struct ptr_16_64 ptr_16_64_t;
} __attribute__ ((packed)) ptr_16_64_t;
 
struct ptr_16_32 {
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed));
typedef struct ptr_16_32 ptr_16_32_t;
} __attribute__ ((packed)) ptr_16_32_t;
 
struct tss {
typedef struct {
uint32_t reserve1;
uint64_t rsp0;
uint64_t rsp1;
167,8 → 159,7
uint16_t reserve4;
uint16_t iomap_base;
uint8_t iomap[TSS_IOMAP_SIZE];
} __attribute__ ((packed));
typedef struct tss tss_t;
} __attribute__ ((packed)) tss_t;
 
extern tss_t *tss_p;
 
/branches/network/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/network/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/network/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;
}
62,7 → 69,11
 
static inline void cpu_halt(void)
{
asm volatile ("hlt\n");
asm volatile (
"0:\n"
" hlt\n"
" jmp 0b\n"
);
}
 
 
72,15 → 83,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 → 146,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 → 200,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 → 221,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 → 241,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 → 256,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 → 273,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 → 298,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 → 327,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)
static inline void gdtr_load(ptr_16_64_t *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)
static inline void gdtr_store(ptr_16_64_t *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)
static inline void idtr_load(ptr_16_64_t *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/network/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/network/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/network/kernel/arch/amd64/include/cpu.h
35,9 → 35,9
#ifndef KERN_amd64_CPU_H_
#define KERN_amd64_CPU_H_
 
#define RFLAGS_IF (1 << 9)
#define RFLAGS_DF (1 << 10)
#define RFLAGS_RF (1 << 16)
#define RFLAGS_IF (1 << 9)
#define RFLAGS_DF (1 << 10)
#define RFLAGS_RF (1 << 16)
 
#define EFER_MSR_NUM 0xc0000080
#define AMD_SCE_FLAG 0
62,17 → 62,15
int family;
int model;
int stepping;
struct tss *tss;
tss_t *tss;
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
struct star_msr {
};
 
struct lstar_msr {
};
 
extern void set_efer_flag(int flag);
/branches/network/kernel/arch/amd64/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-x86-64
BFD_ARCH = i386:x86-64
BFD = binary
45,83 → 41,50
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/network/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/network/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/network/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>
61,9 → 65,8
#include <syscall/syscall.h>
#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 → 73,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 → 89,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 */
133,13 → 149,17
/* hard clock */
i8254_init();
#ifdef CONFIG_FB
if (vesa_present())
vesa_init();
else
#endif
ega_init(); /* video */
#ifdef CONFIG_EGA
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
#else
{}
#endif
/* Enable debugger */
debugger_init();
172,8 → 192,28
 
void arch_post_smp_init(void)
{
/* keyboard controller */
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE);
#ifdef CONFIG_PC_KBD
/*
* Initialize the i8042 controller. Then initialize the keyboard
* module and connect it to i8042. Enable keyboard interrupts.
*/
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
if (kbrdin) {
kbrd_init(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.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);
#endif
}
 
void calibrate_delay_loop(void)
208,15 → 248,38
*/
void arch_grab_console(void)
{
i8042_grab();
#ifdef CONFIG_FB
if (vesa_present())
vesa_redraw();
else
#endif
#ifdef CONFIG_EGA
ega_redraw();
#else
{}
#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/network/kernel/arch/amd64/src/pm.c
137,8 → 137,8
 
void gdt_tss_setlimit(descriptor_t *d, uint32_t limit)
{
struct tss_descriptor *td = (tss_descriptor_t *) d;
 
tss_descriptor_t *td = (tss_descriptor_t *) d;
td->limit_0_15 = limit & 0xffff;
td->limit_16_19 = (limit >> 16) & 0xf;
}
185,14 → 185,14
*/
void pm_init(void)
{
descriptor_t *gdt_p = (struct descriptor *) gdtr.base;
descriptor_t *gdt_p = (descriptor_t *) gdtr.base;
tss_descriptor_t *tss_desc;
 
/*
* Each CPU has its private GDT and TSS.
* All CPUs share one IDT.
*/
 
if (config.cpu_active == 1) {
idt_init();
/*
200,20 → 200,19
* the heap hasn't been initialized so far.
*/
tss_p = &tss;
}
else {
} else {
/* We are going to use malloc, which may return
* non boot-mapped pointer, initialize the CR3 register
* ahead of page_init */
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
 
tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC);
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);
 
tss_desc = (tss_descriptor_t *) (&gdt_p[TSS_DES]);
tss_desc->present = 1;
tss_desc->type = AR_TSS;
221,7 → 220,7
gdt_tss_setbase(&gdt_p[TSS_DES], (uintptr_t) tss_p);
gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1);
 
gdtr_load(&gdtr);
idtr_load(&idtr);
/*
/branches/network/kernel/arch/amd64/src/ddi/ddi.c
57,15 → 57,15
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
count_t bits;
 
bits = ioaddr + size;
if (bits > IO_PORTS)
return ENOENT;
 
if (task->arch.iomap.bits < bits) {
bitmap_t oldiomap;
uint8_t *newmap;
/*
* The I/O permission bitmap is too small and needs to be grown.
*/
77,17 → 77,17
bitmap_initialize(&oldiomap, task->arch.iomap.map,
task->arch.iomap.bits);
bitmap_initialize(&task->arch.iomap, newmap, bits);
 
/*
* Mark the new range inaccessible.
*/
bitmap_set_range(&task->arch.iomap, oldiomap.bits,
bits - oldiomap.bits);
 
/*
* In case there really existed smaller iomap,
* copy its contents and deallocate it.
*/
*/
if (oldiomap.bits) {
bitmap_copy(&task->arch.iomap, &oldiomap,
oldiomap.bits);
94,17 → 94,17
free(oldiomap.map);
}
}
 
/*
* Enable the range and we are done.
*/
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
 
/*
* Increment I/O Permission bitmap generation counter.
*/
task->arch.iomapver++;
 
return 0;
}
 
122,7 → 122,7
descriptor_t *gdt_p;
tss_descriptor_t *tss_desc;
count_t ver;
 
/* First, copy the I/O Permission Bitmap. */
spinlock_lock(&TASK->lock);
ver = TASK->arch.iomapver;
140,7 → 140,7
bitmap_set_range(&iomap, ALIGN_UP(TASK->arch.iomap.bits, 8), 8);
}
spinlock_unlock(&TASK->lock);
 
/*
* Second, adjust TSS segment limit.
* Take the extra ending byte will all bits set into account.
151,10 → 151,10
gdtr_load(&cpugdtr);
/*
* Before we load new TSS limit, the current TSS descriptor
* type must be changed to describe inactive TSS.
*/
tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES];
* Before we load new TSS limit, the current TSS descriptor
* type must be changed to describe inactive TSS.
*/
tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES];
tss_desc->type = AR_TSS;
tr_load(gdtselector(TSS_DES));
/branches/network/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
173,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)
184,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
204,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/network/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/network/kernel/arch/amd64/src/boot/vesa_ret.inc
0,0 → 1,19
.code32
vesa_init_protected:
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %ds # kernel data + stack
movw %cx, %ss
#
# Simics seems to remove hidden part of GS on entering user mode
# when _visible_ part of GS does not point to user-mode segment.
#
movw $gdtselector(UDATA_DES), %cx
movw %cx, %fs
movw %cx, %gs
movl $START_STACK, %esp # initialize stack pointer
jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
/branches/network/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
37,7 → 37,7
#include <arch/cpuid.h>
 
#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
 
.section K_TEXT_START, "ax"
 
.code32
46,7 → 46,7
multiboot_header:
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long multiboot_header
.long unmapped_ktext_start
.long 0
55,15 → 55,19
 
multiboot_image_start:
cld
movl $START_STACK, %esp # initialize stack pointer
lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
 
movl $START_STACK, %esp # initialize stack pointer
lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %ds # kernel data + stack
movw %cx, %ds # kernel data + stack
movw %cx, %ss
#
# Simics seems to remove hidden part of GS on entering user mode
# when _visible_ part of GS does not point to user-mode segment
# when _visible_ part of GS does not point to user-mode segment.
#
movw $gdtselector(UDATA_DES), %cx
movw %cx, %fs
movw %cx, %gs
71,17 → 75,19
jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
multiboot_meeting_point:
movl %eax, grub_eax # save parameters from GRUB
movl %eax, grub_eax # save parameters from GRUB
movl %ebx, grub_ebx
#
# Protected 32-bit. We want to reuse the code-seg descriptor,
# the Default operand size must not be 1 when entering long mode
# the Default operand size must not be 1 when entering long mode.
#
movl $(INTEL_CPUID_EXTENDED), %eax
cpuid
cmp $(INTEL_CPUID_EXTENDED), %eax
movl $(INTEL_CPUID_EXTENDED), %eax
cpuid
cmp $(INTEL_CPUID_EXTENDED), %eax
ja extended_cpuid_supported
movl $extended_cpuid_msg, %esi
jmp error_halt
90,11 → 96,11
movl $(AMD_CPUID_EXTENDED), %eax
cpuid
bt $(AMD_EXT_LONG_MODE), %edx
jc long_mode_supported
jc long_mode_supported
movl $long_mode_msg, %esi
jmp error_halt
 
long_mode_supported:
bt $(AMD_EXT_NOEXECUTE), %edx
108,7 → 114,7
movl $(INTEL_CPUID_STANDARD), %eax
cpuid
bt $(INTEL_FXSAVE), %edx
jc fx_supported
jc fx_supported
movl $fx_msg, %esi
jmp error_halt
116,59 → 122,43
fx_supported:
bt $(INTEL_SSE2), %edx
jc sse2_supported
jc sse2_supported
movl $sse2_msg, %esi
jmp error_halt
sse2_supported:
#ifdef CONFIG_FB
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
rep movsb
 
mov $VESA_INIT_SEGMENT << 4, %edi
jmpl *%edi
vesa_meeting_point:
mov %esi, KA2PA(vesa_ph_addr)
mov %di, KA2PA(vesa_height)
shr $16, %edi
mov %di, KA2PA(vesa_width)
mov %bx, KA2PA(vesa_scanline)
shr $16, %ebx
mov %bx, KA2PA(vesa_bpp)
#endif
#include "vesa_prot.inc"
 
#
# Enable 64-bit page translation entries - CR4.PAE = 1.
# Paging is not enabled until after long mode is enabled
# Paging is not enabled until after long mode is enabled.
#
movl %cr4, %eax
btsl $5, %eax
movl %eax, %cr4
 
# Set up paging tables
# set up paging tables
leal ptl_0, %eax
movl %eax, %cr3
# Enable long mode
# enable long mode
movl $EFER_MSR_NUM, %ecx # EFER MSR number
rdmsr # Read EFER
btsl $AMD_LME_FLAG, %eax # Set LME = 1
wrmsr # Write EFER
movl $EFER_MSR_NUM, %ecx # EFER MSR number
rdmsr # read EFER
btsl $AMD_LME_FLAG, %eax # set LME = 1
wrmsr # write EFER
# Enable paging to activate long mode (set CR0.PG = 1)
# enable paging to activate long mode (set CR0.PG = 1)
movl %cr0, %eax
btsl $31, %eax
movl %eax, %cr0
# At this point we are in compatibility mode
# at this point we are in compatibility mode
jmpl $gdtselector(KTEXT_DES), $start64
 
175,362 → 165,29
.code64
start64:
movq $(PA2KA(START_STACK)), %rsp
movl grub_eax, %eax
movl grub_ebx, %ebx
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:
# call 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
#ifdef CONFIG_SMP
call main_bsp
# copy AP bootstrap routines below 1 MB
# not reached
movq $BOOT_OFFSET, %rsi
movq $AP_BOOT_OFFSET, %rdi
movq $_hardcoded_unmapped_size, %rcx
rep movsb
#endif
call main_bsp # never returns
cli
hlt
hlt0:
hlt
jmp hlt0
 
#ifdef CONFIG_FB
.code32
vesa_init:
jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
.code16
vesa_init_real:
mov %cr0, %eax
and $~1, %eax
mov %eax, %cr0
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
vesa_init_real2:
mov $VESA_INIT_SEGMENT, %bx
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ds
mov %bx, %ss
movl $0x0000fffc, %esp
movl $0x0000fffc, %ebp
#define VESA_INFO_SIZE 1024
 
#define VESA_MODE_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#define VESA_MODE_PHADDR_OFFSET 40
 
#define VESA_END_OF_MODES 0xffff
 
#define VESA_OK 0x4f
 
#define VESA_GET_INFO 0x4f00
#define VESA_GET_MODE_INFO 0x4f01
#define VESA_SET_MODE 0x4f02
#define VESA_SET_PALETTE 0x4f09
 
#define CONFIG_VESA_BPP_a 255
 
#if CONFIG_VESA_BPP == 24
#define CONFIG_VESA_BPP_VARIANT 32
#endif
 
mov $VESA_GET_INFO, %ax
mov $e_vesa_init - vesa_init, %di
push %di
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
mov %si, %gs
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
add $VESA_INFO_SIZE, %di
 
1:# Try next mode
mov %gs:(%si), %cx
cmp $VESA_END_OF_MODES, %cx
jz 0f
inc %si
inc %si
push %cx
push %di
push %si
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %si
pop %di
pop %cx
cmp $VESA_OK, %al
jnz 0f
mov $CONFIG_VESA_WIDTH, %ax
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_HEIGHT, %ax
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_BPP, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
 
#ifdef CONFIG_VESA_BPP_VARIANT
jz 2f
mov $CONFIG_VESA_BPP_VARIANT, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
#endif
jnz 1b
2:
mov %cx, %bx
or $0xc000, %bx
push %di
mov $VESA_SET_MODE, %ax
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
 
#if CONFIG_VESA_BPP == 8
# Set 3:2:3 VGA palette
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # Test if VGA compatible registers are present
jnc vga_compat
# Try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
jmp vga_not_compat
vga_compat:
# Try VGA registers to set palette
movw $0x3c6, %dx # Set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # First index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # Data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
#endif
mov VESA_MODE_PHADDR_OFFSET(%di), %esi
mov VESA_MODE_WIDTH_OFFSET(%di), %ax
shl $16, %eax
mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
mov VESA_MODE_BPP_OFFSET(%di), %bl
xor %bh, %bh
shl $16, %ebx
mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
mov %eax, %edi
8:
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
jmp 9f
9:
ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
0:# No prefered mode found
mov $0x111, %cx
push %di
push %cx
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %cx
pop %di
cmp $VESA_OK, %al
jnz 1f
jz 2b # Force relative jump
 
1:
mov $0x0003, %ax
int $0x10
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
xor %ax, %ax
jz 8b # Force relative jump
 
vga323:
#include "vga323.pal"
.code32
vesa_init_protect:
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %ds # kernel data + stack
movw %cx, %ss
# Simics seems to remove hidden part of GS on entering user mode
# when _visible_ part of GS does not point to user-mode segment
movw $gdtselector(UDATA_DES), %cx
movw %cx, %fs
movw %cx, %gs
movl $START_STACK, %esp # initialize stack pointer
jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
.align 4
e_vesa_init:
#endif
 
# Print string from %esi to EGA display (in red) and halt
error_halt:
movl $0xb8000, %edi # base of EGA text mode memory
movl $0xb8000, %edi # base of EGA text mode memory
xorl %eax, %eax
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
538,7 → 195,7
inb %dx, %al
shl $8, %ax
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
547,7 → 204,9
cmp $1920, %ax
jbe cursor_ok
movw $1920, %ax # sanity check for the cursor on the last line
movw $1920, %ax # sanity check for the cursor on the last line
cursor_ok:
movw %ax, %bx
554,7 → 213,7
shl $1, %eax
addl %eax, %edi
movw $0x0c00, %ax # black background, light red foreground
movw $0x0c00, %ax # black background, light red foreground
ploop:
lodsb
561,11 → 220,11
cmp $0, %al
je ploop_end
stosw
inc %bx
inc %bx
jmp ploop
ploop_end:
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
573,7 → 232,7
movb %bh, %al
outb %al, %dx
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
580,17 → 239,20
movw $0x3d5, %dx
movb %bl, %al
outb %al, %dx
cli
hlt
hlt1:
hlt
jmp hlt1
 
#include "vesa_real.inc"
 
.section K_INI_PTLS, "aw", @progbits
 
#
# Macro for generating initial page table contents.
# @param cnt Number of entries to generat. Must be multiple of 8.
# @param g Number of GB that will be added to the mapping.
# @param cnt Number of entries to generat. Must be multiple of 8.
# @param g Number of GB that will be added to the mapping.
#
.macro ptl2gen cnt g
.if \cnt
642,7 → 304,7
# Mapping of [0; 1G) at -2G
.quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
.fill 1, 8, 0
 
.align 4096
.global ptl_0
ptl_0:
/branches/network/kernel/arch/amd64/src/boot/vesa_real.inc
0,0 → 1,0
link ../../../ia32/src/boot/vesa_real.inc
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/network/kernel/arch/amd64/src/boot/vesa_prot.inc
0,0 → 1,0
link ../../../ia32/src/boot/vesa_prot.inc
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/network/kernel/arch/amd64/src/boot/memmap.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64mm
/** @addtogroup amd64mm
* @{
*/
/** @file
/branches/network/kernel/arch/amd64/src/debugger.c
35,7 → 35,6
#include <arch/debugger.h>
#include <console/kconsole.h>
#include <console/cmd.h>
#include <symtab.h>
#include <print.h>
#include <panic.h>
#include <interrupt.h>
44,6 → 43,7
#include <debug.h>
#include <func.h>
#include <smp/ipi.h>
#include <symtab.h>
 
typedef struct {
uintptr_t address; /**< Breakpoint address */
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,44 → 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;
 
#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;
}
 
/* Setup DR register according to table */
static void setup_dr(int curidx)
{
237,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)
265,12 → 229,15
*((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);
 
printf("Reached breakpoint %d:%lx (%s)\n", slot, getip(istate),
symtab_fmt_name_lookup(getip(istate)));
 
#ifdef CONFIG_KCONSOLE
atomic_set(&haltstate, 1);
kconsole("debug", "Debug console ready.\n", false);
atomic_set(&haltstate, 0);
#endif
}
 
void breakpoint_del(int slot)
299,42 → 266,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;
341,7 → 274,7
int i;
/* Set RF to restart the instruction */
#ifdef amd64
#ifdef __64_BITS__
istate->rflags |= RFLAGS_RF;
#else
istate->eflags |= EFLAGS_RF;
379,24 → 312,24
 
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);
#ifdef CONFIG_SMP
404,5 → 337,77
#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 = symtab_fmt_name_lookup(
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/network/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/network/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,36 → 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"
/* %rdi is defined to hold pcb_ptr - set it to 0 */
"xorq %%rdi, %%rdi\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/network/kernel/arch/amd64/src/interrupt.c
43,7 → 43,6
#include <mm/tlb.h>
#include <mm/as.h>
#include <arch.h>
#include <symtab.h>
#include <arch/asm.h>
#include <proc/scheduler.h>
#include <proc/thread.h>
52,6 → 51,7
#include <arch/ddi/ddi.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <symtab.h>
 
/*
* Interrupt and exception dispatching.
64,10 → 64,8
void decode_istate(int n, istate_t *istate)
{
char *symbol;
/* uint64_t *x = &istate->stack[0]; */
 
if (!(symbol = get_symtab_entry(istate->rip)))
symbol = "";
symbol = symtab_fmt_name_lookup(istate->rip);
 
printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n", n, __func__);
printf("%%rip: %#llx (%s)\n", istate->rip, symbol);
80,12 → 78,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 → 86,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 → 118,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 → 171,7
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
221,7 → 215,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 → 223,7
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
panic("No disable_irqs_function.");
}
 
/** @}
/branches/network/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/network/kernel/arch/mips32/include/boot.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/kernel/arch/mips32/include/types.h
57,6 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef struct {
} fncptr_t;
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
/branches/network/kernel/arch/mips32/include/smp/order.h
File deleted
/branches/network/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/network/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"
" addu %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)
: "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/network/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/network/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/network/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/network/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/network/kernel/arch/mips32/include/mm/tlb.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
40,42 → 40,38
#include <arch/mm/asid.h>
#include <arch/exception.h>
 
#ifdef TLBCNT
# define TLB_ENTRY_COUNT TLBCNT
#else
# define TLB_ENTRY_COUNT 48
#endif
#define TLB_ENTRY_COUNT 48
 
#define TLB_WIRED 1
#define TLB_KSTACK_WIRED_INDEX 0
#define TLB_WIRED 1
#define TLB_KSTACK_WIRED_INDEX 0
 
#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 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
#define PAGE_UNCACHED 2
#define PAGE_CACHEABLE_EXC_WRITE 5
 
typedef union {
struct {
#ifdef BIG_ENDIAN
unsigned : 2; /* zero */
unsigned pfn : 24; /* frame number */
unsigned c : 3; /* cache coherency attribute */
unsigned d : 1; /* dirty/write-protect bit */
unsigned v : 1; /* valid bit */
unsigned g : 1; /* global bit */
unsigned : 2; /* zero */
unsigned pfn : 24; /* frame number */
unsigned c : 3; /* cache coherency attribute */
unsigned d : 1; /* dirty/write-protect bit */
unsigned v : 1; /* valid bit */
unsigned g : 1; /* global bit */
#else
unsigned g : 1; /* global bit */
unsigned v : 1; /* valid bit */
unsigned d : 1; /* dirty/write-protect bit */
unsigned c : 3; /* cache coherency attribute */
unsigned pfn : 24; /* frame number */
unsigned : 2; /* zero */
unsigned g : 1; /* global bit */
unsigned v : 1; /* valid bit */
unsigned d : 1; /* dirty/write-protect bit */
unsigned c : 3; /* cache coherency attribute */
unsigned pfn : 24; /* frame number */
unsigned : 2; /* zero */
#endif
} __attribute__ ((packed));
uint32_t value;
163,7 → 159,7
asm volatile ("tlbwr\n\t");
}
 
#define tlb_invalidate(asid) tlb_invalidate_asid(asid)
#define tlb_invalidate(asid) tlb_invalidate_asid(asid)
 
extern void tlb_invalid(istate_t *istate);
extern void tlb_refill(istate_t *istate);
/branches/network/kernel/arch/mips32/include/cpu.h
42,7 → 42,7
uint32_t imp_num;
uint32_t rev_num;
} cpu_arch_t;
 
#endif
 
/** @}
/branches/network/kernel/arch/mips32/include/drivers/serial.h
File deleted
/branches/network/kernel/arch/mips32/include/drivers/msim.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
36,16 → 36,10
#define KERN_mips32_MSIM_H_
 
/** Address of devices. */
#define MSIM_VIDEORAM 0x90000000
#define MSIM_KBD_ADDRESS 0x90000000
#define MSIM_KBD_IRQ 2
#define MSIM_VIDEORAM 0x90000000
#define MSIM_KBD_ADDRESS 0x90000000
#define MSIM_KBD_IRQ 2
 
#include <console/chardev.h>
 
void msim_console(devno_t devno);
void msim_kbd_release(void);
void msim_kbd_grab(void);
 
#endif
 
/** @}
/branches/network/kernel/arch/mips32/Makefile.inc
29,90 → 29,49
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_ARCH = mips
BFD = binary
TARGET = mipsel-linux-gnu
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 -mips3
 
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss
DEFS += -D__32_BITS__
 
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} -DINIT_ADDRESS=${INIT_ADDRESS} -DINIT_SIZE=${INIT_SIZE}
 
## 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),lgxemul)
BFD_NAME = elf32-tradlittlemips
BFD = binary
GCC_CFLAGS += -DFB_INVERT_ENDIAN -DARCH_HAS_FPU -mips3
endif
ifeq ($(MACHINE),bgxemul)
BFD_NAME = elf32-bigmips
BFD = ecoff-bigmips
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3
INIT_ADDRESS = 0x81800000
BFD_NAME = elf32-tradbigmips
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips
TARGET = mips-linux-gnu
GCC_CFLAGS += -DBIG_ENDIAN
endif
ifeq ($(MACHINE),simics)
# SIMICS 4kc emulation is broken, although for instructions
# that do not bother us
BFD_NAME = elf32-tradlittlemips
BFD = elf32-tradlittlemips
GCC_CFLAGS += -mhard-float -mips3 -DTLBCNT=16
TLBCNT = 16
endif
ifeq ($(MACHINE),msim)
BFD_NAME = elf32-tradlittlemips
BFD = binary
GCC_CFLAGS += -mhard-float -mips3
GCC_CFLAGS += -mhard-float
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/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/smp/dorder.c \
arch/$(KARCH)/src/smp/smp.c
/branches/network/kernel/arch/mips32/src/drivers/msim.c
File deleted
/branches/network/kernel/arch/mips32/src/drivers/serial.c
File deleted
/branches/network/kernel/arch/mips32/src/dummy.S
File deleted
/branches/network/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/network/kernel/arch/mips32/src/exception.c
41,13 → 41,12
#include <arch.h>
#include <debug.h>
#include <proc/thread.h>
#include <symtab.h>
#include <print.h>
#include <interrupt.h>
#include <func.h>
#include <console/kconsole.h>
#include <ddi/irq.h>
#include <arch/debugger.h>
#include <symtab.h>
 
static char * exctable[] = {
"Interrupt",
74,25 → 73,21
 
static void print_regdump(istate_t *istate)
{
char *pcsymbol = "";
char *rasymbol = "";
char *pcsymbol, *rasymbol;
 
char *s = get_symtab_entry(istate->epc);
if (s)
pcsymbol = s;
s = get_symtab_entry(istate->ra);
if (s)
rasymbol = s;
printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol, istate->ra, rasymbol, istate->sp);
pcsymbol = symtab_fmt_name_lookup(istate->epc);
rasymbol = symtab_fmt_name_lookup(istate->ra);
 
printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol,
istate->ra, rasymbol, istate->sp);
}
 
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 → 128,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 → 140,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 → 149,7
/*
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
161,7 → 156,8
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, i);
printf("cpu%u: spurious interrupt (inum=%d)\n",
CPU->id, i);
#endif
}
}
171,7 → 167,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/network/kernel/arch/mips32/src/smp/order.c
File deleted
/branches/network/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/network/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/network/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,235 → 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
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,$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
 
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/network/kernel/arch/mips32/src/console.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
33,24 → 33,16
*/
 
#include <console/console.h>
#include <arch/console.h>
#include <arch/drivers/serial.h>
#include <arch/drivers/msim.h>
#include <genarch/fb/fb.h>
 
void console_init(devno_t devno)
{
if (serial_init())
serial_console(devno);
else
msim_console(devno);
}
 
/** Acquire console back for kernel
*
*/
void arch_grab_console(void)
{
msim_kbd_grab();
#ifdef CONFIG_FB
fb_redraw();
#endif
}
 
/** Return console to userspace
58,7 → 50,6
*/
void arch_release_console(void)
{
msim_kbd_release();
}
 
/** @}
/branches/network/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/network/kernel/arch/mips32/src/debugger.c
37,16 → 37,18
#include <memstr.h>
#include <console/kconsole.h>
#include <console/cmd.h>
#include <symtab.h>
#include <print.h>
#include <panic.h>
#include <arch.h>
#include <arch/cp0.h>
#include <func.h>
#include <symtab.h>
 
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",
123,10 → 125,12
{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)
{
158,7 → 162,7
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 ==
165,10 → 169,10
(uintptr_t)argv->intval - sizeof(unative_t)) {
printf("Adjacent breakpoints not supported, conflict "
"with %d.\n", i);
spinlock_unlock(&bkpoints_lock);
spinlock_unlock(&bkpoint_lock);
return 0;
}
}
 
for (i = 0; i < BKPOINTS_MAX; i++)
255,8 → 259,9
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
symbol = symtab_fmt_name_lookup(
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" :
267,6 → 272,8
return 1;
}
 
#endif
 
/** Initialize debugger */
void debugger_init()
{
274,22 → 281,24
 
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
308,7 → 317,7
 
/* 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++) {
340,9 → 349,10
if (cur->flags & BKPOINT_INPROG)
printf("Warning: breakpoint recursion\n");
if (!(cur->flags & BKPOINT_FUNCCALL))
if (!(cur->flags & BKPOINT_FUNCCALL)) {
printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
get_symtab_entry(istate->epc));
symtab_fmt_name_lookup(istate->epc));
}
 
/* Return first instruction back */
((uint32_t *)cur->address)[0] = cur->instruction;
355,8 → 365,9
}
cur->flags |= BKPOINT_INPROG;
} else {
printf("***Breakpoint %p in %s.\n", fireaddr,
get_symtab_entry(fireaddr));
printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
symtab_fmt_name_lookup(fireaddr));
 
/* Move on to next instruction */
istate->epc += 4;
}
367,19 → 378,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.\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/network/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/network/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
40,22 → 40,21
#include <arch/cp0.h>
#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>
#include <symtab.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 *);
 
/** Initialize TLB
/** Initialize TLB.
*
* Initialize TLB.
* Invalidate all entries and mark wired entries.
*/
void tlb_arch_init(void)
81,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)
{
95,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) {
118,7 → 115,7
page_table_unlock(AS, true);
return;
default:
panic("unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
 
128,13 → 125,14
pte->a = 1;
 
tlb_prepare_entry_hi(&hi, asid, badvaddr);
tlb_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);
 
/*
* 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);
}
153,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)
{
203,7 → 199,7
page_table_unlock(AS, true);
return;
default:
panic("unexpected pfrc (%d)\n", pfrc);
panic("Unexpected pfrc (%d).", pfrc);
}
}
 
217,12 → 213,13
*/
pte->a = 1;
 
tlb_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);
237,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)
{
287,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();
308,12 → 297,13
pte->a = 1;
pte->d = 1;
 
tlb_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);
330,56 → 320,57
 
void tlb_refill_fail(istate_t *istate)
{
char *symbol = "";
char *sym2 = "";
char *symbol, *sym2;
 
char *s = get_symtab_entry(istate->epc);
if (s)
symbol = s;
s = get_symtab_entry(istate->ra);
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);
symbol = symtab_fmt_name_lookup(istate->epc);
sym2 = symtab_fmt_name_lookup(istate->ra);
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);
}
 
 
void tlb_invalid_fail(istate_t *istate)
{
char *symbol = "";
char *symbol;
 
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);
symbol = symtab_fmt_name_lookup(istate->epc);
 
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)
{
char *symbol = "";
char *symbol;
 
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);
symbol = symtab_fmt_name_lookup(istate->epc);
 
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;
398,7 → 389,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.
421,6 → 412,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:
430,18 → 422,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 tlb_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;
480,10 → 473,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);
560,11 → 553,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)
{
588,7 → 582,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/network/kernel/arch/mips32/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
40,22 → 40,22
#include <mm/asid.h>
#include <config.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_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 ZERO_PAGE_VALUE_KSEG1(frame) \
(((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
 
#define MAX_REGIONS 32
#define MAX_REGIONS 32
 
typedef struct {
pfn_t start;
65,7 → 65,6
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.
75,7 → 74,7
*/
static bool frame_available(pfn_t frame)
{
#if MACHINE == msim
#ifdef MACHINE_msim
/* MSIM device (dprinter) */
if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
return false;
84,14 → 83,8
if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#if MACHINE == simics
/* Simics device (serial line) */
if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#if (MACHINE == lgxemul) || (MACHINE == bgxemul)
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
/* gxemul devices */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
0x10000000, MB2SIZE(256)))
218,7 → 211,7
ZERO_PAGE_VALUE = 0xdeadbeef;
if (ZERO_PAGE_VALUE != 0xdeadbeef)
avail = false;
#if (MACHINE == lgxemul) || (MACHINE == bgxemul)
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
else {
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
/branches/network/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/network/kernel/arch/mips32/src/interrupt.c
41,8 → 41,9
#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;
100,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/network/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>
53,39 → 52,52
#include <arch/debugger.h>
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <genarch/drivers/dsrln/dsrlnin.h>
#include <genarch/drivers/dsrln/dsrlnout.h>
#include <genarch/srln/srln.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++;
}
}
 
111,12 → 123,12
*/
cp0_status_write(cp0_status_read() &
~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit));
 
/*
* Mask all interrupts
/*
* Mask all interrupts
*/
cp0_mask_all_int();
debugger_init();
}
 
123,12 → 135,23
void arch_post_mm_init(void)
{
interrupt_init();
console_init(device_assign_devno());
#ifdef CONFIG_FB
/* GXemul framebuffer */
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8);
#endif
sysinfo_set_item_val("machine." STRING(MACHINE), NULL, 1);
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);
#else
#ifdef CONFIG_MIPS_PRN
dsrlnout_init((ioport8_t *) MSIM_KBD_ADDRESS);
#endif /* CONFIG_MIPS_PRN */
#endif /* CONFIG_FB */
}
 
void arch_post_cpu_init(void)
141,8 → 164,31
 
void arch_post_smp_init(void)
{
#ifdef CONFIG_MIPS_KBD
/*
* Initialize the msim/GXemul keyboard port. Then initialize the serial line
* module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts.
*/
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ);
if (kbrdin) {
srln_init(kbrdin);
cp0_unmask_int(MSIM_KBD_IRQ);
}
/*
* 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.inr", NULL, MSIM_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS);
#endif
}
 
void calibrate_delay_loop(void)
{
}
 
void userspace(uspace_arg_t *kernel_uarg)
{
/* EXL = 1, UM = 1, IE = 1 */
153,8 → 199,7
(uintptr_t) kernel_uarg->uspace_uarg,
(uintptr_t) kernel_uarg->uspace_entry);
while (1)
;
while (1);
}
 
/** Perform mips32 specific tasks needed before the new task is run. */
186,10 → 231,22
void arch_reboot(void)
{
___halt();
while (1)
;
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/network/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
/branches/network/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/network/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/network/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/network/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/network/kernel/arch/ia32/include/types.h
57,6 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef struct {
} fncptr_t;
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
/branches/network/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/network/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"
: [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 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,22 → 110,22
static inline void atomic_lock_arch(atomic_t *val)
{
uint32_t tmp;
 
preemption_disable();
asm volatile (
"0:\n"
#ifdef CONFIG_HT
"pause\n" /* Pentium 4's HT love this instruction */
"pause\n" /* Pentium 4's HT love this instruction */
#endif
"mov %0, %1\n"
"testl %1, %1\n"
"mov %[count], %[tmp]\n"
"testl %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
"incl %1\n" /* now use the atomic operation */
"xchgl %0, %1\n"
"testl %1, %1\n"
"incl %[tmp]\n" /* now use the atomic operation */
"xchgl %[count], %[tmp]\n"
"testl %[tmp], %[tmp]\n"
"jnz 0b\n"
: "+m" (val->count), "=&r"(tmp)
: [count] "+m" (val->count), [tmp] "=&r" (tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
/branches/network/kernel/arch/ia32/include/pm.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
35,61 → 35,59
#ifndef KERN_ia32_PM_H_
#define KERN_ia32_PM_H_
 
#define IDT_ITEMS 64
#define GDT_ITEMS 7
#define IDT_ITEMS 64
#define GDT_ITEMS 7
 
#define VESA_INIT_SEGMENT 0x8000
#define NULL_DES 0
#define KTEXT_DES 1
#define KDATA_DES 2
#define UTEXT_DES 3
#define UDATA_DES 4
#define TSS_DES 5
#define TLS_DES 6 /* Pointer to Thread-Local-Storage data */
 
#define NULL_DES 0
#define KTEXT_DES 1
#define KDATA_DES 2
#define UTEXT_DES 3
#define UDATA_DES 4
#define TSS_DES 5
#define TLS_DES 6 /* Pointer to Thread-Local-Storage data */
 
#ifdef CONFIG_FB
 
#define VESA_INIT_SEGMENT 0x8000
#define VESA_INIT_DES 7
#define VESA_INIT_SEGMENT 0x8000
#define VESA_INIT_DES 7
#define KTEXT32_DES KTEXT_DES
 
#undef GDT_ITEMS
#define GDT_ITEMS 8
#define GDT_ITEMS 8
 
#endif /* CONFIG_FB */
 
#define gdtselector(des) ((des) << 3)
 
#define selector(des) ((des) << 3)
#define PL_KERNEL 0
#define PL_USER 3
 
#define PL_KERNEL 0
#define PL_USER 3
#define AR_PRESENT (1 << 7)
#define AR_DATA (2 << 3)
#define AR_CODE (3 << 3)
#define AR_WRITABLE (1 << 1)
#define AR_INTERRUPT (0x0e)
#define AR_TSS (0x09)
 
#define AR_PRESENT (1 << 7)
#define AR_DATA (2 << 3)
#define AR_CODE (3 << 3)
#define AR_WRITABLE (1 << 1)
#define AR_INTERRUPT (0xe)
#define AR_TSS (0x9)
#define DPL_KERNEL (PL_KERNEL << 5)
#define DPL_USER (PL_USER << 5)
 
#define DPL_KERNEL (PL_KERNEL << 5)
#define DPL_USER (PL_USER << 5)
#define TSS_BASIC_SIZE 104
#define TSS_IOMAP_SIZE (16 * 1024 + 1) /* 16K for bitmap + 1 terminating byte for convenience */
 
#define TSS_BASIC_SIZE 104
#define TSS_IOMAP_SIZE (16 * 1024 + 1) /* 16K for bitmap + 1 terminating byte for convenience */
#define IO_PORTS (64 * 1024)
 
#define IO_PORTS (64 * 1024)
 
#ifndef __ASM__
 
#include <arch/types.h>
#include <arch/context.h>
 
struct ptr_16_32 {
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed));
typedef struct ptr_16_32 ptr_16_32_t;
} __attribute__ ((packed)) ptr_16_32_t;
 
struct descriptor {
typedef struct {
unsigned limit_0_15: 16;
unsigned base_0_15: 16;
unsigned base_16_23: 8;
100,19 → 98,17
unsigned special: 1;
unsigned granularity : 1;
unsigned base_24_31: 8;
} __attribute__ ((packed));
typedef struct descriptor descriptor_t;
} __attribute__ ((packed)) descriptor_t;
 
struct idescriptor {
typedef struct {
unsigned offset_0_15: 16;
unsigned selector: 16;
unsigned unused: 8;
unsigned access: 8;
unsigned offset_16_31: 16;
} __attribute__ ((packed));
typedef struct idescriptor idescriptor_t;
} __attribute__ ((packed)) idescriptor_t;
 
struct tss {
typedef struct {
uint16_t link;
unsigned : 16;
uint32_t esp0;
152,13 → 148,12
unsigned : 16;
uint16_t iomap_base;
uint8_t iomap[TSS_IOMAP_SIZE];
} __attribute__ ((packed));
typedef struct tss tss_t;
} __attribute__ ((packed)) tss_t;
 
extern ptr_16_32_t gdtr;
extern ptr_16_32_t bootstrap_gdtr;
extern ptr_16_32_t protected_ap_gdtr;
extern struct tss *tss_p;
extern tss_t *tss_p;
 
extern descriptor_t gdt[];
 
/branches/network/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/network/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/network/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/network/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;
55,11 → 56,16
 
/** Halt CPU
*
* Halt the current CPU until interrupt event.
* Halt the current CPU.
*
*/
static inline void cpu_halt(void)
{
asm volatile ("hlt\n");
asm volatile (
"0:\n"
" hlt\n"
" jmp 0b\n"
);
}
 
static inline void cpu_sleep(void)
68,16 → 74,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 → 116,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 → 132,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 → 148,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 → 164,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 → 185,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 → 206,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 → 227,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 → 249,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 → 270,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 → 284,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 → 335,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 → 347,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 → 359,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/network/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/network/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/network/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/network/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,30 → 58,30
);
}
 
#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
 
/*
90,8 → 90,8
* 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()
#define smc_coherence(a) write_barrier()
#define smc_coherence_block(a, l) write_barrier()
 
#endif
 
/branches/network/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;
struct tss *tss;
unsigned int vendor;
unsigned int family;
unsigned int model;
unsigned int stepping;
tss_t *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/network/kernel/arch/ia32/include/drivers/i8042.h
File deleted
/branches/network/kernel/arch/ia32/include/drivers/ega.h
File deleted
/branches/network/kernel/arch/ia32/include/drivers/i8254.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
/branches/network/kernel/arch/ia32/include/drivers/vesa.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
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/network/kernel/arch/ia32/include/drivers/i8259.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
38,13 → 38,13
#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)
#define PIC_NEEDICW4 (1 << 0)
#define PIC_ICW1 (1 << 4)
 
extern void i8259_init(void);
extern void pic_enable_irqs(uint16_t irqmask);
/branches/network/kernel/arch/ia32/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-i386
BFD_ARCH = i386
BFD = binary
39,7 → 35,7
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686
 
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__
DEFS += -D__32_BITS__
 
CMN1 = -m32
GCC_CFLAGS += $(CMN1)
49,115 → 45,61
## Accepted CPUs
#
 
ifeq ($(MACHINE),athlon-xp)
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-3dnow
ifeq ($(PROCESSOR),athlon_xp)
CMN2 = -march=athlon-xp
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += -xarch=ssea
DEFS += -DCONFIG_FENCES_P3
CONFIG_SMP = n
CONFIG_HT = n
endif
ifeq ($(MACHINE),athlon-mp)
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-3dnow
ifeq ($(PROCESSOR),athlon_mp)
CMN2 = -march=athlon-mp
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += xarch=ssea
DEFS += -DCONFIG_FENCES_P3
CONFIG_HT = n
endif
ifeq ($(MACHINE),pentium3)
FPU_NO_CFLAGS = -mno-mmx -mno-sse
ifeq ($(PROCESSOR),pentium3)
CMN2 = -march=pentium3
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += -xarch=sse
DEFS += -DCONFIG_FENCES_P3
CONFIG_HT = n
endif
ifeq ($(MACHINE),core)
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3
ifeq ($(PROCESSOR),pentium4)
CMN2 = -march=pentium4
SUNCC_CFLAGS += -xarch=sse2
endif
ifeq ($(PROCESSOR),core)
CMN2 = -march=prescott
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
SUNCC_CFLAGS += -xarch=sse3
DEFS += -DCONFIG_FENCES_P4
endif
ifeq ($(MACHINE),pentium4)
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2
GCC_CFLAGS += -march=pentium4
ICC_CFLAGS += -march=pentium4
SUNCC_CFLAGS += -xarch=sse2
DEFS += -DCONFIG_FENCES_P4
endif
 
## Own configuration directives
#
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
 
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
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.
#
 
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/network/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>
 
60,12 → 65,30
#include <proc/thread.h>
#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();
87,13 → 110,17
/* hard clock */
i8254_init();
 
#ifdef CONFIG_FB
if (vesa_present())
if (vesa_present())
vesa_init();
else
#endif
ega_init(); /* video */
#ifdef CONFIG_EGA
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
#else
{}
#endif
/* Enable debugger */
debugger_init();
123,10 → 150,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);
#ifdef CONFIG_PC_KBD
/*
* Initialize the i8042 controller. Then initialize the keyboard
* module and connect it to i8042. Enable keyboard interrupts.
*/
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
if (kbrdin) {
kbrd_init(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.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);
#endif
}
 
void calibrate_delay_loop(void)
159,15 → 204,38
*/
void arch_grab_console(void)
{
i8042_grab();
#ifdef CONFIG_FB
if (vesa_present())
vesa_redraw();
else
#endif
#ifdef CONFIG_EGA
ega_redraw();
#else
{}
#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/network/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/network/kernel/arch/ia32/src/asm.S
147,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
228,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
257,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/network/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/network/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, gdtselector(KTEXT_DES));
/* set kernel mode entry point */
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
}
 
/** @}
*/
/branches/network/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(t, sizeof(struct tss), 0);
memsetb(t, sizeof(tss_t), 0);
}
 
/*
127,7 → 127,7
d = &idt[i];
 
d->unused = 0;
d->selector = selector(KTEXT_DES);
d->selector = gdtselector(KTEXT_DES);
 
d->access = AR_PRESENT | AR_INTERRUPT; /* masking interrupt */
 
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);
214,7 → 214,7
* As of this moment, the current CPU has its own GDT pointing
* to its own TSS. We just need to load the TR register.
*/
tr_load(selector(TSS_DES));
tr_load(gdtselector(TSS_DES));
clean_IOPL_NT_flags(); /* Disable I/O on nonprivileged levels and clear NT flag. */
clean_AM_flag(); /* Disable alignment check */
/branches/network/kernel/arch/ia32/src/smp/smp.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
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();
131,8 → 131,8
uint8_t apic = l_apic_id();
 
for (i = 0; i < ops->cpu_count(); i++) {
struct descriptor *gdt_new;
descriptor_t *gdt_new;
/*
* Skip processors marked unusable.
*/
154,14 → 154,19
/*
* Prepare new GDT for CPU in question.
*/
gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);
/* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
* it needs to be replaced by a generic fuctionality of
* the memory subsystem
*/
gdt_new = (descriptor_t *) malloc(GDT_ITEMS *
sizeof(descriptor_t), 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(&gdt_new[TSS_DES], sizeof(struct descriptor), 0);
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor);
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(descriptor_t));
memsetb(&gdt_new[TSS_DES], sizeof(descriptor_t), 0);
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(descriptor_t);
protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new);
gdtr.base = (uintptr_t) gdt_new;
 
/branches/network/kernel/arch/ia32/src/smp/apic.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
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/network/kernel/arch/ia32/src/ddi/ddi.c
156,7 → 156,7
* type must be changed to describe inactive TSS.
*/
gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
tr_load(selector(TSS_DES));
tr_load(gdtselector(TSS_DES));
/*
* Update the generation count so that faults caused by
/branches/network/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/network/kernel/arch/ia32/src/boot/vesa_ret.inc
0,0 → 1,12
.code32
vesa_init_protected:
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ss
movl $START_STACK, %esp # initialize stack pointer
jmpl $gdtselector(KTEXT_DES), $vesa_meeting_point
/branches/network/kernel/arch/ia32/src/boot/boot.S
42,178 → 42,63
multiboot_header:
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long multiboot_header
.long unmapped_ktext_start
.long 0
.long 0
.long multiboot_image_start
 
multiboot_image_start:
cld
movl $START_STACK, %esp # initialize stack pointer
lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
 
movw $selector(KDATA_DES), %cx
movl $START_STACK, %esp # initialize stack pointer
lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ds # kernel data + stack
movw %cx, %ss
jmpl $selector(KTEXT_DES), $multiboot_meeting_point
jmpl $gdtselector(KTEXT_DES), $multiboot_meeting_point
multiboot_meeting_point:
movl %eax, grub_eax # save parameters from GRUB
movl %eax, grub_eax # save parameters from GRUB
movl %ebx, grub_ebx
xorl %eax, %eax
cpuid
cmp $0x0, %eax # any function > 0?
xorl %eax, %eax
cpuid
cmp $0x0, %eax # any function > 0?
jbe pse_unsupported
movl $0x1, %eax # Basic function code 1
movl $0x1, %eax # basic function code 1
cpuid
bt $3, %edx # Test if PSE is supported
bt $3, %edx # test if PSE is supported
jc pse_supported
 
pse_unsupported:
movl $pse_msg, %esi
jmp error_halt
pse_supported:
#ifdef CONFIG_FB
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
rep movsb
 
mov $VESA_INIT_SEGMENT << 4, %edi
jmpl *%edi
#include "vesa_prot.inc"
 
# map kernel and turn paging on
call map_kernel
vesa_meeting_point:
# call arch_pre_main(grub_eax, grub_ebx)
pushl grub_ebx
pushl grub_eax
call arch_pre_main
mov %esi, KA2PA(vesa_ph_addr)
mov %di, KA2PA(vesa_height)
shr $16, %edi
mov %di, KA2PA(vesa_width)
mov %bx, KA2PA(vesa_scanline)
shr $16, %ebx
mov %bx, KA2PA(vesa_bpp)
#endif
call main_bsp
call map_kernel # map kernel and turn paging on
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:
#ifdef CONFIG_SMP
# 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
 
# not reached
cli
hlt
hlt0:
hlt
jmp hlt0
 
.global map_kernel
map_kernel:
222,8 → 107,8
# For simplicity, we map the entire 4G space.
#
movl %cr4, %ecx
orl $(1 << 4), %ecx # turn PSE on
andl $(~(1 << 5)), %ecx # turn PAE off
orl $(1 << 4), %ecx # turn PSE on
andl $(~(1 << 5)), %ecx # turn PAE off
movl %ecx, %cr4
movl $(page_directory + 0), %esi
230,30 → 115,31
movl $(page_directory + 2048), %edi
xorl %ecx, %ecx
xorl %ebx, %ebx
0:
movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
orl %ebx, %eax
movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
addl $(4 * 1024 * 1024), %ebx
 
incl %ecx
cmpl $512, %ecx
jl 0b
 
floop:
movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
orl %ebx, %eax
movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
addl $(4 * 1024 * 1024), %ebx
incl %ecx
cmpl $512, %ecx
jl floop
movl %esi, %cr3
movl %cr0, %ebx
orl $(1 << 31), %ebx # turn paging on
orl $(1 << 31), %ebx # turn paging on
movl %ebx, %cr0
ret
 
# Print string from %esi to EGA display (in red) and halt
error_halt:
movl $0xb8000, %edi # base of EGA text mode memory
movl $0xb8000, %edi # base of EGA text mode memory
xorl %eax, %eax
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
261,7 → 147,7
inb %dx, %al
shl $8, %ax
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
270,7 → 156,9
cmp $1920, %ax
jbe cursor_ok
movw $1920, %ax # sanity check for the cursor on the last line
movw $1920, %ax # sanity check for the cursor on the last line
cursor_ok:
movw %ax, %bx
277,7 → 165,7
shl $1, %eax
addl %eax, %edi
movw $0x0c00, %ax # black background, light red foreground
movw $0x0c00, %ax # black background, light red foreground
ploop:
lodsb
284,11 → 172,11
cmp $0, %al
je ploop_end
stosw
inc %bx
inc %bx
jmp ploop
ploop_end:
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
296,7 → 184,7
movb %bh, %al
outb %al, %dx
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
303,240 → 191,14
movw $0x3d5, %dx
movb %bl, %al
outb %al, %dx
cli
hlt
hlt1:
hlt
jmp hlt1
 
#ifdef CONFIG_FB
vesa_init:
jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init
.code16
vesa_init_real:
mov %cr0, %eax
and $~1, %eax
mov %eax, %cr0
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
vesa_init_real2:
mov $VESA_INIT_SEGMENT, %bx
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ds
mov %bx, %ss
movl %esp, %eax
movl $0x0000fffc, %esp
movl $0x0000fffc, %ebp
pushl %eax
#define VESA_INFO_SIZE 1024
#include "vesa_real.inc"
 
#define VESA_MODE_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#define VESA_MODE_PHADDR_OFFSET 40
 
#define VESA_END_OF_MODES 0xffff
 
#define VESA_OK 0x4f
 
#define VESA_GET_INFO 0x4f00
#define VESA_GET_MODE_INFO 0x4f01
#define VESA_SET_MODE 0x4f02
#define VESA_SET_PALETTE 0x4f09
 
#if CONFIG_VESA_BPP == 24
#define CONFIG_VESA_BPP_VARIANT 32
#endif
 
mov $VESA_GET_INFO, %ax
mov $e_vesa_init - vesa_init, %di
push %di
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
mov %si, %gs
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
add $VESA_INFO_SIZE, %di
 
1:# Try next mode
mov %gs:(%si), %cx
cmp $VESA_END_OF_MODES, %cx
jz 0f
inc %si
inc %si
push %cx
push %di
push %si
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %si
pop %di
pop %cx
cmp $VESA_OK, %al
jnz 0f
mov $CONFIG_VESA_WIDTH, %ax
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_HEIGHT, %ax
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_BPP, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
 
#ifdef CONFIG_VESA_BPP_VARIANT
jz 2f
mov $CONFIG_VESA_BPP_VARIANT, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
#endif
jnz 1b
 
2:
mov %cx, %bx
or $0xc000, %bx
push %di
mov $VESA_SET_MODE, %ax
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
 
#if CONFIG_VESA_BPP == 8
# Set 3:2:3 VGA palette
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # Test if VGA compatible registers are present
jnc vga_compat
# Try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
jmp vga_not_compat
vga_compat:
# Try VGA registers to set palette
movw $0x3c6, %dx # Set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # First index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # Data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
#endif
mov VESA_MODE_PHADDR_OFFSET(%di), %esi
mov VESA_MODE_WIDTH_OFFSET(%di), %ax
shl $16, %eax
mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
mov VESA_MODE_BPP_OFFSET(%di), %bl
xor %bh, %bh
shl $16, %ebx
mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
mov %eax, %edi
8:
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
jmp 9f
9:
ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
 
0:# No prefered mode found
mov $0x111, %cx
push %di
push %cx
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %cx
pop %di
cmp $VESA_OK, %al
jnz 1f
jz 2b # Force relative jump
1:
mov $0x0003, %ax
int $0x10
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
xor %ax, %ax
jz 8b # Force relative jump
 
vga323:
#include "vga323.pal"
 
.code32
vesa_init_protect:
movw $selector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ss
movl $START_STACK, %esp # initialize stack pointer
 
jmpl $selector(KTEXT_DES), $vesa_meeting_point
 
.align 4
e_vesa_init:
#endif
 
.section K_DATA_START, "aw", @progbits
 
.align 4096
/branches/network/kernel/arch/ia32/src/boot/vesa_real.inc
0,0 → 1,373
#ifdef CONFIG_FB
 
#include <macros.h>
 
#define VESA_INFO_SIZE 1024
 
#define VESA_MODE_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#define VESA_MODE_RED_MASK_OFFSET 31
#define VESA_MODE_RED_POS_OFFSET 32
#define VESA_MODE_GREEN_MASK_OFFSET 33
#define VESA_MODE_GREEN_POS_OFFSET 34
#define VESA_MODE_BLUE_MASK_OFFSET 35
#define VESA_MODE_BLUE_POS_OFFSET 36
#define VESA_MODE_PHADDR_OFFSET 40
 
#define VESA_END_OF_MODES 0xffff
 
#define VESA_OK 0x4f
 
#define VESA_GET_INFO 0x4f00
#define VESA_GET_MODE_INFO 0x4f01
#define VESA_SET_MODE 0x4f02
#define VESA_SET_PALETTE 0x4f09
 
.code32
vesa_init:
jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
.code16
vesa_init_real:
mov %cr0, %eax
and $~1, %eax
mov %eax, %cr0
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
vesa_init_real2:
mov $VESA_INIT_SEGMENT, %bx
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ds
mov %bx, %ss
movl %esp, %eax
movl $0x0000fffc, %esp
movl $0x0000fffc, %ebp
pushl %eax
# parse default mode string
mov $default_mode - vesa_init, %di
xor %eax, %eax
xor %ebx, %ebx
mov $8, %ecx
parse_width:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_width_done
cmp $'9', %al
ja parse_width_done
sub $'0', %al
# multiply default_width by 10 and add digit
mov default_width - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_width - vesa_init
inc %di
loop parse_width
parse_width_done:
mov (%di), %al
cmp $0, %al
jz parse_done
inc %di
mov $8, %ecx
parse_height:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_height_done
cmp $'9', %al
ja parse_height_done
sub $'0', %al
# multiply default_height by 10 and add digit
mov default_height - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_height - vesa_init
inc %di
loop parse_height
parse_height_done:
mov (%di), %al
cmp $0, %al
jz parse_done
inc %di
mov $4, %ecx
parse_bpp:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_bpp_done
cmp $'9', %al
ja parse_bpp_done
sub $'0', %al
# multiply default_bpp by 10 and add digit
mov default_bpp - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_bpp - vesa_init
inc %di
loop parse_bpp
parse_bpp_done:
parse_done:
mov $VESA_GET_INFO, %ax
mov $e_vesa_init - vesa_init, %di
push %di
int $0x10
pop %di
cmp $VESA_OK, %al
jnz no_mode
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
mov %si, %gs
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
add $VESA_INFO_SIZE, %di
next_mode:
# try next mode
mov %gs:(%si), %cx
cmp $VESA_END_OF_MODES, %cx
je no_mode
inc %si
inc %si
push %cx
push %di
push %si
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %si
pop %di
pop %cx
cmp $VESA_OK, %al
jne no_mode
# check for proper attributes (supported, color, graphics, linear framebuffer)
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
and $0x99, %ax
cmp $0x99, %ax
jne next_mode
# check for proper resolution
mov default_width - vesa_init, %ax
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
jne next_mode
mov default_height - vesa_init, %ax
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
jne next_mode
# check for proper bpp
mov default_bpp - vesa_init, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
je set_mode
mov $24, %al
cmp default_bpp - vesa_init, %al
jne next_mode
# for 24 bpp modes accept also 32 bit bpp
mov $32, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
jne next_mode
set_mode:
mov %cx, %bx
or $0xc000, %bx
push %di
mov $VESA_SET_MODE, %ax
int $0x10
pop %di
cmp $VESA_OK, %al
jnz no_mode
# set 3:2:3 VGA palette
mov VESA_MODE_BPP_OFFSET(%di), %al
cmp $8, %al
jnz vga_not_set
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # test if VGA compatible registers are present
jnc vga_compat
# try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
cmp $0x00, %ah
je vga_not_compat
vga_compat:
# try VGA registers to set palette
movw $0x3c6, %dx # set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # first index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
vga_not_set:
# store mode parameters
# eax = bpp[8] scanline[16]
# ebx = width[16] height[16]
# edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8]
# esi = blue_mask[8] blue_pos[8]
# edi = linear frame buffer
mov VESA_MODE_BPP_OFFSET(%di), %al
xor %ah, %ah
shl $16, %eax
mov VESA_MODE_SCANLINE_OFFSET(%di), %ax
mov VESA_MODE_WIDTH_OFFSET(%di), %bx
shl $16, %ebx
mov VESA_MODE_HEIGHT_OFFSET(%di), %bx
mov VESA_MODE_BLUE_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_BLUE_POS_OFFSET(%di), %dl
mov %edx, %esi
mov VESA_MODE_RED_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_RED_POS_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_GREEN_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_GREEN_POS_OFFSET(%di), %dl
mov VESA_MODE_PHADDR_OFFSET(%di), %edi
vesa_leave_real:
mov %cr0, %ecx
or $1, %ecx
mov %ecx, %cr0
jmp vesa_leave_real2
vesa_leave_real2:
ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protected - vesa_init + VESA_INIT_SEGMENT << 4)
no_mode:
# no prefered mode found
mov $0x111, %cx
push %di
push %cx
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %cx
pop %di
cmp $VESA_OK, %al
jnz text_mode
jz set_mode # force relative jump
text_mode:
# reset to EGA text mode (because of problems with VESA)
mov $0x0003, %ax
int $0x10
mov $0xffffffff, %edi
xor %ax, %ax
jz vesa_leave_real # force relative jump
 
vga323:
#include "vga323.pal"
 
default_width:
.word 0
 
default_height:
.word 0
 
default_bpp:
.byte 0
 
default_mode:
.ascii STRING(CONFIG_VESA_MODE)
.ascii "-"
.asciz STRING(CONFIG_VESA_BPP)
.fill 24
 
#include "vesa_ret.inc"
 
.align 4
e_vesa_init:
#endif
/branches/network/kernel/arch/ia32/src/boot/vesa_prot.inc
0,0 → 1,107
#ifdef CONFIG_FB
 
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002
#define MBINFO_BIT_CMDLINE 2
#define MBINFO_OFFSET_CMDLINE 16
 
# copy real mode VESA initialization code
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
rep movsb
# check for GRUB command line
mov grub_eax, %eax
cmp $MULTIBOOT_LOADER_MAGIC, %eax
jne no_cmdline
mov grub_ebx, %ebx
mov (%ebx), %eax
bt $MBINFO_BIT_CMDLINE, %eax
jnc no_cmdline
# skip the kernel path in command line
mov MBINFO_OFFSET_CMDLINE(%ebx), %esi
skip_loop:
lodsb
cmp $0, %al
je no_cmdline
cmp $' ', %al
je skip_loop_done
jmp skip_loop
skip_loop_done:
space_loop:
mov (%esi), %al
cmp $0, %al
je no_cmdline
cmp $' ', %al
jne space_loop_done
inc %esi
jmp space_loop
space_loop_done:
# copy at most 23 characters from command line
mov $VESA_INIT_SEGMENT << 4, %edi
add $default_mode - vesa_init, %edi
mov $23, %ecx
cmd_loop:
lodsb
stosb
cmp $0, %al
je cmd_loop_done
loop cmd_loop
cmd_loop_done:
# zero termination
xor %eax, %eax
stosb
no_cmdline:
# jump to the real mode
mov $VESA_INIT_SEGMENT << 4, %edi
jmpl *%edi
vesa_meeting_point:
# returned back to protected mode
mov %ax, KA2PA(vesa_scanline)
shr $16, %eax
mov %ax, KA2PA(vesa_bpp)
mov %bx, KA2PA(vesa_height)
shr $16, %ebx
mov %bx, KA2PA(vesa_width)
mov %dl, KA2PA(vesa_green_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_green_mask)
shr $8, %edx
mov %dl, KA2PA(vesa_red_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_red_mask)
mov %esi, %edx
mov %dl, KA2PA(vesa_blue_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_blue_mask)
mov %edi, KA2PA(vesa_ph_addr)
#endif
/branches/network/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];
CPU->arch.tss->ss0 = selector(KDATA_DES);
 
/* 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 = gdtselector(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/network/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/network/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/network/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/network/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,35 → 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"
 
"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" (gdtselector(UDATA_DES) | PL_USER),
[stack_size] "r" ((uint8_t *) 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),
[tls_des] "r" (gdtselector(TLS_DES))
: "eax");
/* Unreachable */
for(;;)
;
while (1);
}
 
/** @}
/branches/network/kernel/arch/ia32/src/interrupt.c
44,7 → 44,6
#include <mm/tlb.h>
#include <mm/as.h>
#include <arch.h>
#include <symtab.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <synch/spinlock.h>
52,6 → 51,7
#include <ipc/sysipc.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <symtab.h>
 
/*
* Interrupt and exception dispatching.
63,10 → 63,9
 
void decode_istate(istate_t *istate)
{
char *symbol = get_symtab_entry(istate->eip);
char *symbol;
 
if (!symbol)
symbol = "";
symbol = symtab_fmt_name_lookup(istate->eip);
 
if (CPU)
printf("----------------EXCEPTION OCCURED (cpu%u)----------------\n", CPU->id);
77,9 → 76,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 → 85,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 → 118,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 → 137,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 → 153,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 → 187,7
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
233,7 → 229,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 → 237,7
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
panic("No disable_irqs_function.");
}
 
/** @}
/branches/network/kernel/arch/ia32/src/drivers/ega.c
File deleted
/branches/network/kernel/arch/ia32/src/drivers/vesa.c
56,12 → 56,20
uint16_t vesa_bpp;
uint16_t vesa_scanline;
 
uint8_t vesa_red_mask;
uint8_t vesa_red_pos;
 
uint8_t vesa_green_mask;
uint8_t vesa_green_pos;
 
uint8_t vesa_blue_mask;
uint8_t vesa_blue_pos;
 
int vesa_present(void)
{
if (vesa_width != 0xffff)
if ((vesa_width != 0xffff) && (vesa_height != 0xffff))
return true;
if (vesa_height != 0xffff)
return true;
return false;
}
 
74,7 → 82,12
visual = VISUAL_INDIRECT_8;
break;
case 16:
visual = VISUAL_RGB_5_6_5;
if ((vesa_red_mask == 5) && (vesa_red_pos == 10)
&& (vesa_green_mask == 5) && (vesa_green_pos == 5)
&& (vesa_blue_mask == 5) && (vesa_blue_pos == 0))
visual = VISUAL_RGB_5_5_5;
else
visual = VISUAL_RGB_5_6_5;
break;
case 24:
visual = VISUAL_RGB_8_8_8;
83,12 → 96,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/network/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/network/kernel/arch/ia32/src/drivers/i8254.c
26,12 → 26,12
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief i8254 chip driver.
* @brief i8254 chip driver.
*
* Low level time functions.
*/
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/network/tools/mkfat.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/branches/network/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/network/tools/mktmpfs.py
34,6 → 34,8
import os
import xstruct
 
exclude_names = set(['.svn'])
 
HEADER = """little:
char tag[5] /* 'TMPFS' */
"""
70,7 → 72,7
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon)):
if (os.path.isfile(canon) and (not name in exclude_names)):
size = os.path.getsize(canon)
dentry = xstruct.create(DENTRY_FILE % len(name))
89,7 → 91,7
rd += len(data)
inf.close()
if (os.path.isdir(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)
/branches/network/tools/mkfat.py
34,7 → 34,275
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 */
62,6 → 330,14
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>"
76,27 → 352,59
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 = 512
boot_sector.cluster = 8 # 4096 bytes per cluster
boot_sector.reserved = 1
boot_sector.fats = 2
boot_sector.rootdir = 224 # FIXME: root directory should be sector aligned
boot_sector.sectors = 0 # FIXME
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 = 0 # FIXME
boot_sector.track_sectors = 0 # FIXME
boot_sector.heads = 0 # FIXME
boot_sector.fat_sectors = fat_size / sector_size
boot_sector.track_sectors = 63
boot_sector.heads = 6
boot_sector.hidden = 0
boot_sector.sectors_big = 0 # FIXME
if (sectors > 65535):
boot_sector.sectors_big = sectors
else:
boot_sector.sectors_big = 0
boot_sector.drive = 0
boot_sector.drive = 0x80
boot_sector.extboot_signature = 0x29
boot_sector.serial = random.randint(0, 0xFFFFFFFF)
boot_sector.serial = random.randint(0, 0x7fffffff)
boot_sector.label = "HELENOS"
boot_sector.fstype = "FAT16 "
boot_sector.boot_signature = [0x55, 0xAA]
103,6 → 411,39
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__':
/branches/network/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,432
# 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'
PRECONF = 'defaults'
 
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 == "n") 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
def sorted_dir(root):
list = os.listdir(root)
list.sort()
return list
 
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 read_preconfigured(root, fname, screen, defaults):
options = []
opt2path = {}
cnt = 0
# Look for profiles
for name in sorted_dir(root):
path = os.path.join(root, name)
canon = os.path.join(path, fname)
if ((os.path.isdir(path)) and (os.path.exists(canon)) and (os.path.isfile(canon))):
subprofile = False
# Look for subprofiles
for subname in sorted_dir(path):
subpath = os.path.join(path, subname)
subcanon = os.path.join(subpath, fname)
if ((os.path.isdir(subpath)) and (os.path.exists(subcanon)) and (os.path.isfile(subcanon))):
subprofile = True
options.append("%s (%s)" % (name, subname))
opt2path[cnt] = (canon, subcanon)
cnt += 1
if (not subprofile):
options.append(name)
opt2path[cnt] = (canon, None)
cnt += 1
(button, value) = xtui.choice_window(screen, 'Load preconfigured defaults', 'Choose configuration profile', options, None)
if (button == 'cancel'):
return None
read_defaults(opt2path[value][0], defaults)
if (opt2path[value][1] != None):
read_defaults(opt2path[value][1], defaults)
 
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
position = 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 = {}
cnt = 1
options.append(" --- Load preconfigured defaults ... ")
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 == 'n'):
defaults[varname] = 'n'
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
if (position >= options):
position = None
(button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position)
if (button == 'cancel'):
return 'Configuration canceled'
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 (value == 0):
read_preconfigured(PRECONF, MAKEFILE, screen, defaults)
position = 1
continue
position = None
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 (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/network/uspace/uspace.config
File deleted
/branches/network/uspace/app/bdsh/input.c
33,6 → 33,7
#include <stdlib.h>
#include <string.h>
#include <io/stream.h>
#include <console.h>
 
#include "config.h"
#include "util.h"
41,21 → 42,8
#include "errors.h"
#include "exec.h"
 
extern volatile unsigned int cli_interactive;
 
/* Not exposed in input.h */
static void cli_restricted(char *);
static void read_line(char *, int);
 
/* More than a macro than anything */
static void cli_restricted(char *cmd)
{
printf("%s is not available in %s mode\n", cmd,
cli_interactive ? "interactive" : "non-interactive");
 
return;
}
 
/* 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 */
69,14 → 57,11
if (NULL == usr->line)
return CL_EFAIL;
 
tmp = cli_strdup(usr->line);
tmp = strdup(usr->line);
 
/* Break up what the user typed, space delimited */
 
/* TODO: Protect things in quotes / ticks, expand wildcards */
cmd[n] = cli_strtok(tmp, " ");
cmd[n] = strtok(tmp, " ");
while (cmd[n] && n < WORD_MAX) {
cmd[++n] = cli_strtok(NULL, " ");
cmd[++n] = strtok(NULL, " ");
}
 
/* We have rubbish */
85,39 → 70,19
goto finit;
}
 
/* Its a builtin command */
/* Its a builtin command ? */
if ((i = (is_builtin(cmd[0]))) > -1) {
/* Its not available in this mode, see what try_exec() thinks */
if (builtin_is_restricted(i)) {
rc = try_exec(cmd[0], cmd);
if (rc)
/* No external matching it could be found, tell the
* user that the command does exist, but is not
* available in this mode. */
cli_restricted(cmd[0]);
goto finit;
}
/* Its a builtin, its available, run it */
rc = run_builtin(i, cmd, usr);
goto finit;
/* We repeat the same dance for modules */
/* Its a module ? */
} else if ((i = (is_module(cmd[0]))) > -1) {
if (module_is_restricted(i)) {
rc = try_exec(cmd[0], cmd);
if (rc)
cli_restricted(cmd[0]);
goto finit;
}
rc = run_module(i, cmd);
goto finit;
} else {
/* Its not a module or builtin, restricted or otherwise.
* See what try_exec() thinks of it and just pass its return
* value back to the caller */
rc = try_exec(cmd[0], cmd);
goto finit;
}
 
/* See what try_exec thinks of it */
rc = try_exec(cmd[0], cmd);
 
finit:
if (NULL != usr->line) {
free(usr->line);
129,7 → 94,6
return rc;
}
 
/* Borrowed from Jiri Svoboda's 'cli' uspace app */
static void read_line(char *buffer, int n)
{
char c;
149,8 → 113,10
}
continue;
}
putchar(c);
buffer[chars++] = c;
if (c >= ' ') {
putchar(c);
buffer[chars++] = c;
}
}
putchar('\n');
buffer[chars] = '\0';
164,13 → 130,16
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 = cli_strdup(line);
usr->line = strdup(line);
 
return;
}
/branches/network/uspace/app/bdsh/AUTHORS
8,9 → 8,6
 
* Based on the HelenOS testing sub-system written by Martin Decky
 
* cli_strtok() and cli_strtok_r() (util.c) were adapted from the FreeBSD
strtok() and strtok_r() functions written by Wes Peters.
 
* read_line() (input.c) was written by Jiri Svoboda
 
Individual author copyrights are listed in the headers of each file.
/branches/network/uspace/app/bdsh/cmds/mknewcmd
46,8 → 46,6
-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)
-r, --restrict Restriction level (interactive, non-interactive, both)
(def: module is both, builtin is interactive only)
-t, --type Type of command (module or builtin) (def: module)
-H, --help This help summary
-V, --version Print $PROGNAME version and exit normally
67,8 → 65,7
$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' and available in either interactive or noninteractive
mode.
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.
97,7 → 94,6
"${CMDDESC}",
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
107,7 → 103,6
NULL,
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
120,8 → 115,8
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Entry points for the ${CMDNAME} command */
extern int * ${CMDENTRY}(char **);
extern void * ${HELPENTRY}(unsigned int);
extern int ${CMDENTRY}(char **);
extern void ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
167,25 → 162,25
#include "${CMDNAME}.h"
#include "cmds.h"
 
static char *cmdname = "${CMDNAME}";
static const char *cmdname = "${CMDNAME}";
 
/* Dispays help for ${CMDNAME} in various levels */
void * ${HELPENTRY}(unsigned int level)
void ${HELPENTRY}(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return CMD_VOID;
return;
}
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments */
int * ${CMDENTRY}(char **argv)
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)
int ${CMDENTRY}(char **argv, cliuser_t *usr)
EOF
cat << EOF >> ${OUTDIR}/${CMDNAME}.c
{
234,8 → 229,8
# We need at least one
[ $# = 0 ] && usage && exit 1;
 
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \
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"
}
269,11 → 264,6
shift 2
continue
;;
-r | --restrict)
CMDRESTRICT="$2"
shift 2
continue
;;
-t | --type)
CMDTYPE="$2"
shift 2
305,30 → 295,7
[ -n "$CMDTYPE" ] || CMDTYPE="module"
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}"
 
# Builtins typically only need to be available in interactive mode,
# set the default accordingly.
[ -n "$CMDRESTRICT" ] || {
[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both"
[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive"
}
 
# Set the restriction level as the structure expects to see it
case "$CMDRESTRICT" in
0 | both)
CMDRESTRICT="0"
;;
1 | non-interactive)
CMDRESTRICT="1"
;;
-1 | interactive)
CMDRESTRICT="-1"
;;
*)
usage
exit 1
;;
esac
 
# Do a little sanity
[ -d $OUTDIR ] && {
echo "$OUTDIR already exists, remove it to proceed."
/branches/network/uspace/app/bdsh/cmds/mod_cmds.c
53,26 → 53,6
 
extern volatile unsigned int cli_interactive;
 
int module_is_restricted(int pos)
{
/* Restriction Levels:
* -1 -> Available only in interactive mode
* 0 -> Available in any mode
* 1 -> Available only in non-interactive mode */
 
module_t *mod = modules;
mod += pos;
/* We're interactive, and the module is OK to run */
if (cli_interactive && mod->restricted <= 0)
return 0;
/* We're not interactive, and the module is OK to run */
if (!cli_interactive && mod->restricted >= 0)
return 0;
 
/* Anything else is just a big fat no :) */
return 1;
}
 
/* 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)
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch.c
37,6 → 37,7
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
48,7 → 49,7
static char *cmdname = "touch";
 
/* Dispays help for touch in various levels */
void * help_cmd_touch(unsigned int level)
void help_cmd_touch(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' updates access times for files\n", cmdname);
58,11 → 59,11
"created\n", cmdname);
}
 
return CMD_VOID;
return;
}
 
/* Main entry point for touch, accepts an array of arguments */
int * cmd_touch(char **argv)
int cmd_touch(char **argv)
{
unsigned int argc, i = 0, ret = 0;
int fd;
79,7 → 80,7
}
 
for (i = 1; i < argc; i ++) {
buff = cli_strdup(argv[i]);
buff = strdup(argv[i]);
dirp = opendir(buff);
if (dirp) {
cli_error(CL_ENOTSUP, "%s is a directory", buff);
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch_def.h
3,6 → 3,5
"Create files or update access times",
&cmd_touch,
&help_cmd_touch,
0
},
 
/branches/network/uspace/app/bdsh/cmds/modules/touch/entry.h
2,8 → 2,8
#define TOUCH_ENTRY_H
 
/* Entry points for the touch command */
extern int * cmd_touch(char **);
extern void * help_cmd_touch(unsigned int);
extern int cmd_touch(char **);
extern void help_cmd_touch(unsigned int);
 
#endif /* TOUCH_ENTRY_H */
 
/branches/network/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/network/uspace/app/bdsh/cmds/modules/cp/cp_def.h
0,0 → 1,7
{
"cp",
"Copy files and directories",
&cmd_cp,
&help_cmd_cp,
},
 
/branches/network/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/network/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/network/uspace/app/bdsh/cmds/modules/mkdir/entry.h
2,8 → 2,8
#define MKDIR_ENTRY_H
 
/* Entry points for the mkdir command */
extern int * cmd_mkdir(char **);
extern void * help_cmd_mkdir(unsigned int);
extern int cmd_mkdir(char **);
extern void help_cmd_mkdir(unsigned int);
 
#endif /* MKDIR_ENTRY_H */
 
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
60,7 → 60,7
};
 
 
void * help_cmd_mkdir(unsigned int level)
void help_cmd_mkdir(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' creates a new directory\n", cmdname);
79,7 → 79,7
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
/* This is kind of clunky, but effective for now */
93,7 → 93,7
 
/* Its a good idea to allocate path, plus we (may) need a copy of
* path to tokenize if parents are specified */
if (NULL == (tmp = cli_strdup(path))) {
if (NULL == (tmp = strdup(path))) {
cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
return 1;
}
128,9 → 128,9
absolute = 1;
 
/* TODO: Canonify the path prior to tokenizing it, see below */
dirs[i] = cli_strtok(tmp, "/");
dirs[i] = strtok(tmp, "/");
while (dirs[i] && i < 255)
dirs[++i] = cli_strtok(NULL, "/");
dirs[++i] = strtok(NULL, "/");
 
if (NULL == dirs[0])
return 1;
181,7 → 181,7
return ret;
}
 
int * cmd_mkdir(char **argv)
int cmd_mkdir(char **argv)
{
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
unsigned int verbose = 0;
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h
3,14 → 3,6
"Create new directories",
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
{
"md",
NULL,
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
/branches/network/uspace/app/bdsh/cmds/modules/cat/entry.h
2,8 → 2,8
#define CAT_ENTRY_H
 
/* Entry points for the cat command */
extern int * cmd_cat(char **);
extern void * help_cmd_cat(unsigned int);
extern int cmd_cat(char **);
extern void help_cmd_cat(unsigned int);
 
#endif /* CAT_ENTRY_H */
 
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat.c
59,7 → 59,7
};
 
/* Dispays help for cat in various levels */
void * help_cmd_cat(unsigned int level)
void help_cmd_cat(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' shows the contents of files\n", cmdname);
78,7 → 78,7
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
static unsigned int cat_file(const char *fname, size_t blen)
103,13 → 103,11
}
 
do {
memset(buff, 0, sizeof(buff));
bytes = read(fd, buff, blen);
if (bytes > 0) {
count += bytes;
if (bytes < blen)
buff[bytes] = '\0';
printf(buff);
buff[bytes] = '\0';
printf("%s", buff);
reads++;
}
} while (bytes > 0);
121,12 → 119,6
return 1;
}
 
/* Debug stuff, newline not added purposefully */
printf("** %s is a file with the size of %ld bytes\n",
fname, total);
printf( "** %d bytes were read in a buffer of %d bytes in %d reads\n",
count, blen, reads);
printf("** Read %s\n", count == total ? "Succeeded" : "Failed");
free(buff);
 
return 0;
133,7 → 125,7
}
 
/* Main entry point for cat, accepts an array of arguments */
int * cmd_cat(char **argv)
int cmd_cat(char **argv)
{
unsigned int argc, i, ret = 0, buffer = 0;
int c, opt_ind;
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat_def.h
3,6 → 3,5
"Show the contents of a file",
&cmd_cat,
&help_cmd_cat,
0
},
 
/branches/network/uspace/app/bdsh/cmds/modules/help/entry.h
2,7 → 2,7
#define HELP_ENTRY_H_
 
/* Entry points for the help command */
extern void * help_cmd_help(unsigned int);
extern int * cmd_help(char *[]);
extern void help_cmd_help(unsigned int);
extern int cmd_help(char *[]);
 
#endif
/branches/network/uspace/app/bdsh/cmds/modules/help/help.c
69,7 → 69,7
return HELP_IS_RUBBISH;
}
 
void *help_cmd_help(unsigned int level)
void help_cmd_help(unsigned int level)
{
if (level == HELP_SHORT) {
printf(
86,10 → 86,10
cmdname, cmdname, cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
int *cmd_help(char *argv[])
int cmd_help(char *argv[])
{
module_t *mod;
builtin_t *cmd;
133,13 → 133,11
 
/* First, show a list of built in commands that are available in this mode */
for (cmd = builtins; cmd->name != NULL; cmd++, i++) {
if (!builtin_is_restricted(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;
146,13 → 144,11
 
/* Now, show a list of module commands that are available in this mode */
for (mod = modules; mod->name != NULL; mod++, i++) {
if (!module_is_restricted(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",
/branches/network/uspace/app/bdsh/cmds/modules/help/help_def.h
3,5 → 3,4
"Show help for commands",
&cmd_help,
&help_cmd_help,
0
},
/branches/network/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/network/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/network/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/network/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/network/uspace/app/bdsh/cmds/modules/pwd/entry.h
4,8 → 4,8
#include "scli.h"
 
/* Entry points for the pwd command */
extern void * help_cmd_pwd(unsigned int);
extern int * cmd_pwd(char **);
extern void help_cmd_pwd(unsigned int);
extern int cmd_pwd(char **);
 
#endif
 
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd.c
39,13 → 39,13
 
static char * cmdname = "pwd";
 
void * help_cmd_pwd(unsigned int level)
void help_cmd_pwd(unsigned int level)
{
printf("`%s' prints your current working directory.\n", cmdname);
return CMD_VOID;
return;
}
 
int * cmd_pwd(char *argv[])
int cmd_pwd(char *argv[])
{
char *buff;
 
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h
3,5 → 3,4
"Prints the current working directory",
&cmd_pwd,
&help_cmd_pwd,
-1
},
/branches/network/uspace/app/bdsh/cmds/modules/module_aliases.h
12,10 → 12,6
* the entry point being reached. */
 
char *mod_aliases[] = {
"exit", "quit",
"md", "mkdir",
"del", "rm",
"dir", "ls",
NULL, NULL
};
 
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.c
50,6 → 50,24
 
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;
96,7 → 114,7
ls_print_dir(dp->d_name);
break;
case LS_FILE:
ls_print_file(dp->d_name);
ls_print_file(dp->d_name, buff);
break;
case LS_BOGUS:
/* Odd chance it was deleted from the time readdir() found
120,19 → 138,19
 
static void ls_print_dir(const char *d)
{
printf("%-40s\t<DIR>\n", d);
printf("%-40s\t<dir>\n", d);
 
return;
}
 
static void ls_print_file(const char *f)
static void ls_print_file(const char *name, const char *pathname)
{
printf("%-40s\n", f);
printf("%-40s\t%llu\n", name, (long long) flen(pathname));
 
return;
}
 
void * help_cmd_ls(unsigned int level)
void help_cmd_ls(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' lists files and directories.\n", cmdname);
142,10 → 160,10
"working directory is used.\n", cmdname);
}
 
return CMD_VOID;
return;
}
 
int * cmd_ls(char **argv)
int cmd_ls(char **argv)
{
unsigned int argc;
unsigned int scope;
174,7 → 192,7
free(buff);
return CMD_FAILURE;
case LS_FILE:
ls_print_file(buff);
ls_print_file(buff, buff);
break;
case LS_DIR:
dirp = opendir(buff);
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls_def.h
3,14 → 3,4
"List files and directories",
&cmd_ls,
&help_cmd_ls,
0
},
 
{
"dir",
NULL,
&cmd_ls,
&help_cmd_ls,
0
},
 
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.h
10,7 → 10,7
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 *);
static void ls_print_file(const char *, const char *);
 
#endif /* LS_H */
 
/branches/network/uspace/app/bdsh/cmds/modules/ls/entry.h
2,8 → 2,8
#define LS_ENTRY_H
 
/* Entry points for the ls command */
extern int * cmd_ls(char **);
extern void * help_cmd_ls(unsigned int);
extern int cmd_ls(char **);
extern void help_cmd_ls(unsigned int);
 
#endif /* LS_ENTRY_H */
 
/branches/network/uspace/app/bdsh/cmds/modules/modules.h
18,7 → 18,6
/* Prototypes for each module's entry (help/exec) points */
 
#include "help/entry.h"
#include "quit/entry.h"
#include "mkdir/entry.h"
#include "rm/entry.h"
#include "cat/entry.h"
25,6 → 24,8
#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
32,7 → 33,6
 
module_t modules[] = {
#include "help/help_def.h"
#include "quit/quit_def.h"
#include "mkdir/mkdir_def.h"
#include "rm/rm_def.h"
#include "cat/cat_def.h"
39,6 → 39,8
#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}
};
 
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c
33,7 → 33,6
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <assert.h>
#include <getopt.h>
 
#include "config.h"
144,7 → 143,7
}
 
/* Dispays help for rm in various levels */
void * help_cmd_rm(unsigned int level)
void help_cmd_rm(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' removes files and directories.\n", cmdname);
161,11 → 160,11
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
return CMD_VOID;
return;
}
 
/* Main entry point for rm, accepts an array of arguments */
int * cmd_rm(char **argv)
int cmd_rm(char **argv)
{
unsigned int argc;
unsigned int i, scope, ret = 0;
219,7 → 218,11
while (NULL != argv[i]) {
len = strlen(argv[i]) + 2;
buff = (char *) realloc(buff, len);
assert(buff != NULL);
if (buff == NULL) {
printf("rm: out of memory\n");
ret = 1;
break;
}
memset(buff, 0, sizeof(buff));
snprintf(buff, len, argv[i]);
 
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm_def.h
3,14 → 3,5
"Remove files and directories",
&cmd_rm,
&help_cmd_rm,
0
},
 
{
"del",
NULL,
&cmd_rm,
&help_cmd_rm,
0
},
 
/branches/network/uspace/app/bdsh/cmds/modules/rm/entry.h
2,8 → 2,8
#define RM_ENTRY_H
 
/* Entry points for the rm command */
extern int * cmd_rm(char **);
extern void * help_cmd_rm(unsigned int);
extern int cmd_rm(char **);
extern void help_cmd_rm(unsigned int);
 
#endif /* RM_ENTRY_H */
 
/branches/network/uspace/app/bdsh/cmds/builtins/builtins.h
4,9 → 4,11
#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}
};
 
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd.c
42,7 → 42,7
 
static char * cmdname = "cd";
 
void * help_cmd_cd(unsigned int level)
void help_cmd_cd(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' changes the current working directory.\n", cmdname);
53,12 → 53,12
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */
 
int * cmd_cd(char **argv, cliuser_t *usr)
int cmd_cd(char **argv, cliuser_t *usr)
{
int argc, rc = 0;
 
/branches/network/uspace/app/bdsh/cmds/builtins/cd/entry.h
4,8 → 4,8
#include "scli.h"
 
/* Entry points for the cd command */
extern void * help_cmd_cd(unsigned int);
extern int * cmd_cd(char **, cliuser_t *);
extern void help_cmd_cd(unsigned int);
extern int cmd_cd(char **, cliuser_t *);
 
#endif
 
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd_def.h
3,12 → 3,4
"Change the current working directory",
&cmd_cd,
&help_cmd_cd,
-1
},
{
"chdir",
NULL,
&cmd_cd,
&help_cmd_cd,
-1
},
/branches/network/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/network/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/network/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/network/uspace/app/bdsh/cmds/builtins/exit/exit_def.h
0,0 → 1,6
{
"exit",
"Exit the shell",
&cmd_exit,
&help_cmd_exit,
},
/branches/network/uspace/app/bdsh/cmds/builtins/builtin_aliases.h
4,7 → 4,6
/* See modules/module_aliases.h for an explanation of this file */
 
char *builtin_aliases[] = {
"chdir", "cd",
NULL, NULL
};
 
/branches/network/uspace/app/bdsh/cmds/cmds.h
19,17 → 19,16
#define BUFF_SMALL 255
 
/* Return macros for int type entry points */
#define CMD_FAILURE (int*)1
#define CMD_FAILURE 1
#define CMD_SUCCESS 0
#define CMD_VOID (void *)NULL
 
/* Types for module command entry and help */
typedef int * (* mod_entry_t)(char **);
typedef void * (* mod_help_t)(unsigned int);
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);
typedef int (* builtin_entry_t)(char **, cliuser_t *);
typedef void (* builtin_help_t)(unsigned int);
 
/* Module structure */
typedef struct {
37,7 → 36,6
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;
 
/* Builtin structure, same as modules except different types of entry points */
/branches/network/uspace/app/bdsh/cmds/builtin_cmds.c
40,19 → 40,6
 
extern volatile unsigned int cli_interactive;
 
int builtin_is_restricted(int pos)
{
builtin_t *cmd = builtins;
cmd += pos;
 
if (cli_interactive && cmd->restricted <= 0)
return 0;
if (!cli_interactive && cmd->restricted >= 0)
return 0;
 
return 1;
}
 
int is_builtin(const char *command)
{
builtin_t *cmd;
/branches/network/uspace/app/bdsh/config.h
1,15 → 1,18
/* Various things that are used in many files
* Various temporary port work-arounds are addressed in __HELENOS__ , this
* serves as a convenience and later as a guide to make "phony.h" for future
* ports */
/* 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 0
#define EXIT_FAILURE 1
#endif
 
/* Work around for getenv() */
#define PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
#define PATH "/srv:/app"
#define PATH_DELIM ":"
 
/* Used in many places */
26,7 → 29,7
#define PACKAGE_BUGREPORT "echo@echoreply.us"
#define PACKAGE_NAME "bdsh"
#define PACKAGE_STRING "The brain dead shell"
#define PACKAGE_TARNAME "scli"
#define PACKAGE_TARNAME "bdsh"
#define PACKAGE_VERSION "0.0.1"
 
 
/branches/network/uspace/app/bdsh/README
57,12 → 57,12
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);
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);
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.
153,9 → 153,7
 
2: Change your "usage()" command as shown:
-- void usage(...)
++ void * help_cmd_foo(unsigned int level)
-- return;
++ retrn CMD_VOID;
++ 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
163,33 → 161,19
 
3: Change the programs "main()" as shown:
-- int main(int argc, char **argv)
++ int * cmd_foo(char **argv)
++ int cmd_foo(char **argv)
-- return 1;
++ return CMD_FAILURE;
-- return 0;
++ return CMD_SUCCESS;
 
If main() returns an int that is not 1 or 0 (e.g. 127), cast it as
such:
 
-- return 127;
++ return (int *) 127;
 
NOTE: _ONLY_ the main and help entry points need to return int * or
void *, respectively. Also take note that argc has changed. The type
for entry points may soon change.
 
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)
++ int cmd_foo(char **argv)
 
Similararly, do not try to return CMD_VOID within the modules main
entry point. If somehow you escape the compiler yelling at you, you
will surely see pretty blue and yellow fireworks once its reached.
 
4: Don't expose more than the entry and help points:
-- void my_function(int n)
++ static void my_function(int n)
/branches/network/uspace/app/bdsh/util.c
1,7 → 1,4
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
* Copyright (c) 1988, 1993 The Regents of the University of California.
* All rights reserved by all copyright holders.
/* 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:
30,18 → 27,6
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* NOTES:
* 1 - Various functions were adapted from FreeBSD (copyright holders noted above)
* these functions are identified with comments.
*
* 2 - Some of these have since appeared in libc. They remain here for various
* reasons, such as the eventual integration of garbage collection for things
* that allocate memory and don't automatically free it.
*
* 3 - Things that expect a pointer to an allocated string do _no_ sanity checking
* if developing on a simulator with no debugger, take care :)
*/
 
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
54,190 → 39,6
 
extern volatile int cli_errno;
 
/* some platforms do not have strdup, implement it here.
* Returns a pointer to an allocated string or NULL on failure */
char * cli_strdup(const char *s1)
{
size_t len = strlen(s1) + 1;
void *ret = malloc(len);
 
if (ret == NULL) {
cli_errno = CL_ENOMEM;
return (char *) NULL;
}
 
cli_errno = CL_EOK;
return (char *) memcpy(ret, s1, len);
}
 
/*
* Take a previously allocated string (s1), re-size it to accept s2 and copy
* the contents of s2 into s1.
* Return -1 on failure, or the length of the copied string on success.
*/
int cli_redup(char **s1, const char *s2)
{
size_t len = strlen(s2) + 1;
 
if (! len)
return -1;
 
*s1 = realloc(*s1, len);
 
if (*s1 == NULL) {
cli_errno = CL_ENOMEM;
return -1;
}
 
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, s2, len);
cli_errno = CL_EOK;
return (int) len;
}
 
/* An asprintf() for formatting paths, similar to asprintf() but ensures
* the returned allocated string is <= PATH_MAX. On failure, an attempt
* is made to return the original string (if not null) unmodified.
*
* Returns: Length of the new string on success, 0 if the string was handed
* back unmodified, -1 on failure. On failure, cli_errno is set.
*
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the
* PATH_MAX defined by the kernel.
*
* Use this like:
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) {
* cli_error(cli_errno, "Failed to format path");
* stop_what_your_doing_as_your_out_of_memory();
* }
*/
 
int cli_psprintf(char **s1, const char *fmt, ...)
{
va_list ap;
size_t needed, base = PATH_MAX + 1;
int skipped = 0;
char *orig = NULL;
char *tmp = (char *) malloc(base);
 
/* Don't even touch s1, not enough memory */
if (NULL == tmp) {
cli_errno = CL_ENOMEM;
return -1;
}
 
/* If re-allocating s1, save a copy in case we fail */
if (NULL != *s1)
orig = cli_strdup(*s1);
 
/* Print the string to tmp so we can determine the size that
* we actually need */
memset(tmp, 0, sizeof(tmp));
va_start(ap, fmt);
/* vsnprintf will return the # of bytes not written */
skipped = vsnprintf(tmp, base, fmt, ap);
va_end(ap);
 
/* realloc/alloc s1 to be just the size that we need */
needed = strlen(tmp) + 1;
*s1 = realloc(*s1, needed);
 
if (NULL == *s1) {
/* No string lived here previously, or we failed to
* make a copy of it, either way there's nothing we
* can do. */
if (NULL == *orig) {
cli_errno = CL_ENOMEM;
return -1;
}
/* We can't even allocate enough size to restore the
* saved copy, just give up */
*s1 = realloc(*s1, strlen(orig) + 1);
if (NULL == *s1) {
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return -1;
}
/* Give the string back as we found it */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, orig, strlen(orig) + 1);
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return 0;
}
 
/* Ok, great, we have enough room */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, tmp, needed);
free(tmp);
 
/* Free tmp only if s1 was reallocated instead of allocated */
if (NULL != orig)
free(orig);
 
if (skipped) {
/* s1 was bigger than PATH_MAX when expanded, however part
* of the string was printed. Tell the caller not to use it */
cli_errno = CL_ETOOBIG;
return -1;
}
 
/* Success! */
cli_errno = CL_EOK;
return (int) needed;
}
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok_r(char *s, const char *delim, char **last)
{
char *spanp, *tok;
int c, sc;
 
if (s == NULL && (s = *last) == NULL) {
cli_errno = CL_EFAIL;
return (NULL);
}
 
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
 
if (c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
 
tok = s - 1;
 
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = '\0';
*last = s;
return (tok);
}
} while (sc != 0);
}
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok(char *s, const char *delim)
{
static char *last;
 
return (cli_strtok_r(s, delim, &last));
}
 
/* Count and return the # of elements in an array */
unsigned int cli_count_args(char **args)
{
273,10 → 74,7
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) {
cli_error(cli_errno, "Failed to set prompt");
return 1;
}
asprintf(&usr->prompt, "%s # ", usr->cwd);
 
return 0;
}
/branches/network/uspace/app/bdsh/util.h
3,13 → 3,6
 
#include "scli.h"
 
/* Internal string handlers */
extern char * cli_strdup(const char *);
extern int cli_redup(char **, const char *);
extern int cli_psprintf(char **, const char *, ...);
extern char * cli_strtok_r(char *, const char *, char **);
extern char * cli_strtok(char *, const char *);
 
/* Utility functions */
extern unsigned int cli_count_args(char **);
extern unsigned int cli_set_prompt(cliuser_t *usr);
/branches/network/uspace/app/bdsh/exec.c
46,13 → 46,13
#include "errors.h"
 
/* FIXME: Just have find_command() return an allocated string */
char *found;
static char *found;
 
static char *find_command(char *);
static unsigned int try_access(const char *);
static int try_access(const char *);
 
/* work-around for access() */
static unsigned int try_access(const char *f)
static int try_access(const char *f)
{
int fd;
 
80,10 → 80,10
return (char *) cmd;
}
 
path_tok = cli_strdup(PATH);
path_tok = strdup(PATH);
 
/* Extract the PATH env to a path[] array */
path[n] = cli_strtok(path_tok, PATH_DELIM);
path[n] = strtok(path_tok, PATH_DELIM);
while (NULL != path[n]) {
if ((strlen(path[n]) + x ) > PATH_MAX) {
cli_error(CL_ENOTSUP,
91,7 → 91,7
n, n-1);
break;
}
path[++n] = cli_strtok(NULL, PATH_DELIM);
path[++n] = strtok(NULL, PATH_DELIM);
}
 
/* We now have n places to look for the command */
114,14 → 114,14
task_id_t tid;
char *tmp;
 
tmp = cli_strdup(find_command(cmd));
tmp = strdup(find_command(cmd));
free(found);
 
tid = task_spawn((const char *)tmp, (const char **)argv);
tid = task_spawn((const char *)tmp, argv);
free(tmp);
 
if (tid == 0) {
cli_error(CL_EEXEC, "Can not spawn %s", cmd);
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd);
return 1;
} else {
return 0;
/branches/network/uspace/app/bdsh/scli.c
45,7 → 45,6
/* Globals that are modified during start-up that modules/builtins
* should be aware of. */
volatile unsigned int cli_quit = 0;
volatile unsigned int cli_interactive = 1;
volatile unsigned int cli_verbocity = 1;
 
/* The official name of this program
53,8 → 52,8
const char *progname = PACKAGE_NAME;
 
/* These are not exposed, even to builtins */
static int cli_init(cliuser_t *usr);
static void cli_finit(cliuser_t *usr);
static int cli_init(cliuser_t *);
static void cli_finit(cliuser_t *);
 
/* Constructor */
static int cli_init(cliuser_t *usr)
94,6 → 93,7
get_input(&usr);
if (NULL != usr.line) {
ret = tok_input(&usr);
cli_set_prompt(&usr);
usr.lasterr = ret;
}
}
/branches/network/uspace/app/bdsh/Makefile
30,25 → 30,17
# POSSIBILITY OF SUCH DAMAGE.
 
include ../../../version
include ../../Makefile.config
 
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=\"$(TIMESTAMP)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
PROGRAM = bdsh
 
# Any directory that cleaning targets should know about
57,7 → 49,6
cmds/ \
cmds/modules/ \
cmds/modules/help/ \
cmds/modules/quit/ \
cmds/modules/mkdir/ \
cmds/modules/rm/ \
cmds/modules/cat/ \
64,12 → 55,14
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/quit/quit.c \
cmds/modules/mkdir/mkdir.c \
cmds/modules/rm/rm.c \
cmds/modules/cat/cat.c \
76,6 → 69,9
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 \
108,7 → 104,7
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d
 
$(PROGRAM): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map
$(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
/branches/network/uspace/app/init/init.c
27,9 → 27,9
*/
 
/** @addtogroup init Init
* @brief Init process for testing purposes.
* @brief Init process for user space environment configuration.
* @{
*/
*/
/**
* @file
*/
36,6 → 36,7
 
#include <stdio.h>
#include <unistd.h>
#include <ipc/ipc.h>
#include <vfs/vfs.h>
#include <bool.h>
#include <errno.h>
42,22 → 43,17
#include <fcntl.h>
#include <task.h>
#include <malloc.h>
#include <macros.h>
#include "init.h"
#include "version.h"
 
static void console_wait(void)
{
while (get_cons_phone() < 0)
usleep(50000); // FIXME
}
 
static bool mount_fs(const char *fstype)
{
int rc = -1;
while (rc < 0) {
rc = mount(fstype, "/", "initrd");
 
rc = mount(fstype, "/", "initrd", IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted\n");
71,8 → 67,6
case ENOENT:
printf(NAME ": Unknown filesystem type (%s)\n", fstype);
return false;
default:
sleep(5); // FIXME
}
}
82,15 → 76,17
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) != 0) {
/* Success */
sleep(1);
if (task_spawn(fname, argv)) {
/* Add reasonable delay to avoid intermixed klog output. */
usleep(10000);
} else {
printf(NAME ": Error spawning %s\n", fname);
}
}
 
97,23 → 93,25
int main(int argc, char *argv[])
{
info_print();
sleep(5); // FIXME
if (!mount_fs("tmpfs") && !mount_fs("fat")) {
if (!mount_fs(STRING(RDFMT))) {
printf(NAME ": Exiting\n");
return -1;
}
// FIXME: spawn("/sbin/pci");
spawn("/sbin/fb");
spawn("/sbin/kbd");
// FIXME: spawn("/srv/pci");
spawn("/srv/fb");
spawn("/srv/kbd");
spawn("/sbin/networking_startup");
spawn("/sbin/console");
spawn("/srv/console");
spawn("/srv/fhc");
spawn("/srv/obio");
console_wait();
version_print();
spawn("/sbin/bdsh");
spawn("/app/klog");
spawn("/app/bdsh");
return 0;
}
/branches/network/uspace/app/init/version.c
35,19 → 35,20
 
#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
60,7 → 61,8
/** Print version information. */
void version_print(void)
{
printf("HelenOS init\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n", release, revision, timestamp);
printf("HelenOS init\nRelease %s%s%s\n", release, revision, timestamp);
printf("Copyright (c) 2001-2009 HelenOS project\n");
}
 
/** @}
/branches/network/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
#
 
66,13 → 58,13
-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: $(OUTPUT).disasm
 
/branches/network/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/network/uspace/app/tester/console/console1.def
0,0 → 1,6
{
"console1",
"Console color test",
&test_console1,
true
},
/branches/network/uspace/app/tester/stdio/stdio1.def
0,0 → 1,6
{
"stdio1",
"ANSI C streams reading test",
&test_stdio1,
true
},
/branches/network/uspace/app/tester/stdio/stdio2.def
0,0 → 1,6
{
"stdio2",
"ANSI C streams writing test",
&test_stdio2,
true
},
/branches/network/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/network/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/network/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}
};
 
133,7 → 137,7
if (c == 'a')
break;
if (c > 'a')
if (test->name == NULL)
printf("Unknown test\n\n");
else
run_test(test);
147,6 → 151,8
}
}
 
return 0;
}
 
/** @}
/branches/network/uspace/app/tester/loop/loop1.def
0,0 → 1,6
{
"loop1",
"Endless loop",
&test_loop1,
false
},
/branches/network/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/network/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/network/uspace/app/tester/devmap/devmap1.c
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/network/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/network/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)))
64,13 → 69,13
-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: $(OUTPUT).disasm
 
/branches/network/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/network/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) \
111,10 → 112,11
s = NULL;
 
if (!lastchar) {
again:
if (!getchar_inprog) {
cons_phone = get_cons_phone();
cons_phone = get_console_phone();
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETCHAR, 0, 0, &charcall);
CONSOLE_GETKEY, 0, 0, &charcall);
}
if (!s)
async_wait_for(getchar_inprog, &rc);
127,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/network/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/network/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/network/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
18,7 → 19,7
$(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
/branches/network/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
52,13 → 53,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/app/klog/klog.c
27,9 → 27,9
*/
 
/** @addtogroup klog KLog
* @brief HelenOS KLog
* @brief HelenOS KLog
* @{
*/
*/
/**
* @file
*/
50,12 → 50,6
/* Pointer to klog area */
static char *klog;
 
static void console_wait(void)
{
while (get_cons_phone() < 0)
usleep(50000); // FIXME
}
 
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
async_serialize_start();
86,14 → 80,13
printf(NAME ": Error initializing memory area\n");
return -1;
}
 
int inr = sysinfo_value("klog.inr");
int devno = sysinfo_value("klog.devno");
if (ipc_register_irq(inr, devno, 0, NULL) != EOK) {
printf(NAME ": Error registering klog notifications\n");
return -1;
}
// int inr = sysinfo_value("klog.inr");
// 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();
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/uspace/dist/readme
0,0 → 1,0
Lorem ipsum.
/branches/network/uspace/doc/doxygroups.h
41,6 → 41,16
* @ingroup netif
*/
 
/**
* @defgroup dp8390 Generic DP8390 network interface family service
* @ingroup netif
*/
 
/**
* @defgroup ne2k NE2000 network interface family
* @ingroup dp8390
*/
 
/**
* @defgroup net_nil Network interface layer
* @ingroup net
/branches/network/uspace/lib/libfs/libfs.c
36,7 → 36,6
 
#include "libfs.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <errno.h>
#include <async.h>
#include <ipc/ipc.h>
192,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,
263,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,
331,62 → 336,5
ops->node_put(tmp);
}
 
/** Read data from a block device.
*
* @param phone Phone to be used to communicate with the device.
* @param buffer Communication buffer shared with the 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 True on success, false on failure.
*/
bool libfs_blockread(int phone, void *buffer, 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;
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, buffer + *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(phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return false;
*bufpos = 0;
*buflen = block_size;
}
}
return true;
}
 
/** @}
*/
/branches/network/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 *);
69,9 → 69,6
 
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
 
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *,
size_t, size_t);
 
#endif
 
/** @}
/branches/network/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/network/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/network/uspace/lib/softfloat/arch/ppc64/include/functions.h
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/uspace/lib/libc/include/ddi.h
37,9 → 37,11
 
#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 device_assign_devno(void);
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/network/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/network/uspace/lib/libc/include/string.h
35,16 → 35,9
#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 *);
64,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/network/uspace/lib/libc/include/vfs/vfs.h
39,7 → 39,8
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *);
extern int mount(const char *, const char *, const char *,
const unsigned int flags);
 
#endif
 
/branches/network/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/network/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/network/uspace/lib/libc/include/stdio.h
52,6 → 52,19
(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 *);
59,7 → 72,7
 
extern int printf(const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *fmt, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *, va_list);
66,11 → 79,35
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/network/uspace/lib/libc/include/task.h
40,7 → 40,8
typedef uint64_t task_id_t;
 
extern task_id_t task_get_id(void);
extern task_id_t task_spawn(const char *path, const char *argv[]);
extern int task_set_name(const char *name);
extern task_id_t task_spawn(const char *path, char *const argv[]);
 
#endif
 
/branches/network/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/network/uspace/lib/libc/include/libc.h
39,14 → 39,20
#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 *pcb_ptr);
extern void __exit(void);
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/uspace/lib/libc/include/loader/pcb.h
40,31 → 40,32
 
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 */
/** Program entry point. */
entry_point_t entry;
 
/** Number of command-line arguments */
/** Number of command-line arguments. */
int argc;
/** Command-line arguments */
/** Command-line arguments. */
char **argv;
 
/*
* ELF-specific data
* ELF-specific data.
*/
/** Pointer to ELF dynamic section of the program */
/** Pointer to ELF dynamic section of the program. */
void *dynamic;
/** Pointer to dynamic section of the runtime linker */
void *rtld_dynamic;
/** Runtime-linker load bias */
uintptr_t rtld_bias;
} 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/network/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/network/uspace/lib/libc/include/io/stream.h
47,7 → 47,8
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/network/uspace/lib/libc/include/ctype.h
79,11 → 79,19
static inline int tolower(int c)
{
if (isupper(c))
return (c + ('a' - 'A' > 0 ? 'a' - 'A' : 'A' - 'a'));
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/network/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/network/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/network/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/network/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/network/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,12 → 38,15
#define LIBIPC_SERVICES_H_
 
typedef enum {
SERVICE_PCI = 1,
SERVICE_LOAD = 1,
SERVICE_PCI,
SERVICE_KEYBOARD,
SERVICE_VIDEO,
SERVICE_CONSOLE,
SERVICE_VFS,
SERVICE_DEVMAP,
SERVICE_FHC,
SERVICE_OBIO,
SERVICE_NETWORKING,
SERVICE_LO,
SERVICE_DP8390_ISA,
/branches/network/uspace/lib/libc/include/ipc/loader.h
32,17 → 32,19
/** @file
*/
 
#ifndef LIBC_LOADER_H_
#define LIBC_LOADER_H_
#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
} fb_request_t;
} loader_request_t;
 
#endif
 
/branches/network/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/network/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/network/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/network/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/network/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/network/uspace/lib/libc/generic/ddi.c
33,26 → 33,42
*/
 
#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>
 
/** Return unique device number.
*
* @return New unique device number.
*
*/
int device_assign_devno(void)
{
return __SYSCALL0(SYS_DEVICE_ASSIGN_DEVNO);
}
 
/** Map piece of physical memory to task.
*
* 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 → 75,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 → 97,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 → 104,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/network/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/network/uspace/lib/libc/generic/task.c
34,14 → 34,11
*/
 
#include <task.h>
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <libc.h>
#include <string.h>
#include <stdlib.h>
#include <async.h>
#include <errno.h>
#include <vfs/vfs.h>
#include <loader/loader.h>
#include <string.h>
 
task_id_t task_get_id(void)
{
52,134 → 49,72
return task_id;
}
 
static int task_spawn_loader(void)
/** 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)
{
int phone_id, rc;
 
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
if (rc != 0)
return rc;
 
return phone_id;
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, strlen(name));
}
 
static int loader_set_args(int phone_id, const char *argv[])
{
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
const char **ap;
char *dp;
char *arg_buf;
size_t buffer_size;
size_t len;
 
/*
* 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(phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(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;
}
 
/** Create a new task by running an executable from VFS.
/** 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, const char *argv[])
task_id_t task_spawn(const char *path, char *const argv[])
{
int phone_id;
ipc_call_t answer;
aid_t req;
loader_t *ldr;
task_id_t task_id;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
 
pa = absolutize(path, &pa_len);
if (!pa)
/* Connect to a program loader. */
ldr = loader_connect();
if (ldr == NULL)
return 0;
 
/* Spawn a program loader */
phone_id = task_spawn_loader();
if (phone_id < 0)
return 0;
/* Get task ID. */
rc = loader_get_task_id(ldr, &task_id);
if (rc != EOK)
goto error;
 
/*
* Say hello so that the loader knows the incoming connection's
* phone hash.
*/
rc = async_req_0_0(phone_id, LOADER_HELLO);
/* Send program pathname. */
rc = loader_set_pathname(ldr, path);
if (rc != EOK)
return 0;
goto error;
 
/* Send program pathname */
req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(phone_id, (void *)pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return 1;
}
 
async_wait_for(req, &retval);
if (retval != EOK)
/* Send arguments. */
rc = loader_set_args(ldr, argv);
if (rc != EOK)
goto error;
 
/* Send arguments */
rc = loader_set_args(phone_id, argv);
/* Load the program. */
rc = loader_load_program(ldr);
if (rc != EOK)
goto error;
 
/* Request loader to start the program */
rc = async_req_0_0(phone_id, LOADER_RUN);
/* Run it. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
 
/* Success */
ipc_hangup(phone_id);
return 1;
 
free(ldr);
return task_id;
 
/* Error exit */
error:
ipc_hangup(phone_id);
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
/branches/network/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/network/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/network/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,11
*/
 
#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 *) dst;
}
 
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 *) dst;
}
 
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 *) 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;
}
 
/** Count the number of characters in the string, not including terminating 0.
*
* @param str String.
396,5 → 312,37
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/network/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/network/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/network/uspace/lib/libc/generic/libc.c
53,6 → 53,8
extern char _heap;
extern int main(int argc, char *argv[]);
 
int _errno;
 
void _exit(int status)
{
thread_exit(status);
69,8 → 71,6
f = fibril_setup();
__tcb_set(f->tcb);
open_console();
 
/* Save the PCB pointer */
__pcb = (pcb_t *)pcb_ptr;
 
/branches/network/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.
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,7 → 901,7
*
* @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 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/network/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/network/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 */
/branches/network/uspace/lib/libc/generic/vfs/vfs.c
31,7 → 31,7
*/
/** @file
*/
 
#include <vfs/vfs.h>
#include <vfs/canonify.h>
#include <stdlib.h>
49,7 → 49,7
#include <errno.h>
#include <string.h>
#include <ipc/devmap.h>
#include "../../srv/vfs/vfs.h"
#include "../../../srv/vfs/vfs.h"
 
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
57,7 → 57,7
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_len = 0;
size_t cwd_len = 0;
 
char *absolutize(const char *path, size_t *retlen)
{
109,34 → 109,39
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);
}
 
static int device_get_handle(char *name, dev_handle_t *handle)
static int device_get_handle(const char *name, dev_handle_t *handle,
const unsigned int flags)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
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, 0, 0,
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;
149,7 → 154,8
return retval;
}
 
int mount(const char *fs_name, const char *mp, const char *dev)
int mount(const char *fs_name, const char *mp, const char *dev,
const unsigned int flags)
{
int res;
ipcarg_t rc;
156,7 → 162,7
aid_t req;
dev_handle_t dev_handle;
res = device_get_handle(dev, &dev_handle);
res = device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
164,20 → 170,13
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();
185,8 → 184,8
free(mpa);
return (int) rc;
}
/* Ask VFS whether it likes fs_name. */
rc = async_req_0_0(vfs_phone, IPC_M_PING);
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, strlen(fs_name));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
194,24 → 193,17
free(mpa);
return (int) rc;
}
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
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;
223,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) {
258,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);
282,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;
289,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) {
316,7 → 286,6
 
ssize_t write(int fildes, const void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
323,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) {
350,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);
374,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);
433,7 → 381,6
 
int mkdir(const char *path, mode_t mode)
{
int res;
ipcarg_t rc;
aid_t req;
441,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) {
471,7 → 411,6
 
static int _unlink(const char *path, int lflag)
{
int res;
ipcarg_t rc;
aid_t req;
482,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) {
519,7 → 451,6
 
int rename(const char *old, const char *new)
{
int res;
ipcarg_t rc;
aid_t req;
537,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) {
599,6 → 522,7
cwd_path = pa;
cwd_len = pa_len;
futex_up(&cwd_futex);
return EOK;
}
 
char *getcwd(char *buf, size_t size)
/branches/network/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 {
/branches/network/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/network/uspace/lib/libc/generic/smc.c
34,6 → 34,7
 
#include <libc.h>
#include <sys/types.h>
#include <smc.h>
 
int smc_coherence(void *address, size_t size)
{
/branches/network/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/network/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/network/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>
58,13 → 59,17
{
open_console();
if (console_phone >= 0) {
ipcarg_t r0, r1;
kbd_event_t ev;
int rc;
size_t i = 0;
while (i < count) {
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, &r1) < 0)
return -1;
((char *) buf)[i++] = r0;
do {
rc = kbd_get_event(&ev);
if (rc < 0) return -1;
} while (ev.c == 0 || ev.type == KE_RELEASE);
 
((char *) buf)[i++] = ev.c;
}
return i;
} else {
110,11 → 115,19
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
int get_cons_phone(void)
int get_console_phone(void)
{
open_console();
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/network/uspace/lib/libc/Makefile
31,7 → 31,6
 
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
CONSOLE_PREFIX = ../../srv/console
 
## Setup toolchain
#
38,17 → 37,17
 
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 \
60,6 → 59,8
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 \
71,6 → 72,7
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
generic/loader.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
77,39 → 79,42
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/network/uspace/lib/libc/arch/ppc64/_link.ld.in
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/tls.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/types.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/config.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/thread.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/fibril.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/syscall.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/atomic.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/regname.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/byteorder.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/stackarg.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/faddr.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/include/limits.h
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/Makefile.inc
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/src/entry.s
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/src/tls.c
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/src/fibril.S
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/src/thread_entry.s
File deleted
/branches/network/uspace/lib/libc/arch/ppc64/src/syscall.c
File deleted
/branches/network/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/network/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/network/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/network/uspace/lib/libc/arch/sparc64/Makefile.inc
29,15 → 29,11
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = sparc64-linux-gnu
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/network/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/network/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/network/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/network/uspace/lib/libc/arch/ia64/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
39,9 → 35,10
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/network/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/network/uspace/lib/libc/arch/ia64/src/entry.s
38,7 → 38,7
#
__entry:
alloc loc0 = ar.pfs, 0, 1, 2, 0
mov r1 = _gp
movl r1 = _gp
 
# Pass PCB pointer as the first argument to __main
mov out0 = r2
/branches/network/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/network/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/network/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/network/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/network/uspace/lib/libc/arch/arm32/Makefile.inc
30,20 → 30,16
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = arm-linux-gnu
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/network/uspace/lib/libc/arch/mips32eb/include/ddi.h
0,0 → 1,0
link ../../mips32/include/ddi.h
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/network/uspace/lib/libc/arch/mips32eb/Makefile.inc
29,19 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mips-sgi-irix5
TARGET = mips-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
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
 
BFD_ARCH = mips
BFD_NAME = elf32-big
BFD_NAME = elf32-tradbigmips
/branches/network/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/network/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/network/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/network/uspace/lib/libc/arch/ppc32/Makefile.inc
29,16 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc-linux-gnu
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/network/uspace/lib/libc/arch/ppc32/src/entry.s
34,11 → 34,12
 
## User-space task entry point
#
# r3 contains the PCB pointer
# r6 contains the PCB pointer
#
__entry:
# Pass the PCB pointer to __main() as the first argument.
# Since the first argument is passed in r3, no operation is needed.
# The first argument is passed in r3.
mr %r3, %r6
bl __main
 
bl __exit
/branches/network/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/network/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/network/uspace/lib/libc/arch/amd64/Makefile.inc
29,16 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = amd64-linux-gnu
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/network/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/network/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/network/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 */
" nop\n"
: "=&r" (tmp), "+m" (val->count), "=&r" (v)
: "i" (i), "i" (0)
: "r" (i), "i" (0)
);
 
return v;
/branches/network/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/network/uspace/lib/libc/arch/mips32/Makefile.inc
29,23 → 29,13
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mipsel-linux-gnu
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/network/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/network/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/network/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/network/uspace/lib/libc/arch/ia32/Makefile.inc
29,17 → 29,13
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = i686-pc-linux-gnu
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/network/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
53,3 → 53,38
popl %esi
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/network/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/network/uspace/srv/kbd/arch/ppc64/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ppc64/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/mips32/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/mips32/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ia32/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ia32/include/scanc.h
File deleted
/branches/network/uspace/srv/kbd/arch/ia32/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/ia32/src/scanc.c
File deleted
/branches/network/uspace/srv/kbd/arch/ia32/src/mouse.c
File deleted
/branches/network/uspace/srv/kbd/arch/sparc64/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/sparc64/src/scanc.c
File deleted
/branches/network/uspace/srv/kbd/arch/sparc64/include/scanc.h
File deleted
/branches/network/uspace/srv/kbd/arch/sparc64/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ia64/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ia64/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/arm32/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/arch/arm32/src/kbd_gxemul.c
File deleted
/branches/network/uspace/srv/kbd/arch/arm32/include/kbd.h
File deleted
/branches/network/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/network/uspace/srv/kbd/arch/ppc32/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/arch/ppc32/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/ctl/pc.c
0,0 → 1,231
/*
* 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>
#include <gsp.h>
 
enum dec_state {
ds_s,
ds_e
};
 
static enum dec_state ds;
 
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
};
 
int kbd_ctl_init(void)
{
ds = ds_s;
return 0;
}
 
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/network/uspace/srv/kbd/ctl/stty.c
0,0 → 1,229
/*
* 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>
#include <gsp.h>
#include <stroke.h>
 
/** Scancode parser */
static gsp_t sp;
 
/** Current parser state */
static int ds;
 
#include <stdio.h>
 
int seq_defs[] = {
/* Not shifted */
 
0, KC_BACKTICK, 0x60, GSP_END,
 
0, KC_1, 0x31, GSP_END,
0, KC_2, 0x32, GSP_END,
0, KC_3, 0x33, GSP_END,
0, KC_4, 0x34, GSP_END,
0, KC_5, 0x35, GSP_END,
0, KC_6, 0x36, GSP_END,
0, KC_7, 0x37, GSP_END,
0, KC_8, 0x38, GSP_END,
0, KC_9, 0x39, GSP_END,
0, KC_0, 0x30, GSP_END,
 
0, KC_MINUS, 0x2d, GSP_END,
0, KC_EQUALS, 0x3d, GSP_END,
0, KC_BACKSPACE, 0x08, GSP_END,
 
0, KC_TAB, 0x09, GSP_END,
 
0, KC_Q, 0x71, GSP_END,
0, KC_W, 0x77, GSP_END,
0, KC_E, 0x65, GSP_END,
0, KC_R, 0x72, GSP_END,
0, KC_T, 0x74, GSP_END,
0, KC_Y, 0x79, GSP_END,
0, KC_U, 0x75, GSP_END,
0, KC_I, 0x69, GSP_END,
0, KC_O, 0x6f, GSP_END,
0, KC_P, 0x70, GSP_END,
 
0, KC_LBRACKET, 0x5b, GSP_END,
0, KC_RBRACKET, 0x5d, GSP_END,
 
0, KC_A, 0x61, GSP_END,
0, KC_S, 0x73, GSP_END,
0, KC_D, 0x64, GSP_END,
0, KC_F, 0x66, GSP_END,
0, KC_G, 0x67, GSP_END,
0, KC_H, 0x68, GSP_END,
0, KC_J, 0x6a, GSP_END,
0, KC_K, 0x6b, GSP_END,
0, KC_L, 0x6c, GSP_END,
 
0, KC_SEMICOLON, 0x3b, GSP_END,
0, KC_QUOTE, 0x27, GSP_END,
0, KC_BACKSLASH, 0x5c, GSP_END,
 
0, KC_Z, 0x7a, GSP_END,
0, KC_X, 0x78, GSP_END,
0, KC_C, 0x63, GSP_END,
0, KC_V, 0x76, GSP_END,
0, KC_B, 0x62, GSP_END,
0, KC_N, 0x6e, GSP_END,
0, KC_M, 0x6d, GSP_END,
 
0, KC_COMMA, 0x2c, GSP_END,
0, KC_PERIOD, 0x2e, GSP_END,
0, KC_SLASH, 0x2f, GSP_END,
 
/* Shifted */
 
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END,
 
KM_SHIFT, KC_1, 0x21, GSP_END,
KM_SHIFT, KC_2, 0x40, GSP_END,
KM_SHIFT, KC_3, 0x23, GSP_END,
KM_SHIFT, KC_4, 0x24, GSP_END,
KM_SHIFT, KC_5, 0x25, GSP_END,
KM_SHIFT, KC_6, 0x5e, GSP_END,
KM_SHIFT, KC_7, 0x26, GSP_END,
KM_SHIFT, KC_8, 0x2a, GSP_END,
KM_SHIFT, KC_9, 0x28, GSP_END,
KM_SHIFT, KC_0, 0x29, GSP_END,
 
KM_SHIFT, KC_MINUS, 0x5f, GSP_END,
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END,
 
KM_SHIFT, KC_Q, 0x51, GSP_END,
KM_SHIFT, KC_W, 0x57, GSP_END,
KM_SHIFT, KC_E, 0x45, GSP_END,
KM_SHIFT, KC_R, 0x52, GSP_END,
KM_SHIFT, KC_T, 0x54, GSP_END,
KM_SHIFT, KC_Y, 0x59, GSP_END,
KM_SHIFT, KC_U, 0x55, GSP_END,
KM_SHIFT, KC_I, 0x49, GSP_END,
KM_SHIFT, KC_O, 0x4f, GSP_END,
KM_SHIFT, KC_P, 0x50, GSP_END,
 
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END,
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END,
 
KM_SHIFT, KC_A, 0x41, GSP_END,
KM_SHIFT, KC_S, 0x53, GSP_END,
KM_SHIFT, KC_D, 0x44, GSP_END,
KM_SHIFT, KC_F, 0x46, GSP_END,
KM_SHIFT, KC_G, 0x47, GSP_END,
KM_SHIFT, KC_H, 0x48, GSP_END,
KM_SHIFT, KC_J, 0x4a, GSP_END,
KM_SHIFT, KC_K, 0x4b, GSP_END,
KM_SHIFT, KC_L, 0x4c, GSP_END,
 
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END,
KM_SHIFT, KC_QUOTE, 0x22, GSP_END,
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END,
 
KM_SHIFT, KC_Z, 0x5a, GSP_END,
KM_SHIFT, KC_X, 0x58, GSP_END,
KM_SHIFT, KC_C, 0x43, GSP_END,
KM_SHIFT, KC_V, 0x56, GSP_END,
KM_SHIFT, KC_B, 0x42, GSP_END,
KM_SHIFT, KC_N, 0x4e, GSP_END,
KM_SHIFT, KC_M, 0x4d, GSP_END,
 
KM_SHIFT, KC_COMMA, 0x3c, GSP_END,
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END,
KM_SHIFT, KC_SLASH, 0x3f, GSP_END,
 
/* ... */
 
0, KC_SPACE, 0x20, GSP_END,
0, KC_ENTER, 0x0a, GSP_END,
0, KC_ENTER, 0x0d, GSP_END,
 
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END,
 
0, KC_F1, 0x1b, 0x4f, 0x50, GSP_END,
0, KC_F2, 0x1b, 0x4f, 0x51, GSP_END,
0, KC_F3, 0x1b, 0x4f, 0x52, GSP_END,
0, KC_F4, 0x1b, 0x4f, 0x53, GSP_END,
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END,
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END,
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END,
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END,
0, KC_F9, 0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END,
0, KC_F10, 0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END,
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END,
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END,
 
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END,
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END,
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END,
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END,
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END,
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END,
 
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END,
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END,
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END,
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END,
 
0, 0
};
 
int kbd_ctl_init(void)
{
ds = 0;
 
gsp_init(&sp);
return gsp_insert_defs(&sp, seq_defs);
}
 
void kbd_ctl_parse_scancode(int scancode)
{
unsigned mods, key;
 
ds = gsp_step(&sp, ds, scancode, &mods, &key);
if (key != 0) {
stroke_sim(mods, key);
}
}
 
/**
* @}
*/
/branches/network/uspace/srv/kbd/ctl/sun.c
0,0 → 1,209
/*
* 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[];
 
int kbd_ctl_init(void)
{
return 0;
}
 
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/network/uspace/srv/kbd/ctl/gxe_fb.c
0,0 → 1,229
/*
* 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>
#include <gsp.h>
#include <stroke.h>
 
/** Scancode parser */
static gsp_t sp;
 
/** Current parser state */
static int ds;
 
#include <stdio.h>
 
int seq_defs[] = {
/* Not shifted */
 
0, KC_BACKTICK, 0x60, GSP_END,
 
0, KC_1, 0x31, GSP_END,
0, KC_2, 0x32, GSP_END,
0, KC_3, 0x33, GSP_END,
0, KC_4, 0x34, GSP_END,
0, KC_5, 0x35, GSP_END,
0, KC_6, 0x36, GSP_END,
0, KC_7, 0x37, GSP_END,
0, KC_8, 0x38, GSP_END,
0, KC_9, 0x39, GSP_END,
0, KC_0, 0x30, GSP_END,
 
0, KC_MINUS, 0x2d, GSP_END,
0, KC_EQUALS, 0x3d, GSP_END,
0, KC_BACKSPACE, 0x08, GSP_END,
 
0, KC_TAB, 0x09, GSP_END,
 
0, KC_Q, 0x71, GSP_END,
0, KC_W, 0x77, GSP_END,
0, KC_E, 0x65, GSP_END,
0, KC_R, 0x72, GSP_END,
0, KC_T, 0x74, GSP_END,
0, KC_Y, 0x79, GSP_END,
0, KC_U, 0x75, GSP_END,
0, KC_I, 0x69, GSP_END,
0, KC_O, 0x6f, GSP_END,
0, KC_P, 0x70, GSP_END,
 
0, KC_LBRACKET, 0x5b, GSP_END,
0, KC_RBRACKET, 0x5d, GSP_END,
 
0, KC_A, 0x61, GSP_END,
0, KC_S, 0x73, GSP_END,
0, KC_D, 0x64, GSP_END,
0, KC_F, 0x66, GSP_END,
0, KC_G, 0x67, GSP_END,
0, KC_H, 0x68, GSP_END,
0, KC_J, 0x6a, GSP_END,
0, KC_K, 0x6b, GSP_END,
0, KC_L, 0x6c, GSP_END,
 
0, KC_SEMICOLON, 0x3b, GSP_END,
0, KC_QUOTE, 0x27, GSP_END,
0, KC_BACKSLASH, 0x5c, GSP_END,
 
0, KC_Z, 0x7a, GSP_END,
0, KC_X, 0x78, GSP_END,
0, KC_C, 0x63, GSP_END,
0, KC_V, 0x76, GSP_END,
0, KC_B, 0x62, GSP_END,
0, KC_N, 0x6e, GSP_END,
0, KC_M, 0x6d, GSP_END,
 
0, KC_COMMA, 0x2c, GSP_END,
0, KC_PERIOD, 0x2e, GSP_END,
0, KC_SLASH, 0x2f, GSP_END,
 
/* Shifted */
 
KM_SHIFT, KC_BACKTICK, 0x7e, GSP_END,
 
KM_SHIFT, KC_1, 0x21, GSP_END,
KM_SHIFT, KC_2, 0x40, GSP_END,
KM_SHIFT, KC_3, 0x23, GSP_END,
KM_SHIFT, KC_4, 0x24, GSP_END,
KM_SHIFT, KC_5, 0x25, GSP_END,
KM_SHIFT, KC_6, 0x5e, GSP_END,
KM_SHIFT, KC_7, 0x26, GSP_END,
KM_SHIFT, KC_8, 0x2a, GSP_END,
KM_SHIFT, KC_9, 0x28, GSP_END,
KM_SHIFT, KC_0, 0x29, GSP_END,
 
KM_SHIFT, KC_MINUS, 0x5f, GSP_END,
KM_SHIFT, KC_EQUALS, 0x2b, GSP_END,
 
KM_SHIFT, KC_Q, 0x51, GSP_END,
KM_SHIFT, KC_W, 0x57, GSP_END,
KM_SHIFT, KC_E, 0x45, GSP_END,
KM_SHIFT, KC_R, 0x52, GSP_END,
KM_SHIFT, KC_T, 0x54, GSP_END,
KM_SHIFT, KC_Y, 0x59, GSP_END,
KM_SHIFT, KC_U, 0x55, GSP_END,
KM_SHIFT, KC_I, 0x49, GSP_END,
KM_SHIFT, KC_O, 0x4f, GSP_END,
KM_SHIFT, KC_P, 0x50, GSP_END,
 
KM_SHIFT, KC_LBRACKET, 0x7b, GSP_END,
KM_SHIFT, KC_RBRACKET, 0x7d, GSP_END,
 
KM_SHIFT, KC_A, 0x41, GSP_END,
KM_SHIFT, KC_S, 0x53, GSP_END,
KM_SHIFT, KC_D, 0x44, GSP_END,
KM_SHIFT, KC_F, 0x46, GSP_END,
KM_SHIFT, KC_G, 0x47, GSP_END,
KM_SHIFT, KC_H, 0x48, GSP_END,
KM_SHIFT, KC_J, 0x4a, GSP_END,
KM_SHIFT, KC_K, 0x4b, GSP_END,
KM_SHIFT, KC_L, 0x4c, GSP_END,
 
KM_SHIFT, KC_SEMICOLON, 0x3a, GSP_END,
KM_SHIFT, KC_QUOTE, 0x22, GSP_END,
KM_SHIFT, KC_BACKSLASH, 0x7c, GSP_END,
 
KM_SHIFT, KC_Z, 0x5a, GSP_END,
KM_SHIFT, KC_X, 0x58, GSP_END,
KM_SHIFT, KC_C, 0x43, GSP_END,
KM_SHIFT, KC_V, 0x56, GSP_END,
KM_SHIFT, KC_B, 0x42, GSP_END,
KM_SHIFT, KC_N, 0x4e, GSP_END,
KM_SHIFT, KC_M, 0x4d, GSP_END,
 
KM_SHIFT, KC_COMMA, 0x3c, GSP_END,
KM_SHIFT, KC_PERIOD, 0x3e, GSP_END,
KM_SHIFT, KC_SLASH, 0x3f, GSP_END,
 
/* ... */
 
0, KC_SPACE, 0x20, GSP_END,
0, KC_ENTER, 0x0a, GSP_END,
0, KC_ENTER, 0x0d, GSP_END,
 
0, KC_ESCAPE, 0x1b, 0x1b, GSP_END,
 
0, KC_F1, 0x1b, 0x5b, 0x4f, 0x50, GSP_END,
0, KC_F2, 0x1b, 0x5b, 0x4f, 0x51, GSP_END,
0, KC_F3, 0x1b, 0x5b, 0x4f, 0x52, GSP_END,
0, KC_F4, 0x1b, 0x5b, 0x4f, 0x53, GSP_END,
0, KC_F5, 0x1b, 0x5b, 0x31, 0x35, GSP_END,
0, KC_F6, 0x1b, 0x5b, 0x31, 0x37, GSP_END,
0, KC_F7, 0x1b, 0x5b, 0x31, 0x38, GSP_END,
0, KC_F8, 0x1b, 0x5b, 0x31, 0x39, GSP_END,
0, KC_F9, 0x1b, 0x5b, 0x32, 0x38, GSP_END,
0, KC_F10, 0x1b, 0x5b, 0x32, 0x39, GSP_END,
0, KC_F11, 0x1b, 0x5b, 0x32, 0x33, GSP_END,
0, KC_F12, 0x1b, 0x5b, 0x32, 0x34, GSP_END,
 
0, KC_INSERT, 0x1b, 0x5b, 0x32, 0x7e, GSP_END,
0, KC_HOME, 0x1b, 0x5b, 0x48, GSP_END,
0, KC_PAGE_UP, 0x1b, 0x5b, 0x35, 0x7e, GSP_END,
0, KC_DELETE, 0x1b, 0x5b, 0x33, 0x7e, GSP_END,
0, KC_END, 0x1b, 0x5b, 0x46, GSP_END,
0, KC_PAGE_DOWN, 0x1b, 0x5b, 0x36, 0x7e, GSP_END,
 
0, KC_UP, 0x1b, 0x5b, 0x41, GSP_END,
0, KC_LEFT, 0x1b, 0x5b, 0x44, GSP_END,
0, KC_DOWN, 0x1b, 0x5b, 0x42, GSP_END,
0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END,
 
0, 0
};
 
int kbd_ctl_init(void)
{
ds = 0;
 
gsp_init(&sp);
return gsp_insert_defs(&sp, seq_defs);
}
 
void kbd_ctl_parse_scancode(int scancode)
{
unsigned mods, key;
 
ds = gsp_step(&sp, ds, scancode, &mods, &key);
if (key != 0) {
stroke_sim(mods, key);
}
}
 
/**
* @}
*/
/branches/network/uspace/srv/kbd/include/keys.h
File deleted
/branches/network/uspace/srv/kbd/include/gsp.h
0,0 → 1,84
/*
* 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 Generic scancode parser.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef KBD_GSP_H_
#define KBD_GSP_H_
 
#include <libadt/hash_table.h>
 
enum {
GSP_END = -1, /**< Terminates a sequence. */
GSP_DEFAULT = -2 /**< Wildcard, catches unhandled cases. */
};
 
/** Scancode parser description */
typedef struct {
/** Transition table, (state, input) -> (state, output) */
hash_table_t trans;
 
/** Number of states */
int states;
} gsp_t;
 
/** Scancode parser transition. */
typedef struct {
link_t link; /**< Link to hash table in @c gsp_t */
 
/* Preconditions */
 
int old_state; /**< State before transition */
int input; /**< Input symbol (scancode) */
 
/* Effects */
 
int new_state; /**< State after transition */
 
/* Output emitted during transition */
 
unsigned out_mods; /**< Modifier to emit */
unsigned out_key; /**< Keycode to emit */
} gsp_trans_t;
 
extern void gsp_init(gsp_t *);
extern int gsp_insert_defs(gsp_t *, const int *);
extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
 
#endif
 
/**
* @}
*/
/branches/network/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/network/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/network/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/network/uspace/srv/kbd/include/kbd_ctl.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_CTL_H_
#define KBD_CTL_H_
 
extern void kbd_ctl_parse_scancode(int);
extern int kbd_ctl_init(void);
 
 
#endif
 
/**
* @}
*/
 
/branches/network/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/network/uspace/srv/kbd/include/stroke.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 Generic scancode parser.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef KBD_STROKE_H_
#define KBD_STROKE_H_
 
extern void stroke_sim(unsigned, unsigned);
 
#endif
 
/**
* @}
*/
 
/branches/network/uspace/srv/kbd/port/gxemul.c
0,0 → 1,87
/*
* 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>
#include <ddi.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"), device_assign_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/network/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"), device_assign_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/network/uspace/srv/kbd/port/msim.c
0,0 → 1,92
/*
* 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>
#include <ddi.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"), device_assign_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/network/uspace/srv/kbd/port/i8042.c
0,0 → 1,169
/*
* 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 <ddi.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"), device_assign_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/network/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"), device_assign_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/network/uspace/srv/kbd/port/ski.c
0,0 → 1,110
/*
* 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) {
while (1) {
c = ski_getchar();
if (c == 0)
break;
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/network/uspace/srv/kbd/port/sgcn.c
0,0 → 1,164
/*
* 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 <async.h>
#include <kbd.h>
#include <kbd_port.h>
#include <sysinfo.h>
#include <stdio.h>
#include <thread.h>
 
#define POLL_INTERVAL 10000
 
/**
* 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;
 
/* polling thread */
static void *sgcn_thread_impl(void *arg);
 
 
/**
* Initializes the SGCN driver.
* Maps the physical memory (SRAM) and creates the polling thread.
*/
int kbd_port_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) {
printf("SGCN: uspace driver could not map physical memory.");
return -1;
}
sram_buffer_offset = sysinfo_value("sram.buffer.offset");
 
thread_id_t tid;
int rc;
 
rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
if (rc != 0) {
return rc;
}
 
return 0;
}
 
/**
* Handler of the "key pressed" event. Reads codes of all the pressed keys from
* the buffer.
*/
static void sgcn_key_pressed(void)
{
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);
}
}
 
/**
* Thread to poll SGCN for keypresses.
*/
static void *sgcn_thread_impl(void *arg)
{
(void) arg;
 
while (1) {
sgcn_key_pressed();
usleep(POLL_INTERVAL);
}
}
 
 
/** @}
*/
/branches/network/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/network/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/network/uspace/srv/kbd/genarch/include/kbd.h
File deleted
/branches/network/uspace/srv/kbd/genarch/include/scanc.h
File deleted
/branches/network/uspace/srv/kbd/genarch/src/kbd.c
File deleted
/branches/network/uspace/srv/kbd/genarch/stroke.c
0,0 → 1,84
/*
* 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
* @{
*/
/**
* @file
* @brief Stroke simulator.
*
* When simulating a keyboard using a serial TTY we need to convert the
* recognized strokes (such as Shift-A) to sequences of key presses and
* releases (such as 'press Shift, press A, release A, release Shift').
*/
 
#include <stroke.h>
#include <kbd.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
 
/** Correspondence between modifers and the modifier keycodes. */
static unsigned int mods_keys[][2] = {
{ KM_LSHIFT, KC_LSHIFT },
{ 0, 0 }
};
 
/** Simulate keystroke using sequences of key presses and releases. */
void stroke_sim(unsigned mod, unsigned key)
{
int i;
 
/* Simulate modifier presses. */
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KE_PRESS, mods_keys[i][1]);
}
++i;
}
 
/* Simulate key press and release. */
if (key != 0) {
kbd_push_ev(KE_PRESS, key);
kbd_push_ev(KE_RELEASE, key);
}
 
/* Simulate modifier releases. */
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/network/uspace/srv/kbd/genarch/gsp.c
0,0 → 1,288
/*
* 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
* @ingroup kbd
* @{
*/
/** @file
* @brief Generic scancode parser.
*
* The scancode parser is a simple finite state machine. It is described
* using sequences of input symbols (scancodes) and the corresponding output
* value (mods, key pair). When the parser recognizes a sequence,
* it outputs the value and restarts. If a transition is undefined,
* the parser restarts, too.
*
* Apart from precise values, GSP_DEFAULT allows to catch general cases.
* I.e. if we knew that after 0x1b 0x4f there always follow two more
* scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
* with null output. This will force the parser to read the entire sequence,
* not leaving garbage on the input if it does not recognize the specific
* sequence.
*/
 
#include <gsp.h>
#include <libadt/hash_table.h>
#include <stdlib.h>
#include <stdio.h>
 
#define TRANS_TABLE_CHAINS 256
 
/*
* Hash table operations for the transition function.
*/
 
static hash_index_t trans_op_hash(unsigned long key[]);
static int trans_op_compare(unsigned long key[], hash_count_t keys,
link_t *item);
static void trans_op_remove_callback(link_t *item);
 
static hash_table_operations_t trans_ops = {
.hash = trans_op_hash,
.compare = trans_op_compare,
.remove_callback = trans_op_remove_callback
};
 
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
static void trans_insert(gsp_t *p, gsp_trans_t *t);
static gsp_trans_t *trans_new(void);
 
/** Initialise scancode parser. */
void gsp_init(gsp_t *p)
{
p->states = 1;
hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
}
 
/** Insert a series of definitions into the parser.
*
* @param p The parser.
* @param defs Definition list. Each definition starts with two output values
* (mods, key) and continues with a sequence of input values
* terminated with GSP_END. The definition list is terminated
* with two zeroes (0, 0) for output values.
*/
int gsp_insert_defs(gsp_t *p, const int *defs)
{
unsigned mods, key;
const int *dp;
int rc;
 
dp = defs;
 
while (1) {
/* Read the output values. */
mods = *dp++;
key = *dp++;
if (key == 0) break;
 
/* Insert one sequence. */
rc = gsp_insert_seq(p, dp, mods, key);
if (rc != 0)
return rc;
 
/* Skip to the next definition. */
while (*dp != GSP_END)
++dp;
++dp;
}
 
return 0;
}
 
/** Insert one sequence into the parser.
*
* @param p The parser.
* @param seq Sequence of input values terminated with GSP_END.
* @param mods Corresponsing output value.
* @param key Corresponsing output value.
*/
int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
{
int state;
gsp_trans_t *t;
 
state = 0;
t = NULL;
 
/* Input sequence must be non-empty. */
if (*seq == GSP_END)
return -1;
 
while (*(seq + 1) != GSP_END) {
t = trans_lookup(p, state, *seq);
if (t == NULL) {
/* Create new state. */
t = trans_new();
t->old_state = state;
t->input = *seq;
t->new_state = p->states++;
 
t->out_mods = 0;
t->out_key = 0;
 
trans_insert(p, t);
}
state = t->new_state;
++seq;
}
 
/* Process the last transition. */
t = trans_lookup(p, state, *seq);
if (t != NULL) {
exit(1);
return -1; /* Conflicting definition. */
}
 
t = trans_new();
t->old_state = state;
t->input = *seq;
t->new_state = 0;
 
t->out_mods = mods;
t->out_key = key;
 
trans_insert(p, t);
 
return 0;
}
 
/** Compute one parser step.
*
* Computes the next state and output values for a given state and input.
* This handles everything including restarts and default branches.
*
* @param p The parser.
* @param state Old state.
* @param input Input symbol (scancode).
* @param mods Output value (modifier).
* @param key Output value (key).
* @return New state.
*/
int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
{
gsp_trans_t *t;
 
t = trans_lookup(p, state, input);
if (t == NULL) {
t = trans_lookup(p, state, GSP_DEFAULT);
}
 
if (t == NULL) {
printf("gsp_step: not found\n");
*mods = NULL;
*key = NULL;
return 0;
}
 
*mods = t->out_mods;
*key = t->out_key;
return t->new_state;
}
 
/** Transition function lookup.
*
* Returns the value of the transition function for the given state
* and input. Note that the transition must be specified precisely,
* to obtain the default branch use input = GSP_DEFAULT.
*
* @param p Parser.
* @param state Current state.
* @param input Input value.
* @return The transition or @c NULL if not defined.
*/
static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
{
link_t *item;
unsigned long key[2];
 
key[0] = state;
key[1] = input;
 
item = hash_table_find(&p->trans, key);
if (item == NULL) return NULL;
 
return hash_table_get_instance(item, gsp_trans_t, link);
}
 
/** Define a new transition.
*
* @param p The parser.
* @param t Transition with all fields defined.
*/
static void trans_insert(gsp_t *p, gsp_trans_t *t)
{
unsigned long key[2];
 
key[0] = t->old_state;
key[1] = t->input;
 
hash_table_insert(&p->trans, &key, &t->link);
}
 
/** Allocate transition structure. */
static gsp_trans_t *trans_new(void)
{
gsp_trans_t *t;
 
t = malloc(sizeof(gsp_trans_t));
if (t == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
 
return t;
}
 
/*
* Transition function hash table operations.
*/
 
static hash_index_t trans_op_hash(unsigned long key[])
{
return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
}
 
static int trans_op_compare(unsigned long key[], hash_count_t keys,
link_t *item)
{
gsp_trans_t *t;
 
t = hash_table_get_instance(item, gsp_trans_t, link);
return (key[0] == t->old_state && key[1] == t->input);
}
 
static void trans_op_remove_callback(link_t *item)
{
}
 
/**
* @}
*/
/branches/network/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"
 
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)
125,16 → 176,32
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() != 0)
return -1;
 
/* Initialize controller driver. */
if (kbd_ctl_init() != 0)
return -1;
/* Initialize key buffer */
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;
141,7 → 208,7
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
/* Not reached. */
return 0;
}
 
/branches/network/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/network/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
44,61 → 44,109
OUTPUT = kbd
GENERIC_SOURCES = \
generic/kbd.c \
genarch/gsp.c \
genarch/stroke.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)
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), i460GX)
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)
ifeq ($(MACHINE),serengeti)
GENARCH_SOURCES += \
port/sgcn.c \
ctl/stty.c
else
GENARCH_SOURCES += \
port/z8530.c \
ctl/sun.c
endif
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) $(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 $(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: $(OUTPUT).disasm
 
/branches/network/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/network/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/network/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,40 → 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)
{
printf(NAME ": HelenOS IPC Naming Service\n");
ipc_call_t call;
ipc_callid_t callid;
ipcarg_t retval;
 
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
&ns_hash_table_ops)) {
printf(NAME ": No memory available\n");
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
list_initialize(&pending_req);
list_initialize(&cs_req);
printf(NAME ": Accepting connections\n");
while (1) {
callid = ipc_wait_for_call(&call);
while (true) {
process_pending_req();
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);
142,23 → 213,36
/*
* 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 */
168,10 → 252,11
/** 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)
{
180,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;
}
 
203,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.
243,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;
267,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)
{
274,6 → 456,6
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/**
/**
* @}
*/
/branches/network/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
51,13 → 52,13
-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: $(OUTPUT).disasm
 
/branches/network/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/network/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/network/uspace/srv/console/console.c
35,12 → 35,13
#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>
47,7 → 48,9
#include <screenbuffer.h>
#include <sys/mman.h>
#include <stdio.h>
#include <sysinfo.h>
 
#include "console.h"
#include "gcons.h"
 
#define MAX_KEYREQUESTS_BUFFERED 32
57,6 → 60,7
/** Index of currently used virtual console.
*/
int active_console = 0;
int prev_console = 0;
 
/** Information about framebuffer
*/
86,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.
*
*/
109,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);
187,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 */
303,7 → 298,7
ipc_callid_t callid;
ipc_call_t call;
int retval;
int c;
kbd_event_t ev;
connection_t *conn;
int newcon;
325,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;
}
348,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;
370,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;
387,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);
438,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);
450,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 <
466,13 → 480,23
}
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");
479,43 → 503,43
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 */
535,33 → 559,47
}
}
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)
return -1;
/* Receive kernel notifications */
// if (sysinfo_value("kconsole.present")) {
// int inr = sysinfo_value("kconsole.inr");
// if (ipc_register_irq(inr, device_assign_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/network/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/network/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/network/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/network/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/network/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/network/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,6 → 58,8
$(addsuffix .o,$(basename $(IMAGES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
 
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS)
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
64,13 → 67,13
-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 $(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: $(OUTPUT).disasm
 
/branches/network/uspace/srv/rd/rd.c
188,12 → 188,10
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
 
while (phone < 0) {
usleep(10000);
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(NAME ": Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
257,7 → 255,7
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) {
printf(NAME ": Error mapping RAM disk\n");
return false;
/branches/network/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
51,13 → 53,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/srv/loader/main.c
27,12 → 27,12
*/
 
/** @addtogroup loader
* @brief Loads and runs programs from VFS.
* @brief Loads and runs programs from VFS.
* @{
*/
*/
/**
* @file
* @brief Loads and runs programs from VFS.
* @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
46,9 → 46,11
#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>
58,11 → 60,7
#include <elf.h>
#include <elf_load.h>
 
/**
* Bias used for loading the dynamic linker. This will be soon replaced
* by automatic placement.
*/
#define RTLD_BIAS 0x80000
#define DPRINTF(...)
 
/** Pathname of the file that will be loaded */
static char *pathname = NULL;
77,6 → 75,36
/** 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
87,13 → 115,13
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);
100,15 → 128,15
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;
}
124,23 → 152,23
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);
147,12 → 175,12
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
*/
163,10 → 191,10
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);
173,7 → 201,7
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* Fill argv with argument pointers
*/
181,78 → 209,91
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 and run the previously selected program.
/** Load the previously selected program.
*
* @param rid
* @param request
* @return 0 on success, !0 on error.
*/
static int loader_run(ipc_callid_t rid, ipc_call_t *request)
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
 
elf_info_t prog_info;
elf_info_t interp_info;
 
// printf("Load program '%s'\n", pathname);
 
rc = elf_load_file(pathname, 0, &prog_info);
if (rc < 0) {
printf("failed to load program\n");
DPRINTF("Failed to load executable '%s'.\n", pathname);
ipc_answer_0(rid, EINVAL);
return 1;
}
 
// printf("Create PCB\n");
elf_create_pcb(&prog_info, &pcb);
 
pcb.argc = argc;
pcb.argv = argv;
 
if (prog_info.interp == NULL) {
/* Statically linked program */
// printf("Run statically linked program\n");
// printf("entry point: 0x%llx\n", prog_info.entry);
is_dyn_linked = false;
ipc_answer_0(rid, EOK);
close_console();
elf_run(&prog_info, &pcb);
return 0;
}
 
printf("Load dynamic linker '%s'\n", prog_info.interp);
rc = elf_load_file("/rtld.so", RTLD_BIAS, &interp_info);
rc = elf_load_file(prog_info.interp, 0, &interp_info);
if (rc < 0) {
printf("failed to load dynamic linker\n");
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;
}
 
/*
* Provide dynamic linker with some useful data
*/
pcb.rtld_dynamic = interp_info.dynamic;
pcb.rtld_bias = RTLD_BIAS;
 
printf("run dynamic linker\n");
printf("entry point: 0x%llx\n", interp_info.entry);
close_console();
/** 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);
}
 
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
 
/* Not reached */
return 0;
}
 
/** Handle loader connection.
265,24 → 306,43
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;
 
(void) iid;
(void) icall;
while (1) {
callid = async_get_call(&call);
// printf("received call from phone %d, method=%d\n",
// call.in_phone_hash, IPC_GET_METHOD(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);
exit(0);
continue;
/* Not reached */
default:
retval = ENOENT;
break;
289,7 → 349,7
}
if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
printf("responding EINVAL to method %d\n",
DPRINTF("Responding EINVAL to method %d.\n",
IPC_GET_METHOD(call));
ipc_answer_0(callid, EINVAL);
}
300,31 → 360,20
*/
int main(int argc, char *argv[])
{
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t phone_hash;
 
/* The first call only communicates the incoming phone hash */
callid = ipc_wait_for_call(&call);
 
if (IPC_GET_METHOD(call) != LOADER_HELLO) {
if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP)
ipc_answer_0(callid, EINVAL);
return 1;
}
 
ipc_answer_0(callid, EOK);
phone_hash = call.in_phone_hash;
 
/*
* Up until now async must not be used as it couldn't
* handle incoming requests. (Which means e.g. printf()
* cannot be used)
*/
async_new_connection(phone_hash, 0, NULL, loader_connection);
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();
 
/* not reached */
/* Never reached */
return 0;
}
 
/branches/network/uspace/srv/loader/elf_load.c
57,6 → 57,8
#include "elf_load.h"
#include "arch.h"
 
#define DPRINTF(...)
 
static char *error_codes[] = {
"no error",
"invalid image",
106,11 → 108,9
int fd;
int rc;
 
// printf("open and read '%s'...\n", file_name);
 
fd = open(file_name, O_RDONLY);
if (fd < 0) {
printf("failed opening file\n");
DPRINTF("failed opening file\n");
return -1;
}
 
171,19 → 171,18
 
rc = my_read(elf->fd, header, sizeof(elf_header_t));
if (rc < 0) {
printf("read error\n");
DPRINTF("Read error.\n");
return EE_INVALID;
}
 
elf->header = header;
 
// printf("ELF-load:");
/* 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) {
printf("invalid header\n");
DPRINTF("Invalid header.\n");
return EE_INVALID;
}
193,18 → 192,18
header->e_ident[EI_VERSION] != EV_CURRENT ||
header->e_version != EV_CURRENT ||
header->e_ident[EI_CLASS] != ELF_CLASS) {
printf("incompatible data/version/class\n");
DPRINTF("Incompatible data/version/class.\n");
return EE_INCOMPATIBLE;
}
 
if (header->e_phentsize != sizeof(elf_segment_header_t)) {
printf("e_phentsize:%d != %d\n", header->e_phentsize,
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)) {
printf("e_shentsize:%d != %d\n", header->e_shentsize,
DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
sizeof(elf_section_header_t));
return EE_INCOMPATIBLE;
}
211,23 → 210,19
 
/* Check if the object type is supported. */
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
printf("Object type %d is not supported\n", header->e_type);
DPRINTF("Object type %d is not supported\n", header->e_type);
return EE_UNSUPPORTED;
}
 
/* Shared objects can be loaded with a bias */
// printf("Object type: %d\n", header->e_type);
if (header->e_type == ET_DYN)
elf->bias = so_bias;
else
elf->bias = 0;
 
// printf("Bias set to 0x%x\n", elf->bias);
elf->info->interp = NULL;
elf->info->dynamic = NULL;
 
// printf("parse segments\n");
 
/* Walk through all segment headers and process them. */
for (i = 0; i < header->e_phnum; i++) {
elf_segment_header_t segment_hdr;
239,7 → 234,7
rc = my_read(elf->fd, &segment_hdr,
sizeof(elf_segment_header_t));
if (rc < 0) {
printf("read error\n");
DPRINTF("Read error.\n");
return EE_INVALID;
}
 
248,7 → 243,7
return rc;
}
 
// printf("parse sections\n");
DPRINTF("Parse sections.\n");
 
/* Inspect all section headers and proccess them. */
for (i = 0; i < header->e_shnum; i++) {
261,7 → 256,7
rc = my_read(elf->fd, &section_hdr,
sizeof(elf_section_header_t));
if (rc < 0) {
printf("read error\n");
DPRINTF("Read error.\n");
return EE_INVALID;
}
 
273,7 → 268,7
elf->info->entry =
(entry_point_t)((uint8_t *)header->e_entry + elf->bias);
 
// printf("done\n");
DPRINTF("Done.\n");
 
return EE_OK;
}
316,7 → 311,7
case PT_LOPROC:
case PT_HIPROC:
default:
printf("segment p_type %d unknown\n", entry->p_type);
DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
return EE_UNSUPPORTED;
break;
}
339,8 → 334,8
size_t mem_sz;
int rc;
 
// printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
// entry->p_memsz);
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
entry->p_memsz);
bias = elf->bias;
 
347,7 → 342,7
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) !=
(entry->p_vaddr % entry->p_align)) {
printf("align check 1 failed offset%%align=%d, "
DPRINTF("Align check 1 failed offset%%align=%d, "
"vaddr%%align=%d\n",
entry->p_offset % entry->p_align,
entry->p_vaddr % entry->p_align
369,8 → 364,8
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
// printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
// entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
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
379,17 → 374,16
a = as_area_create((uint8_t *)base + bias, mem_sz,
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
if (a == (void *)(-1)) {
printf("memory mapping failed\n");
DPRINTF("Memory mapping failed.\n");
return EE_MEMORY;
}
 
// printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
// entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
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
*/
// printf("seek to %d\n", entry->p_offset);
rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
if (rc < 0) {
printf("seek error\n");
396,11 → 390,10
return EE_INVALID;
}
 
// printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
/* 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 picewise */
/* Long reads are not possible yet. Load segment piecewise. */
 
unsigned left, now;
uint8_t *dp;
412,12 → 405,10
now = 16384;
if (now > left) now = left;
 
// printf("read %d...", now);
rc = my_read(elf->fd, dp, now);
// printf("->%d\n", rc);
 
if (rc < 0) {
printf("read error\n");
DPRINTF("Read error.\n");
return EE_INVALID;
}
 
425,10 → 416,9
dp += now;
}
 
// printf("set area flags to %d\n", flags);
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
if (rc != 0) {
printf("failed to set memory area flags\n");
DPRINTF("Failed to set memory area flags.\n");
return EE_MEMORY;
}
 
465,7 → 455,7
/* Record pointer to dynamic section into info structure */
elf->info->dynamic =
(void *)((uint8_t *)entry->sh_addr + elf->bias);
printf("dynamic section found at 0x%x\n",
DPRINTF("Dynamic section found at 0x%x.\n",
(uintptr_t)elf->info->dynamic);
break;
default:
/branches/network/uspace/srv/loader/Makefile
27,30 → 27,19
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
include ../../Makefile.config
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
include arch/$(ARCH)/Makefile.inc
include arch/$(UARCH)/Makefile.inc
 
CFLAGS += -Iinclude
 
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(REVISION)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
## Sources
#
 
70,18 → 59,18
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(ARCH)/_link.ld Makefile.depend
-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/$(ARCH)/_link.ld
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map
$(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/$(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/network/uspace/srv/loader/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/network/uspace/srv/loader/arch/sparc64/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/sparc64.s
ARCH_SOURCES := arch/$(UARCH)/sparc64.s
/branches/network/uspace/srv/loader/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 {
12,15 → 12,10
*(.interp);
} :interp
 
. = 0x00084000 + SIZEOF_HEADERS;
/* On Itanium code sections must be aligned to 16 bytes. */
. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
 
.init : {
LONG(0);
LONG(0);
LONG(0);
LONG(0);
LONG(0);
LONG(0);
*(.init);
} : text
.text : {
/branches/network/uspace/srv/loader/arch/ia64/Makefile.inc
27,5 → 27,5
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/ia64.s
ARCH_SOURCES := arch/$(UARCH)/ia64.s
AFLAGS += -xexplicit
/branches/network/uspace/srv/loader/arch/arm32/_link.ld.in
1,8 → 1,8
/*
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
/branches/network/uspace/srv/loader/arch/arm32/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/arm32.s
ARCH_SOURCES := arch/$(UARCH)/arm32.s
/branches/network/uspace/srv/loader/arch/mips32eb
0,0 → 1,0
link mips32
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/network/uspace/srv/loader/arch/ppc32/_link.ld.in
1,8 → 1,8
/*
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
/branches/network/uspace/srv/loader/arch/ppc32/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/ppc32.s
ARCH_SOURCES := arch/$(UARCH)/ppc32.s
/branches/network/uspace/srv/loader/arch/ppc32/ppc32.s
36,5 → 36,5
# Jump to a program entry point
program_run:
mtctr %r3
mr %r3, %r4 # Pass pcb to the entry point in %r3
mr %r6, %r4 # Pass pcb to the entry point in %r6
bctr
/branches/network/uspace/srv/loader/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/network/uspace/srv/loader/arch/amd64/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/amd64.s
ARCH_SOURCES := arch/$(UARCH)/amd64.s
/branches/network/uspace/srv/loader/arch/mips32/_link.ld.in
1,8 → 1,8
/*
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
/branches/network/uspace/srv/loader/arch/mips32/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/mips32.s
ARCH_SOURCES := arch/$(UARCH)/mips32.s
/branches/network/uspace/srv/loader/arch/ia32/_link.ld.in
1,8 → 1,8
/*
/*
* The difference from _link.ld.in for regular statically-linked apps
* is the base address and the special interp section.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
/branches/network/uspace/srv/loader/arch/ia32/Makefile.inc
27,4 → 27,4
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/ia32.s
ARCH_SOURCES := arch/$(UARCH)/ia32.s
/branches/network/uspace/srv/net/nil/eth/eth.c
123,8 → 123,8
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
void eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
eth_proto_ref eth_proccess_packet( packet_t packet );
int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype );
eth_proto_ref eth_proccess_packet( int dummy, packet_t packet );
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype );
 
int eth_initialize( void ){
ERROR_DECLARE;
173,6 → 173,8
device->device_id = device_id;
device->service = service;
device->mtu = mtu;
// TODO get dummy setting
device->dummy = 0;
// bind the device driver
device->phone = bind_service( device->service, device->device_id, SERVICE_ETHERNET, 0, eth_receiver );
// get hardware address
204,7 → 206,7
return EOK;
}
 
eth_proto_ref eth_proccess_packet( packet_t packet ){
eth_proto_ref eth_proccess_packet( int dummy, packet_t packet ){
ERROR_DECLARE;
 
eth_header_ex_ref header;
215,6 → 217,9
eth_fcs_ref fcs;
 
length = packet_get_data_length( packet );
if( dummy ){
packet_trim( packet, sizeof( eth_preamble_t ), 0 );
}
if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_SUFFIX ) return NULL;
header = ( eth_header_ex_ref ) packet_get_data( packet );
type = ntohs( header->header.ethertype );
246,9 → 251,10
// invalid length/type, should not occurr
return NULL;
}
// TODO compute crc with fcs to erase?
if(( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )) != ntohl( * fcs )){
return NULL;
if( dummy ){
if(( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )) != ntohl( * fcs )){
return NULL;
}
}
if( ERROR_OCCURRED( packet_set_addr( packet, header->header.src, header->header.dest, ETH_ADDR ))
|| ERROR_OCCURRED( packet_trim( packet, prefix, suffix ))){
260,11 → 266,21
int eth_receive_message( device_id_t device_id, packet_t packet ){
eth_proto_ref proto;
packet_t next;
eth_device_ref device;
int dummy;
 
rwlock_read_lock( & eth_globals.devices_lock );
device = eth_devices_find( & eth_globals.devices, device_id );
if( ! device ){
rwlock_read_unlock( & eth_globals.devices_lock );
return ENOENT;
}
dummy = device->dummy;
rwlock_read_unlock( & eth_globals.devices_lock );
rwlock_read_lock( & eth_globals.protos_lock );
do{
next = pq_detach( packet );
proto = eth_proccess_packet( packet );
proto = eth_proccess_packet( dummy, packet );
if( proto ){
async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
}else{
347,7 → 363,7
return EOK;
}
 
int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype ){
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){
eth_header_ex_ref header;
eth_fcs_ref fcs;
uint8_t * src;
355,11 → 371,16
int length;
int i;
void * padding;
eth_preamble_ref preamble;
 
if( dummy ){
preamble = PACKET_PREFIX( packet, eth_preamble_t );
if( ! preamble ) return ENOMEM;
for( i = 0; i < 7; ++ i ) preamble->preamble[ i ] = ETH_PREAMBLE;
preamble->sfd = ETH_SFD;
}
header = PACKET_PREFIX( packet, eth_header_ex_t );
if( ! header ) return ENOMEM;
for( i = 0; i < 7; ++ i ) header->header.preamble[ i ] = ETH_PREAMBLE;
header->header.sfd = ETH_SFD;
length = packet_get_addr( packet, & src, & dest );
if( length < 0 ) return length;
if( length < ETH_ADDR ) return EINVAL;
378,9 → 399,11
header->lsap.ctrl = 0;
for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0;
header->snap.ethertype = ethertype;
fcs = PACKET_SUFFIX( packet, eth_fcs_t );
if( ! fcs ) return ENOMEM;
* fcs = htonl( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 ));
if( dummy ){
fcs = PACKET_SUFFIX( packet, eth_fcs_t );
if( ! fcs ) return ENOMEM;
* fcs = htonl( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 ));
}
return EOK;
}
 
406,7 → 429,7
// proccess packet queue
next = packet;
do{
if( ERROR_OCCURRED( eth_prepare_packet( next, ( uint8_t * ) device->addr->value, ethertype ))){
if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){
// release invalid packet
tmp = pq_detach( next );
packet_release( eth_globals.networking_phone, packet_get_id( next ));
/branches/network/uspace/srv/net/nil/eth/eth.h
97,6 → 97,10
/** Maximal transmission unit.
*/
size_t mtu;
/** Dummy device.
* Preamble and FCS are mandatory part of the packets.
*/
int dummy;
/** Actual device hardware address.
*/
measured_string_ref addr;
/branches/network/uspace/srv/net/nil/eth/eth_header.h
76,6 → 76,16
*/
typedef eth_header_snap_t * eth_header_snap_ref;
 
/** Type definition of the Ethernet header preamble.
* @see preamble
*/
typedef struct eth_preamble eth_preamble_t;
 
/** Type definition of the Ethernet header preamble pointer.
* @see eth_preamble
*/
typedef eth_preamble_t * eth_preamble_ref;
 
/** Type definition of the Ethernet header.
* @see eth_header
*/
115,9 → 125,10
uint16_t ethertype;
};
 
/** Ethernet header.
/** Ethernet header preamble.
* Used for dummy devices.
*/
struct eth_header{
struct eth_preamble{
/** Controlling preamble used for the frame transmission synchronization.
* All should be set to ETH_PREAMBLE.
*/
126,6 → 137,11
* Should be set to ETH_SFD.
*/
uint8_t sfd;
};
 
/** Ethernet header.
*/
struct eth_header{
/** Destination host Ethernet address (MAC address).
*/
uint8_t dest[ ETH_ADDR ];
/branches/network/uspace/srv/net/Makefile
30,6 → 30,7
 
DIRS = \
netif/lo \
netif/dp8390 \
networking \
networking/startup
 
/branches/network/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/network/uspace/srv/fb/serial_console.c
0,0 → 1,381
/*
* 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 "../console/screenbuffer.h"
#include "main.h"
#include "serial_console.h"
 
#define MAX_CONTROL 20
 
static void serial_sgr(const unsigned int mode);
 
static int scr_width;
static int scr_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 > scr_height) || (col > scr_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(scr_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)
{
scr_width = w;
scr_height = h;
putc_function = putc_fn;
}
 
static void serial_set_style(int style)
{
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);
}
}
 
static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
unsigned flags)
{
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);
}
}
 
static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
{
if (fgcolor < bgcolor)
serial_sgr(SGR_REVERSE_OFF);
else
serial_sgr(SGR_REVERSE);
}
 
static void serial_set_attrs(const attrs_t *a)
{
switch (a->t) {
case at_style: serial_set_style(a->a.s.style); break;
case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
case at_idx: serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags); break;
default: break;
}
}
 
static void draw_text_data(keyfield_t *data)
{
int i, j;
attrs_t *a0, *a1;
 
serial_goto(0, 0);
a0 = &data[0].attrs;
serial_set_attrs(a0);
 
for (i = 0; i < scr_height; i++) {
for (j = 0; j < scr_width; j++) {
a1 = &data[i * scr_width + j].attrs;
if (!attrs_same(*a0, *a1))
serial_set_attrs(a1);
(*putc_function)(data[i * scr_width + j].character);
a0 = a1;
}
}
}
 
/**
* 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;
keyfield_t *interbuf = NULL;
size_t intersize = 0;
 
char c;
int lastcol = 0;
int lastrow = 0;
int newcol;
int newrow;
int fgcolor;
int bgcolor;
int flags;
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(scr_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 IPC_M_SHARE_OUT:
/* We accept one area for data interchange */
intersize = IPC_GET_ARG2(call);
if (intersize >= scr_width * scr_height *
sizeof(*interbuf)) {
receive_comm_area(callid, &call,
(void *) &interbuf);
continue;
}
retval = EINVAL;
break;
case FB_DRAW_TEXT_DATA:
if (!interbuf) {
retval = EINVAL;
break;
}
draw_text_data(interbuf);
retval = 0;
break;
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, scr_height, scr_width);
continue;
case FB_CLEAR:
serial_clrscr();
retval = 0;
break;
case FB_SET_STYLE:
style = IPC_GET_ARG1(call);
serial_set_style(style);
retval = 0;
break;
case FB_SET_COLOR:
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
flags = IPC_GET_ARG3(call);
 
serial_set_idx(fgcolor, bgcolor, flags);
retval = 0;
break;
case FB_SET_RGB_COLOR:
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
 
serial_set_rgb(fgcolor, bgcolor);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if ((i > scr_height) || (i < -scr_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/network/uspace/srv/fb/msim.c
36,29 → 36,17
*/
 
#include <async.h>
#include <ipc/fb.h>
#include <ipc/ipc.h>
#include <libc.h>
#include <errno.h>
#include <string.h>
#include <libc.h>
#include <stdio.h>
#include <ipc/fb.h>
#include <sysinfo.h>
#include <as.h>
#include <align.h>
#include <ddi.h>
 
#include "serial_console.h"
#include "msim.h"
 
#define WIDTH 80
#define HEIGHT 25
 
#define MAX_CONTROL 20
 
/* Allow only 1 connection */
static int client_connected = 0;
 
static char *virt_addr;
 
static void msim_putc(const char c)
66,159 → 54,17
*virt_addr = c;
}
 
static void msim_puts(char *str)
{
while (*str)
*virt_addr = *(str++);
}
 
static void msim_clrscr(void)
{
msim_puts("\033[2J");
}
 
static void msim_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);
msim_puts(control);
}
 
static void msim_set_style(const unsigned int mode)
{
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%um", mode);
msim_puts(control);
}
 
static void msim_cursor_disable(void)
{
msim_puts("\033[?25l");
}
 
static void msim_cursor_enable(void)
{
msim_puts("\033[?25h");
}
 
static void msim_scroll(int i)
{
if (i > 0) {
msim_goto(HEIGHT - 1, 0);
while (i--)
msim_puts("\033D");
} else if (i < 0) {
msim_goto(0, 0);
while (i++)
msim_puts("\033M");
}
}
 
static void msim_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 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 - 25 lines */
msim_clrscr();
msim_goto(0, 0);
msim_puts("\033[0;25r");
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))
msim_goto(newrow, newcol);
lastcol = newcol + 1;
lastrow = newrow;
msim_putc(c);
retval = 0;
break;
case FB_CURSOR_GOTO:
newrow = IPC_GET_ARG1(call);
newcol = IPC_GET_ARG2(call);
msim_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:
msim_clrscr();
retval = 0;
break;
case FB_SET_STYLE:
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
if (fgcolor < bgcolor)
msim_set_style(0);
else
msim_set_style(7);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if ((i > HEIGHT) || (i < -HEIGHT)) {
retval = EINVAL;
break;
}
msim_scroll(i);
msim_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
if(IPC_GET_ARG1(call))
msim_cursor_enable();
else
msim_cursor_disable();
retval = 0;
break;
default:
retval = ENOENT;
}
ipc_answer_0(callid, retval);
}
}
 
int msim_init(void)
{
void *phys_addr = (void *) sysinfo_value("fb.address.physical");
virt_addr = (char *) as_get_mappable_page(1);
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE);
if (physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE) != 0)
return -1;
async_set_client_connection(msim_client_connection);
serial_console_init(msim_putc, WIDTH, HEIGHT);
async_set_client_connection(serial_client_connection);
return 0;
}
 
/branches/network/uspace/srv/fb/serial_console.h
0,0 → 1,56
/*
* 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_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/network/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/network/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/network/uspace/srv/fb/main.c
38,6 → 38,8
#include "fb.h"
#include "ega.h"
#include "msim.h"
#include "ski.h"
#include "sgcn.h"
#include "main.h"
 
#define NAME "fb"
45,7 → 47,7
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)
60,12 → 62,12
ipcarg_t phonead;
bool initialized = false;
 
#ifdef FB_ENABLED
if (sysinfo_value("fb.kind") == 1) {
if (fb_init() == 0)
initialized = true;
}
}
#endif
#ifdef EGA_ENABLED
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) {
79,15 → 81,28
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)
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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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
45,27 → 46,45
main.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)
SOURCES += msim.c
CFLAGS += -DMSIM_ENABLED -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
75,13 → 94,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/srv/fs/tmpfs/tmpfs_dump.c
38,17 → 38,12
 
#include "tmpfs.h"
#include "../../vfs/vfs.h"
#include <ipc/ipc.h>
#include <async.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <as.h>
#include <libfs.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
#include <sys/mman.h>
#include <libblock.h>
#include <byteorder.h>
 
#define TMPFS_BLOCK_SIZE 1024
59,11 → 54,12
} __attribute__((packed));
 
static bool
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen,
off_t *pos, tmpfs_dentry_t *parent)
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;
70,8 → 66,8
tmpfs_dentry_t *node;
uint32_t size;
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE) != EOK)
return false;
entry.len = uint32_t_le2host(entry.len);
84,14 → 80,14
if (fname == NULL)
return false;
node = (tmpfs_dentry_t *) ops->create(L_FILE);
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE);
if (node == NULL) {
free(fname);
return false;
}
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
98,7 → 94,8
}
fname[entry.len] = 0;
if (!ops->link((void *) parent, (void *) node, fname)) {
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
105,8 → 102,8
}
free(fname);
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
&size, sizeof(size), TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE) != EOK)
return false;
size = uint32_t_le2host(size);
116,8 → 113,8
return false;
node->size = size;
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
node->data, size, TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE) != EOK)
return false;
break;
126,21 → 123,22
if (fname == NULL)
return false;
node = (tmpfs_dentry_t *) ops->create(L_DIRECTORY);
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY);
if (node == NULL) {
free(fname);
return false;
}
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
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;
if (!ops->link((void *) parent, (void *) node, fname)) {
 
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
147,8 → 145,8
}
free(fname);
if (!tmpfs_restore_recursion(phone, block, bufpos,
buflen, pos, node))
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
node))
return false;
break;
163,32 → 161,19
bool tmpfs_restore(dev_handle_t dev)
{
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
 
void *block = mmap(NULL, TMPFS_BLOCK_SIZE,
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
rc = block_init(dev, TMPFS_BLOCK_SIZE);
if (rc != EOK)
return false;
if (block == NULL)
return false;
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev);
 
if (phone < 0) {
munmap(block, TMPFS_BLOCK_SIZE);
return false;
}
if (ipc_share_out_start(phone, block, AS_AREA_READ | AS_AREA_WRITE) !=
EOK)
goto error;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = 0;
char tag[6];
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE))
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE) != EOK)
goto error;
tag[5] = 0;
195,17 → 180,15
if (strcmp(tag, "TMPFS") != 0)
goto error;
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos,
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos,
ops->root_get(dev)))
goto error;
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return true;
error:
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return false;
}
 
/branches/network/uspace/srv/fs/tmpfs/tmpfs.c
55,16 → 55,6
 
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_MOUNTED)] = 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;
136,18 → 126,15
 
int main(int argc, char **argv)
{
int vfs_phone;
 
printf(NAME ": 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);
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(NAME ": Failed to register file system (%d)\n", rc);
/branches/network/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,7 → 230,7
{
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;
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)
/branches/network/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
#
56,13 → 61,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/srv/fs/fat/fat_idx.c
214,7 → 214,7
};
 
/** 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)
{
unused_t *u;
276,7 → 276,7
}
 
/** 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)
{
unused_t *u;
 
338,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)
{
354,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,
370,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);
387,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)
{
408,6 → 470,33
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))
/branches/network/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>
44,7 → 45,12
#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 */
115,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,
223,9 → 201,16
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);
/branches/network/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/network/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/network/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/network/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/network/uspace/srv/fs/fat/fat.c
49,15 → 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_MOUNTED)] = VFS_OP_DEFINED,
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL,
}
};
 
fs_reg_t fat_reg;
110,6 → 101,15
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;
122,16 → 122,16
int vfs_phone;
int rc;
 
printf("FAT: HelenOS FAT file system server.\n");
printf("fat: HelenOS FAT file system server.\n");
 
rc = fat_idx_init();
if (rc != EOK)
goto err;
 
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);
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;
}
rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection);
/branches/network/uspace/srv/fs/fat/fat_ops.c
36,8 → 36,11
*/
 
#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>
50,10 → 53,8
#include <assert.h>
#include <futex.h>
#include <sys/mman.h>
#include <align.h>
 
#define BS_BLOCK 0
#define BS_SIZE 512
 
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
 
60,216 → 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
 
#define min(a, b) ((a) < (b) ? (a) : (b))
 
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)
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';
}
 
static int dev_phone = -1; /* FIXME */
static void *dev_buffer = NULL; /* FIXME */
 
/* TODO move somewhere else */
typedef struct {
void *data;
size_t size;
} block_t;
 
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
{
/* FIXME */
block_t *b;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = offset * bs;
 
assert(dev_phone != -1);
assert(dev_buffer);
 
b = malloc(sizeof(block_t));
if (!b)
return NULL;
b->data = malloc(bs);
if (!b->data) {
free(b);
return NULL;
}
b->size = bs;
 
if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos,
b->data, bs, bs)) {
free(b->data);
free(b);
return NULL;
}
 
return b;
}
 
static void block_put(block_t *block)
{
/* FIXME */
free(block->data);
free(block);
}
 
#define FAT_BS(b) ((fat_bs_t *)((b)->data))
 
#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
 
#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, BS_SIZE);
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_ROOT) {
/* root directory special case */
assert(offset < rds);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
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, bps);
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, bps);
 
return b;
}
 
/** Return number of blocks allocated to a file.
*
* @param dev_handle Device handle of the device with the file.
* @param firstc First cluster of the file.
*
* @return Number of blocks allocated to the file.
*/
static uint16_t
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc)
{
block_t *bb;
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned clusters = 0;
fat_cluster_t clst = firstc;
 
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
spc = FAT_BS(bb)->spc;
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
block_put(bb);
 
if (firstc == FAT_CLST_RES0) {
/* No space allocated to the file. */
return 0;
}
 
while (clst < FAT_CLST_LAST1) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST);
fsec = (clst * sizeof(fat_cluster_t)) / bps;
fidx = clst % (bps / sizeof(fat_cluster_t));
/* read FAT1 */
b = block_get(dev_handle, rscnt + fsec, bps);
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
assert(clst != FAT_CLST_BAD);
block_put(b);
clusters++;
}
 
return clusters * spc;
}
 
static void fat_node_initialize(fat_node_t *node)
{
futex_initialize(&node->lock, 1);
282,52 → 73,73
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, BS_SIZE);
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 */
fat_node_t *nodep;
 
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
return NULL;
}
fat_node_initialize(nodep);
return nodep;
}
 
/** Internal version of fat_node_get().
337,9 → 149,11
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) {
360,41 → 174,18
assert(idxp->pfc);
 
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
return NULL;
}
fat_node_initialize(nodep);
nodep = fat_node_get_new();
if (!nodep)
return NULL;
 
bps = fat_bps_get(idxp->dev_handle);
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);
410,7 → 201,7
* defined for the directory entry type. We must determine the
* size of the directory by walking the FAT.
*/
nodep->size = bps * _fat_blcks_get(idxp->dev_handle,
nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle,
uint16_t_le2host(d->firstc));
} else {
nodep->type = FAT_FILE;
429,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;
444,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;
489,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);
510,10 → 598,10
return NULL;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
break;
}
if (stricmp(name, component) == 0) {
if (fat_dentry_namecmp(name, component) == 0) {
/* hit */
void *node;
/*
542,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)
554,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;
575,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);
616,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 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;
}
641,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,
655,60 → 743,57
.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);
block_t *bb;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
int rc;
 
/*
* For now, we don't bother to remember dev_handle, dev_phone or
* dev_buffer in some data structure. We use global variables because we
* know there will be at most one mount on this file system.
* Of course, this is a huge TODO item.
*/
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!dev_buffer) {
ipc_answer_0(rid, ENOMEM);
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
ipc_answer_0(rid, rc);
return;
}
 
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, dev_phone);
return;
}
 
rc = ipc_share_out_start(dev_phone, dev_buffer,
AS_AREA_READ | AS_AREA_WRITE);
/* prepare the boot block */
rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
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. */
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
block_put(bb);
bps = uint16_t_le2host(bs->bps);
rde = uint16_t_le2host(bs->root_ent_max);
 
if (bps != BS_SIZE) {
munmap(dev_buffer, 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) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
ipc_answer_0(rid, rc);
return;
}
716,7 → 801,7
/* Initialize the root node. */
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
725,7 → 810,7
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
763,7 → 848,8
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);
uint16_t bps = fat_bps_get(dev_handle);
fat_bs_t *bs;
uint16_t bps;
size_t bytes;
block_t *b;
 
781,6 → 867,9
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
787,11 → 876,19
* most and make use of the possibility to return less data than
* requested. This keeps the code very simple.
*/
bytes = min(len, bps - pos % bps);
b = fat_block_get(nodep, pos / bps);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
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;
812,7 → 909,7
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(nodep, bnum);
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++) {
819,6 → 916,7
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);
825,7 → 923,7
goto miss;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
block_put(b);
goto hit;
}
847,6 → 945,186
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/network/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,7 → 50,9
SOURCES = \
fat.c \
fat_ops.c \
fat_idx.c
fat_idx.c \
fat_dentry.c \
fat_fat.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
56,13 → 63,13
-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: $(OUTPUT).disasm
 
/branches/network/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/network/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/network/uspace/srv/obio
Property changes:
Added: svn:mergeinfo
/branches/network/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/network/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,7 → 45,7
SOURCES = \
devmap.c
 
CFLAGS += -D$(ARCH)
CFLAGS += -D$(UARCH)
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
55,13 → 56,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/srv/devmap/devmap.c
28,9 → 28,9
 
/**
* @defgroup devmap Device mapper.
* @brief HelenOS device mapper.
* @brief HelenOS device mapper.
* @{
*/
*/
 
/** @file
*/
46,17 → 46,24
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#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;
63,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.
*
*
*/
90,7 → 98,7
static int devmap_init()
{
/* TODO: */
 
return EOK;
}
 
99,108 → 107,101
*/
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)
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)) {
free(driver);
ipc_answer_0(callid, EREFUSED);
207,7 → 208,7
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (name_size > DEVMAP_NAME_MAXLEN) {
free(driver);
ipc_answer_0(callid, EINVAL);
214,17 → 215,18
ipc_answer_0(iid, EREFUSED);
return;
}
 
/*
* Allocate buffer for device name.
*/
if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
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.
*/
234,22 → 236,23
ipc_answer_0(iid, EREFUSED);
return;
}
 
driver->name[name_size] = 0;
 
/* 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)) {
ipc_answer_0(callid, ENOTSUP);
258,73 → 261,95
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);
 
*odriver = driver;
}
 
/** 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)
if (driver == NULL)
return EEXISTS;
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);
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;
}
 
 
/** 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;
}
}
 
 
/** Register instance of device
*
*/
331,29 → 356,27
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) {
if (driver == NULL) {
ipc_answer_0(iid, EREFUSED);
return;
}
/* Create new device entry */
if (NULL ==
(device = (devmap_device_t *) malloc(sizeof(devmap_device_t)))) {
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);
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (size > DEVMAP_NAME_MAXLEN) {
free(device);
ipc_answer_0(callid, EINVAL);
363,8 → 386,8
/* +1 for terminating \0 */
device->name = (char *) malloc(size + 1);
 
if (NULL == device->name) {
if (device->name == NULL) {
free(device);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
373,12 → 396,12
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(NAME ": Device '%s' already registered\n", device->name);
388,24 → 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);
 
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
ipc_answer_1(iid, EOK, device->handle);
process_pending_lookup();
}
 
/**
415,129 → 440,142
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) {
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);
}
 
/** 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) {
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;
}
 
ipc_answer_1(iid, EOK, dev->handle);
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 */
}
 
546,31 → 584,30
*/
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)
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:
cont = false;
continue; /* Exit thread */
/* Exit thread */
continue;
case DEVMAP_DRIVER_UNREGISTER:
if (NULL == driver) {
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 */
587,20 → 624,18
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.
608,23 → 643,21
*/
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:
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 */
631,14 → 664,13
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)
656,10 → 688,9
devmap_forward(iid, icall);
break;
default:
ipc_answer_0(iid, ENOENT); /* No such interface */
/* No such interface */
ipc_answer_0(iid, ENOENT);
}
 
/* Cleanup */
}
 
/**
669,8 → 700,6
{
printf(NAME ": HelenOS Device Mapper\n");
ipcarg_t phonead;
 
if (devmap_init() != 0) {
printf(NAME ": Error while initializing service\n");
return -1;
678,13 → 707,15
/* 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;
}
/branches/network/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>
49,18 → 49,16
 
#define NAME "vfs"
 
#define dprintf(...) printf(__VA_ARGS__)
 
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = 1;
 
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,18 → 70,38
* connection later.
*/
while (keep_on_going) {
ipc_callid_t callid;
ipc_call_t call;
 
callid = async_get_call(&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);
120,22 → 138,19
break;
}
}
 
/* TODO: cleanup after the client */
}
 
int main(int argc, char **argv)
{
ipcarg_t phonead;
 
printf(NAME ": HelenOS VFS server\n");
 
/*
* Initialize the list of registered file systems.
*/
list_initialize(&fs_head);
 
/*
* Initialize VFS node hash table.
*/
143,7 → 158,7
printf(NAME ": Failed to initialize VFS node hash table\n");
return ENOMEM;
}
 
/*
* Allocate and initialize the Path Lookup Buffer.
*/
153,6 → 168,7
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(NAME ": Cannot create address space area\n");
164,12 → 180,13
* 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.
*/
180,4 → 197,4
 
/**
* @}
*/
*/
/branches/network/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.
67,135 → 79,43
.dev_handle = 0
};
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle,
fs_handle_t fs_handle, char *mp)
{
dev_handle_t dev_handle;
/* Resolve the path to the mountpoint. */
vfs_lookup_res_t mp_res;
vfs_node_t *mp_node = NULL;
ipc_callid_t callid;
ipc_call_t data;
int rc;
int phone;
size_t size;
 
/*
* 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.
*/
 
/*
* 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';
/*
* Wait for IPC_M_PING so that we can return an error if we don't know
* fs_name.
*/
callid = async_get_call(&data);
if (IPC_GET_METHOD(data) != IPC_M_PING) {
ipc_answer_0(callid, ENOTSUP);
ipc_answer_0(rid, ENOTSUP);
return;
}
 
/*
* 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(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
 
/* 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';
 
/* 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);
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);
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);
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.
204,18 → 124,17
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);
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
228,21 → 147,22
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 {
251,7 → 171,6
* being mounted first.
*/
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, ENOENT);
return;
}
258,13 → 177,11
}
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.
*/
 
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
rc = async_req_4_0(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
272,7 → 189,7
(ipcarg_t) fs_handle,
(ipcarg_t) dev_handle);
vfs_release_phone(phone);
 
if (rc != EOK) {
/* Mount failed, drop reference to mp_node. */
if (mp_node)
282,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()) {
302,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)
456,7 → 547,7
* the same open file at a time.
*/
futex_down(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
* the same time.
465,6 → 556,15
rwlock_read_lock(&file->node->contents_rwlock);
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);
490,6 → 590,9
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)
/branches/network/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/network/uspace/srv/vfs/vfs.h
47,8 → 47,6
 
#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;
81,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;
 
/**
190,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;
213,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. */
 
/**
290,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/network/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/network/uspace/srv/vfs/vfs_lookup.c
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/network/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
57,13 → 58,13
-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: $(OUTPUT).disasm
 
/branches/network/uspace/Makefile
29,11 → 29,12
## Include configuration
#
 
-include Makefile.config
-include ../Makefile.config
 
DIRS = \
lib/libc \
lib/libfs \
lib/libblock \
lib/softint \
lib/softfloat \
srv/ns \
49,49 → 50,37
srv/net \
app/tetris \
app/tester \
app/trace \
app/klog \
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) NETWORKING=$(NETWORKING)
$(MAKE) -C $(basename $@) all
 
/branches/network/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,443
# 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 endian
! [PLATFORM=mips32] MACHINE (choice)
 
# Machine type
% Machine type
@ "i460GX" i460GX chipset machine
@ "ski" Ski ia64 simulator
@ "i460GX" i460GX chipset machine
! [PLATFORM=ia64] MACHINE (choice)
 
# Compiler
% Machine type
@ "generic" Generic Sun workstation or server
@ "serengeti" Serengeti system
! [PLATFORM=sparc64] MACHINE (choice)
 
% 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=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=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
 
## 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)
 
% Debug build
! CONFIG_DEBUG (y/n)
 
# Networking architecture
% Deadlock detection support for spinlocks
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (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)
 
% Kernel symbol information
! CONFIG_SYMTAB (y/n)
 
% Detailed kernel logging
! CONFIG_LOG (n/y)
 
% Compile kernel tests
! CONFIG_TEST (y/n)
 
 
## Hardware support
 
% Input device class
@ "generic" Keyboard or serial line
@ "none" No input device
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=sparc64] CONFIG_HID_IN (choice)
 
% Input device class
@ "generic" Keyboard or serial line
@ "keyboard" Keyboard
@ "serial" Serial line
@ "none" No input device
! [PLATFORM=ia64&MACHINE=i460GX] CONFIG_HID_IN (choice)
 
% Output device class
@ "generic" Monitor or serial line
@ "none" No output device
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ppc32|(PLATFORM=ia64&MACHINE=i460GX)|(PLATFORM=mips32&MACHINE=msim)] CONFIG_HID_OUT (choice)
 
% Output device class
@ "generic" Monitor or serial line
@ "monitor" Monitor
@ "serial" Serial line
@ "none" No output device
! [PLATFORM=mips32&(MACHINE=bgxemul|MACHINE=lgxemul)] CONFIG_HID_OUT (choice)
 
% Output device class
@ "generic" Monitor or serial line
@ "monitor" Monitor
@ "serial" Serial line
@ "none" No output device
! [PLATFORM=arm32] CONFIG_HID_OUT (choice)
 
% PC keyboard support
! [CONFIG_HID_IN=generic&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_PC_KBD (y/n)
 
% PC keyboard support
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=ia64&MACHINE=i460GX] CONFIG_PC_KBD (y/n)
 
% Support for msim/GXemul keyboard
! [CONFIG_HID_IN=generic&PLATFORM=mips32] CONFIG_MIPS_KBD (y/n)
 
% Support for msim/GXemul printer
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=mips32] CONFIG_MIPS_PRN (y/n)
 
% Support for GXemul keyboard
! [CONFIG_HID_IN=generic&PLATFORM=arm32] CONFIG_ARM_KBD (y/n)
 
% Support for GXemul printer
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32] CONFIG_ARM_PRN (y/n)
 
% Support for NS16550 controller
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic] CONFIG_NS16550 (y/n)
 
% Support for NS16550 controller
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=serial)&PLATFORM=ia64&MACHINE=i460GX] CONFIG_NS16550 (y/n)
 
% Support for Z8530 controller
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboardl)&PLATFORM=sparc64&MACHINE=generic] CONFIG_Z8530 (y/n)
 
% Support for Serengeti console
! [(CONFIG_HID_IN=generic|CONFIG_HID_OUT=generic)&PLATFORM=sparc64&MACHINE=serengeti] CONFIG_SGCN (y/n)
 
% i8042 controller support
! [CONFIG_PC_KBD=y] CONFIG_I8042 (y)
 
% Sun keyboard support
! [PLATFORM=sparc64&(CONFIG_NS16550=y|CONFIG_Z8530=y)] CONFIG_SUN_KBD (y)
 
% Dummy serial line input
! [CONFIG_MIPS_KBD=y|CONFIG_ARM_KBD=y] CONFIG_DSRLNIN (y)
 
% Dummy serial line output
! [CONFIG_MIPS_PRN=y|CONFIG_ARM_PRN=y] CONFIG_DSRLNOUT (y)
 
% Serial line input module
! [CONFIG_DSRLNIN=y|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)] CONFIG_SRLN (y)
 
% EGA support
! [CONFIG_HID_OUT=generic&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_EGA (y/n)
 
% EGA support
! [CONFIG_HID_OUT=generic&PLATFORM=ia64&MACHINE=i460GX] CONFIG_EGA (y/n)
 
% Framebuffer support
! [CONFIG_HID_OUT=generic&(PLATFORM=ia32|PLATFORM=amd64|PLATFORM=ppc32)] CONFIG_FB (y/n)
 
% Framebuffer support
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor)&PLATFORM=mips32&(MACHINE=lgxemul|MACHINE=bgxemul)] CONFIG_FB (y/n)
 
% Framebuffer support
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor)&PLATFORM=arm32] CONFIG_FB (y/n)
 
% Framebuffer support
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=monitor)&PLATFORM=sparc64&MACHINE=generic] CONFIG_FB (y/n)
 
% Default framebuffer mode
@ "640x480"
@ "800x600"
@ "1024x768"
@ "1152x720"
@ "1152x864"
@ "1280x960"
@ "1280x1024"
@ "1400x1050"
@ "1440x900"
@ "1440x1050"
@ "1600x1200"
@ "1920x1080"
@ "1920x1200"
! [(PLATFORM=ia32|PLATFORM=amd64)&CONFIG_HID_OUT!=none&CONFIG_FB=y] CONFIG_VESA_MODE (choice)
 
% Default framebuffer depth
@ "8"
@ "16"
@ "24"
! [(PLATFORM=ia32|PLATFORM=amd64)&CONFIG_HID_OUT!=none&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)
 
% Networking architecture
@ "modular" Modular
@ "module" One module
! [PLATFORM=ia32] NETWORKING (choice)
 
/branches/network/boot/boot.config
File deleted
/branches/network/boot/tools/ppc32/font-8x16.c
File deleted
/branches/network/boot/tools/ppc32/Makefile
File deleted
/branches/network/boot/tools/ppc32/font-8x16.h
File deleted
/branches/network/boot/tools/ppc32/debug.c
File deleted
/branches/network/boot/tools/ia64/vmaxlma.c
File deleted
/branches/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/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/network/boot/arch/ppc64/Makefile.inc
File deleted
/branches/network/boot/arch/ppc64/loader/asm.h
File deleted
/branches/network/boot/arch/ppc64/loader/ofwarch.c
File deleted
/branches/network/boot/arch/ppc64/loader/types.h
File deleted
/branches/network/boot/arch/ppc64/loader/main.h
File deleted
/branches/network/boot/arch/ppc64/loader/Makefile
File deleted
/branches/network/boot/arch/ppc64/loader/debug.inc
File deleted
/branches/network/boot/arch/ppc64/loader/ofwarch.h
File deleted
/branches/network/boot/arch/ppc64/loader/_link.ld.in
File deleted
/branches/network/boot/arch/ppc64/loader/asm.S
File deleted
/branches/network/boot/arch/ppc64/loader/regname.h
File deleted
/branches/network/boot/arch/ppc64/loader/boot.S
File deleted
/branches/network/boot/arch/ppc64/loader/main.c
File deleted
/branches/network/boot/arch/ia32xen/Makefile.inc
File deleted
/branches/network/boot/arch/ia32xen/grub/COPYING
File deleted
/branches/network/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/network/boot/arch/ia32xen/grub/menu.debug.lst
File deleted
/branches/network/boot/arch/ia32xen/grub/README
File deleted
/branches/network/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/network/boot/arch/ia32xen/grub/menu.lst
File deleted
/branches/network/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/network/boot/arch/sparc64/Makefile.inc
26,26 → 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/network/boot/arch/sparc64/loader/asm.S
105,9 → 105,28
* 1. Make sure that the code we have moved has drained to main memory.
* 2. Invalidate I-cache.
* 3. Flush instruction pipeline.
*/
call icache_flush
membar #StoreStore
*/
 
/*
* 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
134,7 → 153,6
retl
! SF Erratum #51
nop
 
.global ofw
ofw:
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
/branches/network/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/network/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/network/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/network/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,36 → 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,
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) {
93,7 → 101,7
* Start secondary processor.
*/
(void) ofw_call("SUNW,start-cpu", 3, 1,
NULL, node, KERNEL_VIRTUAL_ADDRESS,
NULL, child, KERNEL_VIRTUAL_ADDRESS,
bootinfo.physmem_start |
AP_PROCESSOR);
}
104,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/network/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/network/boot/arch/sparc64/loader/Makefile
27,7 → 27,7
#
 
include ../../../../version
include ../../../Makefile.config
-include ../../../../Makefile.config
 
## Toolchain configuration
#
57,16 → 57,8
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 \
79,6 → 71,9
asm.S \
boot.S
 
#
# All components that go to image.boot without the ramdisk.
#
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
94,19 → 89,40
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
#
# 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/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
 
ifeq ($(MACHINE),generic)
RD_SRVS += \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fhc/fhc \
$(USPACEDIR)/srv/obio/obio
endif
 
RD_APPS = \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
$(USPACEDIR)/app/bdsh/bdsh \
$(USPACEDIR)/app/klog/klog
 
ifeq ($(MACHINE),generic)
RD_APPS += \
$(USPACEDIR)/app/tester/tester
endif
 
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
 
114,31 → 130,37
 
-include Makefile.depend
 
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 $@
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:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend
-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 _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_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.sh $(USPACEDIR)/dist/ initrd.fs
../../../../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" $(COMPONENTS) ./initrd.img
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(ALL_COMPONENTS)
 
%.o: %.S
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/network/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/network/boot/arch/sparc64/silo/silo.conf
1,3 → 1,4
timeout = 0
image = /HelenOS/image.boot.gz
label = HelenOS
initrd = /HelenOS/initrd.img
/branches/network/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/network/boot/arch/ia64/loader/_link.ld.in
12,11 → 12,14
*(.data); /* initialized data */
_got = . ;
*(.got .got.*);
*(.bss); /* uninitialized static variables */
*(COMMON);
}
 
.sboot : {
*(.sdata);
*(.sdata2);
*(.sbss);
*(.bss); /* uninitialized static variables */
*(COMMON);
}
/DISCARD/ : {
/branches/network/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/network/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/network/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/network/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/network/boot/arch/ia64/loader/gefi/apps/Makefile
28,7 → 28,7
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
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name)
FORMAT = efi-app-$(ARCH)
 
TARGETS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi printenv.efi t7.efi
/branches/network/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/network/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/network/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/network/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/network/boot/arch/ia64/loader/gefi/HelenOS/Makefile
28,6 → 28,7
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
FORMAT = efi-app-$(ARCH)
 
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/network/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/network/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/network/boot/arch/ia64/loader/Makefile
27,7 → 27,7
#
 
include ../../../../version
include ../../../Makefile.config
-include ../../../../Makefile.config
 
## Toolchain configuration
#
47,7 → 47,7
LD = ld
OBJCOPY = objcopy
OBJDUMP = objdump
GEFI_PREXIX =
GEFI_PREFIX =
endif
 
ifeq ($(COMPILER),icc_native)
68,16 → 68,8
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 \
87,21 → 79,36
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))))
115,22 → 122,41
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 image.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 _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot image.map image.disasm Makefile.depend ../../../../image.bin ../../../../hello.efi
-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 _components.c _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) _link.ld.in
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned long" $(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 $@
/branches/network/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/network/boot/arch/arm32/loader/boot.S
53,5 → 53,3
# make place for PTL0 page table
page_table:
.skip PTL0_ENTRIES * PTL0_ENTRY_SIZE
 
 
/branches/network/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
101,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;
108,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/network/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/network/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/network/boot/arch/arm32/loader/Makefile
27,7 → 27,7
#
 
include ../../../../version
include ../../../Makefile.config
-include ../../../../Makefile.config
 
## Toolchain configuration
#
57,20 → 57,8
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 \
79,6 → 67,7
print/gxemul.c \
_components.c \
../../../generic/printf.c \
../../../generic/string.c \
../../../genarch/division.c
 
COMPONENTS = \
96,14 → 85,17
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(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/bdsh/bdsh
 
120,23 → 112,29
$(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:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-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 _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_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.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
/branches/network/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/network/boot/arch/ppc32/loader/debug.inc
File deleted
/branches/network/boot/arch/ppc32/loader/_link.ld.in
1,9 → 1,9
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH(powerpc:common)
ENTRY(start)
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH(powerpc:common)
ENTRY(start)
 
SECTIONS {
.boot 0x10000000: AT (0) {
.boot 0x01000000: AT (0) {
*(BOOTSTRAP);
*(REALMODE);
*(.text);
10,12 → 10,12
*(.rodata);
*(.rodata.*);
*(.data); /* initialized data */
*(.data); /* initialized data */
*(.sdata);
*(.sdata2);
*(.sbss);
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
*(.bss); /* uninitialized static variables */
*(COMMON); /* global variables */
[[COMPONENTS]]
}
}
/branches/network/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/network/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/network/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)
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/network/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/network/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/network/boot/arch/ppc32/loader/Makefile
27,7 → 27,7
#
 
include ../../../../version
include ../../../Makefile.config
-include ../../../../Makefile.config
 
## Toolchain configuration
#
57,16 → 57,8
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 \
73,6 → 65,7
_components.c \
../../../genarch/ofw.c \
../../../generic/printf.c \
../../../generic/string.c \
asm.S \
boot.S
 
83,7 → 76,7
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
91,14 → 84,17
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(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/bdsh/bdsh
 
115,23 → 111,29
$(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:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-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 _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_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.sh $(USPACEDIR)/dist/ initrd.fs
../../../../tools/mkfat.py $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
/branches/network/boot/arch/amd64/Makefile.inc
40,49 → 40,58
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/pci/pci \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(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/bdsh/bdsh \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
$(USPACEDIR)/app/bdsh/bdsh
 
build: $(BASE)/image.iso
 
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS)
mkdir -p arch/$(ARCH)/iso/boot/grub
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/
$(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/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst
cat arch/$(BARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(BARCH)/iso/boot/grub/menu.lst
endif
ifneq ($(RDFMT),fat)
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst
cat arch/$(BARCH)/grub/menu.lst | grep -v "fat" >arch/$(BARCH)/iso/boot/grub/menu.lst
endif
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/
cp $(KERNELDIR)/kernel.bin arch/$(BARCH)/iso/boot/
for task in $(INIT_TASKS) ; do \
cp $$task arch/$(ARCH)/iso/boot/ ; \
cp $$task arch/$(BARCH)/iso/boot/ ; \
done
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
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/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/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/$(ARCH)/iso/
$(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:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-rm -fr arch/$(ARCH)/iso
-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/network/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/network/boot/arch/mips32/loader/_link.ld.in.ecoff
File deleted
/branches/network/boot/arch/mips32/loader/_link.ld.in.binary
File deleted
/branches/network/boot/arch/mips32/loader/_link.ld.in
0,0 → 1,20
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/network/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/network/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
72,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);
81,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;
87,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/network/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/network/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/network/boot/arch/mips32/loader/Makefile
27,7 → 27,7
#
 
include ../../../../version
include ../../../Makefile.config
-include ../../../../Makefile.config
 
## Toolchain configuration
#
36,17 → 36,25
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 = $(CROSS_PREFIX)/mipsel/bin
 
ifeq ($(MACHINE),lgxemul)
BFD_NAME = elf32-tradlittlemips
BFD = ecoff-littlemips
endif
ifeq ($(MACHINE),bgxemul)
BFD_NAME = elf32-tradbigmips
BFD = ecoff-bigmips
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
TARGET = mips-linux-gnu
endif
ifeq ($(MACHINE),msim)
BFD_NAME = elf32-tradlittlemips
BFD = binary
endif
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
AS = as
63,21 → 71,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
 
88,7 → 89,7
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
96,18 → 97,20
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(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)))
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
 
117,35 → 120,41
 
-include Makefile.depend
 
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 $@
image.boot: image.raw
$(OBJCOPY) -O $(BFD) $< $@
 
image.raw: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS)
$(LD) -no-check-sections -N -T _link.ld -o $@ $(COMPONENT_OBJECTS) initrd.o $(OBJECTS)
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`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
-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.raw image.boot Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_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.sh $(USPACEDIR)/dist/ initrd.fs
../../../../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/network/boot/arch/ia32/Makefile.inc
40,20 → 40,23
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/pci/pci \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/fat/fat \
$(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/bdsh/bdsh \
$(USPACEDIR)/srv/net/networking/networking \
$(USPACEDIR)/srv/net/networking/startup/networking_startup \
$(USPACEDIR)/srv/net/netif/lo/lo
# $(USPACEDIR)/srv/net/netif/dp8390_isa
$(USPACEDIR)/srv/net/netif/lo/lo \
$(USPACEDIR)/srv/net/netif/dp8390/dp8390
 
ifeq ($(NETWORKING), modular)
RD_TASKS += $(USPACEDIR)/srv/net/il/ip/ip \
68,35 → 71,41
 
build: $(BASE)/image.iso
 
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS)
mkdir -p arch/$(ARCH)/iso/boot/grub
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/
$(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/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst
cat arch/$(BARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(BARCH)/iso/boot/grub/menu.lst
endif
ifneq ($(RDFMT),fat)
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst
cat arch/$(BARCH)/grub/menu.lst | grep -v "fat" >arch/$(BARCH)/iso/boot/grub/menu.lst
endif
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/
cp $(KERNELDIR)/kernel.bin arch/$(BARCH)/iso/boot/
for task in $(INIT_TASKS) ; do \
cp $$task arch/$(ARCH)/iso/boot/ ; \
cp $$task arch/$(BARCH)/iso/boot/ ; \
done
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
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/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
$(BASE)/tools/mkfat.py $(USPACEDIR)/dist/ arch/$(BARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/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/$(ARCH)/iso/
$(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:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-rm -fr arch/$(ARCH)/iso
-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/network/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/network/defaults/sparc64/Makefile.config
0,0 → 1,59
# Platform
PLATFORM = sparc64
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Support for SMP
CONFIG_SMP = y
 
# Debug build
CONFIG_DEBUG = y
 
# Deadlock detection support for spinlocks
CONFIG_DEBUG_SPINLOCK = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
# Use TSB
CONFIG_TSB = y
 
# Virtually indexed D-cache support
CONFIG_VIRT_IDX_DCACHE = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Input device class
CONFIG_HID_IN = generic
 
# Output device class
CONFIG_HID_OUT = generic
 
# 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 = y
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/sparc64/serengeti/Makefile.config
0,0 → 1,2
# Machine type
MACHINE = serengeti
/branches/network/defaults/sparc64/us3/Makefile.config
0,0 → 1,5
# Machine type
MACHINE = generic
 
# CPU type
PROCESSOR = us3
/branches/network/defaults/sparc64/us/Makefile.config
0,0 → 1,5
# Machine type
MACHINE = generic
 
# CPU type
PROCESSOR = us
/branches/network/defaults/sparc64/output
0,0 → 1,0
image.iso
/branches/network/defaults/ia64/Makefile.config
0,0 → 1,47
# Platform
PLATFORM = ia64
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Deadlock detection support for spinlocks
CONFIG_DEBUG_SPINLOCK = y
 
# Support for SMP
CONFIG_SMP = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
# Use VHPT
CONFIG_VHPT = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Input device class
CONFIG_HID_IN = generic
 
# Output device class
CONFIG_HID_OUT = generic
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/ia64/i460GX/Makefile.config
0,0 → 1,3
# Machine type
MACHINE = i460GX
 
/branches/network/defaults/ia64/output
0,0 → 1,0
image.boot
/branches/network/defaults/ia64/ski/Makefile.config
0,0 → 1,2
# Machine type
MACHINE = ski
/branches/network/defaults/arm32/Makefile.config
0,0 → 1,35
# Platform
PLATFORM = arm32
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# What is your input device?
CONFIG_HID_IN = generic
 
# What is your output device?
CONFIG_HID_OUT = generic
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/arm32/output
0,0 → 1,0
image.boot
/branches/network/defaults/ppc32/Makefile.config
0,0 → 1,38
# Platform
PLATFORM = ppc32
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Output device class
CONFIG_HID_OUT = generic
 
# Framebuffer support
CONFIG_FB = y
 
# Use Block Address Translation by the loader
CONFIG_BAT = y
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/ppc32/output
0,0 → 1,0
image.boot
/branches/network/defaults/amd64/Makefile.config
0,0 → 1,62
# Platform
PLATFORM = amd64
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Deadlock detection support for spinlocks
CONFIG_DEBUG_SPINLOCK = y
 
# Support for SMP
CONFIG_SMP = y
 
# Improved support for hyperthreading
CONFIG_HT = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Input device class
CONFIG_HID_IN = generic
 
# Output device class
CONFIG_HID_OUT = generic
 
# PC keyboard support
CONFIG_PC_KBD = y
 
# EGA support
CONFIG_EGA = y
 
# Framebuffer support
CONFIG_FB = y
 
# Default framebuffer mode
CONFIG_VESA_MODE = 800x600
 
# Default framebuffer depth
CONFIG_VESA_BPP = 16
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/amd64/output
0,0 → 1,0
image.iso
/branches/network/defaults/mips32/Makefile.config
0,0 → 1,41
# Platform
PLATFORM = mips32
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Deadlock detection support for spinlocks
CONFIG_DEBUG_SPINLOCK = y
 
# Support for SMP
CONFIG_SMP = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Input device class
CONFIG_HID_IN = generic
 
# Output device class
CONFIG_HID_OUT = generic
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/mips32/GXemul/Makefile.config
0,0 → 1,2
# Machine type
MACHINE = lgxemul
/branches/network/defaults/mips32/output
0,0 → 1,0
image.boot
/branches/network/defaults/mips32/msim/Makefile.config
0,0 → 1,2
# Machine type
MACHINE = msim
/branches/network/defaults/ia32/Makefile.config
0,0 → 1,68
# Platform
PLATFORM = ia32
 
# CPU type
PROCESSOR = pentium4
 
# Ramdisk format
RDFMT = fat
 
# Compiler
COMPILER = gcc_cross
 
# Debug build
CONFIG_DEBUG = y
 
# Deadlock detection support for spinlocks
CONFIG_DEBUG_SPINLOCK = y
 
# ACPI support
CONFIG_ACPI = y
 
# Support for SMP
CONFIG_SMP = y
 
# Improved support for hyperthreading
CONFIG_HT = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
# Support for userspace debuggers
CONFIG_UDEBUG = y
 
# Kernel console support
CONFIG_KCONSOLE = y
 
# Kernel symbol information
CONFIG_SYMTAB = y
 
# Detailed kernel logging
CONFIG_LOG = n
 
# Compile kernel tests
CONFIG_TEST = y
 
# Input device class
CONFIG_HID_IN = generic
 
# Output device class
CONFIG_HID_OUT = generic
 
# PC keyboard support
CONFIG_PC_KBD = y
 
# EGA support
CONFIG_EGA = y
 
# Framebuffer support
CONFIG_FB = y
 
# Default framebuffer mode
CONFIG_VESA_MODE = 800x600
 
# Default framebuffer depth
CONFIG_VESA_BPP = 16
 
# Keyboard layout
KBD_LAYOUT = us_qwerty
/branches/network/defaults/ia32/output
0,0 → 1,0
image.iso
/branches/network/Makefile
29,112 → 29,21
## 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
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 cscope
 
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) NETWORKING=$(NETWORKING)
endif
$(MAKE) -C uspace ARCH=$(UARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) NETWORKING=$(NETWORKING)
ifneq ($(IMAGE),)
$(MAKE) -C boot ARCH=$(BARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) NETWORKING=$(NETWORKING) IMAGE=$(IMAGE)
else
$(MAKE) -C boot ARCH=$(BARCH) COMPILER=$(COMPILER) CONFIG_DEBUG=$(CONFIG_DEBUG) NETWORKING=$(NETWORKING)
endif
 
config:
tools/config.py HelenOS.config
 
distclean:
-$(MAKE) -C kernel distclean
-$(MAKE) -C uspace distclean
-$(MAKE) -C boot distclean
rm -f Makefile.config tools/*.pyc
distclean: clean
rm -f Makefile.config config.h config.defs tools/*.pyc
 
clean:
-$(MAKE) -C kernel clean