mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-22 07:53:36 +08:00
New revision from Andrew
This commit is contained in:
parent
a7dd20e839
commit
3fbe064171
@ -96,13 +96,17 @@ hw_cpu.c
|
||||
hw_cpu.h
|
||||
hw_disk.c
|
||||
hw_eeprom.c
|
||||
hw_glue.c
|
||||
hw_htab.c
|
||||
hw_ide.c
|
||||
hw_init.c
|
||||
hw_iobus.c
|
||||
hw_memory.c
|
||||
hw_nvram.c
|
||||
hw_opic.c
|
||||
hw_pal.c
|
||||
hw_pic.c
|
||||
hw_phb.c
|
||||
hw_phb.h
|
||||
hw_register.c
|
||||
hw_trace.c
|
||||
hw_vm.c
|
||||
@ -158,6 +162,8 @@ sim_calls.c
|
||||
std-config.h
|
||||
table.c
|
||||
table.h
|
||||
tree.c
|
||||
tree.h
|
||||
vm.c
|
||||
vm.h
|
||||
vm_n.h
|
||||
|
@ -13,6 +13,55 @@ else
|
||||
CC_FOR_BUILD=gcc
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-alignment,
|
||||
[ --enable-sim-alignment=align Specify strict or nonstrict alignment.],
|
||||
[case "${enableval}" in
|
||||
yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
|
||||
no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
|
||||
0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-alignment"); sim_alignment="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
|
||||
echo "Setting alignment flags = $sim_alignment" 6>&1
|
||||
fi],[sim_alignment=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-assert,
|
||||
[ --enable-sim-assert Specify whether to perform random assertions.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_assert="-DWITH_ASSERT=1";;
|
||||
no) sim_assert="-DWITH_ASSERT=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-assert does not take a value"); sim_assert="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
|
||||
echo "Setting assert flags = $sim_assert" 6>&1
|
||||
fi],[sim_assert=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-bitsize,
|
||||
[ --enable-sim-bitsize=n Specify target bitsize (32 or 64).],
|
||||
[case "${enableval}" in
|
||||
32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
|
||||
*) AC_MSG_ERROR("--enable-sim-bitsize was given $enableval. Expected 32 or 64"); sim_bitsize="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
|
||||
echo "Setting bitsize flags = $sim_bitsize" 6>&1
|
||||
fi],[sim_bitsize=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-bswap,
|
||||
[ --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_bswap="-DWITH_BSWAP=1";;
|
||||
no) sim_bswap="-DWITH_BSWAP=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-bswap does not take a value"); sim_bswap="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then
|
||||
echo "Setting bswap flags = $sim_bswap" 6>&1
|
||||
fi],[sim_bswap=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-cflags,
|
||||
[ --enable-sim-cflags=opts Extra CFLAGS for use in building simulator],
|
||||
[case "${enableval}" in
|
||||
@ -24,27 +73,6 @@ if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then
|
||||
echo "Setting sim cflags = $sim_cflags" 6>&1
|
||||
fi],[sim_cflags=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-warnings,
|
||||
[ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o],
|
||||
[case "${enableval}" in
|
||||
yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";;
|
||||
no) sim_warnings="-w";;
|
||||
*) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
|
||||
echo "Setting warning flags = $sim_warnings" 6>&1
|
||||
fi],[sim_warnings=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-line-nr,
|
||||
[ --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code],
|
||||
[case "${enableval}" in
|
||||
yes) sim_line_nr="";;
|
||||
no) sim_line_nr="-L";;
|
||||
*) AC_MSG_ERROR("--enable-sim-line-nr does not take a value"); sim_line_nr="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
|
||||
echo "Setting warning flags = $sim_line_nr" 6>&1
|
||||
fi],[sim_line_nr=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-config,
|
||||
[ --enable-sim-config=file Override default config file],
|
||||
@ -66,39 +94,17 @@ if test x"$silent" != x"yes"; then
|
||||
echo "Setting config flags = $sim_config" 6>&1
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-opcode,
|
||||
[ --enable-sim-opcode=which Override default opcode lookup.],
|
||||
[case "${enableval}" in
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-opcode=file");;
|
||||
*) if test -f "${srcdir}/${enableval}"; then
|
||||
sim_opcode="${enableval}"
|
||||
elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
|
||||
sim_opcode="ppc-opcode-${enableval}"
|
||||
else
|
||||
AC_MSG_ERROR("File $enableval is not an opcode rules file");
|
||||
sim_opcode="ppc-opcode-complex"
|
||||
fi;;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
|
||||
echo "Setting opcode flags = $sim_opcode" 6>&1
|
||||
fi],[sim_opcode="ppc-opcode-complex"
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting opcode flags = $sim_opcode"
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-switch,
|
||||
[ --enable-sim-switch Use a switch instead of a table for instruction call.],
|
||||
AC_ARG_ENABLE(sim-default-model,
|
||||
[ --enable-sim-default-model=which Specify default PowerPC to model.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_switch="-s";;
|
||||
no) sim_switch="";;
|
||||
*) AC_MSG_ERROR("--enable-sim-switch does not take a value"); sim_switch="";;
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-default-model=model");;
|
||||
*) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
|
||||
echo "Setting switch flags = $sim_switch" 6>&1
|
||||
fi],[sim_switch="";
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting switch flags = $sim_switch" 6>&1
|
||||
fi])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
|
||||
echo "Setting default-model flags = $sim_default_model" 6>&1
|
||||
fi],[sim_model=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-duplicate,
|
||||
[ --enable-sim-duplicate Expand (duplicate) semantic functions.],
|
||||
@ -114,19 +120,38 @@ if test x"$silent" != x"yes"; then
|
||||
echo "Setting duplicate flags = $sim_dup" 6>&1
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-jump,
|
||||
[ --enable-sim-jump Jump between semantic code (instead of call/return).],
|
||||
|
||||
AC_ARG_ENABLE(sim-endian,
|
||||
[ --enable-sim-endian=endian Specify target byte endian orientation.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_jump="-J";;
|
||||
no) sim_jump="";;
|
||||
*) AC_MSG_ERROR("--enable-sim-jump does not take a value"); sim_jump="";;
|
||||
yes) case "$target" in
|
||||
*powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
|
||||
*powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
|
||||
esac;;
|
||||
no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
|
||||
b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
|
||||
l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-endian"); sim_endian="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
|
||||
echo "Setting jump flag = $sim_jump" 6>&1
|
||||
fi],[sim_jump="-E"
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting jump flag = $sim_jump" 6>&1
|
||||
fi])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
|
||||
echo "Setting endian flags = $sim_endian" 6>&1
|
||||
fi],[sim_endian=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-env,
|
||||
[ --enable-sim-env=env Specify target environment (operating, virtual, user).],
|
||||
[case "${enableval}" in
|
||||
operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
|
||||
virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
|
||||
user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
|
||||
no) sim_env="-DWITH_ENVIRONMENT=0";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-env"); sim_env="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
|
||||
echo "Setting env flags = $sim_env" 6>&1
|
||||
fi],[sim_env=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-filter,
|
||||
[ --enable-sim-filter=rule Specify filter rules.],
|
||||
@ -142,6 +167,75 @@ if test x"$silent" != x"yes"; then
|
||||
echo "Setting filter flags = $sim_filter" 6>&1
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-float,
|
||||
[ --enable-sim-float Specify whether to use host floating point or simulate.],
|
||||
[case "${enableval}" in
|
||||
yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
|
||||
no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-float"); sim_float="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
|
||||
echo "Setting float flags = $sim_float" 6>&1
|
||||
fi],[sim_float=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-hardware,
|
||||
[ --enable-sim-hardware=list Specify the hardware to be included in the build.],
|
||||
[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
|
||||
case "${enableval}" in
|
||||
yes) ;;
|
||||
no) AC_MSG_ERROR("List of hardware must be specified for --enable-sim-hardware"); hardware="";;
|
||||
,*) hardware="${hardware}${enableval}";;
|
||||
*,) hardware="${enableval}${hardware}";;
|
||||
*) hardware="${enableval}"'';;
|
||||
esac
|
||||
sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
|
||||
sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes" && test x"$hardware" != x""; then
|
||||
echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
|
||||
fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
|
||||
sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
|
||||
sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-hostbitsize,
|
||||
[ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64).],
|
||||
[case "${enableval}" in
|
||||
32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
|
||||
*) AC_MSG_ERROR("--enable-sim-hostbitsize was given $enableval. Expected 32 or 64"); sim_hostbitsize="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
|
||||
echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
|
||||
fi],[sim_hostbitsize=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-hostendian,
|
||||
[ --enable-sim-hostendain=end Specify host byte endian orientation.],
|
||||
[case "${enableval}" in
|
||||
no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";;
|
||||
b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";;
|
||||
l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-hostendian"); sim_hostendian="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
|
||||
echo "Setting hostendian flags = $sim_hostendian" 6>&1
|
||||
fi],[
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
AC_C_BIGENDIAN
|
||||
if test $ac_cv_c_bigendian = yes; then
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN"
|
||||
else
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN"
|
||||
fi
|
||||
else
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=0"
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-icache,
|
||||
[ --enable-sim-icache=size Specify instruction cache size.],
|
||||
[icache=""
|
||||
@ -168,46 +262,6 @@ if test x"$silent" != x"yes"; then
|
||||
echo "Setting instruction cache size to 1024 ($sim_icache)"
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-hardware,
|
||||
[ --enable-sim-hardware=list Specify the hardware to be included in the build.],
|
||||
[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com"
|
||||
case "${enableval}" in
|
||||
yes) ;;
|
||||
no) AC_MSG_ERROR("List of hardware must be specified for --enable-sim-hardware"); hardware="";;
|
||||
,*) hardware="${hardware}${enableval}";;
|
||||
*) hardware="${enableval}";;
|
||||
esac
|
||||
sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
|
||||
sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes" && test x"$hardware" != x""; then
|
||||
echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
|
||||
fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com"
|
||||
sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
|
||||
sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-packages,
|
||||
[ --enable-sim-packages=list Specify the packages to be included in the build.],
|
||||
[packages=disklabel
|
||||
case "${enableval}" in
|
||||
yes) ;;
|
||||
no) AC_MSG_ERROR("List of packages must be specified for --enable-sim-packages"); packages="";;
|
||||
,*) packages="${packages}${enableval}";;
|
||||
*) packages="${enableval}"''
|
||||
esac
|
||||
sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
|
||||
sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes" && test x"$packages" != x""; then
|
||||
echo "Setting packages to $sim_pk_src, $sim_pk_obj"
|
||||
fi],[packages=disklabel
|
||||
sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
|
||||
sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting packages to $sim_pk_src, $sim_pk_obj"
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-inline,
|
||||
[ --enable-sim-inline=inlines Specify which functions should be inlined.],
|
||||
@ -243,33 +297,113 @@ else
|
||||
sim_inline=""
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-bswap,
|
||||
[ --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_bswap="-DWITH_BSWAP=1";;
|
||||
no) sim_bswap="-DWITH_BSWAP=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-bswap does not take a value"); sim_bswap="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then
|
||||
echo "Setting bswap flags = $sim_bswap" 6>&1
|
||||
fi],[sim_bswap=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-endian,
|
||||
[ --enable-sim-endian=endian Specify target byte endian orientation.],
|
||||
AC_ARG_ENABLE(sim-jump,
|
||||
[ --enable-sim-jump Jump between semantic code (instead of call/return).],
|
||||
[case "${enableval}" in
|
||||
yes) case "$target" in
|
||||
*powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
|
||||
*powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
|
||||
esac;;
|
||||
no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
|
||||
b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
|
||||
l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-endian"); sim_endian="";;
|
||||
yes) sim_jump="-J";;
|
||||
no) sim_jump="";;
|
||||
*) AC_MSG_ERROR("--enable-sim-jump does not take a value"); sim_jump="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
|
||||
echo "Setting endian flags = $sim_endian" 6>&1
|
||||
fi],[sim_endian=""])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
|
||||
echo "Setting jump flag = $sim_jump" 6>&1
|
||||
fi],[sim_jump="-E"
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting jump flag = $sim_jump" 6>&1
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-line-nr,
|
||||
[ --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code],
|
||||
[case "${enableval}" in
|
||||
yes) sim_line_nr="";;
|
||||
no) sim_line_nr="-L";;
|
||||
*) AC_MSG_ERROR("--enable-sim-line-nr does not take a value"); sim_line_nr="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
|
||||
echo "Setting warning flags = $sim_line_nr" 6>&1
|
||||
fi],[sim_line_nr=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-model,
|
||||
[ --enable-sim-model=which Specify PowerPC to model.],
|
||||
[case "${enableval}" in
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-model=model");;
|
||||
*) sim_model="-DWITH_MODEL=${enableval}";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
|
||||
echo "Setting model flags = $sim_model" 6>&1
|
||||
fi],[sim_model=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-model-issue,
|
||||
[ --enable-sim-model-issue Specify whether to simulate model specific actions],
|
||||
[case "${enableval}" in
|
||||
yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
|
||||
no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
|
||||
*) AC_MSG_ERROR("--enable-sim-model-issue does not take a value"); sim_model_issue="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting model-issue flags = $sim_model_issue" 6>&1
|
||||
fi],[sim_model_issue=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-monitor,
|
||||
[ --enable-sim-monitor=mon Specify whether to enable monitoring events.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
|
||||
no) sim_monitor="-DWITH_MON=0";;
|
||||
instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
|
||||
memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-mon"); sim_env="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
|
||||
echo "Setting monitor flags = $sim_monitor" 6>&1
|
||||
fi],[sim_monitor=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-opcode,
|
||||
[ --enable-sim-opcode=which Override default opcode lookup.],
|
||||
[case "${enableval}" in
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-opcode=file");;
|
||||
*) if test -f "${srcdir}/${enableval}"; then
|
||||
sim_opcode="${enableval}"
|
||||
elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
|
||||
sim_opcode="ppc-opcode-${enableval}"
|
||||
else
|
||||
AC_MSG_ERROR("File $enableval is not an opcode rules file");
|
||||
sim_opcode="ppc-opcode-complex"
|
||||
fi;;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
|
||||
echo "Setting opcode flags = $sim_opcode" 6>&1
|
||||
fi],[sim_opcode="ppc-opcode-complex"
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting opcode flags = $sim_opcode"
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-packages,
|
||||
[ --enable-sim-packages=list Specify the packages to be included in the build.],
|
||||
[packages=disklabel
|
||||
case "${enableval}" in
|
||||
yes) ;;
|
||||
no) AC_MSG_ERROR("List of packages must be specified for --enable-sim-packages"); packages="";;
|
||||
,*) packages="${packages}${enableval}";;
|
||||
*,) packages="${enableval}${packages}";;
|
||||
*) packages="${enableval}"'';;
|
||||
esac
|
||||
sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
|
||||
sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes" && test x"$packages" != x""; then
|
||||
echo "Setting packages to $sim_pk_src, $sim_pk_obj"
|
||||
fi],[packages=disklabel
|
||||
sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
|
||||
sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting packages to $sim_pk_src, $sim_pk_obj"
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-regparm,
|
||||
[ --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific.],
|
||||
@ -283,39 +417,18 @@ if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then
|
||||
echo "Setting regparm flags = $sim_regparm" 6>&1
|
||||
fi],[sim_regparm=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-stdcall,
|
||||
[ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific.],
|
||||
[case "${enableval}" in
|
||||
no) sim_stdcall="" ;;
|
||||
std*) sim_stdcall="-DWITH_STDCALL=1";;
|
||||
yes) sim_stdcall="-DWITH_STDCALL=1";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-stdcall"); sim_stdcall="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then
|
||||
echo "Setting function call flags = $sim_stdcall" 6>&1
|
||||
fi],[sim_stdcall=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-hostendian,
|
||||
[ --enable-sim-hostendain=end Specify host byte endian orientation.],
|
||||
AC_ARG_ENABLE(sim-reserved-bits,
|
||||
[ --enable-sim-reserved-bits Specify whether to check reserved bits in instruction.],
|
||||
[case "${enableval}" in
|
||||
no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";;
|
||||
b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";;
|
||||
l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-hostendian"); sim_hostendian="";;
|
||||
yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
|
||||
no) sim_reserved="-DWITH_RESERVED_BITS=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-reserved-bits does not take a value"); sim_reserved="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
|
||||
echo "Setting hostendian flags = $sim_hostendian" 6>&1
|
||||
fi],[
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
AC_C_BIGENDIAN
|
||||
if test $ac_cv_c_bigendian = yes; then
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN"
|
||||
else
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN"
|
||||
fi
|
||||
else
|
||||
sim_hostendian="-DWITH_HOST_BYTE_ORDER=0"
|
||||
fi])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
|
||||
echo "Setting reserved flags = $sim_reserved" 6>&1
|
||||
fi],[sim_reserved=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-smp,
|
||||
[ --enable-sim-smp=n Specify number of processors to configure for.],
|
||||
@ -331,49 +444,46 @@ if test x"$silent" != x"yes"; then
|
||||
echo "Setting smp flags = $sim_smp" 6>&1
|
||||
fi])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-xor-endian,
|
||||
[ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).],
|
||||
[case "${enableval}" in
|
||||
yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";;
|
||||
no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";;
|
||||
*) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
|
||||
echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
|
||||
fi],[sim_xor_endian=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-bitsize,
|
||||
[ --enable-sim-bitsize=n Specify target bitsize (32 or 64).],
|
||||
AC_ARG_ENABLE(sim-stdcall,
|
||||
[ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific.],
|
||||
[case "${enableval}" in
|
||||
32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
|
||||
*) AC_MSG_ERROR("--enable-sim-bitsize was given $enableval, expected 32 or 64"); sim_bitsize="";;
|
||||
no) sim_stdcall="" ;;
|
||||
std*) sim_stdcall="-DWITH_STDCALL=1";;
|
||||
yes) sim_stdcall="-DWITH_STDCALL=1";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-stdcall"); sim_stdcall="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
|
||||
echo "Setting bitsize flags = $sim_bitsize" 6>&1
|
||||
fi],[sim_bitsize=""])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then
|
||||
echo "Setting function call flags = $sim_stdcall" 6>&1
|
||||
fi],[sim_stdcall=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-hostbitsize,
|
||||
[ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64).],
|
||||
[case "${enableval}" in
|
||||
32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
|
||||
*) AC_MSG_ERROR("--enable-sim-hostbitsize was given $enableval, expected 32 or 64"); sim_hostbitsize="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
|
||||
echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
|
||||
fi],[sim_hostbitsize=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-env,
|
||||
[ --enable-sim-env=env Specify target environment (operating, virtual, user).],
|
||||
AC_ARG_ENABLE(sim-stdio,
|
||||
[ --enable-sim-stdio Specify whether to use stdio for console input/output.],
|
||||
[case "${enableval}" in
|
||||
operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
|
||||
virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
|
||||
user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
|
||||
no) sim_env="-DWITH_ENVIRONMENT=0";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-env"); sim_env="";;
|
||||
yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";;
|
||||
no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-stdio"); sim_stdio="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
|
||||
echo "Setting env flags = $sim_env" 6>&1
|
||||
fi],[sim_env=""])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
|
||||
echo "Setting stdio flags = $sim_stdio" 6>&1
|
||||
fi],[sim_stdio=""])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-switch,
|
||||
[ --enable-sim-switch Use a switch instead of a table for instruction call.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_switch="-s";;
|
||||
no) sim_switch="";;
|
||||
*) AC_MSG_ERROR("--enable-sim-switch does not take a value"); sim_switch="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
|
||||
echo "Setting switch flags = $sim_switch" 6>&1
|
||||
fi],[sim_switch="";
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting switch flags = $sim_switch" 6>&1
|
||||
fi])dnl
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sim-timebase,
|
||||
[ --enable-sim-timebase Specify whether the PPC timebase is supported.],
|
||||
@ -386,17 +496,6 @@ if test x"$silent" != x"yes" && test x"$sim_timebase" != x""; then
|
||||
echo "Setting timebase flags = $sim_timebase" 6>&1
|
||||
fi],[sim_timebase=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-alignment,
|
||||
[ --enable-sim-alignment=align Specify strict or nonstrict alignment.],
|
||||
[case "${enableval}" in
|
||||
yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
|
||||
no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
|
||||
0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-alignment"); sim_alignment="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
|
||||
echo "Setting alignment flags = $sim_alignment" 6>&1
|
||||
fi],[sim_alignment=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-trace,
|
||||
[ --enable-sim-trace Specify whether tracing is supported.],
|
||||
@ -409,93 +508,30 @@ if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then
|
||||
echo "Setting trace flags = $sim_trace" 6>&1
|
||||
fi],[sim_trace=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-assert,
|
||||
[ --enable-sim-assert Specify whether to perform random assertions.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_assert="-DWITH_ASSERT=1";;
|
||||
no) sim_assert="-DWITH_ASSERT=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-assert does not take a value"); sim_assert="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
|
||||
echo "Setting assert flags = $sim_assert" 6>&1
|
||||
fi],[sim_assert=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-reserved-bits,
|
||||
[ --enable-sim-reserved-bits Specify whether to check reserved bits in instruction.],
|
||||
AC_ARG_ENABLE(sim-warnings,
|
||||
[ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o],
|
||||
[case "${enableval}" in
|
||||
yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
|
||||
no) sim_reserved="-DWITH_RESERVED_BITS=0";;
|
||||
*) AC_MSG_ERROR("--enable-sim-reserved-bits does not take a value"); sim_reserved="";;
|
||||
yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";;
|
||||
no) sim_warnings="-w";;
|
||||
*) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
|
||||
echo "Setting reserved flags = $sim_reserved" 6>&1
|
||||
fi],[sim_reserved=""])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
|
||||
echo "Setting warning flags = $sim_warnings" 6>&1
|
||||
fi],[sim_warnings=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-float,
|
||||
[ --enable-sim-float Specify whether to use host floating point or simulate.],
|
||||
[case "${enableval}" in
|
||||
yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
|
||||
no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-float"); sim_float="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
|
||||
echo "Setting float flags = $sim_float" 6>&1
|
||||
fi],[sim_float=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-monitor,
|
||||
[ --enable-sim-monitor=mon Specify whether to enable monitoring events.],
|
||||
AC_ARG_ENABLE(sim-xor-endian,
|
||||
[ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).],
|
||||
[case "${enableval}" in
|
||||
yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
|
||||
no) sim_monitor="-DWITH_MON=0";;
|
||||
instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
|
||||
memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-mon"); sim_env="";;
|
||||
yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";;
|
||||
no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";;
|
||||
*) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
|
||||
echo "Setting monitor flags = $sim_monitor" 6>&1
|
||||
fi],[sim_monitor=""])dnl
|
||||
if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
|
||||
echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
|
||||
fi],[sim_xor_endian=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-model,
|
||||
[ --enable-sim-model=which Specify PowerPC to model.],
|
||||
[case "${enableval}" in
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-model=model");;
|
||||
*) sim_model="-DWITH_MODEL=${enableval}";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
|
||||
echo "Setting model flags = $sim_model" 6>&1
|
||||
fi],[sim_model=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-default-model,
|
||||
[ --enable-sim-default-model=which Specify default PowerPC to model.],
|
||||
[case "${enableval}" in
|
||||
yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-default-model=model");;
|
||||
*) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
|
||||
echo "Setting default-model flags = $sim_default_model" 6>&1
|
||||
fi],[sim_model=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-model-issue,
|
||||
[ --enable-sim-model-issue Specify whether to simulate model specific actions],
|
||||
[case "${enableval}" in
|
||||
yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
|
||||
no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
|
||||
*) AC_MSG_ERROR("--enable-sim-model-issue does not take a value"); sim_model_issue="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting model-issue flags = $sim_model_issue" 6>&1
|
||||
fi],[sim_model_issue=""])dnl
|
||||
|
||||
AC_ARG_ENABLE(sim-stdio,
|
||||
[ --enable-sim-stdio Specify whether to use stdio for console input/output.],
|
||||
[case "${enableval}" in
|
||||
yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";;
|
||||
no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";;
|
||||
*) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-stdio"); sim_stdio="";;
|
||||
esac
|
||||
if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
|
||||
echo "Setting stdio flags = $sim_stdio" 6>&1
|
||||
fi],[sim_stdio=""])dnl
|
||||
|
||||
AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
371
sim/ppc/hw_glue.c
Normal file
371
sim/ppc/hw_glue.c
Normal file
@ -0,0 +1,371 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _HW_GLUE_C_
|
||||
#define _HW_GLUE_C_
|
||||
|
||||
#include "device_table.h"
|
||||
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
glue - glue to interconnect and test interrupts
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
The glue device provides two functions. Firstly, it provides a
|
||||
mechanism for inspecting and driving the interrupt net. Secondly,
|
||||
it provides a set of boolean primitives that can be used add
|
||||
combinatorial operations to the interrupt network.
|
||||
|
||||
Glue devices have a variable number of big endian <<output>>
|
||||
registers. Each host-word size. The registers can be both read
|
||||
and written.
|
||||
|
||||
Writing a value to an output register causes an interrupt (of the
|
||||
specified level) to be driven on the devices corresponding output
|
||||
interrupt port.
|
||||
|
||||
Reading an <<output>> register returns either the last value
|
||||
written or the most recently computed value (for that register) as
|
||||
a result of an interrupt ariving (which ever was computed last).
|
||||
|
||||
At present the following sub device types are available:
|
||||
|
||||
<<glue>>: In addition to driving its output interrupt port with any
|
||||
value written to an interrupt input port is stored in the
|
||||
corresponding <<output>> register. Such input interrupts, however,
|
||||
are not propogated to an output interrupt port.
|
||||
|
||||
<<glue-and>>: The bit-wise AND of the interrupt inputs is computed
|
||||
and then both stored in <<output>> register zero and propogated to
|
||||
output interrupt output port zero.
|
||||
|
||||
|
||||
PROPERTIES
|
||||
|
||||
|
||||
reg = <address> <size> (required)
|
||||
|
||||
Specify the address (within the parent bus) that this device is to
|
||||
live. The address must be 2048 * sizeof(word) (8k in a 32bit
|
||||
simulation) aligned.
|
||||
|
||||
|
||||
interrupt-ranges = <int-number> <range> (optional)
|
||||
|
||||
If present, this specifies the number of valid interrupt inputs (up
|
||||
to the maximum of 2048). By default, <<int-number>> is zero and
|
||||
range is determined by the <<reg>> size.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
|
||||
|
||||
Enable tracing of the device:
|
||||
|
||||
| -t glue-device \
|
||||
|
||||
|
||||
Create source, bitwize-and, and sink glue devices. Since the
|
||||
device at address <<0x10000>> is of size <<8>> it will have two
|
||||
output interrupt ports.
|
||||
|
||||
| -o '/iobus@0xf0000000/glue@0x10000/reg 0x10000 8' \
|
||||
| -o '/iobus@0xf0000000/glue-and@0x20000/reg 0x20000 4' \
|
||||
| -o '/iobus@0xf0000000/glue-and/interrupt-ranges 0 2' \
|
||||
| -o '/iobus@0xf0000000/glue@0x30000/reg 0x30000 4' \
|
||||
|
||||
|
||||
Wire the two source interrupts to the AND device:
|
||||
|
||||
| -o '/iobus@0xf0000000/glue@0x10000 > 0 0 /iobus/glue-and' \
|
||||
| -o '/iobus@0xf0000000/glue@0x10000 > 1 1 /iobus/glue-and' \
|
||||
|
||||
|
||||
Wire the AND device up to the sink so that the and's output is not
|
||||
left open.
|
||||
|
||||
| -o '/iobus@0xf0000000/glue-and > 0 0 /iobus/glue@0x30000' \
|
||||
|
||||
|
||||
With the above configuration. The client program is able to
|
||||
compute a two bit AND. For instance the <<C>> stub below prints 1
|
||||
AND 0.
|
||||
|
||||
| unsigned *input = (void*)0xf0010000;
|
||||
| unsigned *output = (void*)0xf0030000;
|
||||
| unsigned ans;
|
||||
| input[0] = htonl(1);
|
||||
| input[1] = htonl(0);
|
||||
| ans = ntohl(*output);
|
||||
| write_string("AND is ");
|
||||
| write_int(ans);
|
||||
| write_line();
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
|
||||
A future implementation of this device may support multiple
|
||||
interrupt ranges.
|
||||
|
||||
Some of the devices listed may not yet be fully implemented.
|
||||
|
||||
Additional devices such as a dff, an inverter or a latch may be
|
||||
useful.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
enum {
|
||||
max_nr_interrupts = 2048,
|
||||
};
|
||||
|
||||
typedef enum _hw_glue_type {
|
||||
glue_undefined = 0,
|
||||
glue_io,
|
||||
glue_and,
|
||||
glue_nand,
|
||||
glue_or,
|
||||
glue_xor,
|
||||
glue_nor,
|
||||
glue_not,
|
||||
} hw_glue_type;
|
||||
|
||||
typedef struct _hw_glue_device {
|
||||
hw_glue_type type;
|
||||
int int_number;
|
||||
int *input;
|
||||
int nr_inputs;
|
||||
unsigned sizeof_input;
|
||||
/* our output registers */
|
||||
int space;
|
||||
unsigned_word address;
|
||||
unsigned sizeof_output;
|
||||
int *output;
|
||||
int nr_outputs;
|
||||
} hw_glue_device;
|
||||
|
||||
|
||||
static void
|
||||
hw_glue_init_address(device *me)
|
||||
{
|
||||
hw_glue_device *glue = (hw_glue_device*)device_data(me);
|
||||
|
||||
/* attach to my parent */
|
||||
generic_device_init_address(me);
|
||||
|
||||
/* establish the output registers */
|
||||
if (glue->output != NULL) {
|
||||
memset(glue->output, 0, glue->sizeof_output);
|
||||
}
|
||||
else {
|
||||
reg_property_spec unit;
|
||||
int reg_nr;
|
||||
/* find a relevant reg entry */
|
||||
reg_nr = 0;
|
||||
while (device_find_reg_array_property(me, "reg", reg_nr, &unit)
|
||||
&& !device_size_to_attach_size(device_parent(me), &unit.size,
|
||||
&glue->sizeof_output, me))
|
||||
reg_nr++;
|
||||
/* check out the size */
|
||||
if (glue->sizeof_output == 0)
|
||||
device_error(me, "at least one reg property size must be nonzero");
|
||||
if (glue->sizeof_output % sizeof(unsigned_word) != 0)
|
||||
device_error(me, "reg property size must be %d aligned", sizeof(unsigned_word));
|
||||
/* and the address */
|
||||
device_address_to_attach_address(device_parent(me),
|
||||
&unit.address, &glue->space, &glue->address,
|
||||
me);
|
||||
if (glue->address % (sizeof(unsigned_word) * max_nr_interrupts) != 0)
|
||||
device_error(me, "reg property address must be %d aligned",
|
||||
sizeof(unsigned_word) * max_nr_interrupts);
|
||||
glue->nr_outputs = glue->sizeof_output / sizeof(unsigned_word);
|
||||
glue->output = zalloc(glue->sizeof_output);
|
||||
}
|
||||
|
||||
/* establish the input interrupt ports */
|
||||
if (glue->input != NULL) {
|
||||
memset(glue->input, 0, glue->sizeof_input);
|
||||
}
|
||||
else {
|
||||
const device_property *ranges = device_find_property(me, "interrupt-ranges");
|
||||
if (ranges == NULL) {
|
||||
glue->int_number = 0;
|
||||
glue->nr_inputs = glue->nr_outputs;
|
||||
}
|
||||
else if (ranges->sizeof_array != sizeof(unsigned_cell) * 2) {
|
||||
device_error(me, "invalid interrupt-ranges property (incorrect size)");
|
||||
}
|
||||
else {
|
||||
const unsigned_cell *int_range = ranges->array;
|
||||
glue->int_number = BE2H_cell(int_range[0]);
|
||||
glue->nr_inputs = BE2H_cell(int_range[1]);
|
||||
}
|
||||
glue->sizeof_input = glue->nr_inputs * sizeof(unsigned);
|
||||
glue->input = zalloc(glue->sizeof_input);
|
||||
}
|
||||
|
||||
/* determine our type */
|
||||
if (glue->type == glue_undefined) {
|
||||
const char *name = device_name(me);
|
||||
if (strcmp(name, "glue") == 0)
|
||||
glue->type = glue_io;
|
||||
else if (strcmp(name, "glue-and") == 0)
|
||||
glue->type = glue_and;
|
||||
else
|
||||
device_error(me, "unimplemented glue type");
|
||||
}
|
||||
|
||||
DTRACE(glue, ("int-number %d, nr_inputs %d, nr_outputs %d\n",
|
||||
glue->int_number, glue->nr_inputs, glue->nr_outputs));
|
||||
}
|
||||
|
||||
static unsigned
|
||||
hw_glue_io_read_buffer_callback(device *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
hw_glue_device *glue = (hw_glue_device*)device_data(me);
|
||||
int reg = ((addr - glue->address) / sizeof(unsigned_word)) % glue->nr_outputs;
|
||||
if (nr_bytes != sizeof(unsigned_word)
|
||||
|| (addr % sizeof(unsigned_word)) != 0)
|
||||
device_error(me, "missaligned read access (%d:0x%lx:%d) not supported",
|
||||
space, (unsigned long)addr, nr_bytes);
|
||||
*(unsigned_word*)dest = H2BE_4(glue->output[reg]);
|
||||
DTRACE(glue, ("read - interrupt %d (0x%lx), level %d\n",
|
||||
reg, (unsigned long) addr, glue->output[reg]));
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
hw_glue_io_write_buffer_callback(device *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
hw_glue_device *glue = (hw_glue_device*)device_data(me);
|
||||
int reg = ((addr - glue->address) / sizeof(unsigned_word)) % max_nr_interrupts;
|
||||
if (nr_bytes != sizeof(unsigned_word)
|
||||
|| (addr % sizeof(unsigned_word)) != 0)
|
||||
device_error(me, "missaligned write access (%d:0x%lx:%d) not supported",
|
||||
space, (unsigned long)addr, nr_bytes);
|
||||
glue->output[reg] = H2BE_4(*(unsigned_word*)source);
|
||||
DTRACE(glue, ("write - interrupt %d (0x%lx), level %d\n",
|
||||
reg, (unsigned long) addr, glue->output[reg]));
|
||||
device_interrupt_event(me, reg, glue->output[reg], processor, cia);
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
hw_glue_interrupt_event(device *me,
|
||||
int my_port,
|
||||
device *source,
|
||||
int source_port,
|
||||
int level,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
hw_glue_device *glue = (hw_glue_device*)device_data(me);
|
||||
int i;
|
||||
if (my_port < glue->int_number
|
||||
|| my_port >= glue->int_number + glue->nr_inputs)
|
||||
device_error(me, "interrupt %d outside of valid range", my_port);
|
||||
glue->input[my_port - glue->int_number] = level;
|
||||
switch (glue->type) {
|
||||
case glue_io:
|
||||
{
|
||||
int port = my_port % glue->nr_outputs;
|
||||
glue->output[port] = level;
|
||||
DTRACE(glue, ("input - interrupt %d (0x%lx), level %d\n",
|
||||
my_port,
|
||||
(unsigned long)glue->address + port * sizeof(unsigned_word),
|
||||
level));
|
||||
break;
|
||||
}
|
||||
case glue_and:
|
||||
glue->output[0] = glue->input[0];
|
||||
for (i = 1; i < glue->nr_inputs; i++)
|
||||
glue->output[0] &= glue->input[i];
|
||||
DTRACE(glue, ("and - interrupt %d, level %d arrived - output %d\n",
|
||||
my_port, level, glue->output[0]));
|
||||
device_interrupt_event(me, 0, glue->output[0], processor, cia);
|
||||
break;
|
||||
default:
|
||||
device_error(me, "operator not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const device_interrupt_port_descriptor hw_glue_interrupt_ports[] = {
|
||||
{ "int", 0, max_nr_interrupts },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
static device_callbacks const hw_glue_callbacks = {
|
||||
{ hw_glue_init_address, NULL },
|
||||
{ NULL, }, /* address */
|
||||
{ hw_glue_io_read_buffer_callback,
|
||||
hw_glue_io_write_buffer_callback, },
|
||||
{ NULL, }, /* DMA */
|
||||
{ hw_glue_interrupt_event, NULL, hw_glue_interrupt_ports }, /* interrupt */
|
||||
{ NULL, }, /* unit */
|
||||
NULL, /* instance */
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
hw_glue_create(const char *name,
|
||||
const device_unit *unit_address,
|
||||
const char *args)
|
||||
{
|
||||
/* create the descriptor */
|
||||
hw_glue_device *glue = ZALLOC(hw_glue_device);
|
||||
return glue;
|
||||
}
|
||||
|
||||
|
||||
const device_descriptor hw_glue_device_descriptor[] = {
|
||||
{ "glue", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-and", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-nand", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-or", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-xor", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-nor", hw_glue_create, &hw_glue_callbacks },
|
||||
{ "glue-not", hw_glue_create, &hw_glue_callbacks },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
#endif /* _HW_GLUE_C_ */
|
869
sim/ppc/hw_ide.c
Normal file
869
sim/ppc/hw_ide.c
Normal file
@ -0,0 +1,869 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _HW_IDE_C_
|
||||
#define _HW_IDE_C_
|
||||
|
||||
#include "device_table.h"
|
||||
|
||||
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
ide - Integrated Disk Electronics
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
This device models the primary/secondary <<ide>> controller
|
||||
described in the [CHRPIO] document.
|
||||
|
||||
The controller has separate independant interrupt outputs for each
|
||||
<<ide>> bus.
|
||||
|
||||
|
||||
PROPERTIES
|
||||
|
||||
|
||||
reg = ... (required)
|
||||
|
||||
The <<reg>> property is described in the document [CHRPIO].
|
||||
|
||||
|
||||
ready-delay = <integer> (optional)
|
||||
|
||||
If present, this specifies the time that the <<ide>> device takes
|
||||
to complete an I/O operation.
|
||||
|
||||
|
||||
disk@?/ide-byte-count = <integer> (optional)
|
||||
|
||||
disk@?/ide-sector-count = <integer> (optional)
|
||||
|
||||
disk@?/ide-head-count = <integer> (optional)
|
||||
|
||||
The <<ide>> device checks each child (disk device) node to see if
|
||||
it has the above properties. If present, these values will be used
|
||||
to compute the <<LBA>> address in <<CHS>> addressing mode.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
|
||||
|
||||
Enable tracing:
|
||||
|
||||
| -t ide-device \
|
||||
|
||||
|
||||
Attach the <<ide>> device to the <<pci>> bus at slot one. Specify
|
||||
legacy I/O addresses:
|
||||
|
||||
| -o '/phb/ide@1/assigned-addresses \
|
||||
| ni0,0,10,1f0 8 \
|
||||
| ni0,0,14,3f8 8 \
|
||||
| ni0,0,18,170 8 \
|
||||
| ni0,0,1c,378 8 \
|
||||
| ni0,0,20,200 8' \
|
||||
| -o '/phb@0x80000000/ide@1/reg \
|
||||
| 1 0 \
|
||||
| i0,0,10,0 8 \
|
||||
| i0,0,18,0 8 \
|
||||
| i0,0,14,6 1 \
|
||||
| i0,0,1c,6 1 \
|
||||
| i0,0,20,0 8' \
|
||||
|
||||
Note: the fouth and fifth reg entries specify that the register is
|
||||
at an offset into the address specified by the base register
|
||||
(<<assigned-addresses>>); Apart from restrictions placed by the
|
||||
<<pci>> specification, no restrictions are placed on the number of
|
||||
base registers specified by the <<assigned-addresses>> property.
|
||||
|
||||
Attach a <<disk>> to the primary and a <<cdrom>> to the secondary
|
||||
<<ide>> controller.
|
||||
|
||||
| -o '/phb@0x80000000/ide@1/disk@0/file "zero' \
|
||||
| -o '/phb@0x80000000/ide@1/cdrom@2/file "/dev/cdrom"' \
|
||||
|
||||
Connect the two interrupt outputs (a and b) to a <<glue>> device to
|
||||
allow testing of the interrupt port. In a real simulation they
|
||||
would be wired to the interrupt controller.
|
||||
|
||||
| -o '/phb@0x80000000/glue@2/reg 2 0 ni0,0,0,0 8' \
|
||||
| -o '/phb@0x80000000/ide@1 > a 0 /phb@0x80000000/glue@2' \
|
||||
| -o '/phb@0x80000000/ide@1 > b 1 /phb@0x80000000/glue@2'
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
|
||||
While the DMA registers are present, DMA support has not yet been
|
||||
implemented.
|
||||
|
||||
The number of supported commands is very limited.
|
||||
|
||||
The standards documents appear to be vague on how to specify the
|
||||
<<unit-address>> of disk devices devices being attached to the
|
||||
<<ide>> controller. I've chosen to use integers with devices zero
|
||||
and one going to the primary controller while two and three are
|
||||
connected to the secondary controller.
|
||||
|
||||
|
||||
REFERENCES
|
||||
|
||||
|
||||
[CHRPIO] PowerPC(tm) Microprocessor Common Hardware Reference
|
||||
Platform: I/O Device Reference. http://chrp.apple.com/???.
|
||||
|
||||
[SCHMIDT] The SCSI Bus and IDE Interface - Protocols, Applications
|
||||
and Programming. Friedhelm Schmidt (translated by Michael
|
||||
Schultz). ISBN 0-201-42284-0. Addison-Wesley Publishing Company.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef enum _io_direction {
|
||||
is_read,
|
||||
is_write,
|
||||
} io_direction;
|
||||
|
||||
|
||||
enum {
|
||||
nr_ide_controllers = 2,
|
||||
nr_ide_drives_per_controller = 2,
|
||||
nr_fifo_entries = 8192,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* command register block - read */
|
||||
ide_data_reg,
|
||||
ide_error_reg, /*ide_feature_reg*/
|
||||
ide_sector_count_reg,
|
||||
ide_sector_number_reg,
|
||||
ide_cylinder_reg0,
|
||||
ide_cylinder_reg1,
|
||||
ide_drive_head_reg,
|
||||
ide_status_reg, /*ide_command_reg*/
|
||||
/* command register block - write */
|
||||
ide_feature_reg, /*ide_error_reg*/
|
||||
ide_command_reg, /*ide_status_reg*/
|
||||
/* control register block - read */
|
||||
ide_alternate_status_reg, /*ide_control_reg*/
|
||||
ide_control_reg, /*ide_alternate_status_reg*/
|
||||
/* dma register block */
|
||||
ide_dma_command_reg,
|
||||
ide_dma_unused_1_reg,
|
||||
ide_dma_status_reg,
|
||||
ide_dma_unused_3_reg,
|
||||
ide_dma_prd_table_address_reg0,
|
||||
ide_dma_prd_table_address_reg1,
|
||||
ide_dma_prd_table_address_reg2,
|
||||
ide_dma_prd_table_address_reg3,
|
||||
nr_ide_registers,
|
||||
};
|
||||
|
||||
|
||||
typedef enum _ide_states {
|
||||
idle_state,
|
||||
busy_loaded_state,
|
||||
busy_drained_state,
|
||||
busy_dma_state,
|
||||
busy_command_state,
|
||||
loading_state,
|
||||
draining_state,
|
||||
} ide_states;
|
||||
|
||||
static const char *
|
||||
ide_state_name(ide_states state)
|
||||
{
|
||||
switch (state) {
|
||||
case idle_state: return "idle";
|
||||
case busy_loaded_state: return "busy_loaded_state";
|
||||
case busy_drained_state: return "busy_drained_state";
|
||||
case busy_dma_state: return "busy_dma_state";
|
||||
case busy_command_state: return "busy_command_state";
|
||||
case loading_state: return "loading_state";
|
||||
case draining_state: return "draining_state";
|
||||
default: return "illegal-state";
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _ide_geometry {
|
||||
int head;
|
||||
int sector;
|
||||
int byte;
|
||||
} ide_geometry;
|
||||
|
||||
typedef struct _ide_drive {
|
||||
int nr;
|
||||
device *device;
|
||||
ide_geometry geometry;
|
||||
ide_geometry default_geometry;
|
||||
} ide_drive;
|
||||
|
||||
typedef struct _ide_controller {
|
||||
int nr;
|
||||
ide_states state;
|
||||
unsigned8 reg[nr_ide_registers];
|
||||
unsigned8 fifo[nr_fifo_entries];
|
||||
int fifo_pos;
|
||||
int fifo_size;
|
||||
ide_drive *current_drive;
|
||||
int current_byte;
|
||||
int current_transfer;
|
||||
ide_drive drive[nr_ide_drives_per_controller];
|
||||
device *me;
|
||||
event_entry_tag event_tag;
|
||||
int is_interrupting;
|
||||
signed64 ready_delay;
|
||||
} ide_controller;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
set_interrupt(device *me,
|
||||
ide_controller *controller)
|
||||
{
|
||||
if ((controller->reg[ide_control_reg] & 0x2) == 0) {
|
||||
DTRACE(ide, ("controller %d - interrupt set\n", controller->nr));
|
||||
device_interrupt_event(me, controller->nr, 1, NULL, 0);
|
||||
controller->is_interrupting = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clear_interrupt(device *me,
|
||||
ide_controller *controller)
|
||||
{
|
||||
if (controller->is_interrupting) {
|
||||
DTRACE(ide, ("controller %d - interrupt clear\n", controller->nr));
|
||||
device_interrupt_event(me, controller->nr, 0, NULL, 0);
|
||||
controller->is_interrupting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_event(void *data)
|
||||
{
|
||||
ide_controller *controller = data;
|
||||
device *me = controller->me;
|
||||
controller->event_tag = 0;
|
||||
switch (controller->state) {
|
||||
case busy_loaded_state:
|
||||
case busy_drained_state:
|
||||
if (controller->current_transfer > 0) {
|
||||
controller->state = (controller->state == busy_loaded_state
|
||||
? loading_state : draining_state);
|
||||
}
|
||||
else {
|
||||
controller->state = idle_state;
|
||||
}
|
||||
set_interrupt(me, controller);
|
||||
break;
|
||||
default:
|
||||
device_error(me, "controller %d - unexpected event", controller->nr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
schedule_ready_event(device *me,
|
||||
ide_controller *controller)
|
||||
{
|
||||
if (controller->event_tag != 0)
|
||||
device_error(me, "controller %d - attempting to schedule multiple events",
|
||||
controller->nr);
|
||||
controller->event_tag =
|
||||
device_event_queue_schedule(me, controller->ready_delay,
|
||||
do_event, controller);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_fifo_read(device *me,
|
||||
ide_controller *controller,
|
||||
void *dest,
|
||||
int nr_bytes)
|
||||
{
|
||||
if (controller->state != draining_state)
|
||||
device_error(me, "controller %d - reading fifo when not ready (%s)",
|
||||
controller->nr,
|
||||
ide_state_name(controller->state));
|
||||
if (controller->fifo_pos + nr_bytes > controller->fifo_size)
|
||||
device_error(me, "controller %d - fifo underflow", controller->nr);
|
||||
if (nr_bytes > 0) {
|
||||
memcpy(dest, &controller->fifo[controller->fifo_pos], nr_bytes);
|
||||
controller->fifo_pos += nr_bytes;
|
||||
}
|
||||
if (controller->fifo_pos == controller->fifo_size) {
|
||||
controller->current_transfer -= 1;
|
||||
if (controller->current_transfer > 0
|
||||
&& controller->current_drive != NULL) {
|
||||
DTRACE(ide, ("controller %d:%d - reading %d byte block at 0x%x\n",
|
||||
controller->nr,
|
||||
controller->current_drive->nr,
|
||||
controller->fifo_size,
|
||||
controller->current_byte));
|
||||
if (device_io_read_buffer(controller->current_drive->device,
|
||||
controller->fifo,
|
||||
0, controller->current_byte,
|
||||
controller->fifo_size,
|
||||
NULL, 0)
|
||||
!= controller->fifo_size)
|
||||
device_error(me, "controller %d - disk %s io read error",
|
||||
controller->nr,
|
||||
device_path(controller->current_drive->device));
|
||||
}
|
||||
controller->state = busy_drained_state;
|
||||
controller->fifo_pos = 0;
|
||||
controller->current_byte += controller->fifo_size;
|
||||
schedule_ready_event(me, controller);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_fifo_write(device *me,
|
||||
ide_controller *controller,
|
||||
const void *source,
|
||||
int nr_bytes)
|
||||
{
|
||||
if (controller->state != loading_state)
|
||||
device_error(me, "controller %d - writing fifo when not ready (%s)",
|
||||
controller->nr,
|
||||
ide_state_name(controller->state));
|
||||
if (controller->fifo_pos + nr_bytes > controller->fifo_size)
|
||||
device_error(me, "controller %d - fifo overflow", controller->nr);
|
||||
if (nr_bytes > 0) {
|
||||
memcpy(&controller->fifo[controller->fifo_pos], source, nr_bytes);
|
||||
controller->fifo_pos += nr_bytes;
|
||||
}
|
||||
if (controller->fifo_pos == controller->fifo_size) {
|
||||
if (controller->current_transfer > 0
|
||||
&& controller->current_drive != NULL) {
|
||||
DTRACE(ide, ("controller %d:%d - writing %d byte block at 0x%x\n",
|
||||
controller->nr,
|
||||
controller->current_drive->nr,
|
||||
controller->fifo_size,
|
||||
controller->current_byte));
|
||||
if (device_io_write_buffer(controller->current_drive->device,
|
||||
controller->fifo,
|
||||
0, controller->current_byte,
|
||||
controller->fifo_size,
|
||||
NULL, 0)
|
||||
!= controller->fifo_size)
|
||||
device_error(me, "controller %d - disk %s io write error",
|
||||
controller->nr,
|
||||
device_path(controller->current_drive->device));
|
||||
}
|
||||
controller->current_transfer -= 1;
|
||||
controller->fifo_pos = 0;
|
||||
controller->current_byte += controller->fifo_size;
|
||||
controller->state = busy_loaded_state;
|
||||
schedule_ready_event(me, controller);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setup_fifo(device *me,
|
||||
ide_controller *controller,
|
||||
int is_simple,
|
||||
int is_with_disk,
|
||||
io_direction direction)
|
||||
{
|
||||
/* find the disk */
|
||||
if (is_with_disk) {
|
||||
int drive_nr = (controller->reg[ide_drive_head_reg] & 0x10) != 0;
|
||||
controller->current_drive = &controller->drive[drive_nr];
|
||||
}
|
||||
else {
|
||||
controller->current_drive = NULL;
|
||||
}
|
||||
|
||||
/* number of transfers */
|
||||
if (is_simple)
|
||||
controller->current_transfer = 1;
|
||||
else {
|
||||
int sector_count = controller->reg[ide_sector_count_reg];
|
||||
if (sector_count == 0)
|
||||
controller->current_transfer = 256;
|
||||
else
|
||||
controller->current_transfer = sector_count;
|
||||
}
|
||||
|
||||
/* the transfer size */
|
||||
if (controller->current_drive == NULL)
|
||||
controller->fifo_size = 512;
|
||||
else
|
||||
controller->fifo_size = controller->current_drive->geometry.byte;
|
||||
|
||||
/* empty the fifo */
|
||||
controller->fifo_pos = 0;
|
||||
|
||||
/* the starting address */
|
||||
if (controller->current_drive == NULL)
|
||||
controller->current_byte = 0;
|
||||
else if (controller->reg[ide_drive_head_reg] & 0x40) {
|
||||
/* LBA addressing mode */
|
||||
controller->current_byte = controller->fifo_size
|
||||
* (((controller->reg[ide_drive_head_reg] & 0xf) << 24)
|
||||
| (controller->reg[ide_cylinder_reg1] << 16)
|
||||
| (controller->reg[ide_cylinder_reg0] << 8)
|
||||
| (controller->reg[ide_sector_number_reg]));
|
||||
}
|
||||
else if (controller->current_drive->geometry.head != 0
|
||||
&& controller->current_drive->geometry.sector != 0) {
|
||||
/* CHS addressing mode */
|
||||
int head_nr = controller->reg[ide_drive_head_reg] & 0xf;
|
||||
int cylinder_nr = ((controller->reg[ide_cylinder_reg1] << 8)
|
||||
| controller->reg[ide_cylinder_reg0]);
|
||||
int sector_nr = controller->reg[ide_sector_number_reg];
|
||||
controller->current_byte = controller->fifo_size
|
||||
* ((cylinder_nr * controller->current_drive->geometry.head + head_nr)
|
||||
* controller->current_drive->geometry.sector + sector_nr - 1);
|
||||
}
|
||||
else
|
||||
device_error(me, "controller %d:%d - CHS addressing disabled",
|
||||
controller->nr, controller->current_drive->nr);
|
||||
DTRACE(ide, ("controller %ld:%ld - transfer (%s) %ld blocks of %ld bytes from 0x%lx\n",
|
||||
(long)controller->nr,
|
||||
controller->current_drive == NULL ? -1L : (long)controller->current_drive->nr,
|
||||
direction == is_read ? "read" : "write",
|
||||
(long)controller->current_transfer,
|
||||
(long)controller->fifo_size,
|
||||
(unsigned long)controller->current_byte));
|
||||
switch (direction) {
|
||||
case is_read:
|
||||
/* force a primeing read */
|
||||
controller->current_transfer += 1;
|
||||
controller->state = draining_state;
|
||||
controller->fifo_pos = controller->fifo_size;
|
||||
do_fifo_read(me, controller, NULL, 0);
|
||||
break;
|
||||
case is_write:
|
||||
controller->state = loading_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_command(device *me,
|
||||
ide_controller *controller,
|
||||
int command)
|
||||
{
|
||||
if (controller->state != idle_state)
|
||||
device_error(me, "controller %d - command when not idle", controller->nr);
|
||||
switch (command) {
|
||||
case 0x20: case 0x21: /* read-sectors */
|
||||
setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_read);
|
||||
break;
|
||||
case 0x30: case 0x31: /* write */
|
||||
setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_write);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned8
|
||||
get_status(device *me,
|
||||
ide_controller *controller)
|
||||
{
|
||||
switch (controller->state) {
|
||||
case loading_state:
|
||||
case draining_state:
|
||||
return 0x08; /* data req */
|
||||
case busy_loaded_state:
|
||||
case busy_drained_state:
|
||||
return 0x80; /* busy */
|
||||
case idle_state:
|
||||
return 0x40; /* drive ready */
|
||||
default:
|
||||
device_error(me, "internal error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The address presented to the IDE controler is decoded and then
|
||||
mapped onto a controller:reg pair */
|
||||
|
||||
enum {
|
||||
nr_address_blocks = 6,
|
||||
};
|
||||
|
||||
typedef struct _address_block {
|
||||
int space;
|
||||
unsigned_word base_addr;
|
||||
unsigned_word bound_addr;
|
||||
int controller;
|
||||
int base_reg;
|
||||
} address_block;
|
||||
|
||||
typedef struct _address_decoder {
|
||||
address_block block[nr_address_blocks];
|
||||
} address_decoder;
|
||||
|
||||
static void
|
||||
decode_address(device *me,
|
||||
address_decoder *decoder,
|
||||
int space,
|
||||
unsigned_word address,
|
||||
int *controller,
|
||||
int *reg,
|
||||
io_direction direction)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nr_address_blocks; i++) {
|
||||
if (space == decoder->block[i].space
|
||||
&& address >= decoder->block[i].base_addr
|
||||
&& address <= decoder->block[i].bound_addr) {
|
||||
*controller = decoder->block[i].controller;
|
||||
*reg = (address
|
||||
- decoder->block[i].base_addr
|
||||
+ decoder->block[i].base_reg);
|
||||
if (direction == is_write) {
|
||||
switch (*reg) {
|
||||
case ide_error_reg: *reg = ide_feature_reg; break;
|
||||
case ide_status_reg: *reg = ide_command_reg; break;
|
||||
case ide_alternate_status_reg: *reg = ide_control_reg; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
device_error(me, "address %d:0x%lx invalid",
|
||||
space, (unsigned long)address);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_address_decoder(device *me,
|
||||
address_decoder *decoder)
|
||||
{
|
||||
int reg;
|
||||
for (reg = 1; reg < 6; reg++) {
|
||||
reg_property_spec unit;
|
||||
int space;
|
||||
unsigned_word address;
|
||||
unsigned size;
|
||||
/* find and decode the reg property */
|
||||
if (!device_find_reg_array_property(me, "reg", reg, &unit))
|
||||
device_error(me, "missing or invalid reg entry %d", reg);
|
||||
device_address_to_attach_address(device_parent(me), &unit.address,
|
||||
&space, &address, me);
|
||||
device_size_to_attach_size(device_parent(me), &unit.size, &size, me);
|
||||
/* insert it into the address decoder */
|
||||
switch (reg) {
|
||||
case 1:
|
||||
case 2:
|
||||
/* command register block */
|
||||
if (size != 8)
|
||||
device_error(me, "reg entry %d must have a size of 8", reg);
|
||||
decoder->block[reg-1].space = space;
|
||||
decoder->block[reg-1].base_addr = address;
|
||||
decoder->block[reg-1].bound_addr = address + size - 1;
|
||||
decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
|
||||
decoder->block[reg-1].base_reg = ide_data_reg;
|
||||
DTRACE(ide, ("controller %d command register block at %d:0x%lx..0x%lx\n",
|
||||
decoder->block[reg-1].controller,
|
||||
decoder->block[reg-1].space,
|
||||
(unsigned long)decoder->block[reg-1].base_addr,
|
||||
(unsigned long)decoder->block[reg-1].bound_addr));
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
/* control register block */
|
||||
if (size != 1)
|
||||
device_error(me, "reg entry %d must have a size of 1", reg);
|
||||
decoder->block[reg-1].space = space;
|
||||
decoder->block[reg-1].base_addr = address;
|
||||
decoder->block[reg-1].bound_addr = address + size - 1;
|
||||
decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
|
||||
decoder->block[reg-1].base_reg = ide_alternate_status_reg;
|
||||
DTRACE(ide, ("controller %d control register block at %d:0x%lx..0x%lx\n",
|
||||
decoder->block[reg-1].controller,
|
||||
decoder->block[reg-1].space,
|
||||
(unsigned long)decoder->block[reg-1].base_addr,
|
||||
(unsigned long)decoder->block[reg-1].bound_addr));
|
||||
break;
|
||||
case 5:
|
||||
/* dma register block */
|
||||
if (size != 8)
|
||||
device_error(me, "reg entry %d must have a size of 8", reg);
|
||||
decoder->block[reg-1].space = space;
|
||||
decoder->block[reg-1].base_addr = address;
|
||||
decoder->block[reg-1].bound_addr = address + 4 - 1;
|
||||
decoder->block[reg-1].base_reg = ide_dma_command_reg;
|
||||
decoder->block[reg-1].controller = 0;
|
||||
DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
|
||||
decoder->block[reg-1].controller,
|
||||
decoder->block[reg-1].space,
|
||||
(unsigned long)decoder->block[reg-1].base_addr,
|
||||
(unsigned long)decoder->block[reg-1].bound_addr));
|
||||
decoder->block[reg].space = space;
|
||||
decoder->block[reg].base_addr = address + 4;
|
||||
decoder->block[reg].bound_addr = address + 8 - 1;
|
||||
decoder->block[reg].controller = 1;
|
||||
decoder->block[reg].base_reg = ide_dma_command_reg;
|
||||
DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
|
||||
decoder->block[reg].controller,
|
||||
decoder->block[reg-1].space,
|
||||
(unsigned long)decoder->block[reg].base_addr,
|
||||
(unsigned long)decoder->block[reg].bound_addr));
|
||||
break;
|
||||
default:
|
||||
device_error(me, "internal error - bad switch");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct _hw_ide_device {
|
||||
ide_controller controller[nr_ide_controllers];
|
||||
address_decoder decoder;
|
||||
} hw_ide_device;
|
||||
|
||||
|
||||
static void
|
||||
hw_ide_init_address(device *me)
|
||||
{
|
||||
hw_ide_device *ide = device_data(me);
|
||||
int controller;
|
||||
int drive;
|
||||
|
||||
/* zero some things */
|
||||
for (controller = 0; controller < nr_ide_controllers; controller++) {
|
||||
memset(&ide->controller[controller], 0, sizeof(ide_controller));
|
||||
for (drive = 0; drive < nr_ide_drives_per_controller; drive++) {
|
||||
ide->controller[controller].drive[drive].nr = drive;
|
||||
}
|
||||
ide->controller[controller].me = me;
|
||||
if (device_find_property(me, "ready-delay") != NULL)
|
||||
ide->controller[controller].ready_delay =
|
||||
device_find_integer_property(me, "ready-delay");
|
||||
}
|
||||
|
||||
/* attach this device to its parent */
|
||||
generic_device_init_address(me);
|
||||
|
||||
/* determine our own address map */
|
||||
build_address_decoder(me, &ide->decoder);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hw_ide_attach_address(device *me,
|
||||
attach_type type,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
access_type access,
|
||||
device *client) /*callback/default*/
|
||||
{
|
||||
hw_ide_device *ide = (hw_ide_device*)device_data(me);
|
||||
int controller_nr = addr / nr_ide_drives_per_controller;
|
||||
int drive_nr = addr % nr_ide_drives_per_controller;
|
||||
ide_controller *controller;
|
||||
ide_drive *drive;
|
||||
if (controller_nr >= nr_ide_controllers)
|
||||
device_error(me, "no controller for disk %s",
|
||||
device_path(client));
|
||||
|
||||
controller = &ide->controller[controller_nr];
|
||||
drive = &controller->drive[drive_nr];
|
||||
drive->device = client;
|
||||
if (device_find_property(client, "ide-byte-count") != NULL)
|
||||
drive->geometry.byte = device_find_integer_property(client, "ide-byte-count");
|
||||
else
|
||||
drive->geometry.byte = 512;
|
||||
if (device_find_property(client, "ide-sector-count") != NULL)
|
||||
drive->geometry.sector = device_find_integer_property(client, "ide-sector-count");
|
||||
if (device_find_property(client, "ide-head-count") != NULL)
|
||||
drive->geometry.head = device_find_integer_property(client, "ide-head-count");
|
||||
drive->default_geometry = drive->geometry;
|
||||
DTRACE(ide, ("controller %d:%d %s byte-count %d, sector-count %d, head-count %d\n",
|
||||
controller_nr,
|
||||
drive->nr,
|
||||
device_path(client),
|
||||
drive->geometry.byte,
|
||||
drive->geometry.sector,
|
||||
drive->geometry.head));
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
hw_ide_io_read_buffer(device *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
hw_ide_device *ide = (hw_ide_device *)device_data(me);
|
||||
int control_nr;
|
||||
int reg;
|
||||
ide_controller *controller;
|
||||
|
||||
/* find the interface */
|
||||
decode_address(me, &ide->decoder, space, addr, &control_nr, ®, is_read);
|
||||
controller = & ide->controller[control_nr];
|
||||
|
||||
/* process the transfer */
|
||||
memset(dest, 0, nr_bytes);
|
||||
switch (reg) {
|
||||
case ide_data_reg:
|
||||
do_fifo_read(me, controller, dest, nr_bytes);
|
||||
break;
|
||||
case ide_status_reg:
|
||||
*(unsigned8*)dest = get_status(me, controller);
|
||||
clear_interrupt(me, controller);
|
||||
break;
|
||||
case ide_alternate_status_reg:
|
||||
*(unsigned8*)dest = get_status(me, controller);
|
||||
break;
|
||||
case ide_error_reg:
|
||||
case ide_sector_count_reg:
|
||||
case ide_sector_number_reg:
|
||||
case ide_cylinder_reg0:
|
||||
case ide_cylinder_reg1:
|
||||
case ide_drive_head_reg:
|
||||
case ide_control_reg:
|
||||
case ide_dma_command_reg:
|
||||
case ide_dma_status_reg:
|
||||
case ide_dma_prd_table_address_reg0:
|
||||
case ide_dma_prd_table_address_reg1:
|
||||
case ide_dma_prd_table_address_reg2:
|
||||
case ide_dma_prd_table_address_reg3:
|
||||
*(unsigned8*)dest = controller->reg[reg];
|
||||
break;
|
||||
default:
|
||||
device_error(me, "bus-error at address 0x%lx", addr);
|
||||
break;
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
hw_ide_io_write_buffer(device *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
hw_ide_device *ide = (hw_ide_device *)device_data(me);
|
||||
int control_nr;
|
||||
int reg;
|
||||
ide_controller *controller;
|
||||
|
||||
/* find the interface */
|
||||
decode_address(me, &ide->decoder, space, addr, &control_nr, ®, is_write);
|
||||
controller = &ide->controller[control_nr];
|
||||
|
||||
/* process the access */
|
||||
switch (reg) {
|
||||
case ide_data_reg:
|
||||
do_fifo_write(me, controller, source, nr_bytes);
|
||||
break;
|
||||
case ide_command_reg:
|
||||
do_command(me, controller, *(unsigned8*)source);
|
||||
break;
|
||||
case ide_control_reg:
|
||||
controller->reg[reg] = *(unsigned8*)source;
|
||||
/* possibly cancel interrupts */
|
||||
if ((controller->reg[reg] & 0x02) == 0x02)
|
||||
clear_interrupt(me, controller);
|
||||
break;
|
||||
case ide_feature_reg:
|
||||
case ide_sector_count_reg:
|
||||
case ide_sector_number_reg:
|
||||
case ide_cylinder_reg0:
|
||||
case ide_cylinder_reg1:
|
||||
case ide_drive_head_reg:
|
||||
case ide_dma_command_reg:
|
||||
case ide_dma_status_reg:
|
||||
case ide_dma_prd_table_address_reg0:
|
||||
case ide_dma_prd_table_address_reg1:
|
||||
case ide_dma_prd_table_address_reg2:
|
||||
case ide_dma_prd_table_address_reg3:
|
||||
controller->reg[reg] = *(unsigned8*)source;
|
||||
break;
|
||||
default:
|
||||
device_error(me, "bus-error at 0x%lx", addr);
|
||||
break;
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
static const device_interrupt_port_descriptor hw_ide_interrupt_ports[] = {
|
||||
{ "a", 0, 0 },
|
||||
{ "b", 1, 0 },
|
||||
{ "c", 2, 0 },
|
||||
{ "d", 3, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
static device_callbacks const hw_ide_callbacks = {
|
||||
{ hw_ide_init_address, },
|
||||
{ hw_ide_attach_address, }, /* attach */
|
||||
{ hw_ide_io_read_buffer, hw_ide_io_write_buffer, },
|
||||
{ NULL, }, /* DMA */
|
||||
{ NULL, NULL, hw_ide_interrupt_ports }, /* interrupt */
|
||||
{ generic_device_unit_decode,
|
||||
generic_device_unit_encode,
|
||||
generic_device_address_to_attach_address,
|
||||
generic_device_size_to_attach_size },
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
hw_ide_create(const char *name,
|
||||
const device_unit *unit_address,
|
||||
const char *args)
|
||||
{
|
||||
hw_ide_device *ide = ZALLOC(hw_ide_device);
|
||||
return ide;
|
||||
}
|
||||
|
||||
|
||||
const device_descriptor hw_ide_device_descriptor[] = {
|
||||
{ "ide", hw_ide_create, &hw_ide_callbacks },
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
#endif /* _HW_IDE_ */
|
1827
sim/ppc/hw_opic.c
Normal file
1827
sim/ppc/hw_opic.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,98 +0,0 @@
|
||||
/* ICU device: icu@<address>
|
||||
|
||||
<address> : read - processor nr
|
||||
<address> : write - interrupt processor nr
|
||||
<address> + 4 : read - nr processors
|
||||
|
||||
Single byte registers that control a simple ICU.
|
||||
|
||||
Illustrates passing of events to parent device. Passing of
|
||||
interrupts to an interrupt destination. */
|
||||
|
||||
|
||||
static unsigned
|
||||
icu_io_read_buffer_callback(device *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
memset(dest, 0, nr_bytes);
|
||||
switch (addr & 4) {
|
||||
case 0:
|
||||
*(unsigned_1*)dest = cpu_nr(processor);
|
||||
break;
|
||||
case 4:
|
||||
*(unsigned_1*)dest =
|
||||
device_find_integer_property(me, "/openprom/options/smp");
|
||||
break;
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
icu_io_write_buffer_callback(device *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
unsigned_1 val = H2T_1(*(unsigned_1*)source);
|
||||
/* tell the parent device that the interrupt lines have changed.
|
||||
For this fake ICU. The interrupt lines just indicate the cpu to
|
||||
interrupt next */
|
||||
device_interrupt_event(me,
|
||||
val, /*my_port*/
|
||||
val, /*val*/
|
||||
processor, cia);
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
icu_do_interrupt(event_queue *queue,
|
||||
void *data)
|
||||
{
|
||||
cpu *target = (cpu*)data;
|
||||
/* try to interrupt the processor. If the attempt fails, try again
|
||||
on the next tick */
|
||||
if (!external_interrupt(target))
|
||||
event_queue_schedule(queue, 1, icu_do_interrupt, target);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
icu_interrupt_event_callback(device *me,
|
||||
int my_port,
|
||||
device *source,
|
||||
int source_port,
|
||||
int level,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
/* the interrupt controller can't interrupt a cpu at any time.
|
||||
Rather it must synchronize with the system clock before
|
||||
performing an interrupt on the given processor */
|
||||
psim *system = cpu_system(processor);
|
||||
cpu *target = psim_cpu(system, my_port);
|
||||
if (target != NULL) {
|
||||
event_queue *events = cpu_event_queue(target);
|
||||
event_queue_schedule(events, 1, icu_do_interrupt, target);
|
||||
}
|
||||
}
|
||||
|
||||
static device_callbacks const icu_callbacks = {
|
||||
{ generic_device_init_address, },
|
||||
{ NULL, }, /* address */
|
||||
{ icu_io_read_buffer_callback,
|
||||
icu_io_write_buffer_callback, },
|
||||
{ NULL, }, /* DMA */
|
||||
{ icu_interrupt_event_callback, },
|
||||
{ NULL, }, /* unit */
|
||||
};
|
||||
|
||||
|
108
sim/ppc/hw_trace.c
Normal file
108
sim/ppc/hw_trace.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _HW_TRACE_C_
|
||||
#define _HW_TRACE_C_
|
||||
|
||||
#include "device_table.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/* DEVICE
|
||||
|
||||
trace - the properties of this dummy device specify trace options
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The properties of this device are used, during initialization, to
|
||||
specify the value various simulation trace options. The
|
||||
initialization can occure implicitly (during device tree init) or
|
||||
explicitly using this devices ioctl method.
|
||||
|
||||
The actual options and their default values (for a given target)
|
||||
are defined in the file debug.
|
||||
|
||||
This device is normally a child of the /openprom node.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
The trace option dump-device-tree can be enabled by specifying the
|
||||
option:
|
||||
|
||||
| -o '/openprom/trace/dump-device-tree 0x1'
|
||||
|
||||
Alternativly the shorthand version:
|
||||
|
||||
| -t dump-device-tree
|
||||
|
||||
can be used. */
|
||||
|
||||
static void
|
||||
hw_trace_init_data(device *me)
|
||||
{
|
||||
const device_property *prop = device_find_property(me, NULL);
|
||||
while (prop != NULL) {
|
||||
const char *name = prop->name;
|
||||
unsigned32 value = device_find_integer_property(me, name);
|
||||
trace_option(name, value);
|
||||
prop = device_next_property(prop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hook to allow the (re) initialization of the trace options at any
|
||||
time */
|
||||
|
||||
static int
|
||||
hw_trace_ioctl(device *me,
|
||||
cpu *processor,
|
||||
unsigned_word cia,
|
||||
device_ioctl_request request,
|
||||
va_list ap)
|
||||
{
|
||||
switch (request) {
|
||||
case device_ioctl_set_trace:
|
||||
hw_trace_init_data(me);
|
||||
break;
|
||||
default:
|
||||
device_error(me, "insupported ioctl request");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static device_callbacks const hw_trace_callbacks = {
|
||||
{ NULL, hw_trace_init_data, }, /* init */
|
||||
{ NULL, }, /* address */
|
||||
{ NULL, }, /* IO */
|
||||
{ NULL, }, /* DMA */
|
||||
{ NULL, }, /* interrupt */
|
||||
{ NULL, }, /* unit */
|
||||
NULL, /* instance-create */
|
||||
hw_trace_ioctl,
|
||||
};
|
||||
|
||||
const device_descriptor hw_trace_device_descriptor[] = {
|
||||
{ "trace", NULL, &hw_trace_callbacks },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
#endif _HW_TRACE_C_
|
139
sim/ppc/tree.h
Normal file
139
sim/ppc/tree.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TREE_H_
|
||||
#define _TREE_H_
|
||||
|
||||
#ifndef INLINE_TREE
|
||||
#define INLINE_TREE
|
||||
#endif
|
||||
|
||||
/* Constructing the device tree:
|
||||
|
||||
The initial device tree populated with devices and basic properties
|
||||
is created using the function <<device_tree_add_parsed()>>. This
|
||||
function parses a PSIM device specification and uses it to populate
|
||||
the tree accordingly.
|
||||
|
||||
This function accepts a printf style formatted string as the
|
||||
argument that describes the entry. Any properties or interrupt
|
||||
connections added to a device tree using this function are marked
|
||||
as having a permenant disposition. When the tree is (re)
|
||||
initialized they will be restored to their initial value.
|
||||
|
||||
*/
|
||||
|
||||
EXTERN_TREE\
|
||||
(device *) tree_parse
|
||||
(device *root,
|
||||
const char *fmt,
|
||||
...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
|
||||
INLINE_TREE\
|
||||
(void) tree_usage
|
||||
(int verbose);
|
||||
|
||||
INLINE_TREE\
|
||||
(void) tree_print
|
||||
(device *root);
|
||||
|
||||
INLINE_TREE\
|
||||
(device_instance*) tree_instance
|
||||
(device *root,
|
||||
const char *device_specifier);
|
||||
|
||||
|
||||
/* Tree traversal::
|
||||
|
||||
The entire device tree can be traversed using the
|
||||
<<device_tree_traverse()>> function. The traversal can be in
|
||||
either pre- or postfix order.
|
||||
|
||||
*/
|
||||
|
||||
typedef void (tree_traverse_function)
|
||||
(device *device,
|
||||
void *data);
|
||||
|
||||
INLINE_DEVICE\
|
||||
(void) tree_traverse
|
||||
(device *root,
|
||||
tree_traverse_function *prefix,
|
||||
tree_traverse_function *postfix,
|
||||
void *data);
|
||||
|
||||
|
||||
/* Tree lookup::
|
||||
|
||||
The function <<tree_find_device()>> will attempt to locate
|
||||
the specified device within the tree. If the device is not found a
|
||||
NULL device is returned.
|
||||
|
||||
*/
|
||||
|
||||
INLINE_TREE\
|
||||
(device *) tree_find_device
|
||||
(device *root,
|
||||
const char *path);
|
||||
|
||||
|
||||
INLINE_TREE\
|
||||
(const device_property *) tree_find_property
|
||||
(device *root,
|
||||
const char *path_to_property);
|
||||
|
||||
INLINE_TREE\
|
||||
(int) tree_find_boolean_property
|
||||
(device *root,
|
||||
const char *path_to_property);
|
||||
|
||||
INLINE_TREE\
|
||||
(signed_cell) tree_find_integer_property
|
||||
(device *root,
|
||||
const char *path_to_property);
|
||||
|
||||
INLINE_TREE\
|
||||
(device_instance *) tree_find_ihandle_property
|
||||
(device *root,
|
||||
const char *path_to_property);
|
||||
|
||||
INLINE_TREE\
|
||||
(const char *) tree_find_string_property
|
||||
(device *root,
|
||||
const char *path_to_property);
|
||||
|
||||
|
||||
/* Initializing the created tree:
|
||||
|
||||
Once a device tree has been created the <<device_tree_init()>>
|
||||
function is used to initialize it. The exact sequence of events
|
||||
that occure during initialization are described separatly.
|
||||
|
||||
*/
|
||||
|
||||
INLINE_TREE\
|
||||
(void) tree_init
|
||||
(device *root,
|
||||
psim *system);
|
||||
|
||||
|
||||
#endif /* _TREE_H_ */
|
Loading…
Reference in New Issue
Block a user