Showing preview only (2,171K chars total). Download the full file or copy to clipboard to get everything.
Repository: lenticularis39/axpbox
Branch: main
Commit: e81dce564bea
Files: 180
Total size: 2.0 MB
Directory structure:
gitextract_fd_kwrgy/
├── .clang-format
├── .github/
│ └── workflows/
│ └── build-test-and-artifact.yml
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake/
│ ├── CheckLargeFiles.cmake
│ ├── FindPCAP.cmake
│ ├── TestFileOffsetBits.c
│ ├── TestLargeFiles.c.cmake.in
│ └── TestWindowsFSeek.c
├── es40.cfg
├── sonar-project.properties
├── src/
│ ├── AliM1543C.cpp
│ ├── AliM1543C.hpp
│ ├── AliM1543C_ide.cpp
│ ├── AliM1543C_ide.hpp
│ ├── AliM1543C_usb.cpp
│ ├── AliM1543C_usb.hpp
│ ├── AlphaCPU.cpp
│ ├── AlphaCPU.hpp
│ ├── AlphaCPU_ieeefloat.cpp
│ ├── AlphaCPU_vaxfloat.cpp
│ ├── AlphaCPU_vmspal.cpp
│ ├── AlphaSim.cpp
│ ├── Cirrus.cpp
│ ├── Cirrus.hpp
│ ├── Configurator.cpp
│ ├── Configurator.hpp
│ ├── DEC21143.cpp
│ ├── DEC21143.hpp
│ ├── DEC21143_mii.hpp
│ ├── DEC21143_tulipreg.hpp
│ ├── DMA.cpp
│ ├── DMA.hpp
│ ├── DPR.cpp
│ ├── DPR.hpp
│ ├── Disk.cpp
│ ├── Disk.hpp
│ ├── DiskController.cpp
│ ├── DiskController.hpp
│ ├── DiskDevice.cpp
│ ├── DiskDevice.hpp
│ ├── DiskFile.cpp
│ ├── DiskFile.hpp
│ ├── DiskRam.cpp
│ ├── DiskRam.hpp
│ ├── Ethernet.cpp
│ ├── Ethernet.hpp
│ ├── Flash.cpp
│ ├── Flash.hpp
│ ├── FloppyController.cpp
│ ├── FloppyController.hpp
│ ├── FreeTextQuestion.hpp
│ ├── Keyboard.cpp
│ ├── Keyboard.hpp
│ ├── Main.cpp
│ ├── MultipleChoiceQuestion.hpp
│ ├── NumberQuestion.hpp
│ ├── PCIDevice.cpp
│ ├── PCIDevice.hpp
│ ├── Port80.cpp
│ ├── Port80.hpp
│ ├── Question.hpp
│ ├── S3Trio64.cpp
│ ├── S3Trio64.hpp
│ ├── SCSIBus.cpp
│ ├── SCSIBus.hpp
│ ├── SCSIDevice.cpp
│ ├── SCSIDevice.hpp
│ ├── Serial.cpp
│ ├── Serial.hpp
│ ├── ShrinkingChoiceQuestion.hpp
│ ├── StdAfx.hpp
│ ├── Sym53C810.cpp
│ ├── Sym53C810.hpp
│ ├── Sym53C895.cpp
│ ├── Sym53C895.hpp
│ ├── System.cpp
│ ├── System.hpp
│ ├── SystemComponent.cpp
│ ├── SystemComponent.hpp
│ ├── TraceEngine.cpp
│ ├── TraceEngine.hpp
│ ├── VGA.cpp
│ ├── VGA.hpp
│ ├── base/
│ │ ├── Bugcheck.cpp
│ │ ├── Bugcheck.hpp
│ │ ├── ErrorHandler.cpp
│ │ ├── ErrorHandler.hpp
│ │ ├── Event.cpp
│ │ ├── Event.hpp
│ │ ├── Event_POSIX.cpp
│ │ ├── Event_POSIX.hpp
│ │ ├── Event_WIN32.cpp
│ │ ├── Event_WIN32.hpp
│ │ ├── Exception.cpp
│ │ ├── Exception.hpp
│ │ ├── Foundation.hpp
│ │ ├── Mutex.cpp
│ │ ├── Mutex.hpp
│ │ ├── Mutex_POSIX.cpp
│ │ ├── Mutex_POSIX.hpp
│ │ ├── Mutex_WIN32.cpp
│ │ ├── Mutex_WIN32.hpp
│ │ ├── NumberFormatter.cpp
│ │ ├── NumberFormatter.hpp
│ │ ├── Platform.hpp
│ │ ├── Platform_POSIX.hpp
│ │ ├── Platform_VMS.hpp
│ │ ├── Platform_WIN32.hpp
│ │ ├── Poco.hpp
│ │ ├── RWLock.cpp
│ │ ├── RWLock.hpp
│ │ ├── RWLock_POSIX.cpp
│ │ ├── RWLock_POSIX.hpp
│ │ ├── RWLock_WIN32.cpp
│ │ ├── RWLock_WIN32.hpp
│ │ ├── RefCountedObject.cpp
│ │ ├── RefCountedObject.hpp
│ │ ├── ScopedLock.hpp
│ │ ├── Semaphore.cpp
│ │ ├── Semaphore.hpp
│ │ ├── Semaphore_POSIX.cpp
│ │ ├── Semaphore_POSIX.hpp
│ │ ├── Semaphore_WIN32.cpp
│ │ ├── Semaphore_WIN32.hpp
│ │ ├── SingletonHolder.hpp
│ │ ├── Timestamp.cpp
│ │ ├── Timestamp.hpp
│ │ ├── Types.hpp
│ │ └── UnWindows.hpp
│ ├── config.hpp.in
│ ├── config_debug.hpp
│ ├── cpu_arith.hpp
│ ├── cpu_bwx.hpp
│ ├── cpu_control.hpp
│ ├── cpu_debug.hpp
│ ├── cpu_defs.hpp
│ ├── cpu_fp_branch.hpp
│ ├── cpu_fp_memory.hpp
│ ├── cpu_fp_operate.hpp
│ ├── cpu_logical.hpp
│ ├── cpu_memory.hpp
│ ├── cpu_misc.hpp
│ ├── cpu_mvi.hpp
│ ├── cpu_pal.hpp
│ ├── cpu_vax.hpp
│ ├── datatypes.hpp
│ ├── es40-cfg.cpp
│ ├── es40_debug.cpp
│ ├── es40_debug.hpp
│ ├── es40_endian.hpp
│ ├── es40_float.hpp
│ ├── gui/
│ │ ├── gui.cpp
│ │ ├── gui.hpp
│ │ ├── gui_win32_font.hpp
│ │ ├── gui_x11.cpp
│ │ ├── keymap.cpp
│ │ ├── keymap.hpp
│ │ ├── plugin.hpp
│ │ ├── scancodes.cpp
│ │ ├── scancodes.hpp
│ │ ├── sdl.cpp
│ │ ├── sdl_fonts.hpp
│ │ ├── sdlkeys.hpp
│ │ └── vga.hpp
│ ├── lockstep.cpp
│ ├── lockstep.hpp
│ ├── make_unique.hpp
│ └── telnet.hpp
└── test/
├── disk/
│ └── unwritable/
│ ├── axp_correct.log
│ ├── es40.cfg
│ └── test.sh
├── rom/
│ ├── axp_correct.log
│ ├── es40.cfg
│ ├── test.ps1
│ └── test.sh
└── run
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
...
================================================
FILE: .github/workflows/build-test-and-artifact.yml
================================================
name: Build, run test and upload binaries
on: [push, pull_request]
jobs:
linux-x86-clang:
runs-on: "ubuntu-24.04"
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "name=date::$(date +'%Y-%m-%dT%H%M')" >> $GITHUB_OUTPUT
- name: Install build dependencies
run: sudo apt -y update && sudo apt -y install libpcap-dev libsdl-dev netcat-openbsd
- name: Create build environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_C_COMPILER="clang" -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall"
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake --build . --config Release
env:
MAKEFLAGS: "-j2"
- name: Run test scripts
working-directory: ${{runner.workspace}}/axpbox
shell: bash
run: ${{runner.workspace}}/axpbox/test/run
- name: Upload AXPbox binary
uses: actions/upload-artifact@v4
with:
name: AXPbox-linux-x86-clang-${{ env.BUILD_DATE }}
path: ${{runner.workspace}}/build/axpbox
env:
BUILD_DATE: ${{ steps.date.outputs.date }}
linux-x86-gcc:
runs-on: "ubuntu-24.04"
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "name=date::$(date +'%Y-%m-%dT%H%M')" >> $GITHUB_OUTPUT
- name: Install gcovr
run: pip install gcovr
- name: Install build dependencies
run: sudo apt -y update && sudo apt -y install libpcap-dev libsdl1.2-dev netcat-openbsd
- name: Create build environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake --build . --config Release
env:
MAKEFLAGS: "-j2"
- name: Run test scripts
working-directory: ${{runner.workspace}}/axpbox
shell: bash
run: ${{runner.workspace}}/axpbox/test/run
- name: Upload AXPbox binary
uses: actions/upload-artifact@v4
with:
name: AXPbox-linux-x86-gcc-${{ env.BUILD_DATE }}
path: ${{runner.workspace}}/build/axpbox
env:
BUILD_DATE: ${{ steps.date.outputs.date }}
linux-arm-gcc-crosscompile:
runs-on: "ubuntu-24.04"
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%dT%H%M')"
- name: Install build dependencies
run: sudo apt -y update && sudo apt -y install netcat-openbsd qemu-user qemu-user-binfmt gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross
- name: Create build environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DSTATIC_COMPILE=yes -DDISABLE_PCAP=yes -DDISABLE_SDL=yes -DDISABLE_X11=yes -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall" -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_CXX_FLAGS="-O3 -mcpu=cortex-a7 -mfpu=neon -mfloat-abi=hard -mno-unaligned-access"
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake --build . --config Release
env:
MAKEFLAGS: "-j2"
- name: Run binary
working-directory: ${{runner.workspace}}/axpbox
shell: bash
run: ${{runner.workspace}}/build/axpbox
- name: Binary info
working-directory: ${{runner.workspace}}/axpbox
shell: bash
run: file ${{runner.workspace}}/build/axpbox
- name: Upload AXPbox binary
uses: actions/upload-artifact@v4
with:
name: AXPbox-linux-ARM-gcc-${{ env.BUILD_DATE }}
path: ${{runner.workspace}}/build/axpbox
env:
BUILD_DATE: ${{ steps.date.outputs.date }}
windows-x86-msvc:
runs-on: windows-2025
steps:
- uses: actions/checkout@v4
- name: Create npcap sdk folder
working-directory: ${{runner.workspace}}\
run: mkdir pcap
- name: Download npcap sdk
working-directory: ${{runner.workspace}}\pcap
run: curl -o ./npcap-sdk-1.13.zip https://npcap.com/dist/npcap-sdk-1.13.zip
- name: unzip npcap sdk
working-directory: ${{runner.workspace}}\pcap
run: unzip npcap-sdk-1.13.zip
- name: Get current date
id: date
run: echo "name=date::$(date +'%Y-%m-%dT%H%M')" >> $GITHUB_OUTPUT
- name: Create build environment
run: cmake -E make_directory ${{runner.workspace}}\build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release -DPCAP_INCLUDE_DIR="${{runner.workspace}}/pcap/Include/" -DPCAP_LIBRARY="${{runner.workspace}}/pcap/Lib/x64/wpcap.lib"
- name: Build
working-directory: ${{runner.workspace}}\build
shell: bash
run: cmake --build . --config Release
env:
MAKEFLAGS: "-j2"
- name: Test run
working-directory: ${{runner.workspace}}\build
run: ${{runner.workspace}}\build\Release\axpbox.exe
- name: Upload AXPbox Binary
uses: actions/upload-artifact@v4
with:
name: AXPbox-windows-x86-msvc-${{ env.BUILD_DATE }}.exe
path: ${{runner.workspace}}\build\Release\axpbox.exe
env:
BUILD_DATE: ${{ steps.date.outputs.date }}
osx-x86-appleclang:
runs-on: macos-15"
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%dT%H%M')"
- name: Create build environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Install dependencies
run: brew install libpcap netcat gnu-sed # sdl2 libx11 / sdl doesnt work see #44
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall -std=c++11 -stdlib=libc++ -I/usr/local/opt/libpcap/include"
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake --build . --config Release
env:
MAKEFLAGS: "-j2"
- name: Upload AXPbox Binary
uses: actions/upload-artifact@v4
with:
name: AXPbox-osx-x86-12-appleclang-${{ env.BUILD_DATE }}
path: ${{runner.workspace}}/build/axpbox
env:
BUILD_DATE: ${{ steps.date.outputs.date }}
================================================
FILE: .gitignore
================================================
cmake-build-debug/
cmake-build-release/
build**/
.idea/
.vs/
CMakeSettings.json
run/
img/
================================================
FILE: .travis.yml
================================================
language: cpp
dist: focal
compiler: clang
before_install: sudo apt-get install cmake libpcap-dev libsdl-dev netcat-openbsd
install:
- mkdir build
- cd build
- cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wall -Werror"
- make
- cd ..
script:
- test/run
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(AXPBox VERSION 1.1.3)
# Source files
file(GLOB srcs src/*.cpp src/base/*.cpp src/gui/*.cpp)
file(GLOB include_sources src/base/*WIN32.cpp src/base/*POSIX.cpp)
list(REMOVE_ITEM srcs ${include_sources})
add_executable(axpbox ${srcs} src/Main.cpp)
target_include_directories(axpbox PRIVATE src src/base src/gui ${CMAKE_BINARY_DIR}/src)
# Path to additional CMake modules
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
if (CMAKE_GENERATOR MATCHES "Visual Studio")
add_definitions(-DNOMINMAX -D_WIN32_WINNT=0x0A00 -DLANG_CXX11 -DCOMPILER_MSVC -D__VERSION__=\"MSVC\")
add_definitions(-DWIN32 -DOS_WIN -D_MBCS -DWIN64 -DWIN32_LEAN_AND_MEAN -DNOGDI -DPLATFORM_WINDOWS)
add_definitions(/bigobj /nologo /EHsc /GF /FC /MP /Gm-)
# Suppress warnings to reduce build log size.
add_definitions(/wd4267 /wd4244 /wd4800 /wd4503 /wd4554 /wd4996 /wd4348 /wd4018)
add_definitions(/wd4099 /wd4146 /wd4267 /wd4305 /wd4307)
add_definitions(/wd4715 /wd4722 /wd4723 /wd4838 /wd4309 /wd4334)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()
find_package(Threads REQUIRED)
target_link_libraries(axpbox Threads::Threads)
# Configuration options
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckIncludeFiles)
include(TestBigEndian)
include(CheckLargeFiles)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
set(ES40_BIG_ENDIAN 1)
else()
set(ES40_LITTLE_ENDIAN 1)
endif()
check_symbol_exists(alarm "unistd.h" HAVE_ALARM)
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file("arpa/telnet.h" HAVE_ARPA_TELNET_H)
check_symbol_exists(atexit "stdlib.h" HAVE_ATEXIT)
check_include_file("ctype.h" HAVE_CTYPE_H)
check_include_file("errno.h" HAVE_ERRNO_H)
check_include_file("fcntl.h" HAVE_FCNTL_H)
check_symbol_exists(fopen "stdio.h" HAVE_FOPEN)
check_symbol_exists(fopen64 "stdio.h" HAVE_FOPEN64)
check_symbol_exists(fork "unistd.h" HAVE_FORK)
check_symbol_exists(fseek "stdio.h" HAVE_FSEEK)
check_symbol_exists(fseeko "stdio.h" HAVE_FSEEKO)
check_symbol_exists(fseeko64 "stdio.h" HAVE_FSEEKO64)
check_symbol_exists(ftell "stdio.h" HAVE_FTELL)
check_symbol_exists(ftello "stdio.h" HAVE_FTELLO)
check_symbol_exists(ftello64 "stdio.h" HAVE_FTELLO64)
check_symbol_exists(gmtime_s "time.h" HAVE_GMTIME_S)
check_symbol_exists(inet_aton "arpa/inet.h" HAVE_INET_ATON)
check_include_file("inet.h" HAVE_INET_H)
check_include_file("inttypes.h" HAVE_INTTYPES_H)
check_include_file("in.h" HAVE_IN_H)
check_symbol_exists(isblank "ctype.h" HAVE_ISBLANK)
check_symbol_exists(localtime_s "time.h" HAVE_LOCALTIME_S)
check_symbol_exists(malloc "stdlib.h" HAVE_MALLOC)
check_include_file("malloc.h" HAVE_MALLOC_H)
check_include_file("memory.h" HAVE_MEMORY_H)
check_symbol_exists(memset "string.h" HAVE_MEMSET)
check_include_file("netinet/in.h" HAVE_NETINET_IN_H)
check_symbol_exists(pow "math.h" HAVE_POW)
check_include_file("process.h" HAVE_PROCESS_H)
check_library_exists(pthread pthread_self "" HAVE_PTHREAD)
check_include_file("pthread.h" HAVE_PTHREAD_H)
check_symbol_exists(realloc "stdlib.h" HAVE_REALLOC)
check_symbol_exists(select "sys/select.h" HAVE_SELECT)
check_include_file("signal.h" HAVE_SIGNAL_H)
check_symbol_exists(socket "sys/socket.h" HAVE_SOCKET)
check_include_file("socket.h" HAVE_SOCKET_H)
check_symbol_exists(sqrt "math.h" HAVE_SQRT)
check_include_file("stdbool.h" HAVE_STDBOOL_H)
check_include_file("stdint.h" HAVE_STDINT_H)
check_include_file("stdlib.h" HAVE_STDLIB_H)
check_symbol_exists(strcasecmp "string.h" HAVE_STRCASECMP)
check_symbol_exists(strchr "string.h" HAVE_STRCHR)
check_symbol_exists(strdup "string.h" HAVE_STRDUP)
check_include_file("stddef.h" HAVE_STDDEF_H)
check_include_file("strings.h" HAVE_STRINGS_H)
check_include_file("string.h" HAVE_STRING_H)
check_symbol_exists(strncasecmp "string.h" HAVE_STRNCASECMP)
check_symbol_exists(strspn "string.h" HAVE_STRSPN)
check_include_file("sys/param.h" HAVE_SYS_PARAM_H)
check_include_file("sys/select.h" HAVE_SYS_SELECT_H)
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H)
check_include_file("sys/stat.h" HAVE_SYS_STAT_H)
check_include_file("sys/time.h" HAVE_SYS_TIME_H)
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
check_include_file("sys/wait.h" HAVE_SYS_WAIT_H)
check_include_file("unistd.h" HAVE_UNISTD_H)
check_symbol_exists(vfork "unistd.h" HAVE_VFORK)
check_include_file("vfork.h" HAVE_VFORK_H)
check_include_file("windows.h" HAVE_WINDOWS_H)
check_include_file("winsock2.h" HAVE_WINSOCK2_H)
set(HAVE_WORKING_FORK ${HAVE_FORK})
set(HAVE_WORKING_VFORK ${HAVE_VFORK})
check_include_file("ws2tcpip.h" HAVE_WS2TCPIP_H)
check_type_size(_Bool _BOOL)
check_symbol_exists(_fseeki64 "stdio.h" HAVE__FSEEKI64)
check_symbol_exists(_ftelli64 "stdio.h" HAVE__FTELLI64)
check_symbol_exists(_strdup "string.h" HAVE__STRDUP)
check_symbol_exists(_stricasecmp "string.h" HAVE__STRICASECMP)
check_symbol_exists(_stricmp "string.h" HAVE__STRICMP)
# Features
check_include_file("SDL/SDL.h" HAVE_SDL)
check_include_file("X11/X.h" HAVE_X11)
# Large file support (fopen64 / disk files > 2 GB)
AXPBOX_TEST_LARGE_FILES(HAVE_LARGE_FILES)
if (DISABLE_PCAP STREQUAL "yes")
set(WANT_PCAP 0)
else()
set(WANT_PCAP 1)
endif()
if(WANT_PCAP)
find_package(PCAP)
if(PCAP_FOUND)
message(STATUS "pcap found. Networking support enabled")
set(HAVE_PCAP 1)
include_directories(${PCAP_INCLUDE_DIR})
target_link_libraries(axpbox ${PCAP_LIBRARY})
else()
message(STATUS "pcap not found. Networking support disabled")
endif()
else()
message(STATUS "pcap disabled. Networking support disabled")
endif()
if (DISABLE_SDL STREQUAL "yes")
set(HAVE_SDL 0)
endif()
if (DISABLE_X11 STREQUAL "yes")
set(HAVE_X11 0)
endif()
if(HAVE_SDL)
target_link_libraries(axpbox SDL)
message(STATUS "sdl found. SDL graphics support enabled")
else()
message(WARNING "sdl not found. Building without SDL graphics support")
endif()
if(HAVE_X11)
target_link_libraries(axpbox X11)
message(STATUS "x11 found. x11 graphics support enabled")
else()
message(WARNING "x11 not found. Building without x11 graphics support")
endif()
if (STATIC_COMPILE STREQUAL "yes")
message(STATUS "Static compilation")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -lpthread -lrt -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)
endif()
if (NOT CMAKE_GENERATOR MATCHES "Visual Studio")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Og -ggdb")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG")
endif()
endif()
if(HAVE_LARGE_FILES)
message(STATUS "Large file support enabled")
else()
message(WARNING "Building without large file graphics support")
endif()
find_package(Git)
if (GIT_FOUND)
execute_process(COMMAND
"${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=40 --dirty
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_SHA
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
set(PACKAGE_GITSHA "\"${GIT_SHA}\"")
endif()
set(PACKAGE ${PROJECT_NAME})
set(PACKAGE_BUGREPORT "tglozar@gmail.com")
set(PACKAGE_NAME string(TOLOWER ${PROJECT_NAME}))
set(PACKAGE_VERSION ${PROJECT_VERSION})
set(PACKAGE_STRING ${PACKAGE_NAME}-${PACKAGE_VERSION})
set(PACKAGE_TARNAME ${PACKAGE_STRING}.tar.gz)
set(PACKAGE_URL "http://github.com/lenticularis39/axpbox")
set(PTHREAD_CREATE_JOINABLE "PTHREAD_CREATE_JOINABLE")
set(SELECT_TYPE_ARG1 "int")
set(SELECT_TYPE_ARG234 "fd_set *")
set(SELECT_TYPE_ARG5 "struct timeval *")
set(RETSIGTYPE "void")
set(STDC_HEADERS 1)
check_include_files("time.h;sys/time.h" TIME_WITH_SYS_TIME)
configure_file(src/config.hpp.in src/config.hpp)
install(TARGETS axpbox DESTINATION bin)
message(STATUS "C++ compiler flags : ${CMAKE_CXX_FLAGS}")
message(STATUS "C compiler flags : ${CMAKE_C_FLAGS}")
message(STATUS "Linker flags : ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_STATIC_LINKER_FLAGS}")
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================
# AXPbox Alpha emulator
AXPbox is a fork of the discontinued es40 emulator. It could theoretically used for running any operating system that runs on the OpenVMS or Tru64 PALcode (e.g. OpenVMS, Tru64 UNIX, Linux, NetBSD), however as of now only OpenVMS and some versions of NetBSD can be installed (for more details see [Guest support](https://github.com/lenticularis39/axpbox/wiki/Guest-support)).
The emulator supports SCSI, IDE, serial ports, Ethernet (using PCAP) and [VGA graphics](https://github.com/lenticularis39/axpbox/wiki/VGA) (using SDL).

OpenVMS 8.4 desktop in AXPbox. [Here is a wiki page showing you how to get this CDE desktop running](https://github.com/lenticularis39/axpbox/wiki/GUI-Desktop-Environment-(CDE))
## Getting AXPbox
Pre-built binaries for generic Linux amd64, Windows 10 amd64 and macOS amd64 are available for each release, and also as artifacts produced for each commit in CI. T2 SDE has an [official package](http://t2sde.org/packages/axpbox) for AXPbox, and openSUSE's Emulators project has an [AXPbox package](https://build.opensuse.org/package/show/Emulators/axpbox), too. The former gets updated the same day when a release happens, while requests are submitted now the latter that undergo approval of Emulators maintainers.
You can also build from source using CMake; you need a C++ 11 compiler, optional dependencies are PCAP for networking and SDL or X11 for graphics support.
## Usage
First invoke the interactive configuration file generator:
```
axpbox configure
```
This creates a file named es40.cfg, which you can now modify (the generator UI doesn't allow to set all options). After the configuration file and the required ROM image are ready, you can start the emulation:
```
axpbox run
```
Please read the [Installation Guide](https://github.com/lenticularis39/axpbox/wiki/OpenVMS-installation-guide) for information to get OpenVMS installed in the emulator. A guide for NetBSD is [also available on the Wiki](https://github.com/lenticularis39/axpbox/wiki/NetBSD-9.2-install-guide)
## Changes in comparison with es40
- Renamed from es40 to AXPbox to avoid confusion with the physical machine (AlphaServer ES40)
- CMake is used for compilation instead of autotools
- OpenVMS host support was dropped
- es40 and es40_cfg were merged into one executable (axpbox)
- The code was cleaned to compile without warnings on most compilers
- Code modernizing, replacing POCO framework parts by native C++11 counterparts not available in 2008 (std::threads, etc)
- Incorporate various patches from other es40 forks, for example, added MC146818 periodic interrupt to allow netbsd to boot and install, skip_memtest for faster booting.
- Bug fixes, less segfaults, overall less crashes.
- [More](https://github.com/lenticularis39/axpbox/wiki/) documentation and usage information on the various features and operating systems
## What doesn't work (also see issues)
- Some guest operating systems (see [Guest support](https://github.com/lenticularis39/axpbox/wiki/Guest-support))
- ARC
- VGA in OpenVMS
- SDL keyboard (partly works, but easily breaks)
- Multiple CPU system emulation
- Running on big endian platforms
- Some SCSI and IDE commands
- Copying large files between IDE CD-ROM to IDE hard drive (this usually doesn't affect OpenVMS installation)
================================================
FILE: cmake/CheckLargeFiles.cmake
================================================
# Via: https://github.com/uclouvain/openjpeg/blob/master/cmake/TestLargeFiles.cmake
# - Define macro to check large file support
#
# AXPBOX_TEST_LARGE_FILES(VARIABLE)
#
# VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present.
# This macro will also defines the necessary variable enable large file support, for instance
# _LARGE_FILES
# _LARGEFILE_SOURCE
# _FILE_OFFSET_BITS 64
# AXPBOX_HAVE_FSEEKO
#
# Adapted from Gromacs project (http://www.gromacs.org/)
# by Julien Malik
#
macro(AXPBOX_TEST_LARGE_FILES VARIABLE)
if(NOT DEFINED ${VARIABLE})
# On most platforms it is probably overkill to first test the flags for 64-bit off_t,
# and then separately fseeko. However, in the future we might have 128-bit filesystems
# (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64.
message(STATUS "Checking for 64-bit off_t")
# First check without any special flags
try_compile(FILE64_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c")
if(FILE64_OK)
message(STATUS "Checking for 64-bit off_t - present")
endif()
if(NOT FILE64_OK)
# Test with _FILE_OFFSET_BITS=64
try_compile(FILE64_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" )
if(FILE64_OK)
message(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64")
set(_FILE_OFFSET_BITS 64)
endif()
endif()
if(NOT FILE64_OK)
# Test with _LARGE_FILES
try_compile(FILE64_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_LARGE_FILES" )
if(FILE64_OK)
message(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES")
set(_LARGE_FILES 1)
endif()
endif()
if(NOT FILE64_OK)
# Test with _LARGEFILE_SOURCE
try_compile(FILE64_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" )
if(FILE64_OK)
message(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE")
set(_LARGEFILE_SOURCE 1)
endif()
endif()
#if(NOT FILE64_OK)
# # now check for Windows stuff
# try_compile(FILE64_OK "${PROJECT_BINARY_DIR}"
# "${PROJECT_SOURCE_DIR}/cmake/TestWindowsFSeek.c")
# if(FILE64_OK)
# message(STATUS "Checking for 64-bit off_t - present with _fseeki64")
# set(HAVE__FSEEKI64 1)
# endif()
#endif()
if(NOT FILE64_OK)
message(STATUS "Checking for 64-bit off_t - not present")
endif()
set(_FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} CACHE INTERNAL "Result of test for needed _FILE_OFFSET_BITS=64")
set(_LARGE_FILES ${_LARGE_FILES} CACHE INTERNAL "Result of test for needed _LARGE_FILES")
set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE")
# Set the flags we might have determined to be required above
configure_file("${PROJECT_SOURCE_DIR}/cmake/TestLargeFiles.c.cmake.in"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c")
message(STATUS "Checking for fseeko/ftello")
# Test if ftello/fseeko are available
try_compile(FSEEKO_COMPILE_OK
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c")
if(FSEEKO_COMPILE_OK)
message(STATUS "Checking for fseeko/ftello - present")
endif()
if(NOT FSEEKO_COMPILE_OK)
# glibc 2.2 needs _LARGEFILE_SOURCE for fseeko (but not for 64-bit off_t...)
try_compile(FSEEKO_COMPILE_OK
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c"
COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" )
if(FSEEKO_COMPILE_OK)
message(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE")
set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE")
endif()
endif()
if(FSEEKO_COMPILE_OK)
set(AXPBOX_HAVE_FSEEKO ON CACHE INTERNAL "Result of test for fseeko/ftello")
else()
message(STATUS "Checking for fseeko/ftello - not found")
set(AXPBOX_HAVE_FSEEKO OFF CACHE INTERNAL "Result of test for fseeko/ftello")
endif()
if(FILE64_OK AND FSEEKO_COMPILE_OK)
message(STATUS "Large File support - found")
set(${VARIABLE} ON CACHE INTERNAL "Result of test for large file support")
else()
message(STATUS "Large File support - not found")
set(${VARIABLE} OFF CACHE INTERNAL "Result of test for large file support")
endif()
endif()
endmacro()
================================================
FILE: cmake/FindPCAP.cmake
================================================
# ~~~
# - Try to find libpcap include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(PCAP)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# Imported Targets:
# PCAP::PCAP The libpcap library, if found
#
# Variables defined by this module:
#
# PCAP_FOUND System has libpcap, include and library dirs found
# PCAP_INCLUDE_DIR The libpcap include directories.
# PCAP_LIBRARY The libpcap library (possibly includes a thread
# library e.g. required by pf_ring's libpcap)
# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode
# HAVE_PCAP_DIRECTION If the version of libpcap found support for setting direction
#
# Hints and Backward Compatibility
# ================================
#
# To tell this module where to look, a user may set the environment variable
# PCAP_ROOT to point cmake to the *root* of a directory with include and lib
# subdirectories for packet.dll (e.g WpdPack or npcap-sdk). Alternatively,
# PCAP_ROOT may also be set from cmake command line or GUI (e.g cmake
# -DPCAP_ROOT=C:\path\to\packet [...])
# ~~~
find_path(
PCAP_INCLUDE_DIR
NAMES pcap/pcap.h pcap.h
PATH_SUFFIXES include Include)
# The 64-bit Wpcap.lib is located under /x64
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
#
# For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level directory contains 32-bit libraries. The
# 64-bit libraries are in the Lib/x64 directory.
#
# The only way to *FORCE* CMake to look in the Lib/x64 directory without searching in the Lib directory first appears
# to be to set CMAKE_LIBRARY_ARCHITECTURE to "x64".
#
set(CMAKE_LIBRARY_ARCHITECTURE "x64")
endif()
find_library(PCAP_LIBRARY NAMES pcap wpcap)
# If Pcap is not found as this level no need to continue
if(NOT PCAP_LIBRARY OR NOT PCAP_INCLUDE_DIR)
return()
endif()
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_cxx_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO)
set(CMAKE_REQUIRED_LIBRARIES)
# check if linking against libpcap also needs to link against a thread library
if(NOT PCAP_LINKS_SOLO)
find_package(Threads)
if(THREADS_FOUND)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
check_cxx_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS)
set(CMAKE_REQUIRED_LIBRARIES)
endif(THREADS_FOUND)
if(THREADS_FOUND AND PCAP_NEEDS_THREADS)
set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
list(REMOVE_DUPLICATES _tmp)
set(PCAP_LIBRARY
${_tmp}
CACHE STRING "Libraries needed to link against libpcap" FORCE)
else(THREADS_FOUND AND PCAP_NEEDS_THREADS)
message(FATAL_ERROR "Couldn't determine how to link against libpcap")
endif(THREADS_FOUND AND PCAP_NEEDS_THREADS)
endif(NOT PCAP_LINKS_SOLO)
include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE)
check_function_exists(pcap_setdirection HAVE_PCAP_DIRECTION)
check_function_exists(pcap_lib_version HAVE_PCAP_LIB_VERSION)
set(CMAKE_REQUIRED_LIBRARIES)
# Check libPCAP version
if(HAVE_PCAP_LIB_VERSION AND NOT CMAKE_CROSSCOMPILING)
# Simple C code to extract the libpcap version
set(PCAP_VERSION_CODE
"
#include <stdio.h>
#include <string.h>
#include <pcap/pcap.h>
int main() {
const char* version = pcap_lib_version();
const char* prefix = \"libpcap version \";
if (strncmp(version, prefix, strlen(prefix)) == 0) {
version += strlen(prefix);
}
printf(\"%s\", version);
return 0;
}
")
# Write the code to a temporary file
set(detect_pcap_version_file "${PROJECT_BINARY_DIR}/detect_pcap_version.c")
file(WRITE "${detect_pcap_version_file}" "${PCAP_VERSION_CODE}")
# Try to compile and run the program
try_run(
RUN_RESULT_VAR
COMPILE_RESULT_VAR
"${CMAKE_BINARY_DIR}"
"${detect_pcap_version_file}"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PCAP_INCLUDE_DIR}" LINK_LIBRARIES ${PCAP_LIBRARY}
RUN_OUTPUT_VARIABLE PCAP_VERSION_OUTPUT)
# If successful, parse the output to get the version string
if(COMPILE_RESULT_VAR AND RUN_RESULT_VAR EQUAL 0)
set(PCAP_VERSION ${PCAP_VERSION_OUTPUT})
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
PCAP
REQUIRED_VARS PCAP_LIBRARY PCAP_INCLUDE_DIR
VERSION_VAR PCAP_VERSION)
# create IMPORTED target for libpcap dependency
if(NOT TARGET PCAP::PCAP)
add_library(PCAP::PCAP IMPORTED SHARED)
set_target_properties(
PCAP::PCAP
PROPERTIES IMPORTED_LOCATION ${PCAP_LIBRARY}
IMPORTED_IMPLIB ${PCAP_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${PCAP_INCLUDE_DIR})
endif()
mark_as_advanced(PCAP_INCLUDE_DIR PCAP_LIBRARY)
================================================
FILE: cmake/TestFileOffsetBits.c
================================================
#include <sys/types.h>
/* Cause a compile-time error if off_t is smaller than 64 bits */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ];
int main(int argc, char **argv)
{
return 0;
}
================================================
FILE: cmake/TestLargeFiles.c.cmake.in
================================================
#cmakedefine _LARGEFILE_SOURCE
#cmakedefine _LARGE_FILES
#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
/* Cause a compile-time error if off_t is smaller than 64 bits,
* and make sure we have ftello / fseeko.
*/
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ];
FILE *fp = fopen(argv[0],"r");
off_t offset = ftello( fp );
fseeko( fp, offset, SEEK_CUR );
fclose(fp);
return 0;
}
================================================
FILE: cmake/TestWindowsFSeek.c
================================================
#include <stdio.h>
int main()
{
__int64 off=0;
_fseeki64(NULL, off, SEEK_SET);
return 0;
}
================================================
FILE: es40.cfg
================================================
/**
* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
* \file
* Sample configuration file.
*
* $Id: es40.cfg,v 1.22 2008/03/05 14:41:46 iamcamiel Exp $
*
* X-1.22 Camiel Vanderhoeven 05-MAR-2008
* Multi-threading version.
*
* X-1.21 Camiel Vanderhoeven 02-MAR-2008
* Natural way to specify large numeric values ("10M").
*
* X-1.20 Camiel Vanderhoeven 16-FEB-2008
* Added Symbios 53C810 controller.
*
* X-1.19 Camiel Vanderhoeven 13-FEB-2008 Put SCSI controller on a
*different PCI ID, and clarified PCI configuration rules. Thanks to Eduardo
*Marcelo Serrat.
*
* X-1.18 Camiel Vanderhoeven 25-JAN-2008 Added autocreate_size
*option for disk-images.
*
* X-1.17 Camiel Vanderhoeven 25-JAN-2008 Added option to disable
*the icache.
*
* X-1.16 Camiel Vanderhoeven 23-JAN-2008 Added comments for win32
*and X11 gui's.
*
* X-1.15 Camiel Vanderhoeven 05-JAN-2008 Added device as a disk.
*
* X-1.14 David Hittner 04-JAN-2008 Replaced decnet variable with
*mac variable.
*
* X-1.13 Camiel Vanderhoeven 12-DEC-2007 Changed the way disks
*work.
*
* X-1.12 Camiel Vanderhoeven 10-DEC-2007 Added vga_console
*parameter.
*
* X-1.11 Camiel Vanderhoeven 10-DEC-2007 New structure for
*configuration file.
*
* X-1.10 Camiel Vanderhoeven 10-DEC-2007 Unintended version #
*increase.
*
* X-1.9 Brian Wheeler 22-NOV-2007 Added nic0.disabled
*configuration option.
*
* X-1.8 Camiel Vanderhoeven 17-NOV-2007 Clarified nic0.adapter
*syntax.
*
* X-1.7 Camiel Vanderhoeven 17-NOV-2007 Added configuration
*lines for the network interface.
*
* X-1.6 Camiel Vanderhoeven 16-APR-2007 Added configuration
*lines to start PuTTy for each serial port.
*
* X-1.5 Camiel Vanderhoeven 10-APR-2007 a) Added
*rom.decompressed variable. b) Fixed some of the documentation mistakes.
*
* X-1.4 Camiel Vanderhoeven 1-APR-2007 Documented, and added old
*changelog comments.
*
* X-1.3 Brian wheeler 7-FEB-2007 Added memory.bits variable.
*
* X-1.2 Brian Wheeler 3-FEB-2007 Added serial.base variable.
*
* X-1.1 Brian Wheeler 3-FEB-2007 Created this file.
**/
// Specifying values
//
// Numeric values can be specified as a number ("500"), as a number with a
// suffix ("100K" = 102400), or as a fancy combination ("2G512M" = 2.5 G).
//
// Boolean values can be specified as "true"/"false", "yes"/"no", or "1"/"0".
//
// String-constants are best specified in double quotes ("string"). If the
// string needs to contain double quotes, double the double quotes.
// ("One ""word"" in this string is quoted")
// GUI
//
// If you want to use an emulated graphics card, the emulator needs to interface
// with the OS'es user interface. There are three ways to do this:
//
// On systems that have the SDL (simple directmedia layer) run-time libraries
// installed, you can use SDL. (gui=sdl) The emulator needs to be compiled with
// -DHAVE_SDL.
//
// On MS Windows-systems, you can use Win32 API calls. (gui=win32)
//
// On many Linux, BSD and UNIX systems, you can use X11. (gui=X11)
gui = sdl {
keyboard.use_mapping = false;
keyboard.map = "keys.map";
}
sys0 = tsunami {
// VARIABLE: rom.srm
//
// Specify the filename of the original (compressed) ROM image. This file is
// essential to the functioning of the emulator. This file an be obtained from
// HP (it's on the firmware-update CD-ROM for Alpha ES40 systems).
//
rom.srm = "rom\cl67srmrom.exe";
// VARIABLE: rom.decompressed
//
// Specify the filename of the decompressed ROM image. If possible, it will be
// created the first time the emulator is run. When it exists, it allows the
// emulator to start quicker by skipping the ROM decompression.
//
rom.decompressed = "rom\decompressed.rom";
// VARIABLES: rom.flash and rom.dpr
//
// Specify the filenames of Flash and DPR ROM images. These files are not
// required, but will be created he first time the emulator runs. Contents of
// Flash and DPR ROM will be put in these files after successful termination
// of the emulator. This allows setting SRM variables such as auto_action and
// boot_osflags.
//
rom.flash = "rom\flash.rom";
rom.dpr = "rom\dpr.rom";
// VARIABLE: memory.bits
//
// Only amounts of memory that are a power of 2 are supported. This number
// determines the amount of memory, by setting the number of bits in the
// address (and thus which power of 2).
//
// 26 = 64 MB
// 27 = 128MB
// 28 = 256 MB
// 29 = 512 MB
// 30 = 1GB
// 31 = 2GB
//
memory.bits = 30;
// VARIABLE: time
//
// Override the guest clock with a fixed date/time.
// Format: "YYYY-MM-DD" or "YYYY-MM-DD HH:MM:SS"
//
//time = "2017-05-01"; // fake date (YYYY-MM-DD)
//time = "2017-05-01 12:00:00"; // fake date+time (YYYY-MM-DD HH:MM:SS)
cpu0 = ev68cb {
// VARIABLE: icache
//
// enables or disables the onchip-cache. The emulator runs faster
// when this is disabled, but that might lead to problems with some
// OS'es, so here is the option to enable it.
icache = false;
speed = 800M;
}
cpu1 = ev68cb {
icache = false;
speed = 800M;
}
// System Internal PCI Devices: ali, ali_ide, ali_usb
//
// The following PCI-devices are built into the system, and should
// always be at the PCI-id's they are on in this sample configuration
// file for compatibility.
pci0 .7 = ali {
mouse.enabled = true;
lpt.outfile = "lpt.out";
vga_console = true;
timezone = "utc"; // Sets timezone to UTC
timezone = "local"; // Sets timezone to host timezone (default)
timezone = "utc+1h"; // Sets timezone to UTC plus 1 hour
timezone = "local-20M"; // Sets timezone to localtime minus 20 months
timezone = "utc+2y"; // Sets timezone to UTC + two years
}
pci0 .15 = ali_ide {
// sub-components: disk<x>.<y>
//
// Here, up to 4 IDE disks can be defined (0.0, 0.1, 1.0 and 1.1).
//
// file: create a disk using a file on the host filesystem as a disk image
disk0 .0 = file {
file = "img\disk0.img";
serial_number = "VMS";
rev_number = "8.3";
model_number = "OpenVMS8.3";
read_only = false;
cdrom = false;
// if the file does not exist, it will be created if autocreate_size is
// set to the desired size of the disk.
autocreate_size = 600M;
}
disk1 .0 = file {
file = "img\vms83.iso";
read_only = true;
cdrom = true;
}
// device: create a disk using a physical device
//
// WARNING: making a physical disk device writeable here may
// seriously jeopardize the contents of that disk.
//
// Windows syntax for device: \\.\CDRom0, \\.\PhysicalDrive0
//
// UNIX-like syntax for device: /dev/sda
disk1 .0 = device {
device = "\\.\CDRom0";
read_only = true;
cdrom = true;
}
// ramdisk: create a disk using a portion of host RAM
disk1 .1 = ramdisk { size = 10M; }
}
pci0 .19 = ali_usb {}
// "Free" PCI Devices
//
// These can occupy pci0.1 .. pci0.4 and pci1.1 .. pci1.6
//
// AFAIK, VGA should always be on pci0.x.
pci0 .2 = cirrus { rom = "rom\vgabios-0.6a.debug.bin"; }
// pci0.2 = s3
//{
// rom = "rom\vgabios-0.6a.debug.bin";
//}
// Symbios SCSI controller
//
// There are two flavors of SCSI controllers on the emulator; 53c810
// and 53c895. The 53c810 supports 7 disks (0.0..0.6), the 53c895
// supports 15 disks (0.0..0.6 and 0.8..0.15).
//
// Right now, the 53c810 is the only controller that works with OpenVMS.
pci0 .3 = sym53c810 {
disk0 .0 = file {
file = "img\dka0.img";
read_only = false;
cdrom = false;
}
disk0 .4 = file {
file = "img\scsi_cd.iso";
read_only = true;
cdrom = true;
}
disk0 .5 = ramdisk { size = 10M; }
}
pci0 .4 = dec21143 {
// VARIABLE: adapter
//
// Defines the host computer's adapter to use for the emulated NIC. If
// you're unsure of this, start the emulator without this variable set, and
// you will be presented with a list of adapters to choose from. You can
// enter the name indicated on this line.
//
// Windows syntax:
// adapter = "\Device\NPF_{F266CDC2-6BA2-43D8-8B00-1C468F737ED7}";
//
// Linux syntax:
// adapter = "eth0";
// adapter = "\Device\NPF_{F266CDC2-6BA2-43D8-8B00-1C468F737ED7}";
// VARIABLE: mac
//
// Defines the ethernet MAC address to be used by the virtual nic.
// The variable format is: xx-xx-xx-xx-xx-xx, where all values are in hex.
// This value should be unique on your network, or Bad Things Will Happen.
//
// The default value is: 08-00-2B-E5-40-<nic#>
// mac = "08-00-2B-E5-40-00";
}
serial0 = serial {
// VARIABLE: port
//
// Determines which Telnet port is opened to receive connections for the
// emulated serial port. The default is 8000 + the port number.
port = 21264;
// VARIABLE: action
//
// Defines the action to take for each serial port (= a telnet client). If
// you want to connect manually, leave this out.
action = ""
"c:\Program Files\PuTTY\putty.exe"
" telnet://localhost:21264";
}
serial1 = serial {
port = 21265;
action = ""
"c:\Program Files\PuTTY\putty.exe"
" telnet://localhost:21265";
}
}
================================================
FILE: sonar-project.properties
================================================
sonar.projectKey=rve_axpbox
sonar.organization=rve
# This is the name and version displayed in the SonarCloud UI.
sonar.projectName=AXPBox
sonar.projectVersion=1.1.3
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
sonar.sources=src/
# use complation database
sonar.cfamily.compile-commands=../build/compile_commands.json
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
================================================
FILE: src/AliM1543C.cpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Copyright (C) 2020 Martin Vorländer
* Copyright (C) 2012 Dmitry Kalinkin
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
*/
#include "AliM1543C.hpp"
#include "StdAfx.hpp"
#include "System.hpp"
#include "VGA.hpp"
#ifdef DEBUG_PIC
bool pic_messages = false;
#endif
/* Timer Calibration: Instructions per Microsecond (assuming 1 clock = 1
* instruction) */
#define IPus 847
u32 ali_cfg_data[64] = {
/*00*/ 0x153310b9, // CFID: vendor + device
/*04*/ 0x0200000f, // CFCS: command + status
/*08*/ 0x060100c3, // CFRV: class + revision
/*0c*/ 0x00000000, // CFLT: latency timer + cache line size
/*10*/ 0x00000000, // BAR0:
/*14*/ 0x00000000, // BAR1:
/*18*/ 0x00000000, // BAR2:
/*1c*/ 0x00000000, // BAR3:
/*20*/ 0x00000000, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x00000000, // CFIT: interrupt configuration
0,
0,
0,
0,
0,
/*54*/ 0x00000200, //
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
u32 ali_cfg_mask[64] = {
/*00*/ 0x00000000, // CFID: vendor + device
/*04*/ 0x00000000, // CFCS: command + status
/*08*/ 0x00000000, // CFRV: class + revision
/*0c*/ 0x00000000, // CFLT: latency timer + cache line size
/*10*/ 0x00000000, // BAR0
/*14*/ 0x00000000, // BAR1: CBMA
/*18*/ 0x00000000, // BAR2:
/*1c*/ 0x00000000, // BAR3:
/*20*/ 0x00000000, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x00000000, // CFIT: interrupt configuration
/*40*/ 0xffcfff7f,
/*44*/ 0xff00cbdf,
/*48*/ 0xffffffff,
/*4c*/ 0x000000ff,
/*50*/ 0xffff8fff,
/*54*/ 0xf0ffff00,
/*58*/ 0x030f0d7f,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
/**
* Constructor.
**/
CAliM1543C::CAliM1543C(CConfigurator *cfg, CSystem *c, int pcibus, int pcidev)
: CPCIDevice(cfg, c, pcibus, pcidev) {
if (theAli != 0)
FAILURE(Configuration, "More than one Ali");
theAli = this;
}
/**
* Initialize the Ali device.
**/
void CAliM1543C::init() {
add_function(0, ali_cfg_data, ali_cfg_mask);
int i;
char *filename;
add_legacy_io(1, 0x61, 1);
state.reg_61 = 0;
add_legacy_io(2, 0x70, 4);
cSystem->RegisterMemory(this, 2, U64(0x00000801fc000070), 4);
for (i = 0; i < 4; i++)
state.toy_access_ports[i] = 0;
for (i = 0; i < 256; i++)
state.toy_stored_data[i] = 0;
state.toy_stored_data[0x17] = myCfg->get_bool_value("vga_console") ? 1 : 0;
if (state.toy_stored_data[0x17] && !theVGA) {
printf("! CONFIGURATION WARNING ! vga_console set to true, but no VGA card "
"installed.\n");
state.toy_stored_data[0x17] = 0;
}
state.toy_pi_last_fire = 0;
ResetPCI();
// PIT Setup
add_legacy_io(6, 0x40, 4);
for (i = 0; i < 3; i++)
state.pit_status[i] = 0x40; // invalid/null counter
for (i = 0; i < 9; i++)
state.pit_counter[i] = 0;
add_legacy_io(7, 0x20, 2);
add_legacy_io(8, 0xa0, 2);
add_legacy_io(30, 0x4d0, 2);
// odd one, byte read in PCI IACK (interrupt acknowledge) cycle. Interrupt
// vector.
cSystem->RegisterMemory(this, 20, U64(0x00000801f8000000), 1);
for (i = 0; i < 2; i++) {
state.pic_mode[i] = 0;
state.pic_intvec[i] = 0;
state.pic_mask[i] = 0;
state.pic_asserted[i] = 0;
}
// Initialize parallel port
add_legacy_io(27, 0x3bc, 4);
filename = myCfg->get_text_value("lpt.outfile");
if (filename) {
lpt = fopen(filename, "ab");
} else {
lpt = NULL;
}
lpt_reset();
myRegLock = new CMutex("ali-reg");
printf("%s: $Id: AliM1543C.cpp,v 1.66 2008/05/31 15:47:07 iamcamiel Exp $\n",
devid_string);
}
void CAliM1543C::start_threads() {
if (!myThread) {
printf(" ali");
StopThread = false;
myThread = std::make_unique<std::thread>([this]() { this->run(); });
}
}
void CAliM1543C::stop_threads() {
StopThread = true;
if (myThread) {
printf(" ali");
myThread->join();
myThread = nullptr;
}
}
/**
* Destructor.
**/
CAliM1543C::~CAliM1543C() {
stop_threads();
if (lpt)
fclose(lpt);
}
/**
* Calculates VM time based on the configuration specified in the configuration
* file.
* @return The time.
*/
struct tm CAliM1543C::get_time() {
struct tm time_out;
time_t time_raw;
// Timezone setting from configuration file
std::string timezone{myCfg->get_text_value("timezone", "local")};
// Time base (local or utc)
std::string timebase;
// Time offset
bool offset_present = false;
long offset;
// Check for absolute time override: "YYYY-MM-DD" or "YYYY-MM-DD HH:MM:SS"
// Read from system-level config (sys0 block)
char *faketime = myCfg->get_myParent()->get_text_value("time");
if (faketime) {
struct tm ft;
memset(&ft, 0, sizeof(ft));
ft.tm_isdst = -1; // let mktime figure it out
int n = sscanf(faketime, "%d-%d-%d %d:%d:%d", &ft.tm_year, &ft.tm_mon,
&ft.tm_mday, &ft.tm_hour, &ft.tm_min, &ft.tm_sec);
if (n >= 3) {
ft.tm_year -= 1900;
ft.tm_mon -= 1;
time_raw = mktime(&ft);
if (time_raw == (time_t)-1) {
FAILURE_1(Configuration, "Invalid time value: %s", faketime);
}
// Apply timezone conversion and return
if (timezone.rfind("utc") == 0) {
gmtime_s(&time_out, &time_raw);
} else {
#ifdef _WIN32
localtime_s(&time_out, &time_raw);
#else
localtime_s(&time_raw, &time_out);
#endif
}
return time_out;
} else {
FAILURE_1(Configuration,
"Invalid time format: %s (use YYYY-MM-DD or "
"YYYY-MM-DD HH:MM:SS)",
faketime);
}
}
// Get raw time
time(&time_raw);
// Set time base
if (timezone.rfind("local") == 0) {
timebase = "local";
} else if (timezone.rfind("utc") == 0) {
timebase = "utc";
} else {
FAILURE_1(Configuration, "Invalid timezone %s", timezone.c_str());
}
// Characters remaining after time base
int remaining_chars = timezone.length() - timebase.length();
if (remaining_chars > 0 &&
timezone.at(timezone.length() - remaining_chars) == '+') {
// An offset is included in the timezone
offset_present = true;
sscanf(timezone.c_str() + timezone.length() - remaining_chars + 1, "%ld",
&offset);
remaining_chars -= std::to_string(offset).length() + 1;
if (remaining_chars != 1) {
// Offset type always has one character
FAILURE_1(Configuration, "Invalid timezone %s", timezone.c_str());
}
} else if (remaining_chars > 0) {
FAILURE_1(Configuration, "Invalid timezone %s", timezone.c_str());
}
if (offset_present) {
// Apply POSIX time offset (seconds, minutes, hours, days)
switch (timezone.at(timezone.length() - 1)) {
case 's':
time_raw += offset;
break;
case 'm':
time_raw += offset * 60;
break;
case 'h':
time_raw += offset * 3600;
break;
case 'd':
time_raw += offset * 86400;
break;
case 'M':
case 'y':
break;
default:
FAILURE_1(Configuration, "Invalid timezone offset type %c",
timezone.at(timezone.length() - 1));
}
}
// Convert POSIX time to date
if (timebase == "local") {
#ifdef _WIN32
localtime_s(&time_out, &time_raw);
#else
localtime_s(&time_raw, &time_out);
#endif
} else if (timebase == "utc") {
gmtime_s(&time_out, &time_raw);
} else {
// This shouldn't happen
FAILURE_1(Configuration, "Invalid timezone %s", timezone.c_str());
}
if (offset_present) {
// Apply date offset (months, years)
switch (timezone.at(timezone.length() - 1)) {
case 'M':
time_out.tm_year += offset / 12;
time_out.tm_mon += offset % 12;
break;
case 'y':
time_out.tm_year += offset;
break;
}
// Fix day of week
mktime(&time_out);
}
return time_out;
}
/**
* Read (byte,word,longword) from one of the legacy ranges. Only byte-accesses
*are supported.
*
* Ranges are:
* - 1. I/O port 61h
* - 2. I/O ports 70h-73h (time-of-year clock)
* - 6. I/O ports 40h-43h (programmable interrupt timer)
* - 7. I/O ports 20h-21h (primary programmable interrupt controller)
* - 8. I/O ports a0h-a1h (secondary (cascaded) programmable interrupt
*controller)
* - 20. PCI IACK address (interrupt vector)
* - 27. I/O ports 3bch-3bfh (parallel port)
* - 30. I/O ports 4d0h-4d1h (edge/level register of programmable interrupt
*controller)
* .
**/
u32 CAliM1543C::ReadMem_Legacy(int index, u32 address, int dsize) {
if (dsize != 8 &&
index != 20) // when interrupt vector is read, dsize doesn't matter.
{
FAILURE_4(
InvalidArgument,
"%s: DSize %d reading from legacy memory range # %d at address %02x\n",
devid_string, dsize, index, address);
}
int channel = 0;
switch (index) {
case 1:
return reg_61_read();
case 2:
return toy_read(address);
case 6:
return pit_read(address);
case 8:
channel = 1;
case 7:
return pic_read(channel, address);
case 20:
return pic_read_vector();
case 30:
return pic_read_edge_level(address);
case 27:
return lpt_read(address);
}
return 0;
}
/**
* Write (byte,word,longword) to one of the legacy ranges. Only byte-accesses
*are supported.
*
* Ranges are:
* - 1. I/O port 61h
* - 2. I/O ports 70h-73h (time-of-year clock)
* - 6. I/O ports 40h-43h (programmable interrupt timer)
* - 7. I/O ports 20h-21h (primary programmable interrupt controller)
* - 8. I/O ports a0h-a1h (secondary (cascaded) programmable interrupt
*controller)
* - 12. I/O ports 00h-0fh (primary DMA controller)
* - 13. I/O ports c0h-dfh (secondary DMA controller)
* - 20. PCI IACK address (interrupt vector)
* - 27. I/O ports 3bch-3bfh (parallel port)
* - 30. I/O ports 4d0h-4d1h (edge/level register of programmable interrupt
*controller)
* - 33. I/O ports 80h-8fh (DMA controller memory base low page register)
* - 34. I/O ports 480h-48fh (DMA controller memory base high page register)
* .
**/
void CAliM1543C::WriteMem_Legacy(int index, u32 address, int dsize, u32 data) {
if (dsize != 8) {
FAILURE_4(
InvalidArgument,
"%s: DSize %d writing to legacy memory range # %d at address %02x\n",
devid_string, dsize, index, address);
}
int channel = 0;
switch (index) {
case 1:
reg_61_write((u8)data);
return;
case 2:
toy_write(address, (u8)data);
return;
case 6:
pit_write(address, (u8)data);
return;
case 8:
channel = 1;
case 7:
pic_write(channel, address, (u8)data);
return;
case 30:
pic_write_edge_level(address, (u8)data);
return;
case 27:
lpt_write(address, (u8)data);
return;
}
}
/**
* Read port 61h (speaker/ miscellaneous).
*
* BDW:
* This may need some expansion to help with timer delays. It looks like
* the 8254 flips bits on occasion, and the linux kernel (at least) uses
* do {
* count++;
* } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT);
* to calibrate the cpu clock.
*
* Every 1500 reads the bit gets flipped so maybe the timing will
* seem reasonable to the OS.
*/
u8 CAliM1543C::reg_61_read() {
#if 0
static long read_count = 0;
if(!(state.reg_61 & 0x20))
{
if(read_count % 1500 == 0)
state.reg_61 |= 0x20;
}
else
{
state.reg_61 &= ~0x20;
}
read_count++;
#else
state.reg_61 &= ~0x20;
state.reg_61 |= (state.pit_status[2] & 0x80) >> 2;
#endif
return state.reg_61;
}
/**
* Write port 61h (speaker/ miscellaneous).
**/
void CAliM1543C::reg_61_write(u8 data) {
state.reg_61 = (state.reg_61 & 0xf0) | (((u8)data) & 0x0f);
}
/**
* Read time-of-year clock ports (70h-73h).
**/
u8 CAliM1543C::toy_read(u32 address) {
// printf("%%ALI-I-READTOY: read port %02x: 0x%02x\n", (u32)(0x70 + address),
// state.toy_access_ports[address]);
return (u8)state.toy_access_ports[address];
}
/**
* Write time-of-year clock ports (70h-73h). On a write to port 0, recalculate
* clock values.
**/
void CAliM1543C::toy_write(u32 address, u8 data) {
struct tm stime;
static long read_count = 0;
static long hold_count = 0;
// printf("%%ALI-I-WRITETOY: write port %02x: 0x%02x\n", (u32)(0x70 +
// address), data);
state.toy_access_ports[address] = (u8)data;
switch (address) {
case 0:
if ((data & 0x7f) < 14) {
// Assign VRT (valid RAM and time) bit
state.toy_stored_data[RTC_REG_D] = RTC_VRT;
// Update time
stime = get_time();
if (state.toy_stored_data[RTC_REG_B] & RTC_DM) {
// binary
state.toy_stored_data[0] = (u8)(stime.tm_sec);
state.toy_stored_data[2] = (u8)(stime.tm_min);
if (state.toy_stored_data[RTC_REG_B] & RTC_2412) // 24-hour
state.toy_stored_data[4] = (u8)(stime.tm_hour);
else
// 12-hour
state.toy_stored_data[4] =
(u8)(((stime.tm_hour / 12) ? 0x80 : 0) | (stime.tm_hour % 12));
state.toy_stored_data[6] = (u8)(stime.tm_wday + 1);
state.toy_stored_data[7] = (u8)(stime.tm_mday);
state.toy_stored_data[8] = (u8)(stime.tm_mon + 1);
state.toy_stored_data[9] = (u8)(stime.tm_year % 100);
} else {
// BCD
state.toy_stored_data[0] =
(u8)(((stime.tm_sec / 10) << 4) | (stime.tm_sec % 10));
state.toy_stored_data[2] =
(u8)(((stime.tm_min / 10) << 4) | (stime.tm_min % 10));
if (state.toy_stored_data[0x0b] & 2) // 24-hour
state.toy_stored_data[4] =
(u8)(((stime.tm_hour / 10) << 4) | (stime.tm_hour % 10));
else { // 12-hour
state.toy_stored_data[4] = (u8)(((stime.tm_hour / 12) ? 0x80 : 0) |
(((stime.tm_hour % 12) / 10) << 4) |
((stime.tm_hour % 12) % 10));
}
state.toy_stored_data[6] = (u8)(stime.tm_wday + 1);
state.toy_stored_data[7] =
(u8)(((stime.tm_mday / 10) << 4) | (stime.tm_mday % 10));
state.toy_stored_data[8] =
(u8)((((stime.tm_mon + 1) / 10) << 4) | ((stime.tm_mon + 1) % 10));
state.toy_stored_data[9] = (u8)((((stime.tm_year % 100) / 10) << 4) |
((stime.tm_year % 100) % 10));
}
// SRM initializes the value of A register to 0x26. This means:
// xtal speed is set to MC_BASE_32_KHz 32.768KHz (standard)
// periodic interrupt rate divisor of 32 = interrupt every 976.562 ms
// (1024Hz clock)
if (state.toy_stored_data[RTC_REG_A] & RTC_UIP) {
// Once the UIP line goes high, we have to stay high for 2228us.
hold_count--;
if (hold_count == 0 || (state.toy_stored_data[RTC_REG_B] & RTC_SET)) {
// Set UIP low and trigger the related interrupt.
state.toy_stored_data[RTC_REG_A] &= ~RTC_UIP;
state.toy_stored_data[RTC_REG_C] |= RTC_UF;
toy_update_irqf();
read_count = 0;
}
} else {
// UIP isn't high, so if we're looping and waiting for it to go, it
// will take 1,000,000/(IPus*3) reads for a 3 instruction loop.
// If it happens to be a one time read, it'll only throw our
// calculations off a tiny bit, and they'll be re-synced on the next
// read-loop.
read_count++;
if (read_count > 1000000 / (IPus * 3)) // 3541 @ 847IPus
{
state.toy_stored_data[RTC_REG_A] |= RTC_UIP;
hold_count =
(2228 / (IPus * 3)) + 1; // .876 @ 847IPus, so we add one.
}
}
}
toy_handle_periodic_interrupt(data);
toy_update_irqf();
// Assign specified data to port so it can be read by the program
state.toy_access_ports[1] = state.toy_stored_data[data & 0x7f];
// Register C is cleared after a read, and we don't care if it's a write
if (data == RTC_REG_C)
state.toy_stored_data[data & 0x7f] = 0;
break;
case 1:
if (state.toy_access_ports[0] == RTC_REG_B &&
data & 0x040) // If we're writing to register B, we make register C look
// like it fired.
// TODO: Do actual interrupt implementation instead of
// a workaround.
state.toy_stored_data[RTC_REG_C] = 0xf0;
state.toy_stored_data[state.toy_access_ports[0] & 0x7f] = (u8)data;
break;
case 2:
state.toy_access_ports[3] = state.toy_stored_data[0x80 + (data & 0x7f)];
break;
case 3:
state.toy_stored_data[0x80 + (state.toy_access_ports[2] & 0x7f)] = (u8)data;
break;
}
}
/**
* Handle RTC periodic interrupt.
**/
void CAliM1543C::toy_handle_periodic_interrupt(u8 data) {
/*
See sys/dev/ic/mc146818reg.h and sys/arch/alpha/alpha/mcclock.c in NetBSD and
the RTC datasheet: https://www.nxp.com/docs/en/data-sheet/MC146818.pdf.
*/
clock_t now = clock();
double timedelta = (now - state.toy_pi_last_fire) / (double)CLOCKS_PER_SEC;
// For the meaning of the period calculation see the table on page 14 of the
// aforementioned datasheet
int rate_pow = state.toy_stored_data[RTC_REG_A] & 0x0f;
double period = (1 << rate_pow) / 65536.0;
if (state.toy_stored_data[RTC_REG_A] & MC_BASE_32_KHz) {
if (rate_pow == 0x1) {
period = 1 / 256.0;
} else if (rate_pow == 0x2) {
period = 1 / 128.0;
}
}
if (rate_pow && (timedelta >= period)) {
// Elapsed time since last check is equal or greater than the specified
// period - fire the interrupt by setting the PF flag in register C
// (see page 16 in the datasheet).
state.toy_stored_data[RTC_REG_C] |= RTC_PF;
state.toy_pi_last_fire = now;
}
}
/**
* Update RTC interrupt request flag
**/
void CAliM1543C::toy_update_irqf() {
if ((state.toy_stored_data[RTC_REG_B] & RTC_PIE &&
state.toy_stored_data[RTC_REG_C] & RTC_PF) ||
(state.toy_stored_data[RTC_REG_B] & RTC_UIE &&
state.toy_stored_data[RTC_REG_C] & RTC_UF) ||
(state.toy_stored_data[RTC_REG_B] & RTC_AIE &&
state.toy_stored_data[RTC_REG_C] & RTC_AF))
state.toy_stored_data[RTC_REG_C] |= RTC_IRQF;
else
state.toy_stored_data[RTC_REG_C] &= ~RTC_IRQF;
}
/**
* Read from the programmable interrupt timer ports (40h-43h)
*
* BDW:
* Here's the PIT Traffic during SRM and Linux Startup:
*
* SRM
* PIT Write: 3, 36 = counter 0, load lsb + msb, mode 3
* PIT Write: 0, 00
* PIT Write: 0, 00 = 65536 = 18.2 Hz = timer interrupt.
* PIT Write: 3, 54 = counter 1, msb only, mode 2
* PIT Write: 1, 12 = 0x1200 = memory refresh?
* PIT Write: 3, b6 = counter 2, load lsb + msb, mode 3
* PIT Write: 3, 00
* PIT Write: 0, 00
* PIT Write: 0, 00
*
* Linux Startup
* PIT Write: 3, b0 = counter 2, load lsb+msb, mode 0
* PIT Write: 2, a4
* PIT Write: 2, ec = eca4
* PIT Write: 3, 36 = counter 0, load lsb+msb, mode 3
* PIT Write: 0, 00
* PIT Write: 0, 00 = 65536
* PIT Write: 3, b6 = counter 2, load lsb+msb, mode 3
* PIT Write: 2, 31
* PIT Write: 2, 13 = 1331
**/
u8 CAliM1543C::pit_read(u32 address) {
// printf("PIT Read: %02" PRIx64 " \n",address);
u8 data;
data = 0;
return data;
}
/**
* Write to the programmable interrupt timer ports (40h-43h)
**/
void CAliM1543C::pit_write(u32 address, u8 data) {
// printf("PIT Write: %02" PRIx64 ", %02x \n",address,data);
if (address == 3) { // control
if (data != 0) {
state.pit_status[address] = data; // last command seen.
if ((data & 0xc0) >> 6 != 3) {
state.pit_status[(data & 0xc0) >> 6] = data & 0x3f;
state.pit_mode[(data & 0xc0) >> 6] = (data & 0x30) >> 4;
} else { // readback command 8254 only
state.pit_status[address] = 0xc0; // bogus :)
}
}
} else { // a counter
switch (state.pit_mode[address]) {
case 0:
break;
case 1:
case 3:
state.pit_counter[address] =
(state.pit_counter[address] & 0xff) | data << 8;
state.pit_counter[address + PIT_OFFSET_MAX] = state.pit_counter[address];
if (state.pit_mode[address] == 3) {
state.pit_mode[address] = 2;
} else
state.pit_status[address] &= ~0xc0; // no longer high, counter valid.
break;
case 2:
state.pit_counter[address] = (state.pit_counter[address] & 0xff00) | data;
// two bytes were written with 0x00, so its really 0x10000
if ((state.pit_status[address] & 0x30) >> 4 == 3 &&
state.pit_counter[address] == 0) {
state.pit_counter[address] = 65536;
}
state.pit_counter[address + PIT_OFFSET_MAX] = state.pit_counter[address];
state.pit_status[address] &= ~0xc0; // no longer high, counter valid.
break;
}
}
}
#define PIT_FACTOR 5000
#define PIT_DEC(p) p = (p < PIT_FACTOR ? 0 : p - PIT_FACTOR);
/**
* Handle the PIT interrupt.
*
* - counter 0 is the 18.2Hz time counter.
* - counter 1 is the ram refresh, we don't care.
* - counter 2 is the speaker and/or generic timer
* .
**/
void CAliM1543C::pit_clock() {
int i;
for (i = 0; i < 3; i++) {
// decrement the counter.
if (state.pit_status[i] & 0x40)
continue;
PIT_DEC(state.pit_counter[i]);
switch ((state.pit_status[i] & 0x0e) >> 1) {
case 0: // interrupt at terminal
if (!state.pit_counter[i]) {
state.pit_status[i] |= 0xc0; // out pin high, no count set.
}
break;
case 3: // square wave generator
if (!state.pit_counter[i]) {
if (state.pit_status[i] & 0x80) {
state.pit_status[i] &= ~0x80; // lower output;
} else {
state.pit_status[i] |= 0x80; // raise output
if (i == 0) {
pic_interrupt(0, 0); // counter 0 is tied to irq 0.
// printf("Generating timer interrupt.\n");
}
}
state.pit_counter[i] = state.pit_counter[i + PIT_OFFSET_MAX];
}
// decrement again, since we want a half-wide square wave.
PIT_DEC(state.pit_counter[i]);
break;
default:
break; // we don't care to handle it.
}
}
}
/**
* Thread entry point.
**/
void CAliM1543C::run() {
try {
for (;;) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (StopThread)
return;
do_pit_clock();
}
}
catch (CException &e) {
printf("Exception in Ali thread: %s.\n", e.displayText().c_str());
myThreadDead.store(true);
// Let the thread die...
}
}
#define PIT_RATIO 1
/**
* Handle all events that need to be handled on a clock-driven basis.
*
* This is a slow-clocked device, which means this DoClock isn't called as often
*as the CPU's DoClock. Do the following:
* - Handle PIT clock.
* .
**/
void CAliM1543C::do_pit_clock() {
static int pit_counter = 0;
if (pit_counter++ >= PIT_RATIO) {
pit_counter = 0;
pit_clock();
}
}
#define PIC_STD 0
#define PIC_INIT_0 1
#define PIC_INIT_1 2
#define PIC_INIT_2 3
/**
* Read a byte from one of the programmable interrupt controller's registers.
**/
u8 CAliM1543C::pic_read(int index, u32 address) {
u8 data;
data = 0;
if (address == 1)
data = state.pic_mask[index];
#ifdef DEBUG_PIC
if (pic_messages)
printf("%%PIC-I-READ: read %02x from port %" PRId64 " on PIC %d\n", data,
address, index);
#endif
return data;
}
/**
* Read a byte from the edge/level register of one of the programmable interrupt
*controllers.
**/
u8 CAliM1543C::pic_read_edge_level(int index) {
return state.pic_edge_level[index];
}
/**
* Read the interrupt vector during a PCI IACK cycle.
**/
u8 CAliM1543C::pic_read_vector() {
if (state.pic_asserted[0] & 1)
return state.pic_intvec[0];
if (state.pic_asserted[0] & 2)
return state.pic_intvec[0] + 1;
if (state.pic_asserted[0] & 4) {
if (state.pic_asserted[1] & 1)
return state.pic_intvec[1];
if (state.pic_asserted[1] & 2)
return state.pic_intvec[1] + 1;
if (state.pic_asserted[1] & 4)
return state.pic_intvec[1] + 2;
if (state.pic_asserted[1] & 8)
return state.pic_intvec[1] + 3;
if (state.pic_asserted[1] & 16)
return state.pic_intvec[1] + 4;
if (state.pic_asserted[1] & 32)
return state.pic_intvec[1] + 5;
if (state.pic_asserted[1] & 64)
return state.pic_intvec[1] + 6;
if (state.pic_asserted[1] & 128)
return state.pic_intvec[1] + 7;
}
if (state.pic_asserted[0] & 8)
return state.pic_intvec[0] + 3;
if (state.pic_asserted[0] & 16)
return state.pic_intvec[0] + 4;
if (state.pic_asserted[0] & 32)
return state.pic_intvec[0] + 5;
if (state.pic_asserted[0] & 64)
return state.pic_intvec[0] + 6;
if (state.pic_asserted[0] & 128)
return state.pic_intvec[0] + 7;
return 0;
}
/**
* Write a byte to one of the programmable interrupt controller's registers.
**/
void CAliM1543C::pic_write(int index, u32 address, u8 data) {
int level;
int op;
#ifdef DEBUG_PIC
if (pic_messages)
printf("%%PIC-I-WRITE: write %02x to port %" PRId64 " on PIC %d\n", data,
address, index);
#endif
switch (address) {
case 0:
if (data & 0x10)
state.pic_mode[index] = PIC_INIT_0;
else
state.pic_mode[index] = PIC_STD;
if (data & 0x08) {
// OCW3
} else {
// OCW2
op = (data >> 5) & 7;
level = data & 7;
switch (op) {
case 1:
// non-specific EOI
state.pic_asserted[index] = 0;
//
if (index == 1)
state.pic_asserted[0] &= ~(1 << 2);
//
if (!state.pic_asserted[0])
cSystem->interrupt(55, false);
#ifdef DEBUG_PIC
pic_messages = false;
#endif
break;
case 3:
// specific EOI
state.pic_asserted[index] &= ~(1 << level);
//
if ((index == 1) && (!state.pic_asserted[1]))
state.pic_asserted[0] &= ~(1 << 2);
//
if (!state.pic_asserted[0])
cSystem->interrupt(55, false);
#ifdef DEBUG_PIC
pic_messages = false;
#endif
break;
}
}
return;
case 1:
switch (state.pic_mode[index]) {
case PIC_INIT_0:
state.pic_intvec[index] = (u8)data & 0xf8;
state.pic_mode[index] = PIC_INIT_1;
return;
case PIC_INIT_1:
state.pic_mode[index] = PIC_INIT_2;
return;
case PIC_INIT_2:
state.pic_mode[index] = PIC_STD;
return;
case PIC_STD:
state.pic_mask[index] = data;
state.pic_asserted[index] &= ~data;
return;
}
}
}
/**
* Write a byte to the edge/level register of one of the programmable interrupt
*controllers.
**/
void CAliM1543C::pic_write_edge_level(int index, u8 data) {
state.pic_edge_level[index] = data;
}
#define DEBUG_EXPR (index != 0 || (intno != 0 && intno > 4))
/**
* Assert an interrupt on one of the programmable interrupt controllers.
**/
void CAliM1543C::pic_interrupt(int index, int intno) {
#ifdef DEBUG_PIC
if (DEBUG_EXPR) {
printf("%%PIC-I-INCOMING: Interrupt %d incomming on PIC %d", intno, index);
pic_messages = true;
}
#endif
// do we have this interrupt enabled?
if (state.pic_mask[index] & (1 << intno)) {
#ifdef DEBUG_PIC
if (DEBUG_EXPR)
printf(" (masked)\n");
pic_messages = false;
#endif
return;
}
if (state.pic_asserted[index] & (1 << intno)) {
#ifdef DEBUG_PIC
if (DEBUG_EXPR)
printf(" (already asserted)\n");
#endif
return;
}
#ifdef DEBUG_PIC
if (DEBUG_EXPR)
printf("\n");
#endif
state.pic_asserted[index] |= (1 << intno);
if (index == 1)
pic_interrupt(0, 2); // cascade
if (index == 0)
cSystem->interrupt(55, true);
}
/**
* De-assert an interrupt on one of the programmable interrupt controllers.
**/
void CAliM1543C::pic_deassert(int index, int intno) {
if (!(state.pic_asserted[index] & (1 << intno)))
return;
// printf("De-asserting %d,%d\n",index,intno);
state.pic_asserted[index] &= ~(1 << intno);
if (index == 1 && state.pic_asserted[1] == 0)
pic_deassert(0, 2); // cascade
if (index == 0 && state.pic_asserted[0] == 0)
cSystem->interrupt(55, false);
}
static u32 ali_magic1 = 0xA111543C;
static u32 ali_magic2 = 0xC345111A;
/**
* Save state to a Virtual Machine State file.
**/
int CAliM1543C::SaveState(FILE *f) {
long ss = sizeof(state);
int res;
if ((res = CPCIDevice::SaveState(f)))
return res;
fwrite(&ali_magic1, sizeof(u32), 1, f);
fwrite(&ss, sizeof(long), 1, f);
fwrite(&state, sizeof(state), 1, f);
fwrite(&ali_magic2, sizeof(u32), 1, f);
printf("%s: %d bytes saved.\n", devid_string, (int)ss);
return 0;
}
/**
* Restore state from a Virtual Machine State file.
**/
int CAliM1543C::RestoreState(FILE *f) {
long ss;
u32 m1;
u32 m2;
int res;
size_t r;
if ((res = CPCIDevice::RestoreState(f)))
return res;
r = fread(&m1, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m1 != ali_magic1) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
r = fread(&ss, sizeof(long), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (ss != sizeof(state)) {
printf("%s: STRUCT SIZE does not match!\n", devid_string);
return -1;
}
r = fread(&state, sizeof(state), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
r = fread(&m2, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m2 != ali_magic2) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
printf("%s: %d bytes restored.\n", devid_string, (int)ss);
return 0;
}
/**
* Parallel Port information:
* address 0 (R/W): data pins. On read, the last byte written is returned.
*
*
* address 1 (R): status register
* \code
* 1 0 0 0 0 0 00 <-- default
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | +- Undefined
* | | | | | +--- IRQ (undefined?)
* | | | | +----- printer has error condition
* | | | +------- printer is not selected.
* | | +--------- printer has paper (online)
* | +----------- printer is asserting 'ack'
* +------------- printer busy (active low).
* \endcode
*
* address 2 (R/W): control register.
* \code
* 00 0 0 1 0 1 1 <-- default
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | +-- Strobe (active low)
* | | | | | +---- Auto feed (active low)
* | | | | +------ Initialize
* | | | +-------- Select (active low)
* | | +---------- Interrupt Control
* | +------------ Bidirectional control (unimplemented)
* +--------------- Unused
* \endcode
**/
void CAliM1543C::lpt_reset() {
state.lpt_data = ~0;
state.lpt_status = 0xd8; // busy, ack, online, error
state.lpt_control = 0x0c; // select, init
state.lpt_init = false;
}
/**
* Read a byte from one of the parallel port controller's registers.
**/
u8 CAliM1543C::lpt_read(u32 address) {
u8 data = 0;
switch (address) {
case 0:
data = state.lpt_data;
break;
case 1:
data = state.lpt_status;
if ((state.lpt_status & 0x80) == 0 && (state.lpt_control & 0x01) == 0) {
if (state.lpt_status & 0x40) { // test ack
state.lpt_status &= ~0x40; // turn off ack
} else {
state.lpt_status |= 0x40; // set ack.
state.lpt_status |= 0x80; // set (not) busy.
}
}
break;
case 2:
data = state.lpt_control;
}
#ifdef DEBUG_LPT
printf("%%LPT-I-READ: port %d = %x\n", address, data);
#endif
return data;
}
/**
* Write a byte to one of the parallel port controller's registers.
**/
void CAliM1543C::lpt_write(u32 address, u8 data) {
#ifdef DEBUG_LPT
printf("%%LPT-I-WRITE: port %d = %x\n", address, data);
#endif
switch (address) {
case 0:
state.lpt_data = data;
break;
case 1:
break;
case 2:
if ((data & 0x04) == 0) {
state.lpt_init = true;
state.lpt_status = 0xd8;
} else {
if (data & 0x08) { // select bit
if (data & 0x01) { // strobe?
state.lpt_status &= ~0x80; // we're busy
// do the write!
if (lpt && state.lpt_init)
fputc(state.lpt_data, lpt);
if (state.lpt_control & 0x10) {
pic_interrupt(0, 7);
}
} else {
// ?
}
}
}
state.lpt_control = data;
}
}
/**
* Check if threads are still running.
**/
void CAliM1543C::check_state() {
if (myThreadDead.load())
FAILURE(Thread, "ALi thread has died");
}
CAliM1543C *theAli = 0;
================================================
FILE: src/AliM1543C.hpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
*/
#if !defined(INCLUDED_ALIM1543C_H_)
#define INCLUDED_ALIM1543C_H_
#include "PCIDevice.hpp"
#define PIT_OFFSET_MAX 6
// RTC register A (MC_BASE_32_KHz is a divider bits configuration)
#define RTC_REG_A 0x0a
#define RTC_UIP 0x80
#define MC_BASE_32_KHz 0x20
// RTC register B (here most options reside; 0x08 is the unused square wave
// enable pin)
#define RTC_REG_B 0x0b
#define RTC_SET 0x80
#define RTC_PIE 0x40
#define RTC_AIE 0x20
#define RTC_UIE 0x10
#define RTC_DM 0x04
#define RTC_2412 0x02
#define RTC_DSE 0x01
// RTC register C (rest of register is always zero)
#define RTC_REG_C 0x0c
#define RTC_IRQF 0x80
#define RTC_PF 0x40
#define RTC_AF 0x20
#define RTC_UF 0x10
// RTC register D (rest of register is always zero)
#define RTC_REG_D 0x0d
#define RTC_VRT 0x80
/**
* \brief Emulated ISA part of the ALi M1543C chipset.
*
* The ALi M1543C device provides i/o and glue logic support to the system:
* ISA, DMA, Interrupt, Timer, TOY Clock.
*
* Documentation consulted:
* - Ali M1543C B1 South Bridge Version 1.20
*(http://mds.gotdns.com/sensors/docs/ali/1543dScb1-120.pdf)
* - MC146818 RTC
*(https://www.nxp.com/docs/en/data-sheet/MC146818.pdf)
* - Keyboard Scancodes, by Andries Brouwer
*(http://www.win.tue.nl/~aeb/linux/kbd/scancodes.html)
* .
**/
class CAliM1543C : public CPCIDevice {
public:
virtual int SaveState(FILE *f);
virtual int RestoreState(FILE *f);
virtual void check_state();
virtual void WriteMem_Legacy(int index, u32 address, int dsize, u32 data);
virtual u32 ReadMem_Legacy(int index, u32 address, int dsize);
void do_pit_clock();
CAliM1543C(CConfigurator *cfg, class CSystem *c, int pcibus, int pcidev);
virtual ~CAliM1543C();
void pic_interrupt(int index, int intno);
void pic_deassert(int index, int intno);
void init();
void start_threads();
void stop_threads();
void run();
private:
std::unique_ptr<std::thread> myThread;
std::atomic_bool myThreadDead{false};
CMutex *myRegLock;
bool StopThread;
struct tm get_time();
// REGISTER 61 (NMI)
u8 reg_61_read();
void reg_61_write(u8 data);
// REGISTERS 70 - 73: TOY
u8 toy_read(u32 address);
void toy_write(u32 address, u8 data);
void toy_handle_periodic_interrupt(u8 data);
void toy_update_irqf();
// Timer/Counter
u8 pit_read(u32 address);
void pit_write(u32 address, u8 data);
void pit_clock();
// interrupt controller
u8 pic_read(int index, u32 address);
void pic_write(int index, u32 address, u8 data);
u8 pic_read_vector();
u8 pic_read_edge_level(int index);
void pic_write_edge_level(int index, u8 data);
// LPT controller
u8 lpt_read(u32 address);
void lpt_write(u32 address, u8 data);
void lpt_reset();
/// The state structure contains all elements that need to be saved to the
/// statefile.
struct SAli_state {
// REGISTER 61 (NMI)
u8 reg_61;
// REGISTERS 70 - 73: TOY
u8 toy_stored_data[256];
u8 toy_access_ports[4];
// TOY periodic interrupt last fire
clock_t toy_pi_last_fire;
// Timer/Counter
u32 pit_counter[9];
u8 pit_status[4];
u8 pit_mode[4];
// interrupt controller
int pic_mode[2];
u8 pic_intvec[2];
u8 pic_mask[2];
u8 pic_asserted[2];
u8 pic_edge_level[2];
u8 lpt_data;
u8 lpt_control;
u8 lpt_status;
bool lpt_init;
} state;
FILE *lpt;
};
extern CAliM1543C *theAli;
#endif // !defined(INCLUDED_ALIM1543C_H_)
================================================
FILE: src/AliM1543C_ide.cpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* Although this is not required, the author would appreciate being
* notified of, and receiving any modifications you may make to the
* source code that might serve the general public.
*/
#ifdef DEBUG_IDE_LOCKS
#define DEBUG_LOCKS
#endif
#include "AliM1543C_ide.hpp"
#include "StdAfx.hpp"
#include "System.hpp"
#include <cmath>
#include "gui/keymap.hpp"
#include "gui/scancodes.hpp"
#include "AliM1543C.hpp"
#include "Disk.hpp"
#define PAUSE(msg) \
do { \
printf("Debug Pause: "); \
printf(msg); \
getc(stdin); \
} while (0);
u32 AliM1543C_ide_cfg_data[64] = {
/*00*/ 0x522910b9, // CFID: vendor + device
/*04*/ 0x02800000, // CFCS: command + status
/*08*/ 0x0101fac1, // CFRV: class + revision
/*0c*/ 0x00000000, // CFLT: latency timer + cache line size
/*10*/ 0x000001f1, // BAR0:
/*14*/ 0x000003f5, // BAR1:
/*18*/ 0x00000171, // BAR2:
/*1c*/ 0x00000375, // BAR3:
/*20*/ 0x0000f001, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x040201ff, // CFIT: interrupt configuration
0,
0,
/*48*/ 0x4a000000, // UDMA test
/*4c*/ 0x1aba0000, // reserved
0,
/*54*/ 0x44445555, // udma setting + fifo treshold
0,
0,
0,
0,
0,
0,
0,
0,
/*78*/ 0x00000021, // ide clock
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
u32 AliM1543C_ide_cfg_mask[64] = {
/*00*/ 0x00000000, // CFID: vendor + device
/*04*/ 0x00000105, // CFCS: command + status
/*08*/ 0x00000000, // CFRV: class + revision
/*0c*/ 0x0000ffff, // CFLT: latency timer + cache line size
/*10*/ 0xfffffff8, // BAR0
/*14*/ 0xfffffffc, // BAR1: CBMA
/*18*/ 0xfffffff8, // BAR2:
/*1c*/ 0xfffffffc, // BAR3:
/*20*/ 0xfffffff0, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x000000ff, // CFIT: interrupt configuration
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
/**
* Constructor.
**/
CAliM1543C_ide::CAliM1543C_ide(CConfigurator *cfg, CSystem *c, int pcibus,
int pcidev)
: CPCIDevice(cfg, c, pcibus, pcidev), CDiskController(2, 2) {
if (theIDE != 0)
FAILURE(Configuration, "More than one IDE controller");
theIDE = this;
// create scsi busses
CSCSIBus *a = new CSCSIBus(cfg, c);
CSCSIBus *b = new CSCSIBus(cfg, c);
scsi_register(0, a, 7); // scsi id 7 by default
scsi_register(1, b, 7); // scsi id 7 by default
}
/**
* Initialize the IDE device.
**/
void CAliM1543C_ide::init() {
add_function(0, AliM1543C_ide_cfg_data, AliM1543C_ide_cfg_mask);
add_legacy_io(PRI_COMMAND, 0x1f0, 8);
add_legacy_io(PRI_CONTROL, 0x3f6, 2);
add_legacy_io(SEC_COMMAND, 0x170, 8);
add_legacy_io(SEC_CONTROL, 0x376, 2);
add_legacy_io(PRI_BUSMASTER, 0xf000, 8);
add_legacy_io(SEC_BUSMASTER, 0xf008, 8);
usedma = myCfg->get_bool_value("dma", true);
if (!usedma) {
printf("IDE: DMA Transfers turned off.\n");
}
ResetPCI();
// start controller threads
StopThread = false;
mtRegisters[0] = new CRWLock("ide0-registers");
mtRegisters[1] = new CRWLock("ide1-registers");
mtBusMaster[0] = new CRWLock("ide0-busmaster");
mtBusMaster[1] = new CRWLock("ide1-busmaster");
for (int i = 0; i < 2; i++) {
semController[i] = new CSemaphore(0, 1); // disk controller
semControllerReady[i] = new CSemaphore(0, 1); // disk controller ready
semBusMaster[i] = new CSemaphore(0, 1); // bus master
semBusMasterReady[i] = new CSemaphore(0, 1); // bus master ready
semControllerReady[i]->set();
semBusMasterReady[i]->set();
thrController[i] = 0;
}
printf("%%IDE-I-INIT: New IDE emulator initialized.\n");
}
void CAliM1543C_ide::start_threads() {
char buffer[5];
for (int i = 0; i < 2; i++) {
if (!thrController[i]) {
sprintf(buffer, "ide%d", i);
thrController[i] =
std::make_unique<std::thread>([this, i]() { this->run(i); });
printf(" %s", buffer);
StopThread = false;
}
}
}
void CAliM1543C_ide::stop_threads() {
char buffer[5];
StopThread = true;
for (int i = 0; i < 2; i++) {
if (thrController[i]) {
sprintf(buffer, "ide%d", i);
printf(" %s", buffer);
semController[i]->set();
thrController[i]->join();
thrController[i] = nullptr;
}
}
}
CAliM1543C_ide::~CAliM1543C_ide() { stop_threads(); }
void CAliM1543C_ide::ResetPCI() {
int i;
int j;
CPCIDevice::ResetPCI();
for (i = 0; i < 2; i++) {
CONTROLLER(i).bm_status = 0;
CONTROLLER(i).selected = 0;
for (j = 0; j < 2; j++) {
REGISTERS(i, j).error = 0;
COMMAND(i, j).command_in_progress = 0;
COMMAND(i, j).command_cycle = 0;
STATUS(i, j).busy = false;
STATUS(i, j).drive_ready = false;
STATUS(i, j).drq = false;
STATUS(i, j).err = false;
STATUS(i, j).index_pulse = false;
STATUS(i, j).index_pulse_count = 0;
STATUS(i, j).seek_complete = false;
PER_DRIVE(i, j).multiple_size = 1;
set_signature(i, j);
}
}
}
void CAliM1543C_ide::register_disk(class CDisk *dsk, int bus, int dev) {
CDiskController::register_disk(dsk, bus, dev);
if (dsk->cdrom()) {
dsk->scsi_register(0, scsi_bus[bus], dev);
dsk->set_atapi_mode();
}
}
static u32 ide_magic1 = 0xB222654D;
static u32 ide_magic2 = 0xD456222C;
/**
* Save state to a Virtual Machine State file.
**/
int CAliM1543C_ide::SaveState(FILE *f) {
long ss = sizeof(state);
int res;
if ((res = CPCIDevice::SaveState(f)))
return res;
fwrite(&ide_magic1, sizeof(u32), 1, f);
fwrite(&ss, sizeof(long), 1, f);
fwrite(&state, sizeof(state), 1, f);
fwrite(&ide_magic2, sizeof(u32), 1, f);
printf("%s: %d bytes saved.\n", devid_string, (int)ss);
return 0;
}
/**
* Restore state from a Virtual Machine State file.
**/
int CAliM1543C_ide::RestoreState(FILE *f) {
long ss;
u32 m1;
u32 m2;
int res;
size_t r;
if ((res = CPCIDevice::RestoreState(f)))
return res;
r = fread(&m1, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m1 != ide_magic1) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
r = fread(&ss, sizeof(long), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (ss != sizeof(state)) {
printf("%s: STRUCT SIZE does not match!\n", devid_string);
return -1;
}
r = fread(&state, sizeof(state), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
r = fread(&m2, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m2 != ide_magic2) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
printf("%s: %d bytes restored.\n", devid_string, (int)ss);
return 0;
}
/*
* Region read/write redirection
*/
u32 CAliM1543C_ide::ReadMem_Legacy(int index, u32 address, int dsize) {
int channel = 0;
switch (index) {
case SEC_COMMAND:
channel = 1;
case PRI_COMMAND:
return ide_command_read(channel, address, dsize);
case SEC_CONTROL:
channel = 1;
case PRI_CONTROL:
return ide_control_read(channel, address);
case SEC_BUSMASTER:
channel = 1;
case PRI_BUSMASTER:
return ide_busmaster_read(channel, address, dsize);
}
return 0;
}
void CAliM1543C_ide::WriteMem_Legacy(int index, u32 address, int dsize,
u32 data) {
int channel = 0;
switch (index) {
case SEC_COMMAND:
channel = 1;
case PRI_COMMAND:
ide_command_write(channel, address, dsize, data);
break;
case SEC_CONTROL:
channel = 1;
case PRI_CONTROL:
ide_control_write(channel, address, data);
break;
case SEC_BUSMASTER:
channel = 1;
case PRI_BUSMASTER:
ide_busmaster_write(channel, address, dsize, data);
break;
}
}
u32 CAliM1543C_ide::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
int channel = 0;
switch (bar) {
case BAR_SEC_COMMAND:
channel = 1;
case BAR_PRI_COMMAND:
return ide_command_read(channel, address, dsize);
case BAR_SEC_CONTROL:
channel = 1;
case BAR_PRI_CONTROL:
// we have to offset by two because the BAR starts at 3f4 vs 3f6
return ide_control_read(channel, address - 2);
case BAR_BUSMASTER:
if (address < 8)
return ide_busmaster_read(0, address, dsize);
else
return ide_busmaster_read(1, address - 8, dsize);
}
return 0;
}
void CAliM1543C_ide::WriteMem_Bar(int func, int bar, u32 address, int dsize,
u32 data) {
int channel = 0;
switch (bar) {
case BAR_SEC_COMMAND:
channel = 1;
case BAR_PRI_COMMAND:
ide_command_write(channel, address, dsize, data);
return;
case BAR_SEC_CONTROL:
channel = 1;
case BAR_PRI_CONTROL:
// we have to offset by two because the BAR starts at 3f4 vs 3f6
ide_control_write(channel, address - 2, data);
return;
case BAR_BUSMASTER:
if (address < 8)
return ide_busmaster_write(0, address, data, dsize);
else
return ide_busmaster_write(1, address - 8, data, dsize);
}
}
/*
* Register read/write handlers
*/
u32 CAliM1543C_ide::ide_command_read(int index, u32 address, int dsize) {
u32 data = 0;
if (!get_disk(index, 0) && !get_disk(index, 1)) {
// no disks are present, so the data lines actually float to
// a high state, which is logical 1.
return 0xffffffff;
}
switch (address) {
case REG_COMMAND_DATA:
if (!SEL_STATUS(index).drq) {
#ifdef DEBUG_IDE_REG_COMMAND
printf("Reading from data buffer when data is not ready.\n");
ide_status(index);
PAUSE("WTF");
#endif
break;
}
data = 0;
switch (dsize) {
case 32:
data = CONTROLLER(index).data[CONTROLLER(index).data_ptr++];
data |= CONTROLLER(index).data[CONTROLLER(index).data_ptr++] << 16;
break;
case 16:
data = CONTROLLER(index).data[CONTROLLER(index).data_ptr++];
}
if (CONTROLLER(index).data_ptr >= CONTROLLER(index).data_size) {
// there's no more to take.
SEL_STATUS(index).drq = false;
if (SEL_COMMAND(index).command_in_progress) {
SEL_STATUS(index).busy = true;
SEL_STATUS(index).drive_ready = false;
UPDATE_ALT_STATUS(index);
semControllerReady[index]->wait();
semController[index]->set(); // wake up the controller.
#if defined(DEBUG_IDE_MULTIPLE) || defined(DEBUG_IDE_PACKET)
printf("Command still in progress, waking up controller.\n");
printf("-- Packet Phase: %d\n", SEL_COMMAND(index).packet_phase);
ide_status(index);
#endif
}
}
if (CONTROLLER(index).data_ptr > IDE_BUFFER_SIZE) {
printf("%%IDE-W-OVERFLOW: data pointer past end of buffer, setting to "
"0.\n");
CONTROLLER(index).data_ptr = 0;
SEL_STATUS(index).drq = false;
UPDATE_ALT_STATUS(index);
}
break;
case REG_COMMAND_ERROR:
data = SEL_REGISTERS(index).error;
break;
case REG_COMMAND_SECTOR_COUNT:
data = SEL_REGISTERS(index).sector_count;
break;
case REG_COMMAND_SECTOR_NO:
data = SEL_REGISTERS(index).sector_no;
break;
case REG_COMMAND_CYL_LOW:
data = SEL_REGISTERS(index).cylinder_no & 0xff;
break;
case REG_COMMAND_CYL_HI:
data = (SEL_REGISTERS(index).cylinder_no >> 8) & 0xff;
break;
case REG_COMMAND_DRIVE:
data = 0x80 | (SEL_REGISTERS(index).lba_mode ? 0x40 : 0x00) |
0x20 // 512 byte sector size
| (CONTROLLER(index).selected ? 0x10 : 0x00) |
(SEL_REGISTERS(index).head_no & 0x0f);
break;
case REG_COMMAND_STATUS:
// get the status and clear the interrupt.
data = get_status(index);
theAli->pic_deassert(1, 6 + index);
#ifdef DEBUG_IDE_INTERRUPT
printf("%%IDE-I-INTERRUPT: Interrupt Acknowledged on %d.\n", index);
#endif
break;
}
#ifdef DEBUG_IDE_REG_COMMAND
if (address != 0) {
printf("%%IDE-I-REGCMD: Read from command register %d (%s) on controller "
"%d, value: %x\n",
address, register_names[address], index, data);
}
#endif
return data;
}
void CAliM1543C_ide::ide_command_write(int index, u32 address, int dsize,
u32 data) {
#ifdef DEBUG_IDE_REG_COMMAND
if (address != 0) {
printf("%%IDE-I-REGCMD: Write to command register %d (%s) on controller "
"%d, value: %x\n",
address, register_names[address], index, data);
}
SEL_STATUS(index).debug_status_update = true;
#endif
switch (address) {
case REG_COMMAND_DATA:
if (!SEL_STATUS(index).drq) {
#ifdef DEBUG_IDE_REG_COMMAND
printf("%%IDE-I-DATA: Unrequested data written to data port: %x\n", data);
ide_status(index);
#endif
break;
}
switch (dsize) {
case 32:
CONTROLLER(index).data[CONTROLLER(index).data_ptr++] = data & 0xffff;
CONTROLLER(index).data[CONTROLLER(index).data_ptr++] =
(data >> 16) & 0xffff;
break;
case 16:
CONTROLLER(index).data[CONTROLLER(index).data_ptr++] = data & 0xffff;
}
if (CONTROLLER(index).data_ptr >= CONTROLLER(index).data_size) {
// we don't want any more.
SEL_STATUS(index).drq = false;
SEL_STATUS(index).busy = true;
UPDATE_ALT_STATUS(index);
semControllerReady[index]->wait();
semController[index]->set(); // wake the controller up.
}
if (CONTROLLER(index).data_ptr > IDE_BUFFER_SIZE) {
printf("%%IDE-W-OVERFLOW: data pointer overflow, setting to 0.\n");
CONTROLLER(index).data_ptr = 0;
SEL_STATUS(index).drq = false;
UPDATE_ALT_STATUS(index);
}
break;
case REG_COMMAND_FEATURES:
REGISTERS(index, 0).features = data;
REGISTERS(index, 1).features = data;
break;
case REG_COMMAND_SECTOR_COUNT:
REGISTERS(index, 0).sector_count = REGISTERS(index, 1).sector_count =
data & 0xff;
break;
case REG_COMMAND_SECTOR_NO:
REGISTERS(index, 0).sector_no = REGISTERS(index, 1).sector_no = data & 0xff;
break;
case REG_COMMAND_CYL_LOW:
REGISTERS(index, 0).cylinder_no = REGISTERS(index, 1).cylinder_no =
(REGISTERS(index, 1).cylinder_no & 0xff00) | (data & 0xff);
break;
case REG_COMMAND_CYL_HI:
REGISTERS(index, 0).cylinder_no = REGISTERS(index, 1).cylinder_no =
(REGISTERS(index, 1).cylinder_no & 0xff) | ((data << 8) & 0xff00);
break;
case REG_COMMAND_DRIVE:
if (((data >> 4) & 1) != CONTROLLER(index).selected)
#ifdef DEBUG_IDE
printf("Setting selected device on %d to: %d. val=%02x\n", index,
(data >> 4) & 1, data);
#endif
CONTROLLER(index).selected = (data >> 4) & 1;
REGISTERS(index, 0).head_no = REGISTERS(index, 1).head_no = data & 0x0f;
REGISTERS(index, 0).lba_mode = REGISTERS(index, 1).lba_mode =
(data >> 6) & 1;
break;
case REG_COMMAND_COMMAND:
theAli->pic_deassert(1, 6 + index); // interrupt is cleared on write.
if (!SEL_DISK(index)) {
#ifdef DEBUG_IDE
printf("%%IDE-I-NODEV: Command to non-existing device %d.%d. cmd=%x\n",
index, CONTROLLER(index).selected, data);
#endif
}
if (SEL_COMMAND(index).command_in_progress == true) {
// we're already working, why is another command being issued?
#ifdef DEBUG_IDE
printf("%%IDE-W-CIP: Command is already in progress.\n");
PAUSE("dang it!");
#endif
}
if ((data & 0xf0) == 0x10)
data = 0x10;
SEL_COMMAND(index).command_in_progress = false;
SEL_COMMAND(index).current_command = data;
#ifdef DEBUG_IDE_CMD
printf("%%IDE-I-CMD: Command %02x issued on controller %d, disk %d.\n",
data, index, CONTROLLER(index).selected);
#endif
SEL_COMMAND(index).command_cycle = 0;
SEL_STATUS(index).drq = false;
UPDATE_ALT_STATUS(index);
CONTROLLER(index).data_ptr = 0;
if (data != 0x00) {
SEL_STATUS(index).busy = true;
UPDATE_ALT_STATUS(index);
SEL_COMMAND(index).command_in_progress = true;
SEL_COMMAND(index).packet_phase = PACKET_NONE;
semControllerReady[index]->wait();
semController[index]->set(); // wake up the controller.
} else {
// this is a nop, so we cancel everything that's pending and
// pretend that this operation got done super fast!
if (SEL_DISK(index))
command_aborted(index, data);
}
break;
}
}
u32 CAliM1543C_ide::ide_control_read(int index, u32 address) {
u32 data = 0;
switch (address) {
case 0:
// Compute status live from current state rather than using cached
// alt_status, to avoid stale values when the controller thread has
// updated status fields but not yet called UPDATE_ALT_STATUS.
// Unlike get_status(), this does not affect index_pulse or clear interrupts.
if (SEL_DISK(index)) {
data = (SEL_STATUS(index).busy ? 0x80 : 0x00) |
(SEL_STATUS(index).drive_ready ? 0x40 : 0x00) |
(SEL_STATUS(index).fault ? 0x20 : 0x00) |
(SEL_STATUS(index).seek_complete ? 0x10 : 0x00) |
(SEL_STATUS(index).drq ? 0x08 : 0x00) |
(SEL_STATUS(index).index_pulse ? 0x02 : 0x00) |
(SEL_STATUS(index).err ? 0x01 : 0x00);
}
#ifdef DEBUG_IDE_REG_CONTROL
static u32 last_data = 0;
if (last_data != data) {
printf("%%IDE-I-READCTRL: alternate status on IDE control %d: 0x%02x\n",
index, data);
}
last_data = data;
#endif
break;
case 1:
// 3x7h drive address register. (floppy?)
data |= (CONTROLLER(index).selected == 0) ? 1 : 2;
data |= (SEL_REGISTERS(index).head_no) << 2;
data = (~data) & 0xff; // negate everything
#ifdef DEBUG_IDE_REG_CONTROL
printf("%%IDE-I-READCTRL: drive address port on IDE control %d: 0x%02x\n",
index, data);
#endif
break;
}
return data;
}
/**
* Write to the IDE controller control interface.
**/
void CAliM1543C_ide::ide_control_write(int index, u32 address, u32 data) {
bool prev_reset;
#ifdef DEBUG_IDE_REG_CONTROL
printf("%%IDE-I-WRITCTRL: write port %d on IDE control %d: 0x%02x\n",
(u32)(address), index, data);
#endif
switch (address) {
case 0:
prev_reset = CONTROLLER(index).reset;
CONTROLLER(index).reset = (data >> 2) & 1;
CONTROLLER(index).disable_irq = (data >> 1) & 1;
if (!prev_reset && CONTROLLER(index).reset) {
#ifdef DEBUG_IDE_REG_CONTROL
printf("IDE reset on index %d started.\n", index);
#endif
STATUS(index, 0).busy = true;
STATUS(index, 0).drive_ready = false;
STATUS(index, 0).seek_complete = true;
STATUS(index, 0).drq = false;
STATUS(index, 0).err = false;
COMMAND(index, 0).current_command = 0;
COMMAND(index, 0).command_in_progress = false;
STATUS(index, 1).busy = true;
STATUS(index, 1).drive_ready = false;
STATUS(index, 1).seek_complete = true;
STATUS(index, 1).drq = false;
STATUS(index, 1).err = false;
COMMAND(index, 1).current_command = 0;
COMMAND(index, 1).command_in_progress = false;
CONTROLLER(index).reset_in_progress = true;
SEL_REGISTERS(index).error = 0x01; // no error
COMMAND(index, 0).current_command = 0;
CONTROLLER(index).disable_irq = false;
} else if (prev_reset && !CONTROLLER(index).reset) {
#ifdef DEBUG_IDE_REG_CONTROL
printf("IDE reset on index %d ended.\n", index);
#endif
STATUS(index, 0).busy = false;
STATUS(index, 0).drive_ready = true;
STATUS(index, 1).busy = false;
STATUS(index, 1).drive_ready = true;
CONTROLLER(index).reset_in_progress = false;
set_signature(index, 0);
set_signature(index, 1);
}
break;
case 1:
// floppy?
break;
}
}
/**
* Read from the IDE controller busmaster interface.
**/
u32 CAliM1543C_ide::ide_busmaster_read(int index, u32 address, int dsize) {
u32 data = 0;
switch (dsize) {
case 8:
data = CONTROLLER(index).busmaster[address];
break;
case 32:
data = *(u32 *)(&CONTROLLER(index).busmaster[address]);
break;
default:
FAILURE(InvalidArgument, "16-bit read from busmaster");
break;
}
#ifdef DEBUG_IDE_BUSMASTER
printf(
"%%IDE-I-READBUSM: read port %d on IDE bus master %d: 0x%02x, %d bytes\n",
(u32)(address), index, data, dsize / 8);
#endif
return data;
}
/**
* Write to the IDE controller busmaster interface.
**/
void CAliM1543C_ide::ide_busmaster_write(int index, u32 address, u32 data,
int dsize) {
#ifdef DEBUG_IDE_BUSMASTER
if (!(dsize == 8 && (address >= 4 && address <= 7))) {
printf("%%IDE-I-WRITBUSM: write port %d on IDE bus master %d: 0x%02x, %d "
"bytes\n",
(u32)(address), index, data, dsize / 8);
}
#endif
u32 prd_address;
// u32 base, control;
switch (dsize) {
case 32:
ide_busmaster_write(index, address, data & 0xff, 8);
ide_busmaster_write(index, address + 1, (data >> 8) & 0xff, 8);
ide_busmaster_write(index, address + 2, (data >> 16) & 0xff, 8);
ide_busmaster_write(index, address + 3, (data >> 24) & 0xff, 8);
return;
case 16:
ide_busmaster_write(index, address, data & 0xff, 8);
ide_busmaster_write(index, address + 1, (data >> 8) & 0xff, 8);
return;
}
switch (address) {
case 0: // command register
#ifdef DEBUG_IDE_BUSMASTER
printf("%%IDE-I-BUSM: Bus master command got data: %x (%s,%s)\n", data,
(data & 0x08 ? "write" : "read"), (data & 0x01 ? "start" : "stop"));
#endif
// bits 7:4 & 2:1 are reserved and must return zero on read.
CONTROLLER(index).busmaster[0] = data & 0x09;
if (data & 0x01) {
// set the status register
CONTROLLER(index).busmaster[2] |= 0x01;
semBusMasterReady[index]->wait();
semBusMaster[index]->set(); // wake up the controller for busmastering
} else {
// clear the status register
CONTROLLER(index).busmaster[2] &= 0xfe;
}
break;
case 2: // status
// bit 7 = simplex only (0=both channels are independent)
// bit 6 = drive 1 dma capable.
// bit 5 = drive 0 dma capable.
// bit 4,3 = reserved
// bit 2 = interrupt (write 1 to reset)
// bit 1 = error (write 1 to reset)
// bit 0 = busmaster active.
CONTROLLER(index).busmaster[2] = data & 0x67;
if (data & 0x04) // interrupt
CONTROLLER(index).busmaster[2] &= ~0x04;
if (data & 0x02) // error
CONTROLLER(index).busmaster[2] &= ~0x02;
if (data & 0x01) // busy
CONTROLLER(index).busmaster[2] &= ~0x01;
break;
case 4: // descriptor table pointer register(s)
case 5:
case 6:
CONTROLLER(index).busmaster[address] = data;
break;
case 7:
CONTROLLER(index).busmaster[address] = data;
prd_address = endian_32(*(u32 *)(&CONTROLLER(index).busmaster[4]));
#ifdef DEBUG_IDE_BUSMASTER
printf("%%IDE-I-PRD: Virtual address: %" PRIx64 " \n",
endian_32(*(u32 *)(&CONTROLLER(index).busmaster[4])));
printf("-IDE-I-PRD: Physical address: %" PRIx64 " \n", prd_address);
u32 base, control;
do {
do_pci_read(prd_address, &base, 4, 1);
do_pci_read(prd_address + 4, &control, 4, 1);
printf("-IDE-I-PRD: base: %x, control: %x \n", base, control);
prd_address += 8;
} while (base & 0x80 == 0);
#endif
break;
default:
break;
}
}
void CAliM1543C_ide::set_signature(int index, int id) {
// Device signature
REGISTERS(index, id).head_no = 0;
REGISTERS(index, id).sector_count = 1;
REGISTERS(index, id).sector_no = 1;
if (get_disk(index, id)) {
if (!get_disk(index, id)->cdrom()) {
REGISTERS(index, id).cylinder_no = 0;
CONTROLLER(index).selected = 0; // XXX: This may not be correct.
} else {
REGISTERS(index, id).cylinder_no = 0xeb14;
}
} else {
REGISTERS(index, id).cylinder_no = 0xffff;
}
}
void CAliM1543C_ide::raise_interrupt(int index) {
if (!CONTROLLER(index).disable_irq) {
#ifdef DEBUG_IDE_INTERRUPT
printf("%%IDE-I-INTERRUPT: Interrupt raised on controller %d.\n", index);
#endif
#if !defined(IDE_YIELD_INTERRUPTS)
{
SCOPED_WRITE_LOCK(mtBusMaster[index]);
CONTROLLER(index).busmaster[2] |= 0x04;
}
UPDATE_ALT_STATUS(index);
theAli->pic_interrupt(1, 6 + index);
#else
CONTROLLER(index).interrupt_pending = true;
#endif
}
}
u8 CAliM1543C_ide::get_status(int index) {
u8 data;
if (!SEL_DISK(index)) {
#ifdef DEBUG_IDE_REG_COMMAND
printf("%%IDE-I-STATUS: Read status for nonexiting device %d.%d\n", index,
CONTROLLER(index).selected);
#endif
return 0;
}
data = (SEL_STATUS(index).busy ? 0x80 : 0x00) |
(SEL_STATUS(index).drive_ready ? 0x40 : 0x00) |
(SEL_STATUS(index).fault ? 0x20 : 0x00) |
(SEL_STATUS(index).seek_complete ? 0x10 : 0x00) |
(SEL_STATUS(index).drq ? 0x08 : 0x00) |
(SEL_STATUS(index).index_pulse ? 0x02 : 0x00) |
(SEL_STATUS(index).err ? 0x01 : 0x00);
SEL_STATUS(index).index_pulse_count++;
SEL_STATUS(index).index_pulse = false;
if (SEL_STATUS(index).index_pulse_count >= 10) {
SEL_STATUS(index).index_pulse_count = 0;
SEL_STATUS(index).index_pulse = true;
}
#ifdef DEBUG_IDE_REG_COMMAND
if ((SEL_STATUS(index).debug_last_status & 0xfd) != (data & 0xfd) ||
SEL_STATUS(index).debug_status_update) {
printf("%%IDE-I-STATUS: Controller %d status: %x = %s %s %s %s %s %s %s\n",
index, data, SEL_STATUS(index).busy ? "busy" : "",
SEL_STATUS(index).drive_ready ? "drdy" : "",
SEL_STATUS(index).fault ? "fault" : "",
SEL_STATUS(index).seek_complete ? "seek_complete" : "",
SEL_STATUS(index).drq ? "drq" : "",
SEL_STATUS(index).index_pulse ? "pulse" : "",
SEL_STATUS(index).err ? "error" : "");
SEL_STATUS(index).debug_status_update = false;
}
SEL_STATUS(index).debug_last_status = data;
#endif
return data;
}
void CAliM1543C_ide::identify_drive(int index, bool packet) {
char serial_number[21];
char model_number[41];
char rev_number[9];
size_t i;
// clear the block.
for (i = 0; i < 256; i++)
CONTROLLER(index).data[i] = 0;
CONTROLLER(index).data_ptr = 0;
CONTROLLER(index).data_size = 256;
// The data here was taken from T13/1153D revision 18
if (!packet) {
// flags: 0x0080 = removable, 0x0040 = fixed.
CONTROLLER(index).data[0] = SEL_DISK(index)->cdrom() ? 0x0080 : 0x0040;
} else {
// flags: 15-14: 10=atapi, 11=reserved; 12-8: packet set; 7:
// removable 6-5: timing info, 4-2: command, 1-0: 00= 12 byte packet
CONTROLLER(index).data[0] = 0x8580;
}
// logical cylinders
if (SEL_DISK(index)->get_cylinders() > 16383)
CONTROLLER(index).data[1] = 16383;
else
CONTROLLER(index).data[1] = (u16)(SEL_DISK(index)->get_cylinders());
// logical heads
CONTROLLER(index).data[3] = (u16)(SEL_DISK(index)->get_heads());
// logical sectors per logical track
CONTROLLER(index).data[6] = (u16)(SEL_DISK(index)->get_sectors());
// serial number
strcpy(serial_number, " ");
i = strlen(SEL_DISK(index)->get_serial());
i = (i > 20) ? 20 : i;
memcpy(model_number, SEL_DISK(index)->get_serial(), i);
for (i = 0; i < 10; i++)
CONTROLLER(index).data[10 + i] =
(serial_number[i * 2] << 8) | serial_number[i * 2 + 1];
// firmware revision
strcpy(rev_number, " ");
i = strlen(SEL_DISK(index)->get_rev());
i = (i > 8) ? 8 : i;
memcpy(model_number, SEL_DISK(index)->get_rev(), i);
for (i = 0; i < 4; i++)
CONTROLLER(index).data[23 + i] =
(rev_number[i * 2] << 8) | rev_number[i * 2 + 1];
// model number
strcpy(model_number, " ");
i = strlen(SEL_DISK(index)->get_model());
i = (i > 40) ? 40 : i;
memcpy(model_number, SEL_DISK(index)->get_model(), i);
for (i = 0; i < 20; i++)
CONTROLLER(index).data[i + 27] =
(model_number[i * 2] << 8) | model_number[i * 2 + 1];
// read/write multiple (15-8 = 0x80, 7-0 = # sectors)
CONTROLLER(index).data[47] = 0x8000 | MAX_MULTIPLE_SECTORS;
// capabilities
if (!packet) {
CONTROLLER(index).data[49] = 0x0300;
} else {
CONTROLLER(index).data[49] = 0x0b00; // dma, iordy
}
// capabilities (2)
CONTROLLER(index).data[50] = 0x4000;
// pio data transfer number (bits 15-8)
CONTROLLER(index).data[51] = 0x0300;
// validity: bit 2 = #88 valid, 1 = 64-70 valid, 0 = 54-58 valid
CONTROLLER(index).data[53] = 7;
// geometry
CONTROLLER(index).data[54] = (u16)(SEL_DISK(index)->get_cylinders());
CONTROLLER(index).data[55] = (u16)(SEL_DISK(index)->get_heads());
CONTROLLER(index).data[56] = (u16)(SEL_DISK(index)->get_sectors());
CONTROLLER(index).data[57] =
(u16)(SEL_DISK(index)->get_chs_size() >> 0) & 0xFFFF;
CONTROLLER(index).data[58] =
(u16)(SEL_DISK(index)->get_chs_size() >> 16) & 0xFFFF;
// multiple sector setting (valid, 1 sector per interrupt)
if (SEL_PER_DRIVE(index).multiple_size != 0) {
CONTROLLER(index).data[59] = 0x0100 | SEL_PER_DRIVE(index).multiple_size;
} else {
CONTROLLER(index).data[59] = 0x0000;
}
// lba capacity
CONTROLLER(index).data[60] =
(u16)(SEL_DISK(index)->get_lba_size() >> 0) & 0xFFFF;
CONTROLLER(index).data[61] =
(u16)(SEL_DISK(index)->get_lba_size() >> 16) & 0xFFFF;
// multiword dma capability (10-8: modes selected, 2-0, modes
// supported)
if (usedma)
CONTROLLER(index).data[63] =
CONTROLLER(index).dma_mode << 8 | 0x01; // dma 0 supported
else
CONTROLLER(index).data[63] =
CONTROLLER(index).dma_mode << 8 | 0x00; // dma not supported
// pio modes supported (bit 0 = mode 3, bit 1 = mode 4)
CONTROLLER(index).data[64] = 0x0002;
// minimum cycle times
CONTROLLER(index).data[65] = 480; // mode 0
CONTROLLER(index).data[66] = 480; // mode 0
CONTROLLER(index).data[67] = 120; // pio4
CONTROLLER(index).data[68] = 120; // pio4
if (packet) {
// packet to bus release time
CONTROLLER(index).data[71] = 120;
// service to bus release time
CONTROLLER(index).data[72] = 120;
}
// queue depth (we don't do queing)
CONTROLLER(index).data[75] = 0;
// ata version supported (bits/version: 1,2,3,4)
CONTROLLER(index).data[80] = 0x001e;
// atapi revision supported (ata/atapi-4 T13 1153D revision 17)
CONTROLLER(index).data[81] = 0x0017;
// command set supported (cdrom = nop,packet,removable; disk=nop)
CONTROLLER(index).data[82] = SEL_DISK(index)->cdrom() ? 0x4014 : 0x4000;
// command sets supported(no additional command sets)
CONTROLLER(index).data[83] = 0x4000;
CONTROLLER(index).data[84] = 0x4000;
// command sets enabled.
CONTROLLER(index).data[85] = SEL_DISK(index)->cdrom() ? 0x4014 : 0x4000;
CONTROLLER(index).data[86] = 0x4000;
CONTROLLER(index).data[87] = 0x4000;
// ultra dma modes supported (10-8: modes selected, 2-0, modes
// supported)
CONTROLLER(index).data[88] = 0x0000;
}
void CAliM1543C_ide::command_aborted(int index, u8 command) {
printf("ide%d.%d aborting on command 0x%02x \n", index,
CONTROLLER(index).selected, command);
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).err = true;
SEL_STATUS(index).drq = false;
SEL_REGISTERS(index).error |= 0x04; // command ABORTED
CONTROLLER(index).data_ptr = 0;
SEL_COMMAND(index).command_in_progress = false;
UPDATE_ALT_STATUS(index);
raise_interrupt(index);
}
CAliM1543C_ide *theIDE = 0;
void CAliM1543C_ide::ide_status(int index) {
printf("IDE %d.%d: [busy: %d, drdy: %d, flt: %d, drq: %d, err: %d]\n"
" [c: %d, h: %d, s: %d, #: %d, f: %x, lba: %d]\n"
" [ptr: %d, size: %d, error: %d, cmd: %x, in progress: %d]\n"
" [cycle: %d, pkt phase: %d, pkt cmd: %x, dma: %d]\n"
" [bm-cmd: %x bm-stat: %x]\n",
index, CONTROLLER(index).selected, SEL_STATUS(index).busy,
SEL_STATUS(index).drive_ready, SEL_STATUS(index).fault,
SEL_STATUS(index).drq, SEL_STATUS(index).err,
SEL_REGISTERS(index).cylinder_no, SEL_REGISTERS(index).head_no,
SEL_REGISTERS(index).sector_no, SEL_REGISTERS(index).sector_count,
SEL_REGISTERS(index).features,
(SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no,
CONTROLLER(index).data_ptr, CONTROLLER(index).data_size,
SEL_REGISTERS(index).error, SEL_COMMAND(index).current_command & 0xff,
SEL_COMMAND(index).command_in_progress,
SEL_COMMAND(index).command_cycle, SEL_COMMAND(index).packet_phase,
SEL_COMMAND(index).packet_command[0], SEL_COMMAND(index).packet_dma,
CONTROLLER(index).busmaster[0], CONTROLLER(index).busmaster[2]);
}
/**
* Check if threads are still running.
**/
void CAliM1543C_ide::check_state() {
if (thrController[0] && thrControllerDead[0].load())
FAILURE(Thread, "IDE 0 thread has died");
if (thrController[1] && thrControllerDead[1].load())
FAILURE(Thread, "IDE 1 thread has died");
}
void CAliM1543C_ide::execute(int index) {
if (SEL_DISK(index) == NULL && SEL_COMMAND(index).current_command != 0x90) {
// this device doesn't exist (and its not execute device
// diagnostic)
// so we'll just timeout
SEL_COMMAND(index).command_in_progress = false;
} else {
#ifdef DEBUG_IDE_COMMAND
printf("%%IDE-I-COMMAND: Processing command on controller %d.\n", index);
ide_status(index);
#endif
switch (SEL_COMMAND(index).current_command) {
case 0x00: // nop
SEL_REGISTERS(index).error = 0x04;
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = true;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = true;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
printf("got nop on %d.%d\n", index, CONTROLLER(index).selected);
// FAILURE("This isn't possible, but you're seeing it.");
break;
case 0x08: // device reset
if (SEL_DISK(index)->cdrom() || 1) {
// the spec says that non-packet devices must not respond
// to device reset. However, by allowing it, Tru64
// recognizes the device properly.
SEL_COMMAND(index).command_in_progress = false;
if (CONTROLLER(index).selected == 0) {
REGISTERS(index, 0).error = 0x01; // device passed.
REGISTERS(index, 1).error = 0x01; // slave not present or passed
} else {
REGISTERS(index, 1).error = 0x01; // slave passed
}
set_signature(index, CONTROLLER(index).selected);
// step "k", page 216 (232)
SEL_STATUS(index).drq = false; // bit 3
SEL_STATUS(index).bit_2 = false; // bit 2
SEL_STATUS(index).err = false; // bit 0
if (SEL_DISK(index)->cdrom()) {
SEL_STATUS(index).fault = false; // bit 5
SEL_STATUS(index).drive_ready = false; // per step "m2"
} else {
SEL_STATUS(index).drive_ready = true; // step "m1"
}
SEL_STATUS(index).busy = false;
// some sources say there's no reset on device reset.
// raise_interrupt(index);
} else {
command_aborted(index, SEL_COMMAND(index).current_command);
}
break;
case 0x10: // calibrate drive
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_REGISTERS(index).cylinder_no = 0;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
break;
case 0x20: // read with retries
case 0x21: // read without retries
if (SEL_COMMAND(index).command_cycle == 0) {
// fixup the 0=256 case.
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
}
if (!SEL_STATUS(index).drq) {
// buffer is empty, so lets fill it.
if (!SEL_REGISTERS(index).lba_mode) {
FAILURE(NotImplemented, "Non-LBA disk read");
} else {
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->read_blocks(&(CONTROLLER(index).data[0]), 1);
#if defined(ES40_BIG_ENDIAN)
for (int i = 0; i < SEL_DISK(index)->get_block_size() / sizeof(u16);
i++)
CONTROLLER(index).data[i] = endian_16(CONTROLLER(index).data[i]);
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
CONTROLLER(index).data_ptr = 0;
CONTROLLER(index).data_size = 256;
// prepare for next sector
SEL_REGISTERS(index).sector_count--;
if (SEL_REGISTERS(index).sector_count == 0) {
SEL_COMMAND(index).command_in_progress = false;
if (SEL_DISK(index)->cdrom())
set_signature(index, CONTROLLER(index).selected); // per 9.1
} else {
// set the next block to read.
// increment the lba.
SEL_REGISTERS(index).sector_no++;
if (SEL_REGISTERS(index).sector_no > 255) {
SEL_REGISTERS(index).sector_no = 0;
SEL_REGISTERS(index).cylinder_no++;
if (SEL_REGISTERS(index).cylinder_no > 65535) {
SEL_REGISTERS(index).cylinder_no = 0;
SEL_REGISTERS(index).head_no++;
}
}
}
}
UPDATE_ALT_STATUS(index);
raise_interrupt(index);
}
break;
case 0x30: // write with retries
case 0x31: // write without retries
if (SEL_COMMAND(index).command_cycle == 0) {
// this is our first time through
if (SEL_DISK(index)->cdrom() || SEL_DISK(index)->ro()) {
printf("%%IDE-W-RO: Write attempt to read-only disk %d.%d.\n", index,
CONTROLLER(index).selected);
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
SEL_STATUS(index).drq = true;
SEL_STATUS(index).busy = false;
CONTROLLER(index).data_size = 256;
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
}
} else {
// now we should be getting data.
if (!SEL_STATUS(index).drq) {
// the buffer is full. Do something with the data.
if (!SEL_REGISTERS(index).lba_mode) {
FAILURE(NotImplemented, "Non-LBA disk write");
} else {
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
#if defined(ES40_BIG_ENDIAN)
{
u16 data[IDE_BUFFER_SIZE];
SEL_DISK(index)->seek_block(lba);
for (int i = 0;
i < SEL_DISK(index)->get_block_size() / sizeof(u16); i++)
data[i] = endian_16(CONTROLLER(index).data[i]);
SEL_DISK(index)->write_blocks(&(data[0]), 1);
}
#else
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]), 1);
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
CONTROLLER(index).data_ptr = 0;
// prepare for next sector
SEL_REGISTERS(index).sector_count--;
if (SEL_REGISTERS(index).sector_count == 0) {
// we're done
SEL_STATUS(index).drq = false;
SEL_COMMAND(index).command_in_progress = false;
} else {
// set the next block to read.
// increment the lba.
SEL_REGISTERS(index).sector_no++;
if (SEL_REGISTERS(index).sector_no > 255) {
SEL_REGISTERS(index).sector_no = 0;
SEL_REGISTERS(index).cylinder_no++;
if (SEL_REGISTERS(index).cylinder_no > 65535) {
SEL_REGISTERS(index).cylinder_no = 0;
SEL_REGISTERS(index).head_no++;
}
}
}
}
raise_interrupt(index);
}
}
break;
/*
* case 0x40, 0x41: read verify sector(s) is mandatory for
* non-packet (no w/packet
*/
case 0x70: // seek
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
}
break;
/*
* 0x90: execute device diagnostic: mandatory
*/
case 0x91: // initialize device parameters
SEL_COMMAND(index).command_in_progress = false;
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
#ifdef DEBUG_IDE
printf("Original c: %d, h: %d, s: %d\n",
SEL_DISK(index)->get_cylinders(), SEL_DISK(index)->get_heads(),
SEL_DISK(index)->get_sectors());
printf("Requested c: %d, h: %d, s: %d\n",
SEL_REGISTERS(index).cylinder_no,
SEL_REGISTERS(index).head_no + 1,
SEL_REGISTERS(index).sector_count);
#endif
if (SEL_DISK(index)->get_heads() ==
(SEL_REGISTERS(index).head_no + 1) &&
SEL_DISK(index)->get_sectors() ==
SEL_REGISTERS(index).sector_count) {
// use the default translation -- ok!
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
raise_interrupt(index);
} else {
#ifdef DEBUG_IDE
PAUSE("INIT DEV PARAMS -- geometry not supported!");
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = true;
SEL_REGISTERS(index).error = 0x04; // ABORT.
raise_interrupt(index);
}
}
break;
case 0xa0: // packet send
/*
* The state machine and protocol used here was actually
* derived from ATA/ATAPI-5 (D1321R3) instead of the -4
* documenation. State names were taken from that document.
*/
if (!SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
if (SEL_REGISTERS(index).features & 0x02) {
// overlap not supported
PAUSE("overlapping not supported");
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
if (SEL_COMMAND(index).packet_phase == PACKET_NONE) {
// this must be the first time through.
if (!scsi_arbitrate(index))
FAILURE(IllegalState, "ATAPI SCSI bus busy");
if (!scsi_select(index, CONTROLLER(index).selected))
FAILURE(IllegalState, "ATAPI device not responding to selection");
SEL_REGISTERS(index).REASON = IR_CD;
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).DMRD = false;
SEL_STATUS(index).SERV = false;
CONTROLLER(index).data_ptr = 0;
CONTROLLER(index).data_size = 6;
SEL_COMMAND(index).packet_dma =
(SEL_REGISTERS(index).features & 0x01) ? true : false;
SEL_COMMAND(index).packet_phase = PACKET_DP1;
// we drop out of the thread and shut down the
// controller. we will be awakened when the drq flag
// is false, and the process will start in the state machine.
break;
}
/*
* This is the Packet I/O state machine. The gist of
* it is this: we loop until yield==true, so we can
* move from state to state in the same DoClock().
* By the time we get here, we're in DP1 (Receive
* Packet) and we're waiting for an actual packet to
* arrive.
*/
#ifdef DEBUG_IDE_PACKET
printf("Entering Packet state machine %d\n", index);
ide_status(index);
#endif
bool yield = false;
do {
#ifdef DEBUG_IDE_PACKET
printf("PACKET STATE: %s (%d)\n",
packet_states[SEL_COMMAND(index).packet_phase],
SEL_COMMAND(index).packet_phase);
#endif
switch (SEL_COMMAND(index).packet_phase) {
case PACKET_DP1: // receive packet
// we now have a full command packet.
if (scsi_get_phase(index) != SCSI_PHASE_COMMAND)
FAILURE(IllegalState, "SCSI command phase expected");
memcpy(scsi_xfer_ptr(index, 12), CONTROLLER(index).data, 12);
memcpy(SEL_COMMAND(index).packet_command, CONTROLLER(index).data,
12);
scsi_xfer_done(index);
SEL_COMMAND(index).packet_phase = PACKET_DP2;
SEL_COMMAND(index).packet_buffersize =
SEL_REGISTERS(index).cylinder_no;
SEL_STATUS(index).busy = true;
break;
case PACKET_DP2: // prepare b
SEL_STATUS(index).busy = true;
SEL_STATUS(index).drq = false;
if (SEL_COMMAND(index).command_in_progress) {
switch (scsi_get_phase(index)) {
case SCSI_PHASE_DATA_IN: {
size_t num_bytes = scsi_expected_xfer(index);
void *data_ptr = scsi_xfer_ptr(index, num_bytes);
memcpy(CONTROLLER(index).data, data_ptr, num_bytes);
scsi_xfer_done(index);
SEL_COMMAND(index).packet_phase = PACKET_DP34;
SEL_REGISTERS(index).BYTE_COUNT = (int)num_bytes;
CONTROLLER(index).data_size =
(int)num_bytes / 2; // word count.
CONTROLLER(index).data_ptr = 0;
} break;
case SCSI_PHASE_DATA_OUT:
FAILURE(NotImplemented,
"ATAPI for now does not support write operations");
break;
case SCSI_PHASE_STATUS:
scsi_xfer_ptr(index, scsi_expected_xfer(index));
scsi_xfer_done(index);
if (scsi_get_phase(index) != SCSI_PHASE_FREE)
FAILURE(IllegalState, "SCSI bus free phase expected");
SEL_COMMAND(index).packet_phase = PACKET_DI;
break;
default:
FAILURE(IllegalState, "Unexpected SCSI phase");
}
} else {
// transition to an idle state
#if defined(DEBUG_IDE_PACKET)
printf("Transition into idle state from DP2.\n");
#endif
SEL_COMMAND(index).packet_phase = PACKET_DI;
}
break;
case PACKET_DP34:
if (SEL_COMMAND(index).packet_dma) {
// send back via dma
#ifdef DEBUG_IDE_PACKET
printf("Sending ATAPI data back via DMA.\n");
#endif
do_dma_transfer(index, (u8 *)(&CONTROLLER(index).data[0]),
SEL_REGISTERS(index).BYTE_COUNT, false);
if (scsi_get_phase(index) != SCSI_PHASE_STATUS)
FAILURE(IllegalState, "SCSI status phase expected");
scsi_xfer_ptr(index, scsi_expected_xfer(index));
scsi_xfer_done(index);
if (scsi_get_phase(index) != SCSI_PHASE_FREE)
FAILURE(IllegalState, "SCSI bus free phase expected");
SEL_STATUS(index).drq = true;
SEL_STATUS(index).busy = false;
SEL_COMMAND(index).packet_phase = PACKET_DI;
} else {
// send back via pio
#ifdef DEBUG_IDE_PACKET
printf("Sending ATAPI data back via PIO.\n");
#endif
#if 0
if((!SEL_STATUS(index).drq) && (CONTROLLER(index).data_ptr == 0))
{
// first time through: no data
// transferred, and drq=0
SEL_STATUS(index).drq = true;
SEL_STATUS(index).busy = false;
SEL_REGISTERS(index).REASON = IR_IO;
raise_interrupt(index);
yield = true;
}
else
{
if(!SEL_STATUS(index).drq)
{
// all of the data has been read
// from the buffer.
// for now I assume that it is
// everything.
if(scsi_get_phase(index) != SCSI_PHASE_STATUS)
FAILURE(IllegalState, "SCSI status phase expected");
scsi_xfer_ptr(index, scsi_expected_xfer(index));
scsi_xfer_done(index);
if(scsi_get_phase(index) != SCSI_PHASE_FREE)
FAILURE(IllegalState, "SCSI bus free phase expected");
#ifdef DEBUG_IDE_PACKET
printf("Finished transferring!\n");
#endif
SEL_COMMAND(index).packet_phase = PACKET_DI;
yield = false;
}
}
#else
// do the transfer
SEL_STATUS(index).drq = true;
SEL_STATUS(index).busy = false;
SEL_REGISTERS(index).REASON = IR_IO;
if (scsi_get_phase(index) != SCSI_PHASE_STATUS)
FAILURE(IllegalState, "SCSI status phase expected");
scsi_xfer_ptr(index, scsi_expected_xfer(index));
scsi_xfer_done(index);
if (scsi_get_phase(index) != SCSI_PHASE_FREE)
FAILURE(IllegalState, "SCSI Bus free phase expected");
#ifdef DEBUG_IDE_PACKET
printf("Finished Transferring\n");
#endif
raise_interrupt(index);
SEL_COMMAND(index).packet_phase = PACKET_DI;
yield = true;
#endif
}
break;
case PACKET_DI:
// this is either DI0 or DI1
SEL_REGISTERS(index).REASON = IR_CD | IR_IO;
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).SERV = false;
SEL_STATUS(index).CHK = false;
SEL_STATUS(index).drq = false;
raise_interrupt(index);
SEL_COMMAND(index).command_in_progress = false;
yield = true;
break;
default:
FAILURE(InvalidArgument, "Unknown packet phase");
}
} while (!yield);
#ifdef DEBUG_IDE_PACKET
printf("Drop out of packet state machine %d\n", index);
ide_status(index);
#endif
}
}
break;
case 0xa1: // identify packet device
if (SEL_DISK(index)->cdrom()) {
identify_drive(index, true);
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
} else {
command_aborted(index, SEL_COMMAND(index).current_command);
}
break;
case 0xc4: // read multiple
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
if (SEL_COMMAND(index).command_cycle == 0) {
// fixup the 0=256 case.
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
SEL_STATUS(index).drq = false;
}
if (!SEL_STATUS(index).drq) {
// buffer is empty, so lets fill it.
if (!SEL_REGISTERS(index).lba_mode) {
FAILURE(NotImplemented, "Non-LBA disk read");
} else {
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
if (SEL_REGISTERS(index).sector_count >=
SEL_PER_DRIVE(index).multiple_size) {
// easy, its a full block
CONTROLLER(index).data_size =
256 * SEL_PER_DRIVE(index).multiple_size;
SEL_REGISTERS(index).sector_count -=
SEL_PER_DRIVE(index).multiple_size;
} else {
// partial block.
CONTROLLER(index).data_size =
256 * SEL_REGISTERS(index).sector_count;
SEL_REGISTERS(index).sector_count = 0;
}
#ifdef DEBUG_IDE_MULTIPLE
printf("IDE %d.%d: Reading %d sectors, %d sectors left.\n", index,
CONTROLLER(index).selected,
CONTROLLER(index).data_size / 256,
SEL_REGISTERS(index).sector_count);
#endif
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->read_blocks(
&(CONTROLLER(index).data[0]),
CONTROLLER(index).data_size /
256); // actual number of blocks we want.
#if defined(ES40_BIG_ENDIAN)
for (int i = 0; i < 256; i++)
CONTROLLER(index).data[i] = endian_16(CONTROLLER(index).data[i]);
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
CONTROLLER(index).data_ptr = 0;
// prepare for next sector
if (SEL_REGISTERS(index).sector_count == 0) {
SEL_COMMAND(index).command_in_progress = false;
if (SEL_DISK(index)->cdrom())
set_signature(index, CONTROLLER(index).selected); // per 9.1
} else {
// set the next block to read.
// increment the lba.
SEL_REGISTERS(index).sector_no +=
CONTROLLER(index).data_size / 256; // # sectors read.
if (SEL_REGISTERS(index).sector_no > 255) {
SEL_REGISTERS(index).sector_no = 0;
SEL_REGISTERS(index).cylinder_no++;
if (SEL_REGISTERS(index).cylinder_no > 65535) {
SEL_REGISTERS(index).cylinder_no = 0;
SEL_REGISTERS(index).head_no++;
}
}
}
}
raise_interrupt(index);
}
}
break;
case 0xc5: // write multiple
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
if (SEL_COMMAND(index).command_cycle == 0) {
// this is our first time through
if (SEL_DISK(index)->ro()) {
printf("%%IDE-W-RO: Write attempt to read-only disk %d.%d.\n",
index, CONTROLLER(index).selected);
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
SEL_STATUS(index).drq = true;
SEL_STATUS(index).busy = false;
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
if (SEL_REGISTERS(index).sector_count >=
SEL_PER_DRIVE(index).multiple_size) {
CONTROLLER(index).data_size =
256 * SEL_PER_DRIVE(index).multiple_size;
SEL_REGISTERS(index).sector_count -=
SEL_PER_DRIVE(index).multiple_size;
} else {
CONTROLLER(index).data_size =
256 * SEL_REGISTERS(index).sector_count;
SEL_REGISTERS(index).sector_count = 0;
}
}
} else {
// now we should be getting data.
if (!SEL_STATUS(index).drq) {
// the buffer is full. Do something with the data.
if (!SEL_REGISTERS(index).lba_mode) {
FAILURE(NotImplemented, "Non-LBA disk write");
} else {
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
#if defined(ES40_BIG_ENDIAN)
{
u16 data[IDE_BUFFER_SIZE];
SEL_DISK(index)->seek_block(lba);
for (int i = 0; i < CONTROLLER(index).data_size; i++)
data[i] = endian_16(CONTROLLER(index).data[i]);
SEL_DISK(index)->write_blocks(
&(data[0]), CONTROLLER(index).data_size / 256);
}
#else
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]),
CONTROLLER(index).data_size / 256);
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
CONTROLLER(index).data_ptr = 0;
if (SEL_REGISTERS(index).sector_count == 0) {
// we're done
SEL_STATUS(index).drq = false;
SEL_COMMAND(index).command_in_progress = false;
} else {
// prepare for next block
if (SEL_REGISTERS(index).sector_count >=
SEL_PER_DRIVE(index).multiple_size) {
CONTROLLER(index).data_size =
256 * SEL_PER_DRIVE(index).multiple_size;
SEL_REGISTERS(index).sector_count -=
SEL_PER_DRIVE(index).multiple_size;
} else {
CONTROLLER(index).data_size =
256 * SEL_REGISTERS(index).sector_count;
SEL_REGISTERS(index).sector_count = 0;
}
// set the next block to read.
// increment the lba.
SEL_REGISTERS(index).sector_no++;
if (SEL_REGISTERS(index).sector_no > 255) {
SEL_REGISTERS(index).sector_no = 0;
SEL_REGISTERS(index).cylinder_no++;
if (SEL_REGISTERS(index).cylinder_no > 65535) {
SEL_REGISTERS(index).cylinder_no = 0;
SEL_REGISTERS(index).head_no++;
}
}
}
}
raise_interrupt(index);
}
}
}
break;
case 0xc6: // set multiple mode
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
SEL_PER_DRIVE(index).multiple_size = SEL_REGISTERS(index).sector_count;
#ifdef DEBUG_IDE_MULTIPLE
printf("Set multiple mode: sector_count = %d\n",
SEL_REGISTERS(index).sector_count);
#endif
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
}
break;
case 0xc8: // read dma
case 0xc9: // read dma (old)
if (SEL_DISK(index)->cdrom()) {
command_aborted(index, SEL_COMMAND(index).current_command);
SEL_COMMAND(index).command_in_progress = false;
} else {
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
#ifdef DEBUG_IDE_DMA
printf("%%IDE-I-DMA: Read %d sectors = %d bytes.\n",
SEL_REGISTERS(index).sector_count,
SEL_REGISTERS(index).sector_count * 512);
#endif
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->read_blocks(&(CONTROLLER(index).data[0]),
SEL_REGISTERS(index).sector_count);
u8 *ptr = (u8 *)(&CONTROLLER(index).data[0]);
do_dma_transfer(index, ptr, SEL_REGISTERS(index).sector_count * 512,
false);
SEL_COMMAND(index).command_in_progress = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_STATUS(index).busy = false;
}
break;
case 0xca: // write dma
case 0xcb: // write dma (old)
if (SEL_DISK(index)->cdrom() || SEL_DISK(index)->ro()) {
command_aborted(index, SEL_COMMAND(index).current_command);
SEL_COMMAND(index).command_in_progress = false;
} else {
if (SEL_DISK(index)->ro()) {
printf("%%IDE-W-RO: DMA Write attempt to read-only disk %d.%d.\n",
index, CONTROLLER(index).selected);
command_aborted(index, SEL_COMMAND(index).current_command);
} else {
if (SEL_REGISTERS(index).sector_count == 0)
SEL_REGISTERS(index).sector_count = 256;
#ifdef DEBUG_IDE_DMA
printf("%%IDE-I-DMA: Write %d sectors = %d bytes.\n",
SEL_REGISTERS(index).sector_count,
SEL_REGISTERS(index).sector_count * 512);
#endif
u8 *ptr = (u8 *)(&CONTROLLER(index).data[0]);
do_dma_transfer(index, ptr, SEL_REGISTERS(index).sector_count * 512,
true);
u32 lba = (SEL_REGISTERS(index).head_no << 24) |
(SEL_REGISTERS(index).cylinder_no << 8) |
SEL_REGISTERS(index).sector_no;
SEL_DISK(index)->seek_block(lba);
SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]),
SEL_REGISTERS(index).sector_count);
SEL_COMMAND(index).command_in_progress = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_STATUS(index).busy = false;
}
}
break;
#if 0
case 0xe5: // check power mode
ide_status(index);
command_aborted(index, SEL_COMMAND(index).current_command);
SEL_COMMAND(index).command_in_progress = false;
// raise_interrupt(index);
break;
#endif
case 0xec: // identify
if (!SEL_DISK(index)->cdrom()) {
identify_drive(index, false);
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = true;
SEL_STATUS(index).err = false;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
} else {
set_signature(index, CONTROLLER(index).selected); // per
//
// 9.1
command_aborted(index, 0xec);
}
break;
case 0xef: // set features
SEL_COMMAND(index).command_in_progress = false;
switch (SEL_REGISTERS(index).features) {
case 0x03: // set transfer mode
if (SEL_REGISTERS(index).sector_count < 16) {
// allow all PIO modes.
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
raise_interrupt(index);
break;
} else {
// a DMA mode.
switch (SEL_REGISTERS(index).sector_count) {
case 0x20:
case 0x21:
case 0x22:
// multiword dma
CONTROLLER(index).dma_mode =
SEL_REGISTERS(index).sector_count & 0x03;
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).seek_complete = true;
SEL_STATUS(index).fault = false;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
raise_interrupt(index);
break;
case 0x40:
case 0x41:
case 0x42:
// ultra dma
command_aborted(index, SEL_COMMAND(index).current_command);
break;
}
break;
}
default:
printf("%%IDE-I-FEAT: Unhandled set feature subcommand %x\n",
SEL_REGISTERS(index).features);
command_aborted(index, SEL_COMMAND(index).current_command);
break;
}
break;
/***
* Special cases: commands we don't support, but return success.
***/
case 0xe0: // standby now
case 0xe1: // idle immediate
case 0xe2: // standby
case 0xe3: // idle
case 0xe6: // sleep
case 0xe7: // flush cache
case 0xea: // flush cache ext
SEL_STATUS(index).busy = false;
SEL_STATUS(index).drive_ready = true;
SEL_STATUS(index).drq = false;
SEL_STATUS(index).err = false;
SEL_COMMAND(index).command_in_progress = false;
raise_interrupt(index);
break;
default: // unknown/unhandled ATA command
ide_status(index);
FAILURE_1(NotImplemented, "Unknown IDE command %x",
SEL_COMMAND(index).current_command);
break;
}
#ifdef DEBUG_IDE_COMMAND
if (SEL_COMMAND(index).command_in_progress == false) {
printf("%%IDE-I-COMMAND: Command has completed on controller %d.\n",
index);
ide_status(index);
printf("==================================================\n");
} else {
printf("%%IDE-I-COMMAND: controller %d is yielding to host.\n", index);
ide_status(index);
printf("--------------------------------------------------\n");
}
#endif
}
SEL_COMMAND(index).command_cycle++;
}
int CAliM1543C_ide::do_dma_transfer(int index, u8 *buffer, u32 buffersize,
bool direction) {
u8 xfer;
size_t xfersize = 0;
u8 status = 0;
u8 count = 0;
u32 prd;
semBusMaster[index]->wait(); // wait until the start bit is set.
{
SCOPED_READ_LOCK(mtBusMaster[index]);
prd = endian_32(*(u32 *)(&CONTROLLER(index).busmaster[4]));
}
do {
u32 base;
do_pci_read(prd, &base, 4, 1);
u16 size_16;
do_pci_read(prd + 4, &size_16, 2, 1);
size_t size = size_16 ? size_16 : 65536;
do_pci_read(prd + 7, &xfer, 1, 1);
#ifdef DEBUG_IDE_DMA
printf("-IDE-I-DMA: Transfer %d bytes to/from %lx (%x)\n", size, base,
xfer);
#endif
if (xfersize + size > buffersize) {
// only copy as much data as we have from the disk.
size = buffersize - xfersize;
status = 2;
#ifdef DEBUG_IDE_DMA
printf("-IDE-I-DMA: Actual transfer size: %d bytes\n", size);
#endif
}
// copy it to/from ram.
if (!direction) {
do_pci_write(base, buffer, 1, size);
buffer += size;
} else {
do_pci_read(base, buffer, 1, size);
buffer += size;
}
xfersize += size;
prd += 8; // go to next entry.
if (xfer == 0x80 && xfersize < buffersize) {
// we still have disk data left over!
status = 1;
}
if (count++ > 32) {
FAILURE(InvalidArgument, "Too many PRD nodes?");
}
if (buffersize == xfersize && xfer != 0x80) {
// we're done, but there's more prd nodes.
status = 2;
}
} while (xfer != 0x80 && status == 0);
switch (status) {
case 0: // normal completion.
{
SCOPED_WRITE_LOCK(mtBusMaster[index]);
CONTROLLER(index).busmaster[2] &= 0xfe; // clear active.
}
raise_interrupt(index);
break;
case 1: // PRD is smaller than the data we have.
{
SCOPED_WRITE_LOCK(mtBusMaster[index]);
CONTROLLER(index).busmaster[2] &= 0xfe; // clear active.
}
// do not raise an interrupt
break;
case 2: // PRD is larger than the data we have.
// leave active set.
raise_interrupt(index);
break;
}
semBusMasterReady[index]->set();
return status;
}
/**
* Thread entry point.
**/
void CAliM1543C_ide::run(int index) {
try {
for (;;) {
semController[index]->wait();
if (StopThread)
return;
{
#ifdef DEBUG_IDE_THREADS
printf("Thread %d: \n", index);
ide_status(index);
#endif
if (SEL_COMMAND(index).command_in_progress)
execute(index);
UPDATE_ALT_STATUS(index);
#ifdef IDE_YIELD_INTERRUPTS
if (CONTROLLER(index).interrupt_pending) {
{
SCOPED_WRITE_LOCK(mtBusMaster[index]);
CONTROLLER(index).busmaster[2] |= 0x04;
}
theAli->pic_interrupt(1, 6 + index);
}
#endif
}
semControllerReady[index]->set();
}
}
catch (CException &e) {
printf("Exception in IDE thread: %s.\n", e.displayText().c_str());
thrControllerDead[index].store(true);
// Let the thread die...
}
}
================================================
FILE: src/AliM1543C_ide.hpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
*/
#if !defined(INCLUDED_ALIM1543C_IDE_H_)
#define INCLUDED_ALIM1543C_IDE_H_
// If DEBUG_IDE is defined, define all IDE debugging flags.
#ifdef DEBUG_IDE
#define DEBUG_IDE_BUSMASTER
#define DEBUG_IDE_COMMAND
#define DEBUG_IDE_DMA
#define DEBUG_IDE_INTERRUPT
#define DEBUG_IDE_REG_COMMAND
#define DEBUG_IDE_REG_CONTROL
#define DEBUG_IDE_PACKET
#define DEBUG_IDE_MULTIPLE
#endif
#include "Configurator.hpp"
#include "DiskController.hpp"
#include "PCIDevice.hpp"
#include "SCSIBus.hpp"
#include "SCSIDevice.hpp"
#define MAX_MULTIPLE_SECTORS 128
/**
* \brief Emulated IDE part of ALi M1543C multi-function device.
*
* Documentation consulted:
* - Ali M1543C B1 South Bridge Version 1.20
*(http://mds.gotdns.com/sensors/docs/ali/1543dScb1-120.pdf)
* - AT Attachment with Packet Interface - 5 (ATA/ATAPI-5)
*(http://www.t13.org/Documents/UploadedDocuments/project/d1321r3-ATA-ATAPI-5.pdf)
* - Programming Interface for Bus Master IDE COntroller
*(http://suif.stanford.edu/%7Ecsapuntz/specs/idems100.ps)
* - T13-1153Dr18 ATA/ATAPI-4
* - Mt. Fuji Commands for Multimedia Devices Version 7 INF-8090i v7
* .
**/
class CAliM1543C_ide : public CPCIDevice,
public CDiskController,
public CSCSIDevice {
public:
CAliM1543C_ide(CConfigurator *cfg, class CSystem *c, int pcibus, int pcidev);
virtual ~CAliM1543C_ide();
virtual void register_disk(class CDisk *dsk, int bus, int dev);
virtual void WriteMem_Legacy(int index, u32 address, int dsize, u32 data);
virtual u32 ReadMem_Legacy(int index, u32 address, int dsize);
virtual void WriteMem_Bar(int func, int bar, u32 address, int dsize,
u32 data);
virtual u32 ReadMem_Bar(int func, int bar, u32 address, int dsize);
virtual int SaveState(FILE *f);
virtual int RestoreState(FILE *f);
virtual void check_state();
virtual void ResetPCI();
void run(int index);
virtual void init();
virtual void start_threads();
virtual void stop_threads();
private:
// IDE controller
u32 ide_command_read(int channel, u32 address, int dsize);
void ide_command_write(int channel, u32 address, int dsize, u32 data);
u32 ide_control_read(int channel, u32 address);
void ide_control_write(int channel, u32 address, u32 data);
u32 ide_busmaster_read(int channel, u32 address, int dsize);
void ide_busmaster_write(int channel, u32 address, u32 data, int dsize);
int do_dma_transfer(int index, u8 *buffer, u32 size, bool direction);
void raise_interrupt(int channel);
void set_signature(int channel, int id);
u8 get_status(int index);
void command_aborted(int index, u8 command);
void identify_drive(int index, bool packet);
void ide_status(int index);
void execute(int index);
std::unique_ptr<std::thread> thrController[2];
std::atomic_bool thrControllerDead[2] = {{false}, {false}};
CSemaphore *semController[2]; // controller start/stop
CSemaphore *semControllerReady[2]; // controller ready
CSemaphore *semBusMaster[2]; // bus master start/stop
CSemaphore *semBusMasterReady[2]; // bus master ready
CRWLock *mtRegisters[2]; // main registers
CRWLock *mtBusMaster[2]; // busmaster registers
bool StopThread;
bool usedma;
// The state structure contains all elements that need to be saved to the
// statefile.
struct SAliM1543C_ideState {
struct SDriveState {
struct {
bool busy;
bool drive_ready;
bool fault;
bool seek_complete;
bool drq;
bool bit_2;
bool index_pulse;
bool err;
int index_pulse_count;
// debugging
u8 debug_last_status;
bool debug_status_update;
u8 alt_status; // this is the latched status.
} status;
struct {
bool lba_mode;
int features;
int error;
int sector_count;
int sector_no;
int cylinder_no;
int head_no;
int command;
} registers;
struct {
bool command_in_progress;
int current_command;
int command_cycle;
bool packet_dma;
int packet_phase;
u8 packet_command[12];
int packet_buffersize;
u8 packet_sense;
u8 packet_asc;
u8 packet_ascq;
} command;
u8 multiple_size;
};
struct SControllerState {
// the attached devices
struct SDriveState drive[2];
// control data.
bool disable_irq;
bool reset;
// internal state
bool reset_in_progress;
int selected;
// dma stuff
u8 busmaster[8];
u8 dma_mode;
u8 bm_status;
// pio stuff
#define IDE_BUFFER_SIZE 65536 // 64K words = 128K = 256 sectors @ 512 bytes
u16 data[IDE_BUFFER_SIZE];
int data_ptr;
int data_size;
bool interrupt_pending;
} controller[2];
} state;
};
/// Status for selected drive on controller a
#define SEL_STATUS(a) \
state.controller[a].drive[state.controller[a].selected].status
/// Command for selected drive on controller a
#define SEL_COMMAND(a) \
state.controller[a].drive[state.controller[a].selected].command
/// Registers for selected drive on controller a
#define SEL_REGISTERS(a) \
state.controller[a].drive[state.controller[a].selected].registers
/// Selected drive on controller a
#define SEL_DISK(a) get_disk(a, state.controller[a].selected)
/// Per-drive data for selected drive on controller a
#define SEL_PER_DRIVE(a) state.controller[a].drive[state.controller[a].selected]
// Status for drive b on controller a
#define STATUS(a, b) state.controller[a].drive[b].status
// Command for drive b on controller a
#define COMMAND(a, b) state.controller[a].drive[b].command
// Registers for drive b on controller a
#define REGISTERS(a, b) state.controller[a].drive[b].registers
// Per-drive data for drive b on controller a
#define PER_DRIVE(a, b) state.controller[a].drive[b]
// Data for controller a
#define CONTROLLER(a) state.controller[a]
// Update alt-status for controller a with locking
#define UPDATE_ALT_STATUS(a) \
{ \
SCOPED_WRITE_LOCK(mtRegisters[a]); \
SEL_STATUS(a).alt_status = get_status(a); \
}
/* memory region ids */
#define PRI_COMMAND 1
#define PRI_CONTROL 2
#define SEC_COMMAND 3
#define SEC_CONTROL 4
#define PRI_BUSMASTER 5
#define SEC_BUSMASTER 6
/* bar IDs */
#define BAR_PRI_COMMAND 0
#define BAR_PRI_CONTROL 1
#define BAR_SEC_COMMAND 2
#define BAR_SEC_CONTROL 3
#define BAR_BUSMASTER 4
/* device registers */
#define REG_COMMAND_DATA 0
#define REG_COMMAND_ERROR 1
#define REG_COMMAND_FEATURES 1
#define REG_COMMAND_SECTOR_COUNT 2
#define REG_COMMAND_SECTOR_NO 3
#define REG_COMMAND_CYL_LOW 4
#define REG_COMMAND_CYL_HI 5
#define REG_COMMAND_DRIVE 6
#define REG_COMMAND_STATUS 7
#define REG_COMMAND_COMMAND 7
static const char *register_names[] = {
"DATA", "ERROR/FEATURES", "SECTOR_COUNT/PKT REASON",
"SECTOR_NO", "CYL_LOW/PKT BYTE LOW", "CYL_HI/PKT BYTE HI",
"DRIVE", "STATUS/COMMAND",
};
/* misc constants */
/* Packet Protocol Aliases */
#define DMRD fault
#define SERV seek_complete
#define CHK err
#define BYTE_COUNT cylinder_no
#define REASON sector_count
#define IR_CD 0x01
#define IR_IO 0x02
#define IR_REL 0x04
/* Packet protocol states */
static const char *packet_states[] = {
"DP0: Prepare A", "DP1: Receive Packet",
"DP2: Prepare B", "DP3/4: Ready INITRQ/Transfer Data",
"DIx: Device Interrupt ",
};
#define PACKET_NONE 0
#define PACKET_DP0 0
#define PACKET_DP1 1
#define PACKET_DP2 2
#define PACKET_DP34 3
#define PACKET_DI 4
/* SCSI SENSE Constants */
#define SENSE_NONE 0x00
#define SENSE_RECOVERED_ERROR 0x01
#define SENSE_NOT_READY 0x02
#define SENSE_MEDIUM_ERROR 0x03
#define SENSE_HARDWARE_ERROR 0x04
#define SENSE_ILLEGAL_REQUEST 0x05
#define SENSE_UNIT_ATTENTION 0x06
#define SENSE_DATA_PROTECT 0x07
#define SENSE_BLANK_CHECK 0x08
#define SENSE_ABORT_COMMAND 0x0b
#define SENSE_MISCOMPARE 0x0e
extern CAliM1543C_ide *theIDE;
#endif
================================================
FILE: src/AliM1543C_usb.cpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
*/
#include "AliM1543C_usb.hpp"
#include "StdAfx.hpp"
#include "System.hpp"
u32 usb_cfg_data[64] = {
/*00*/ 0x523710b9, // CFID: vendor + device
/*04*/ 0x02800000, // CFCS: command + status
/*08*/ 0x0c031003, // CFRV: class + revision
/*0c*/ 0x00000000, // CFLT: latency timer + cache line size
/*10*/ 0x00000000, // BAR0:
/*14*/ 0x00000000, // BAR1:
/*18*/ 0x00000000, // BAR2:
/*1c*/ 0x00000000, // BAR3:
/*20*/ 0x00000000, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x500001ff, // CFIT: interrupt configuration
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
u32 usb_cfg_mask[64] = {
/*00*/ 0x00000000, // CFID: vendor + device
/*04*/ 0x00000157, // CFCS: command + status
/*08*/ 0x00000000, // CFRV: class + revision
/*0c*/ 0x0000ffff, // CFLT: latency timer + cache line size
/*10*/ 0xfffff000, // BAR0
/*14*/ 0x00000000, // BAR1:
/*18*/ 0x00000000, // BAR2:
/*1c*/ 0x00000000, // BAR3:
/*20*/ 0x00000000, // BAR4:
/*24*/ 0x00000000, // BAR5:
/*28*/ 0x00000000, // CCIC: CardBus
/*2c*/ 0x00000000, // CSID: subsystem + vendor
/*30*/ 0x00000000, // BAR6: expansion rom base
/*34*/ 0x00000000, // CCAP: capabilities pointer
/*38*/ 0x00000000,
/*3c*/ 0x000000ff, // CFIT: interrupt configuration
/*40*/ 0x04100000, // TM - test mode register
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0};
/**
* Constructor.
**/
CAliM1543C_usb::CAliM1543C_usb(CConfigurator *cfg, CSystem *c, int pcibus,
int pcidev)
: CPCIDevice(cfg, c, pcibus, pcidev) {
add_function(0, usb_cfg_data, usb_cfg_mask);
ResetPCI();
state.usb_data[0x34 / 4] = 0x2edf;
state.usb_data[0x48 / 4] = 0x01000003;
printf(
"%s: $Id: AliM1543C_usb.cpp,v 1.6 2008/03/14 15:30:50 iamcamiel Exp $\n",
devid_string);
}
CAliM1543C_usb::~CAliM1543C_usb() {}
u32 CAliM1543C_usb::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
u32 data = 0;
switch (bar) {
case 0:
data = usb_hci_read(address, dsize);
break;
default:
printf("%%USB-W-READBAR: Bad BAR %d selected.\n", bar);
}
return data;
}
void CAliM1543C_usb::WriteMem_Bar(int func, int bar, u32 address, int dsize,
u32 data) {
switch (bar) {
case 0:
usb_hci_write(address, dsize, data);
break;
default:
printf("%%USB-W-WRITEBAR: Bad BAR %d selected.\n", bar);
}
return;
}
u64 CAliM1543C_usb::usb_hci_read(u64 address, int dsize) {
u64 data = 0;
if (dsize != 32)
printf("%%USB-W-HCIREAD: Non dword read, returning 32 bits anyway.\n");
switch (address) {
case 0: // HcRevision
data = 0x00000110;
break;
case 4: // HcControl
case 8: // HcCommandStatus
case 0x0c: // HcInterruptStatus
case 0x10: // HcInterrupt Enable
case 0x14: // HcInterruptDisable
case 0x18: // HcHCCA (datasheet says 0x17, but that's wrong)
case 0x1c: // HcPeriodCurrentED
case 0x20: // HcControlHeadED
case 0x24: // HcControlCurrentED
case 0x28: // HcBulkHeadED
case 0x2c: // HcBulkCurrentED
case 0x30: // HcDoneHead
case 0x34: // HcFmInterval
case 0x38: // HcFrameRemaining
case 0x3c: // HcFmNumber
case 0x40: // HcPeriodicStart
case 0x44: // HcLSThreshold
case 0x48: // HcRhDescriptorA
case 0x4c: // HcRhDescriptorB
case 0x50: // HcRhStatus
case 0x54: // HcRhPortStatus1
case 0x58: // HcRhPortStatus1
case 0x5c: // HcRhPortStatus1
case 0x100: // HceControlRegister
case 0x104: // HceInputRegister
case 0x108: // HceOutputRegister
case 0x10c: // HceStatusRegister
data = state.usb_data[address / 4];
break;
default:
printf("%%USB-W-HCIREAD: Reading from unknown address %x. Ignoring.\n",
(int)address);
}
return data;
}
void CAliM1543C_usb::usb_hci_write(u64 address, int dsize, u64 data) {
if (dsize != 32)
printf("%%USB-W-HCIWRITE: Non dword write, writing 32 bits anyway.\n");
switch (address) {
case 4: // HcControl
case 8: // HcCommandStatus
case 0x0c: // HcInterruptStatus
case 0x10: // HcInterrupt Enable
case 0x14: // HcInterruptDisable
case 0x18: // HcHCCA (datasheet says 0x17, but that's wrong)
case 0x1c: // HcPeriodCurrentED
case 0x20: // HcControlHeadED
case 0x24: // HcControlCurrentED
case 0x28: // HcBulkHeadED
case 0x2c: // HcBulkCurrentED
case 0x30: // HcDoneHead
case 0x34: // HcFmInterval
case 0x38: // HcFrameRemaining
case 0x3c: // HcFmNumber
case 0x40: // HcPeriodicStart
case 0x44: // HcLSThreshold
case 0x48: // HcRhDescriptorA
case 0x4c: // HcRhDescriptorB
case 0x50: // HcRhStatus
case 0x54: // HcRhPortStatus1
case 0x58: // HcRhPortStatus1
case 0x5c: // HcRhPortStatus1
case 0x100: // HceControlRegister
case 0x104: // HceInputRegister
case 0x108: // HceOutputRegister
case 0x10c: // HceStatusRegister
state.usb_data[address / 4] = data;
break;
default:
printf("%%USB-W-HCIWRITE: Writing to unknown address %x. Ignoring.\n",
(int)address);
}
}
static u32 usb_magic1 = 0x9000432B;
static u32 usb_magic2 = 0xB2340009;
/**
* Save state to a Virtual Machine State file.
**/
int CAliM1543C_usb::SaveState(FILE *f) {
long ss = sizeof(state);
int res;
if ((res = CPCIDevice::SaveState(f)))
return res;
fwrite(&usb_magic1, sizeof(u32), 1, f);
fwrite(&ss, sizeof(long), 1, f);
fwrite(&state, sizeof(state), 1, f);
fwrite(&usb_magic2, sizeof(u32), 1, f);
printf("%s: %d bytes saved.\n", devid_string, (int)ss);
return 0;
}
/**
* Restore state from a Virtual Machine State file.
**/
int CAliM1543C_usb::RestoreState(FILE *f) {
long ss;
u32 m1;
u32 m2;
int res;
size_t r;
if ((res = CPCIDevice::RestoreState(f)))
return res;
r = fread(&m1, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m1 != usb_magic1) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
r = fread(&ss, sizeof(long), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (ss != sizeof(state)) {
printf("%s: STRUCT SIZE does not match!\n", devid_string);
return -1;
}
r = fread(&state, sizeof(state), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
r = fread(&m2, sizeof(u32), 1, f);
if (r != 1) {
printf("%s: unexpected end of file!\n", devid_string);
return -1;
}
if (m2 != usb_magic2) {
printf("%s: MAGIC 1 does not match!\n", devid_string);
return -1;
}
printf("%s: %d bytes restored.\n", devid_string, (int)ss);
return 0;
}
================================================
FILE: src/AliM1543C_usb.hpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source code that might
* serve the general public.
*/
#if !defined(INCLUDED_ALIM1543C_USB_H_)
#define INCLUDED_ALIM1543C_USB_H_
#include "PCIDevice.hpp"
/**
* \brief Emulated USB part of ALi M1543C multi-function device.
*
* \todo This device is just a stub. Not functional yet.
*
* Documentation consulted:
* - Ali M1543C B1 South Bridge Version 1.20
* (http://mds.gotdns.com/sensors/docs/ali/1543dScb1-120.pdf)
* .
**/
class CAliM1543C_usb : public CPCIDevice {
public:
virtual int SaveState(FILE *f);
virtual int RestoreState(FILE *f);
CAliM1543C_usb(CConfigurator *cfg, class CSystem *c, int pcibus, int pcidev);
virtual ~CAliM1543C_usb();
virtual void WriteMem_Bar(int func, int bar, u32 address, int dsize,
u32 data);
virtual u32 ReadMem_Bar(int func, int bar, u32 address, int dsize);
private:
u64 usb_hci_read(u64 address, int dsize);
void usb_hci_write(u64 address, int dsize, u64 data);
/// The state structure contains all elements that need to be saved to the
/// statefile.
struct SUSB_state {
u32 usb_data[0x110 / 4];
} state;
};
#endif // !defined(INCLUDED_ALIM1543C_USB_H)
================================================
FILE: src/AlphaCPU.cpp
================================================
/* AXPbox Alpha Emulator
* Copyright (C) 2020 Tomáš Glozar
* Copyright (C) 2012 Dmitry Kalinkin
* Website: https://github.com/lenticularis39/axpbox
*
* Forked from: ES40 emulator
* Copyright (C) 2007-2008 by the ES40 Emulator Project
* Copyright (C) 2007 by Camiel Vanderhoeven
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Although this is not required, the author would appreciate being notified of,
* and receiving any modifications you may make to the source c
gitextract_fd_kwrgy/
├── .clang-format
├── .github/
│ └── workflows/
│ └── build-test-and-artifact.yml
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake/
│ ├── CheckLargeFiles.cmake
│ ├── FindPCAP.cmake
│ ├── TestFileOffsetBits.c
│ ├── TestLargeFiles.c.cmake.in
│ └── TestWindowsFSeek.c
├── es40.cfg
├── sonar-project.properties
├── src/
│ ├── AliM1543C.cpp
│ ├── AliM1543C.hpp
│ ├── AliM1543C_ide.cpp
│ ├── AliM1543C_ide.hpp
│ ├── AliM1543C_usb.cpp
│ ├── AliM1543C_usb.hpp
│ ├── AlphaCPU.cpp
│ ├── AlphaCPU.hpp
│ ├── AlphaCPU_ieeefloat.cpp
│ ├── AlphaCPU_vaxfloat.cpp
│ ├── AlphaCPU_vmspal.cpp
│ ├── AlphaSim.cpp
│ ├── Cirrus.cpp
│ ├── Cirrus.hpp
│ ├── Configurator.cpp
│ ├── Configurator.hpp
│ ├── DEC21143.cpp
│ ├── DEC21143.hpp
│ ├── DEC21143_mii.hpp
│ ├── DEC21143_tulipreg.hpp
│ ├── DMA.cpp
│ ├── DMA.hpp
│ ├── DPR.cpp
│ ├── DPR.hpp
│ ├── Disk.cpp
│ ├── Disk.hpp
│ ├── DiskController.cpp
│ ├── DiskController.hpp
│ ├── DiskDevice.cpp
│ ├── DiskDevice.hpp
│ ├── DiskFile.cpp
│ ├── DiskFile.hpp
│ ├── DiskRam.cpp
│ ├── DiskRam.hpp
│ ├── Ethernet.cpp
│ ├── Ethernet.hpp
│ ├── Flash.cpp
│ ├── Flash.hpp
│ ├── FloppyController.cpp
│ ├── FloppyController.hpp
│ ├── FreeTextQuestion.hpp
│ ├── Keyboard.cpp
│ ├── Keyboard.hpp
│ ├── Main.cpp
│ ├── MultipleChoiceQuestion.hpp
│ ├── NumberQuestion.hpp
│ ├── PCIDevice.cpp
│ ├── PCIDevice.hpp
│ ├── Port80.cpp
│ ├── Port80.hpp
│ ├── Question.hpp
│ ├── S3Trio64.cpp
│ ├── S3Trio64.hpp
│ ├── SCSIBus.cpp
│ ├── SCSIBus.hpp
│ ├── SCSIDevice.cpp
│ ├── SCSIDevice.hpp
│ ├── Serial.cpp
│ ├── Serial.hpp
│ ├── ShrinkingChoiceQuestion.hpp
│ ├── StdAfx.hpp
│ ├── Sym53C810.cpp
│ ├── Sym53C810.hpp
│ ├── Sym53C895.cpp
│ ├── Sym53C895.hpp
│ ├── System.cpp
│ ├── System.hpp
│ ├── SystemComponent.cpp
│ ├── SystemComponent.hpp
│ ├── TraceEngine.cpp
│ ├── TraceEngine.hpp
│ ├── VGA.cpp
│ ├── VGA.hpp
│ ├── base/
│ │ ├── Bugcheck.cpp
│ │ ├── Bugcheck.hpp
│ │ ├── ErrorHandler.cpp
│ │ ├── ErrorHandler.hpp
│ │ ├── Event.cpp
│ │ ├── Event.hpp
│ │ ├── Event_POSIX.cpp
│ │ ├── Event_POSIX.hpp
│ │ ├── Event_WIN32.cpp
│ │ ├── Event_WIN32.hpp
│ │ ├── Exception.cpp
│ │ ├── Exception.hpp
│ │ ├── Foundation.hpp
│ │ ├── Mutex.cpp
│ │ ├── Mutex.hpp
│ │ ├── Mutex_POSIX.cpp
│ │ ├── Mutex_POSIX.hpp
│ │ ├── Mutex_WIN32.cpp
│ │ ├── Mutex_WIN32.hpp
│ │ ├── NumberFormatter.cpp
│ │ ├── NumberFormatter.hpp
│ │ ├── Platform.hpp
│ │ ├── Platform_POSIX.hpp
│ │ ├── Platform_VMS.hpp
│ │ ├── Platform_WIN32.hpp
│ │ ├── Poco.hpp
│ │ ├── RWLock.cpp
│ │ ├── RWLock.hpp
│ │ ├── RWLock_POSIX.cpp
│ │ ├── RWLock_POSIX.hpp
│ │ ├── RWLock_WIN32.cpp
│ │ ├── RWLock_WIN32.hpp
│ │ ├── RefCountedObject.cpp
│ │ ├── RefCountedObject.hpp
│ │ ├── ScopedLock.hpp
│ │ ├── Semaphore.cpp
│ │ ├── Semaphore.hpp
│ │ ├── Semaphore_POSIX.cpp
│ │ ├── Semaphore_POSIX.hpp
│ │ ├── Semaphore_WIN32.cpp
│ │ ├── Semaphore_WIN32.hpp
│ │ ├── SingletonHolder.hpp
│ │ ├── Timestamp.cpp
│ │ ├── Timestamp.hpp
│ │ ├── Types.hpp
│ │ └── UnWindows.hpp
│ ├── config.hpp.in
│ ├── config_debug.hpp
│ ├── cpu_arith.hpp
│ ├── cpu_bwx.hpp
│ ├── cpu_control.hpp
│ ├── cpu_debug.hpp
│ ├── cpu_defs.hpp
│ ├── cpu_fp_branch.hpp
│ ├── cpu_fp_memory.hpp
│ ├── cpu_fp_operate.hpp
│ ├── cpu_logical.hpp
│ ├── cpu_memory.hpp
│ ├── cpu_misc.hpp
│ ├── cpu_mvi.hpp
│ ├── cpu_pal.hpp
│ ├── cpu_vax.hpp
│ ├── datatypes.hpp
│ ├── es40-cfg.cpp
│ ├── es40_debug.cpp
│ ├── es40_debug.hpp
│ ├── es40_endian.hpp
│ ├── es40_float.hpp
│ ├── gui/
│ │ ├── gui.cpp
│ │ ├── gui.hpp
│ │ ├── gui_win32_font.hpp
│ │ ├── gui_x11.cpp
│ │ ├── keymap.cpp
│ │ ├── keymap.hpp
│ │ ├── plugin.hpp
│ │ ├── scancodes.cpp
│ │ ├── scancodes.hpp
│ │ ├── sdl.cpp
│ │ ├── sdl_fonts.hpp
│ │ ├── sdlkeys.hpp
│ │ └── vga.hpp
│ ├── lockstep.cpp
│ ├── lockstep.hpp
│ ├── make_unique.hpp
│ └── telnet.hpp
└── test/
├── disk/
│ └── unwritable/
│ ├── axp_correct.log
│ ├── es40.cfg
│ └── test.sh
├── rom/
│ ├── axp_correct.log
│ ├── es40.cfg
│ ├── test.ps1
│ └── test.sh
└── run
SYMBOL INDEX (543 symbols across 108 files)
FILE: cmake/TestFileOffsetBits.c
function main (line 7) | int main(int argc, char **argv)
FILE: cmake/TestWindowsFSeek.c
function main (line 3) | int main()
FILE: src/AliM1543C.cpp
type tm (line 289) | struct tm
type tm (line 290) | struct tm
type tm (line 307) | struct tm
function u32 (line 443) | u32 CAliM1543C::ReadMem_Legacy(int index, u32 address, int dsize) {
function u8 (line 544) | u8 CAliM1543C::reg_61_read() {
function u8 (line 575) | u8 CAliM1543C::toy_read(u32 address) {
type tm (line 586) | struct tm
function u8 (line 777) | u8 CAliM1543C::pit_read(u32 address) {
function u8 (line 929) | u8 CAliM1543C::pic_read(int index, u32 address) {
function u8 (line 949) | u8 CAliM1543C::pic_read_edge_level(int index) {
function u8 (line 956) | u8 CAliM1543C::pic_read_vector() {
function u8 (line 1264) | u8 CAliM1543C::lpt_read(u32 address) {
FILE: src/AliM1543C.hpp
class CAliM1543C (line 78) | class CAliM1543C : public CPCIDevice {
class CSystem (line 89) | class CSystem
type tm (line 105) | struct tm
type SAli_state (line 136) | struct SAli_state {
FILE: src/AliM1543C_ide.cpp
class CDisk (line 295) | class CDisk
function u32 (line 383) | u32 CAliM1543C_ide::ReadMem_Legacy(int index, u32 address, int dsize) {
function u32 (line 435) | u32 CAliM1543C_ide::ReadMem_Bar(int func, int bar, u32 address, int dsiz...
function u32 (line 492) | u32 CAliM1543C_ide::ide_command_read(int index, u32 address, int dsize) {
function u32 (line 736) | u32 CAliM1543C_ide::ide_control_read(int index, u32 address) {
function u32 (line 843) | u32 CAliM1543C_ide::ide_busmaster_read(int index, u32 address, int dsize) {
function u8 (line 1001) | u8 CAliM1543C_ide::get_status(int index) {
FILE: src/AliM1543C_ide.hpp
class CAliM1543C_ide (line 66) | class CAliM1543C_ide : public CPCIDevice,
class CSystem (line 70) | class CSystem
class CDisk (line 72) | class CDisk
type SAliM1543C_ideState (line 125) | struct SAliM1543C_ideState {
type SDriveState (line 126) | struct SDriveState {
type SControllerState (line 172) | struct SControllerState {
type SDriveState (line 175) | struct SDriveState
FILE: src/AliM1543C_usb.cpp
function u32 (line 184) | u32 CAliM1543C_usb::ReadMem_Bar(int func, int bar, u32 address, int dsiz...
function u64 (line 210) | u64 CAliM1543C_usb::usb_hci_read(u64 address, int dsize) {
FILE: src/AliM1543C_usb.hpp
class CAliM1543C_usb (line 44) | class CAliM1543C_usb : public CPCIDevice {
class CSystem (line 49) | class CSystem
type SUSB_state (line 61) | struct SUSB_state {
FILE: src/AlphaCPU.cpp
function handle_debug_string (line 180) | void handle_debug_string(char *s) {
function u64 (line 1229) | u64 CAlphaCPU::get_instruction_count() { return state.instruction_count; }
FILE: src/AlphaCPU.hpp
class CAlphaCPU (line 64) | class CAlphaCPU : public CSystemComponent {
method get_waiting (line 93) | bool get_waiting() { return state.wait_for_start; }
method stop_waiting (line 94) | void stop_waiting() { state.wait_for_start = false; }
method u64 (line 99) | u64 get_last_read_loc() { return last_read_loc; }
method u64 (line 100) | u64 get_last_write_loc() { return last_write_loc; }
method u64 (line 107) | u64 get_speed() { return cpu_hz; }
type SCPU_state (line 255) | struct SCPU_state {
type SICache (line 326) | struct SICache {
type STBEntry (line 343) | struct STBEntry {
function u64 (line 541) | inline u64 CAlphaCPU::va_form(u64 address, bool bIBOX) {
function u64 (line 599) | inline u64 CAlphaCPU::get_pc() { return state.pc; }
function u64 (line 606) | inline u64 CAlphaCPU::get_current_pc_physical() { return state.pc_phys; }
function u64 (line 612) | inline u64 CAlphaCPU::get_clean_pc() { return state.pc & ~U64(0x3); }
function u64 (line 644) | inline u64 CAlphaCPU::get_r(int i, bool translate) {
function u64 (line 654) | inline u64 CAlphaCPU::get_f(int i) { return state.f[i]; }
function u64 (line 669) | inline u64 CAlphaCPU::get_pal_base() { return state.pal_base; }
function u64 (line 675) | inline u64 CAlphaCPU::get_prbr(void) {
function u64 (line 694) | inline u64 CAlphaCPU::get_hwpcb(void) {
function u32 (line 714) | inline u32 CAlphaCPU::get_last_instruction(void) { return last_instructi...
FILE: src/AlphaCPU_ieeefloat.cpp
function u64 (line 204) | u64 CAlphaCPU::ieee_lds(u32 op) {
function u32 (line 224) | u32 CAlphaCPU::ieee_sts(u64 op) {
function u64 (line 259) | u64 CAlphaCPU::ieee_cvtst(u64 op, u32 ins) {
function u64 (line 282) | u64 CAlphaCPU::ieee_cvtts(u64 op, u32 ins) {
function s32 (line 322) | s32 CAlphaCPU::ieee_fcmp(u64 s1, u64 s2, u32 ins, u32 trap_nan) {
function u64 (line 359) | u64 CAlphaCPU::ieee_cvtif(u64 val, u32 ins, u32 dp) {
function u64 (line 390) | u64 CAlphaCPU::ieee_cvtfi(u64 op, u32 ins) {
function u64 (line 478) | u64 CAlphaCPU::ieee_fadd(u64 s1, u64 s2, u32 ins, u32 dp, bool sub) {
function u64 (line 567) | u64 CAlphaCPU::ieee_fmul(u64 s1, u64 s2, u32 ins, u32 dp) {
function u64 (line 623) | u64 CAlphaCPU::ieee_fdiv(u64 s1, u64 s2, u32 ins, u32 dp) {
function u64 (line 690) | u64 CAlphaCPU::ieee_sqrt(u64 op, u32 ins, u32 dp) {
function u64 (line 834) | u64 CAlphaCPU::ieee_rpack(UFP *r, u32 ins, u32 dp) {
FILE: src/AlphaCPU_vaxfloat.cpp
function u64 (line 87) | u64 CAlphaCPU::vax_ldf(u32 op) {
function u64 (line 108) | u64 CAlphaCPU::vax_ldg(u64 op) { return SWAP_VAXG(op); /* swizzle bits */ }
function u32 (line 121) | u32 CAlphaCPU::vax_stf(u64 op) {
function u64 (line 148) | u64 CAlphaCPU::vax_stg(u64 op) { return SWAP_VAXG(op); /* swizzle bits */ }
function u64 (line 193) | u64 CAlphaCPU::vax_cvtif(u64 val, u32 ins, u32 dp) {
function u64 (line 222) | u64 CAlphaCPU::vax_cvtfi(u64 op, u32 ins) {
function u64 (line 263) | u64 CAlphaCPU::vax_fadd(u64 s1, u64 s2, u32 ins, u32 dp, bool sub) {
function u64 (line 328) | u64 CAlphaCPU::vax_fmul(u64 s1, u64 s2, u32 ins, u32 dp) {
function u64 (line 358) | u64 CAlphaCPU::vax_fdiv(u64 s1, u64 s2, u32 ins, u32 dp) {
function u64 (line 390) | u64 CAlphaCPU::vax_sqrt(u64 op, u32 ins, u32 dp) {
function u64 (line 538) | u64 CAlphaCPU::vax_rpack(UFP *r, u32 ins, u32 dp) {
function u64 (line 581) | u64 CAlphaCPU::vax_rpack_d(UFP *r, u32 ins) {
FILE: src/AlphaSim.cpp
function segv_handler (line 61) | void segv_handler(int signum) {
function main_sim (line 101) | int main_sim(int argc, char *argv[]) {
FILE: src/Cirrus.cpp
type SCirrus_state (line 258) | struct SCirrus_state
function u32 (line 377) | u32 CCirrus::ReadMem_Legacy(int index, u32 address, int dsize) {
function u32 (line 473) | u32 CCirrus::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
function u32 (line 586) | u32 CCirrus::mem_read(u32 address, int dsize) {
function u32 (line 616) | u32 CCirrus::legacy_read(u32 address, int dsize) {
function u32 (line 660) | u32 CCirrus::rom_read(u32 address, int dsize) {
function u32 (line 690) | u32 CCirrus::io_read(u32 address, int dsize) {
function u8 (line 2485) | u8 CCirrus::read_b_3c0() {
function u8 (line 2502) | u8 CCirrus::read_b_3c1() {
function u8 (line 2572) | u8 CCirrus::read_b_3c2() {
function u8 (line 2581) | u8 CCirrus::read_b_3c3() { return state.vga_enabled; }
function u8 (line 2588) | u8 CCirrus::read_b_3c4() { return state.sequencer.index; }
function u8 (line 2595) | u8 CCirrus::read_b_3c5() {
function u8 (line 2635) | u8 CCirrus::read_b_3c9() {
function u8 (line 2675) | u8 CCirrus::read_b_3ca() { return 0; }
function u8 (line 2683) | u8 CCirrus::read_b_3cc() {
function u8 (line 2699) | u8 CCirrus::read_b_3cf() {
function u8 (line 2762) | u8 CCirrus::read_b_3d4() { return state.CRTC.address; }
function u8 (line 2769) | u8 CCirrus::read_b_3d5() {
function u8 (line 2801) | u8 CCirrus::read_b_3da() {
function u8 (line 2844) | u8 CCirrus::get_actl_palette_idx(u8 index) {
function u8 (line 3328) | u8 CCirrus::vga_mem_read(u32 addr) {
FILE: src/Cirrus.hpp
class CCirrus (line 47) | class CCirrus : public CVGA {
class CSystem (line 59) | class CSystem
type SCirrus_state (line 128) | struct SCirrus_state {
type SCirrus_attr (line 153) | struct SCirrus_attr {
type SCirrus_mode (line 162) | struct SCirrus_mode {
type SCirrus_misc (line 173) | struct SCirrus_misc {
type SCirrus_seq (line 192) | struct SCirrus_seq {
type SCirus_pel (line 205) | struct SCirus_pel {
type SCirrus_peldata (line 211) | struct SCirrus_peldata {
type SCirrus_gfx (line 219) | struct SCirrus_gfx {
type SCirrus_crtc (line 243) | struct SCirrus_crtc {
FILE: src/Configurator.cpp
class CConfigurator (line 73) | class CConfigurator
function u64 (line 466) | u64 CConfigurator::get_num_value(const char *n, bool decimal, u64 def) {
FILE: src/Configurator.hpp
class CConfigurator (line 70) | class CConfigurator {
class CConfigurator (line 72) | class CConfigurator
method get_bool_value (line 82) | bool get_bool_value(const char *n) { return get_bool_value(n, false); }
method u64 (line 85) | u64 get_num_value(const char *n, bool decimal_suffixes) {
method classid (line 90) | classid get_class_id() { return myClassId; }
method get_flags (line 92) | int get_flags() { return myFlags; }
method CConfigurator (line 96) | CConfigurator *get_myParent() { return pParent; }
class CConfigurator (line 101) | class CConfigurator
class CConfigurator (line 102) | class CConfigurator
type SCfg_Value (line 110) | struct SCfg_Value {
FILE: src/DEC21143.cpp
function u32 (line 416) | u32 CDEC21143::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
type pcap_pkthdr (line 448) | struct pcap_pkthdr
function u32 (line 472) | u32 CDEC21143::nic_read(u32 address, int dsize) {
FILE: src/DEC21143.hpp
class CDEC21143 (line 54) | class CDEC21143 : public CPCIDevice {
class CSystem (line 64) | class CSystem
type bpf_program (line 94) | struct bpf_program
type SNIC_state (line 99) | struct SNIC_state {
type SNIC_srom (line 107) | struct SNIC_srom {
type SNIC_mii (line 116) | struct SNIC_mii {
type SNIC_tx (line 128) | struct SNIC_tx {
type SNIC_rx (line 138) | struct SNIC_rx {
FILE: src/DMA.cpp
function u64 (line 79) | u64 CDMA::ReadMem(int index, u64 address, int dsize) {
FILE: src/DMA.hpp
class CDMA (line 38) | class CDMA : public CSystemComponent {
method get_count (line 52) | int get_count(int channel) { return state.channel[channel].count; }
type SDMA_state (line 59) | struct SDMA_state {
type SDMA_chan (line 61) | struct SDMA_chan {
type SDMA_ctrl (line 72) | struct SDMA_ctrl {
FILE: src/DPR.cpp
type tm (line 83) | struct tm
type tm (line 94) | struct tm
function u64 (line 353) | u64 CDPR::ReadMem(int index, u64 address, int dsize) {
FILE: src/DPR.hpp
class CDPR (line 37) | class CDPR : public CSystemComponent {
class CSystem (line 39) | class CSystem
type SDPR_state (line 54) | struct SDPR_state {
FILE: src/Disk.cpp
function u32 (line 550) | static u32 lba2msf(off_t_large lba) {
function off_t_large (line 1529) | static off_t_large get_primes(off_t_large value, int pri[54]) {
FILE: src/Disk.hpp
class CDisk (line 42) | class CDisk : public CSystemComponent, public CSCSIDevice {
method set_atapi_mode (line 55) | void set_atapi_mode() { atapi_mode = true; }
method seek_block (line 65) | bool seek_block(off_t_large lba) {
method read_blocks (line 68) | size_t read_blocks(void *dest, size_t blocks) {
method write_blocks (line 71) | size_t write_blocks(void *src, size_t blocks) {
method get_block_size (line 75) | size_t get_block_size() { return state.block_size; }
method set_block_size (line 76) | void set_block_size(size_t bs) {
method off_t_large (line 83) | off_t_large get_lba_size() { return byte_size / state.block_size; }
method off_t_large (line 84) | off_t_large get_byte_size() { return byte_size; }
method off_t_large (line 85) | off_t_large get_chs_size() { return cylinders * heads * sectors; }
method off_t_large (line 86) | off_t_large get_cylinders() { return cylinders; }
method get_heads (line 87) | long get_heads() { return heads; }
method get_sectors (line 88) | long get_sectors() { return sectors; }
method ro (line 94) | bool ro() { return read_only; }
method rw (line 95) | bool rw() { return !read_only; }
method cdrom (line 96) | bool cdrom() { return is_cdrom; }
type SDisk_state (line 122) | struct SDisk_state {
type SDisk_scsi (line 128) | struct SDisk_scsi {
type SDisk_msgi (line 131) | struct SDisk_msgi {
type SDisk_msgo (line 138) | struct SDisk_msgo {
type SDisk_cmd (line 147) | struct SDisk_cmd {
type SDisk_dati (line 153) | struct SDisk_dati {
type SDisk_dato (line 160) | struct SDisk_dato {
type SDisk_stat (line 168) | struct SDisk_stat {
type SDisk_sense (line 175) | struct SDisk_sense {
FILE: src/DiskController.cpp
class CDisk (line 42) | class CDisk
class CDisk (line 51) | class CDisk
FILE: src/DiskController.hpp
class CDiskController (line 35) | class CDiskController {
class CDisk (line 40) | class CDisk
class CDisk (line 41) | class CDisk
class CDisk (line 47) | class CDisk
FILE: src/DiskDevice.hpp
class CDiskDevice (line 37) | class CDiskDevice : public CDisk {
FILE: src/DiskFile.hpp
class CDiskFile (line 38) | class CDiskFile : public CDisk {
method FILE (line 48) | FILE *get_handle() { return handle; }
FILE: src/DiskRam.hpp
class CDiskRam (line 37) | class CDiskRam : public CDisk {
FILE: src/Ethernet.cpp
function u32 (line 105) | static u32 eth_crc32(u32 crc, const void *vbuf, int len) {
FILE: src/Ethernet.hpp
type eth_frame (line 40) | struct eth_frame { // ethernet (wire) frame
type eth_packet (line 48) | struct eth_packet { // ethernet packet
class CPacketQueue (line 57) | class CPacketQueue { // Ethernet Packet Queue
method count (line 70) | inline int count() { return cnt; }
method lost (line 73) | inline int lost() { return dropped; }
FILE: src/Flash.cpp
function u64 (line 74) | u64 CFlash::ReadMem(int index, u64 address, int dsize) {
FILE: src/Flash.hpp
class CFlash (line 40) | class CFlash : public CSystemComponent {
class CSystem (line 44) | class CSystem
type SFlash_state (line 56) | struct SFlash_state {
FILE: src/FloppyController.cpp
type cmdinfo_t (line 61) | struct cmdinfo_t {
function u64 (line 294) | u64 CFloppyController::ReadMem(int index, u64 address, int dsize) {
function u8 (line 427) | u8 CFloppyController::get_status() {
FILE: src/FloppyController.hpp
class CFloppyController (line 39) | class CFloppyController : public CSystemComponent, public CDiskController {
class CConfigurator (line 43) | class CConfigurator
class CSystem (line 43) | class CSystem
FILE: src/FreeTextQuestion.hpp
class FreeTextQuestion (line 34) | class FreeTextQuestion : public Question {
method setOptions (line 40) | void setOptions(string options) { mOptions = options; }
method string (line 45) | virtual string ask() {
FILE: src/Keyboard.cpp
function u64 (line 134) | u64 CKeyboard::ReadMem(int index, u64 address, int dsize) {
function u8 (line 365) | u8 CKeyboard::read_60() {
function u8 (line 493) | u8 CKeyboard::read_64() {
FILE: src/Keyboard.hpp
class CKeyboard (line 46) | class CKeyboard : public CSystemComponent {
type SKb_state (line 91) | struct SKb_state {
type SAli_kbdc_status (line 94) | struct SAli_kbdc_status {
type SAli_mouse (line 126) | struct SAli_mouse {
method u8 (line 137) | u8 get_status_byte() {
method u8 (line 148) | u8 get_resolution_byte() {
type SAli_kbdib (line 179) | struct SAli_kbdib {
type SAli_mib (line 193) | struct SAli_mib {
FILE: src/Main.cpp
function main (line 33) | int main(int argc, char **argv) {
FILE: src/MultipleChoiceQuestion.hpp
class Answer (line 33) | class Answer {
method Answer (line 41) | Answer(string answer, string value, string explanation) {
method string (line 54) | string getAnswer() { return mAnswer; }
method string (line 59) | string getValue() { return mValue; }
method string (line 64) | string getExplanation() { return mExplanation; }
class MultipleChoiceQuestion (line 86) | class MultipleChoiceQuestion : public FreeTextQuestion {
method addAnswer (line 91) | void addAnswer(string answer, string value, string explanation) {
method explain (line 98) | virtual void explain() {
method countAnswers (line 124) | size_t countAnswers() { return mAnswerSet.size(); }
method string (line 129) | virtual string ask() {
method dropChoice (line 186) | void dropChoice(string choice) {
method haveChosen (line 206) | virtual void haveChosen(string choice) {}
method string (line 211) | string getFirstChoice() { return mAnswerSet.begin()->getAnswer(); }
FILE: src/NumberQuestion.hpp
function string (line 32) | inline string i2s(int x) {
function s2i (line 43) | inline int s2i(const string x) {
class NumberQuestion (line 57) | class NumberQuestion : public FreeTextQuestion {
method setRange (line 62) | void setRange(int low, int high) {
method getNum (line 70) | int getNum() { return s2i(mAnswer); }
method string (line 75) | virtual string ask() {
FILE: src/PCIDevice.cpp
function pci_dma_chunk_limit (line 33) | static size_t pci_dma_chunk_limit(u64 phys_addr, size_t remaining) {
function u32 (line 89) | u32 CPCIDevice::config_read(int func, u32 address, int dsize) {
function u64 (line 250) | u64 CPCIDevice::ReadMem(int index, u64 address, int dsize) {
function u32 (line 456) | u32 CPCIDevice::ReadMem_Legacy(int index, u32 address, int dsize) {
function u32 (line 466) | u32 CPCIDevice::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
FILE: src/PCIDevice.hpp
class CPCIDevice (line 41) | class CPCIDevice : public CSystemComponent {
class CConfigurator (line 43) | class CConfigurator
class CSystem (line 43) | class CSystem
method u32 (line 62) | virtual u32 config_read_custom(int func, u32 address, int dsize, u32 d...
type SPCI_state (line 92) | struct SPCI_state {
FILE: src/Port80.cpp
function u64 (line 50) | u64 CPort80::ReadMem(int index, u64 address, int dsize) { return state.p...
FILE: src/Port80.hpp
class CPort80 (line 42) | class CPort80 : public CSystemComponent {
class CSystem (line 44) | class CSystem
type SPort80_state (line 54) | struct SPort80_state {
FILE: src/Question.hpp
class Question (line 35) | class Question {
method string (line 40) | string getAnswer() { return mAnswer; }
method setAnswer (line 45) | void setAnswer(string answer) { mAnswer = answer; }
method setExplanation (line 51) | void setExplanation(string explanation) { mExplanation = explanation; }
method setQuestion (line 56) | void setQuestion(string question) { mQuestion = question; }
method setDefault (line 62) | void setDefault(string defval) { mDefault = defval; }
method explain (line 72) | virtual void explain() {
FILE: src/S3Trio64.cpp
function u32 (line 375) | u32 CS3Trio64::ReadMem_Legacy(int index, u32 address, int dsize) {
function u32 (line 471) | u32 CS3Trio64::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
function u32 (line 584) | u32 CS3Trio64::mem_read(u32 address, int dsize) {
function u32 (line 612) | u32 CS3Trio64::legacy_read(u32 address, int dsize) {
function u32 (line 656) | u32 CS3Trio64::rom_read(u32 address, int dsize) {
function u32 (line 686) | u32 CS3Trio64::io_read(u32 address, int dsize) {
function u8 (line 2480) | u8 CS3Trio64::read_b_3c0() {
function u8 (line 2497) | u8 CS3Trio64::read_b_3c1() {
function u8 (line 2567) | u8 CS3Trio64::read_b_3c2() {
function u8 (line 2576) | u8 CS3Trio64::read_b_3c3() { return state.vga_enabled; }
function u8 (line 2583) | u8 CS3Trio64::read_b_3c4() { return state.sequencer.index; }
function u8 (line 2590) | u8 CS3Trio64::read_b_3c5() {
function u8 (line 2630) | u8 CS3Trio64::read_b_3c9() {
function u8 (line 2671) | u8 CS3Trio64::read_b_3ca() { return 0; }
function u8 (line 2679) | u8 CS3Trio64::read_b_3cc() {
function u8 (line 2695) | u8 CS3Trio64::read_b_3cf() {
function u8 (line 2758) | u8 CS3Trio64::read_b_3d4() { return state.CRTC.address; }
function u8 (line 2765) | u8 CS3Trio64::read_b_3d5() {
function u8 (line 2797) | u8 CS3Trio64::read_b_3da() {
function u8 (line 2840) | u8 CS3Trio64::get_actl_palette_idx(u8 index) {
function u8 (line 3324) | u8 CS3Trio64::vga_mem_read(u32 addr) {
FILE: src/S3Trio64.hpp
class CS3Trio64 (line 47) | class CS3Trio64 : public CVGA {
class CSystem (line 59) | class CSystem
type SS3_state (line 128) | struct SS3_state {
type SS3_attr (line 147) | struct SS3_attr {
type SS3_mode (line 156) | struct SS3_mode {
type SS3_misc (line 167) | struct SS3_misc {
type SS3_seq (line 186) | struct SS3_seq {
type SS3_pel (line 199) | struct SS3_pel {
type SS3_pel_data (line 205) | struct SS3_pel_data {
type SS3_gfx (line 213) | struct SS3_gfx {
type SS3_crtc (line 237) | struct SS3_crtc {
FILE: src/SCSIBus.hpp
class CSCSIBus (line 42) | class CSCSIBus : public CSystemComponent {
method get_phase (line 55) | int get_phase() { return state.phase; }
type SSCSI_state (line 68) | struct SSCSI_state {
FILE: src/SCSIDevice.cpp
class CSCSIBus (line 53) | class CSCSIBus
FILE: src/SCSIDevice.hpp
class CSCSIDevice (line 40) | class CSCSIDevice {
class CSCSIBus (line 45) | class CSCSIBus
class CSCSIBus (line 64) | class CSCSIBus
FILE: src/Serial.cpp
type sockaddr_in (line 70) | struct sockaddr_in
type sockaddr (line 84) | struct sockaddr
type sockaddr_in (line 92) | struct sockaddr_in
type sockaddr (line 105) | struct sockaddr
type sockaddr (line 106) | struct sockaddr
function u64 (line 150) | u64 CSerial::ReadMem(int index, u64 address, int dsize) {
type timeval (line 342) | struct timeval
type timeval (line 423) | struct timeval
type sockaddr_in (line 567) | struct sockaddr_in
type sockaddr_in (line 568) | struct sockaddr_in
type sockaddr (line 636) | struct sockaddr
FILE: src/Serial.hpp
class CSerial (line 40) | class CSerial : public CSystemComponent {
type SSrl_state (line 70) | struct SSrl_state {
FILE: src/ShrinkingChoiceQuestion.hpp
class ShrinkingChoiceQuestion (line 36) | class ShrinkingChoiceQuestion : public MultipleChoiceQuestion {
method haveChosen (line 41) | virtual void haveChosen(string choice) { dropChoice(choice); }
FILE: src/StdAfx.hpp
function gmtime_s (line 132) | inline void gmtime_s(struct tm *t1, time_t *t2) {
type tm (line 141) | struct tm
type tm (line 141) | struct tm
type tm (line 143) | struct tm
type tm (line 143) | struct tm
type tm (line 146) | struct tm
type tm (line 148) | struct tm
type tm (line 148) | struct tm
function isblank (line 153) | inline bool isblank(char c) {
function printable (line 160) | inline char printable(char c) {
FILE: src/Sym53C810.cpp
type SSym_state (line 579) | struct SSym_state
class CDisk (line 663) | class CDisk
function u32 (line 950) | u32 CSym53C810::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
function u32 (line 1111) | u32 CSym53C810::config_read_custom(int func, u32 address, int dsize, u32...
function u8 (line 1258) | u8 CSym53C810::read_b_ctest2() {
function u8 (line 1345) | u8 CSym53C810::read_b_dstat() {
function u8 (line 1364) | u8 CSym53C810::read_b_sist(int id) {
FILE: src/Sym53C810.hpp
class CSym53C810 (line 51) | class CSym53C810 : public CPCIDevice,
class CDisk (line 72) | class CDisk
class CSystem (line 74) | class CSystem
type SSym_state (line 114) | struct SSym_state {
type SSym_alu (line 123) | struct SSym_alu {
FILE: src/Sym53C895.cpp
class CDisk (line 697) | class CDisk
function u32 (line 989) | u32 CSym53C895::ReadMem_Bar(int func, int bar, u32 address, int dsize) {
function u32 (line 1154) | u32 CSym53C895::config_read_custom(int func, u32 address, int dsize, u32...
function u8 (line 1309) | u8 CSym53C895::read_b_ctest2() {
function u8 (line 1396) | u8 CSym53C895::read_b_dstat() {
function u8 (line 1415) | u8 CSym53C895::read_b_sist(int id) {
function u8 (line 1460) | u8 CSym53C895::read_b_scratcha(int reg) {
function u8 (line 1476) | u8 CSym53C895::read_b_scratchb(int reg) {
FILE: src/Sym53C895.hpp
class CSym53C895 (line 52) | class CSym53C895 : public CPCIDevice,
class CDisk (line 73) | class CDisk
class CSystem (line 75) | class CSystem
type SSym_state (line 118) | struct SSym_state {
type SSym_alu (line 127) | struct SSym_alu {
FILE: src/System.cpp
type SSys_state::SSys_pchip (line 80) | struct SSys_state::SSys_pchip
class CAlphaCPU (line 166) | class CAlphaCPU
type SMemoryUser (line 179) | struct SMemoryUser
type SMemoryUser (line 223) | struct SMemoryUser
type SMemoryUser (line 223) | struct SMemoryUser
function sigint_handler (line 239) | void sigint_handler(int signum) { got_sigint = 1; }
function u64 (line 708) | u64 CSystem::ReadMem(u64 address, int dsize, CSystemComponent *source) {
function u64 (line 1227) | u64 CSystem::pchip_csr_read(int num, u32 a) {
function u64 (line 1331) | u64 CSystem::cchip_csr_read(u32 a, CSystemComponent *source) {
function u8 (line 1456) | u8 CSystem::dchip_csr_read(u32 a) {
function u8 (line 1520) | u8 CSystem::tig_read(u32 a) {
function u64 (line 1887) | u64 CSystem::PCI_Phys(int pcibus, u32 address) {
function u64 (line 1979) | u64 CSystem::PCI_Phys_direct_mapped(u32 address, u64 wsm, u64 tba) {
function u64 (line 2060) | u64 CSystem::PCI_Phys_scatter_gather(u32 address, u64 wsm, u64 tba) {
FILE: src/System.hpp
type SMemoryUser (line 67) | struct SMemoryUser {
type SConfig (line 76) | struct SConfig {
class CSystem (line 104) | class CSystem {
class CAlphaCPU (line 129) | class CAlphaCPU
method CAlphaCPU (line 134) | CAlphaCPU *get_cpu(int cpunum) { return acCPUs[cpunum]; }
method get_cpu_num (line 135) | int get_cpu_num() { return iNumCPUs; }
type SSys_state (line 171) | struct SSys_state {
type SSys_tig (line 184) | struct SSys_tig {
type SSys_cchip (line 202) | struct SSys_cchip {
type SSys_dchip (line 328) | struct SSys_dchip {
type SSys_pchip (line 352) | struct SSys_pchip {
type SMemoryUser (line 370) | struct SMemoryUser
class CAlphaCPU (line 372) | class CAlphaCPU
function u64 (line 383) | inline u64 CSystem::get_c_misc() { return state.cchip.misc; }
function u64 (line 385) | inline u64 CSystem::get_c_dir(int ProcNum) {
function u64 (line 389) | inline u64 CSystem::get_c_dim(int ProcNum) { return state.cchip.dim[Proc...
FILE: src/SystemComponent.hpp
class CSystemComponent (line 37) | class CSystemComponent {
class CConfigurator (line 42) | class CConfigurator
class CSystem (line 42) | class CSystem
method u64 (line 46) | virtual u64 ReadMem(int index, u64 address, int dsize) { return 0; }
class CSystem (line 57) | class CSystem
class CConfigurator (line 58) | class CConfigurator
FILE: src/TraceEngine.cpp
function write_printable_s (line 50) | inline void write_printable_s(char *dest, const char *org) {
function u64 (line 64) | inline u64 real_address(u64 address, CAlphaCPU *c, bool bIBOX) {
function FILE (line 610) | FILE *CTraceEngine::trace_file() { return current_trace_file; }
type sRegion (line 1454) | struct sRegion {
type sRegion (line 1457) | struct sRegion
type sRegion (line 1465) | struct sRegion
type sRegion (line 1457) | struct sRegion
type sRegion (line 1466) | struct sRegion
type sRegion (line 1457) | struct sRegion
type sRegion (line 1467) | struct sRegion
type sRegion (line 1457) | struct sRegion
FILE: src/TraceEngine.hpp
type STraceFunction (line 36) | struct STraceFunction {
type STracePRBR (line 44) | struct STracePRBR {
type STraceCPU (line 57) | struct STraceCPU {
class CTraceEngine (line 64) | class CTraceEngine {
class CSystem (line 67) | class CSystem
class CAlphaCPU (line 69) | class CAlphaCPU
class CAlphaCPU (line 71) | class CAlphaCPU
class CAlphaCPU (line 74) | class CAlphaCPU
class CAlphaCPU (line 75) | class CAlphaCPU
class CSystem (line 83) | class CSystem
type STraceFunction (line 87) | struct STraceFunction
type STraceCPU (line 88) | struct STraceCPU
type STracePRBR (line 89) | struct STracePRBR
FILE: src/VGA.cpp
class CConfigurator (line 37) | class CConfigurator
class CSystem (line 37) | class CSystem
FILE: src/VGA.hpp
class CVGA (line 37) | class CVGA : public CPCIDevice {
class CConfigurator (line 39) | class CConfigurator
class CSystem (line 39) | class CSystem
FILE: src/base/Bugcheck.hpp
class CBugcheck (line 75) | class CBugcheck
FILE: src/base/ErrorHandler.cpp
function CErrorHandler (line 111) | CErrorHandler *CErrorHandler::set(CErrorHandler *pHandler) {
function CErrorHandler (line 120) | CErrorHandler *CErrorHandler::defaultHandler() {
FILE: src/base/ErrorHandler.hpp
class CErrorHandler (line 76) | class CErrorHandler
function CErrorHandler (line 157) | inline CErrorHandler *CErrorHandler::get() { return _pHandler; }
FILE: src/base/Event.hpp
class CEvent (line 81) | class CEvent : private CEventImpl
FILE: src/base/Event_POSIX.cpp
type timespec (line 98) | struct timespec
type timespec (line 101) | struct timespec
type timeval (line 106) | struct timeval
FILE: src/base/Event_POSIX.hpp
class CEventImpl (line 77) | class CEventImpl {
FILE: src/base/Event_WIN32.hpp
class CEventImpl (line 76) | class CEventImpl {
FILE: src/base/Exception.cpp
function CException (line 94) | CException &CException::operator=(const CException &exc) {
function CException (line 121) | CException *CException::clone() const { return new CException(*this); }
FILE: src/base/Exception.hpp
class CException (line 75) | class CException : public std::exception
function CException (line 150) | inline const CException *CException::nested() const { return _pNested; }
FILE: src/base/Mutex.hpp
class CMutex (line 94) | class CMutex : private CMutexImpl
class CFastMutex (line 155) | class CFastMutex : private CFastMutexImpl
FILE: src/base/Mutex_POSIX.cpp
type timespec (line 117) | struct timespec
type timeval (line 118) | struct timeval
type timeval (line 143) | struct timeval
FILE: src/base/Mutex_POSIX.hpp
class CMutexImpl (line 77) | class CMutexImpl {
class CFastMutexImpl (line 91) | class CFastMutexImpl : public CMutexImpl {
FILE: src/base/Mutex_WIN32.hpp
class CMutexImpl (line 76) | class CMutexImpl {
FILE: src/base/NumberFormatter.hpp
class CNumberFormatter (line 74) | class CNumberFormatter
FILE: src/base/RWLock.hpp
class CScopedRWLock (line 86) | class CScopedRWLock
class CRWLock (line 88) | class CRWLock : private CRWLockImpl
class CScopedRWLock (line 137) | class CScopedRWLock
FILE: src/base/RWLock_POSIX.hpp
class CRWLockImpl (line 77) | class CRWLockImpl {
FILE: src/base/RWLock_WIN32.hpp
class CRWLockImpl (line 76) | class CRWLockImpl {
FILE: src/base/RefCountedObject.hpp
class CRefCountedObject (line 75) | class CRefCountedObject
FILE: src/base/ScopedLock.hpp
class CScopedLock (line 81) | class CScopedLock {
method CScopedLock (line 83) | inline CScopedLock(M *mutex) : _mutex(mutex) {
FILE: src/base/Semaphore.hpp
class CSemaphore (line 81) | class CSemaphore : private CSemaphoreImpl
FILE: src/base/Semaphore_POSIX.cpp
type timespec (line 132) | struct timespec
type timeval (line 151) | struct timeval
FILE: src/base/Semaphore_POSIX.hpp
class CSemaphoreImpl (line 77) | class CSemaphoreImpl {
FILE: src/base/Semaphore_WIN32.hpp
class CSemaphoreImpl (line 76) | class CSemaphoreImpl {
FILE: src/base/SingletonHolder.hpp
class CSingletonHolder (line 76) | class CSingletonHolder
method CSingletonHolder (line 84) | CSingletonHolder()
method S (line 95) | S *get()
FILE: src/base/Timestamp.cpp
function CTimestamp (line 87) | CTimestamp &CTimestamp::operator=(const CTimestamp &other) {
function CTimestamp (line 92) | CTimestamp &CTimestamp::operator=(TimeVal tv) {
function CTimestamp (line 99) | CTimestamp CTimestamp::fromEpochTime(std::time_t t) {
function CTimestamp (line 103) | CTimestamp CTimestamp::fromUtcTime(UtcTimeVal val) {
type timeval (line 127) | struct timeval
function CTimestamp (line 137) | CTimestamp CTimestamp::fromFileTimeNP(UInt32 fileTimeLow, UInt32 fileTim...
FILE: src/base/Timestamp.hpp
class CTimestamp (line 71) | class CTimestamp
function CTimestamp (line 189) | inline CTimestamp CTimestamp::operator+(CTimestamp::TimeDiff d) const {
function CTimestamp (line 193) | inline CTimestamp CTimestamp::operator-(CTimestamp::TimeDiff d) const {
function CTimestamp (line 201) | inline CTimestamp &CTimestamp::operator+=(CTimestamp::TimeDiff d) {
function CTimestamp (line 206) | inline CTimestamp &CTimestamp::operator-=(CTimestamp::TimeDiff d) {
function swap (line 234) | inline void swap(CTimestamp &s1, CTimestamp &s2) { s1.swap(s2); }
FILE: src/cpu_defs.hpp
type ufp (line 198) | struct ufp {
type ufp (line 204) | struct ufp
function u64 (line 256) | inline u64 uemul64(u64 a, u64 b, u64 *hi) {
function u64 (line 296) | inline u64 ufdiv64(u64 dvd, u64 dvr, u32 prec, u32 *sticky) {
function u64 (line 318) | inline u64 fsqrt64(u64 asig, s32 exp) {
FILE: src/datatypes.hpp
function u64 (line 77) | inline u64 sext_u64_8(u64 a) {
function u64 (line 93) | inline u64 sext_u64_12(u64 a) {
function u64 (line 101) | inline u64 sext_u64_13(u64 a) {
function u64 (line 109) | inline u64 sext_u64_16(u64 a) {
function u64 (line 125) | inline u64 sext_u64_21(u64 a) {
function u64 (line 133) | inline u64 sext_u64_32(u64 a) {
function u64 (line 149) | inline u64 sext_u64_48(u64 a) {
function test_bit_64 (line 154) | inline bool test_bit_64(u64 x, int bit) {
function u32 (line 161) | inline u32 sext_u32_24(u32 a) {
FILE: src/es40-cfg.cpp
function add_disks (line 62) | void add_disks(ShrinkingChoiceQuestion *disk_q, ostream *os) {
function main_cfg (line 243) | int main_cfg(int argc, char *argv[]) {
FILE: src/es40_debug.cpp
function va_debug (line 56) | static void va_debug(va_list argp, char *fmt) {
function debug_indentation (line 87) | void debug_indentation(int diff) {
function debug (line 98) | void debug(char *fmt, ...) {
function fatal (line 115) | void fatal(char *fmt, ...) {
FILE: src/es40_endian.hpp
function u64 (line 78) | inline u64 endian_bits(u64 x, int numbits) {
FILE: src/es40_float.hpp
function f2host (line 39) | inline double f2host(u64 val) {
function d2host (line 65) | inline double d2host(u64 val) {
function s2host (line 89) | inline double s2host(u64 val) {
function i_isnan (line 136) | inline bool i_isnan(u64 val) {
function u64 (line 147) | inline u64 host2f(double val) {
function u64 (line 191) | inline u64 host2g(double val) {
function u64 (line 235) | inline u64 host2d(double val) {
function u32 (line 278) | inline u32 map_s(u32 val) {
function u64 (line 293) | inline u64 host2s(double val) {
function u64 (line 359) | inline u64 host2t(double val) {
function u32 (line 419) | inline u32 store_f(u64 val) {
function u64 (line 437) | inline u64 store_g(u64 val) {
function u64 (line 453) | inline u64 load_f(u32 val) {
function u64 (line 473) | inline u64 itof_f(u64 val) {
function u64 (line 491) | inline u64 load_g(u64 val) {
function u64 (line 507) | inline u64 load_s(u32 val) {
function u32 (line 517) | inline u32 store_s(u64 val) {
FILE: src/gui/gui.cpp
function u32 (line 100) | u32 get_user_key(char *key) {
function bx_svga_tileinfo_t (line 157) | bx_svga_tileinfo_t *bx_gui_c::graphics_tile_info(bx_svga_tileinfo_t *inf...
function u8 (line 208) | u8 *bx_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned *w,
FILE: src/gui/gui.hpp
class bx_gui_c (line 68) | class bx_gui_c
method u32 (line 97) | virtual u32 get_sighandler_mask() { return 0; }
method sighandler (line 98) | virtual void sighandler(int sig) {}
class bx_gui_c (line 73) | class bx_gui_c {
method u32 (line 97) | virtual u32 get_sighandler_mask() { return 0; }
method sighandler (line 98) | virtual void sighandler(int sig) {}
FILE: src/gui/gui_x11.cpp
class bx_x11_gui_c (line 56) | class bx_x11_gui_c : public bx_gui_c {
method bx_x11_gui_c (line 58) | bx_x11_gui_c(CConfigurator *cfg) {
function test_alloc_colors (line 222) | static bool test_alloc_colors(Colormap cmap, u32 n_tries) {
function create_internal_vga_font (line 539) | void create_internal_vga_font(void) {
function send_keyboard_mouse_status (line 737) | void send_keyboard_mouse_status(void) {
function xkeypress (line 775) | void xkeypress(KeySym keysym, int press_release) {
function bx_svga_tileinfo_t (line 1436) | bx_svga_tileinfo_t *bx_x11_gui_c::graphics_tile_info(bx_svga_tileinfo_t ...
function u8 (line 1516) | u8 *bx_x11_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned *w,
function warp_cursor (line 1612) | static void warp_cursor(int dx, int dy) {
function disable_cursor (line 1620) | static void disable_cursor() {
function enable_cursor (line 1660) | static void enable_cursor() { XUndefineCursor(bx_x_display, win); }
function u32 (line 1668) | static u32 convertStringToXKeysym(const char *string) {
FILE: src/gui/keymap.cpp
function init_parse (line 198) | static void init_parse() { lineCount = 0; }
function init_parse_line (line 200) | static void init_parse_line(char *line_to_parse) {
function s32 (line 211) | static s32 get_next_word(char *output) {
function s32 (line 233) | static s32 get_next_keymap_line(FILE *fp, char *bxsym, char *modsym, s32...
function u32 (line 366) | u32 bx_keymap_c::convertStringToBXKey(const char *string) {
function BXKeyEntry (line 383) | BXKeyEntry *bx_keymap_c::findHostKey(u32 key) {
function BXKeyEntry (line 403) | BXKeyEntry *bx_keymap_c::findAsciiChar(u8 ch) {
FILE: src/gui/keymap.hpp
class bx_keymap_c (line 50) | class bx_keymap_c {
FILE: src/gui/sdl.cpp
class bx_sdl_gui_c (line 60) | class bx_sdl_gui_c : public bx_gui_c {
function bx_sdl_morphos_exit (line 119) | void bx_sdl_morphos_exit(void) {
function bx_svga_tileinfo_t (line 429) | bx_svga_tileinfo_t *bx_sdl_gui_c::graphics_tile_info(bx_svga_tileinfo_t ...
function u8 (line 456) | u8 *bx_sdl_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned *w,
function u32 (line 474) | static u32 sdl_sym_to_bx_key(SDLKey sym) {
function u32 (line 1168) | static u32 convertStringToSDLKey(const char *string) {
FILE: src/lockstep.cpp
function lockstep_init (line 41) | void lockstep_init() {
function lockstep_sync_m2s (line 96) | void lockstep_sync_m2s(char *s) {
function lockstep_sync_s2m (line 121) | void lockstep_sync_s2m(char *s) {
function lockstep_compare (line 148) | void lockstep_compare(char *s) {
function lockstep_send (line 197) | void lockstep_send(char *s) {
function lockstep_receive (line 218) | void lockstep_receive(char *s, int sz) {
FILE: src/make_unique.hpp
type std (line 32) | namespace std
function make_unique (line 35) | std::unique_ptr<T> make_unique( Args&& ...args )
FILE: src/telnet.hpp
function inet_aton (line 135) | inline int inet_aton(const char *name, struct in_addr *addr) {
Condensed preview — 180 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,232K chars).
[
{
"path": ".clang-format",
"chars": 3666,
"preview": "---\nLanguage: Cpp\n# BasedOnStyle: LLVM\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignConsecutiveMac"
},
{
"path": ".github/workflows/build-test-and-artifact.yml",
"chars": 7015,
"preview": "name: Build, run test and upload binaries \n\non: [push, pull_request]\n\njobs:\n\n linux-x86-clang:\n runs-on: \"ubuntu-24."
},
{
"path": ".gitignore",
"chars": 90,
"preview": "cmake-build-debug/\ncmake-build-release/\nbuild**/\n.idea/\n.vs/\nCMakeSettings.json\nrun/\nimg/\n"
},
{
"path": ".travis.yml",
"chars": 331,
"preview": "language: cpp\ndist: focal\ncompiler: clang\n\nbefore_install: sudo apt-get install cmake libpcap-dev libsdl-dev netcat-open"
},
{
"path": "CMakeLists.txt",
"chars": 8347,
"preview": "cmake_minimum_required(VERSION 3.10)\nset(CMAKE_CXX_STANDARD 11)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nproject(AXPBox VERSI"
},
{
"path": "LICENSE",
"chars": 18092,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "README.md",
"chars": 3388,
"preview": "# AXPbox Alpha emulator\n\nAXPbox is a fork of the discontinued es40 emulator. It could theoretically used for running any"
},
{
"path": "cmake/CheckLargeFiles.cmake",
"chars": 5362,
"preview": "# Via: https://github.com/uclouvain/openjpeg/blob/master/cmake/TestLargeFiles.cmake\n# - Define macro to check large file"
},
{
"path": "cmake/FindPCAP.cmake",
"chars": 5141,
"preview": "# ~~~\n# - Try to find libpcap include dirs and libraries\n#\n# Usage of this module as follows:\n#\n# find_package(PCAP)"
},
{
"path": "cmake/TestFileOffsetBits.c",
"chars": 303,
"preview": "#include <sys/types.h>\n\n/* Cause a compile-time error if off_t is smaller than 64 bits */\n#define LARGE_OFF_T (((off_t) "
},
{
"path": "cmake/TestLargeFiles.c.cmake.in",
"chars": 615,
"preview": "#cmakedefine _LARGEFILE_SOURCE\n#cmakedefine _LARGE_FILES\n#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@\n\n#include <s"
},
{
"path": "cmake/TestWindowsFSeek.c",
"chars": 99,
"preview": "#include <stdio.h>\n\nint main()\n{\n __int64 off=0;\n\n _fseeki64(NULL, off, SEEK_SET);\n\n return 0;\n}"
},
{
"path": "es40.cfg",
"chars": 10738,
"preview": "/**\n * AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n"
},
{
"path": "sonar-project.properties",
"chars": 474,
"preview": "sonar.projectKey=rve_axpbox\r\nsonar.organization=rve\r\n\r\n# This is the name and version displayed in the SonarCloud UI.\r\ns"
},
{
"path": "src/AliM1543C.cpp",
"chars": 34599,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2020 Martin Vorländer\n * Copyright (C) 2012"
},
{
"path": "src/AliM1543C.hpp",
"chars": 4594,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AliM1543C_ide.cpp",
"chars": 72827,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AliM1543C_ide.hpp",
"chars": 9561,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AliM1543C_usb.cpp",
"chars": 8675,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AliM1543C_usb.hpp",
"chars": 2278,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AlphaCPU.cpp",
"chars": 54792,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2012 Dmitry Kalinkin\n * Website: https://gi"
},
{
"path": "src/AlphaCPU.hpp",
"chars": 24058,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AlphaCPU_ieeefloat.cpp",
"chars": 33679,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AlphaCPU_vaxfloat.cpp",
"chars": 20023,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AlphaCPU_vmspal.cpp",
"chars": 33635,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/AlphaSim.cpp",
"chars": 5864,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Cirrus.cpp",
"chars": 139508,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Cirrus.hpp",
"chars": 7053,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Configurator.cpp",
"chars": 23040,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Configurator.hpp",
"chars": 2970,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DEC21143.cpp",
"chars": 46489,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2021 Dietmar M. Zettl\n * Website: https://g"
},
{
"path": "src/DEC21143.hpp",
"chars": 4260,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DEC21143_mii.hpp",
"chars": 9254,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DEC21143_tulipreg.hpp",
"chars": 31291,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DMA.cpp",
"chars": 12931,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DMA.hpp",
"chars": 2775,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DPR.cpp",
"chars": 19841,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DPR.hpp",
"chars": 1985,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Disk.cpp",
"chars": 50409,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Disk.hpp",
"chars": 6447,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskController.cpp",
"chars": 1968,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskController.hpp",
"chars": 1633,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskDevice.cpp",
"chars": 8137,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskDevice.hpp",
"chars": 1829,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskFile.cpp",
"chars": 5581,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2020 Remy van Elst\n * Website: https://gith"
},
{
"path": "src/DiskFile.hpp",
"chars": 1952,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2020 Remy van Elst\n * Website: https://gith"
},
{
"path": "src/DiskRam.cpp",
"chars": 2781,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/DiskRam.hpp",
"chars": 1678,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Ethernet.cpp",
"chars": 7048,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Ethernet.hpp",
"chars": 2985,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Flash.cpp",
"chars": 8532,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Flash.hpp",
"chars": 2100,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/FloppyController.cpp",
"chars": 13705,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/FloppyController.hpp",
"chars": 3806,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/FreeTextQuestion.hpp",
"chars": 2545,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Keyboard.cpp",
"chars": 51008,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Keyboard.hpp",
"chars": 5934,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Main.cpp",
"chars": 1759,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2020 Remy van Elst\n * Website: https://gith"
},
{
"path": "src/MultipleChoiceQuestion.hpp",
"chars": 5382,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/NumberQuestion.hpp",
"chars": 3112,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/PCIDevice.cpp",
"chars": 19668,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/PCIDevice.hpp",
"chars": 3387,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Port80.cpp",
"chars": 3234,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Port80.hpp",
"chars": 2088,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Question.hpp",
"chars": 2434,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/S3Trio64.cpp",
"chars": 139454,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/S3Trio64.hpp",
"chars": 6859,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SCSIBus.cpp",
"chars": 5763,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SCSIBus.hpp",
"chars": 2841,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SCSIDevice.cpp",
"chars": 6304,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SCSIDevice.hpp",
"chars": 2403,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Serial.cpp",
"chars": 16477,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Serial.hpp",
"chars": 3070,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/ShrinkingChoiceQuestion.hpp",
"chars": 1607,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/StdAfx.hpp",
"chars": 4677,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Sym53C810.cpp",
"chars": 71205,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Sym53C810.hpp",
"chars": 4204,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Sym53C895.cpp",
"chars": 72557,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/Sym53C895.hpp",
"chars": 4335,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/System.cpp",
"chars": 91291,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/System.hpp",
"chars": 16840,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SystemComponent.cpp",
"chars": 1767,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/SystemComponent.hpp",
"chars": 2035,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/TraceEngine.cpp",
"chars": 44567,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/TraceEngine.hpp",
"chars": 6734,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/VGA.cpp",
"chars": 1644,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/VGA.hpp",
"chars": 1627,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Bugcheck.cpp",
"chars": 4001,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Bugcheck.hpp",
"chars": 5624,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/ErrorHandler.cpp",
"chars": 4221,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/ErrorHandler.hpp",
"chars": 5683,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event.cpp",
"chars": 3128,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event.hpp",
"chars": 4884,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event_POSIX.cpp",
"chars": 4713,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event_POSIX.hpp",
"chars": 3982,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event_WIN32.cpp",
"chars": 3634,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Event_WIN32.hpp",
"chars": 3652,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Exception.cpp",
"chars": 9321,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Exception.hpp",
"chars": 11198,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Foundation.hpp",
"chars": 4040,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex.cpp",
"chars": 8970,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex.hpp",
"chars": 7980,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex_POSIX.cpp",
"chars": 5516,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex_POSIX.hpp",
"chars": 4039,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex_WIN32.cpp",
"chars": 3715,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Mutex_WIN32.hpp",
"chars": 3847,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/NumberFormatter.cpp",
"chars": 9607,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/NumberFormatter.hpp",
"chars": 9566,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Platform.hpp",
"chars": 7691,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Platform_POSIX.hpp",
"chars": 3432,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Platform_VMS.hpp",
"chars": 4437,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Platform_WIN32.hpp",
"chars": 4779,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Poco.hpp",
"chars": 3088,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock.cpp",
"chars": 3232,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock.hpp",
"chars": 11765,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock_POSIX.cpp",
"chars": 3165,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock_POSIX.hpp",
"chars": 4342,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock_WIN32.cpp",
"chars": 6142,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RWLock_WIN32.hpp",
"chars": 3535,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RefCountedObject.cpp",
"chars": 3346,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/RefCountedObject.hpp",
"chars": 4104,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/ScopedLock.hpp",
"chars": 3619,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore.cpp",
"chars": 3226,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore.hpp",
"chars": 5974,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore_POSIX.cpp",
"chars": 5807,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore_POSIX.hpp",
"chars": 3981,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore_WIN32.cpp",
"chars": 3713,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Semaphore_WIN32.hpp",
"chars": 3563,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/SingletonHolder.hpp",
"chars": 3968,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Timestamp.cpp",
"chars": 5365,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/Timestamp.hpp",
"chars": 7719,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * T"
},
{
"path": "src/base/Types.hpp",
"chars": 6824,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/base/UnWindows.hpp",
"chars": 5384,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/config.hpp.in",
"chars": 11115,
"preview": "/* Define to 1 if you have the `alarm' function. */\n#cmakedefine HAVE_ALARM\n\n/* Define to 1 if you have the <arpa/inet.h"
},
{
"path": "src/config_debug.hpp",
"chars": 3587,
"preview": "// This is config_debug.h\n//\n// This file contains the debug configuration options.\n// This file was generated by config"
},
{
"path": "src/cpu_arith.hpp",
"chars": 10543,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_bwx.hpp",
"chars": 8644,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_control.hpp",
"chars": 3518,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_debug.hpp",
"chars": 37449,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_defs.hpp",
"chars": 27151,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_fp_branch.hpp",
"chars": 5238,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_fp_memory.hpp",
"chars": 5684,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_fp_operate.hpp",
"chars": 31769,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_logical.hpp",
"chars": 3560,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_memory.hpp",
"chars": 3378,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_misc.hpp",
"chars": 19445,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_mvi.hpp",
"chars": 10933,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_pal.hpp",
"chars": 35096,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/cpu_vax.hpp",
"chars": 1546,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/datatypes.hpp",
"chars": 4882,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/es40-cfg.cpp",
"chars": 28156,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/es40_debug.cpp",
"chars": 3550,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/es40_debug.hpp",
"chars": 6047,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/es40_endian.hpp",
"chars": 3645,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/es40_float.hpp",
"chars": 12962,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/gui.cpp",
"chars": 7018,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/gui.hpp",
"chars": 8751,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/gui_win32_font.hpp",
"chars": 29515,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/gui_x11.cpp",
"chars": 45054,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/keymap.cpp",
"chars": 10690,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/keymap.hpp",
"chars": 2180,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/plugin.hpp",
"chars": 2297,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/scancodes.cpp",
"chars": 19571,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/scancodes.hpp",
"chars": 1516,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/sdl.cpp",
"chars": 28616,
"preview": "/* ES40 emulator.\n * Copyright (C) 2007-2008 by the ES40 Emulator Project\n *\n * WWW : http://es40.org\n * E-mail : cam"
},
{
"path": "src/gui/sdl_fonts.hpp",
"chars": 35096,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/sdlkeys.hpp",
"chars": 7076,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/gui/vga.hpp",
"chars": 5337,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/lockstep.cpp",
"chars": 6168,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/lockstep.hpp",
"chars": 1723,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "src/make_unique.hpp",
"chars": 1450,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Copyright (C) 2020 Remy van Elst\n * Website: https://git"
},
{
"path": "src/telnet.hpp",
"chars": 4018,
"preview": "/* AXPbox Alpha Emulator\n * Copyright (C) 2020 Tomáš Glozar\n * Website: https://github.com/lenticularis39/axpbox\n *\n * F"
},
{
"path": "test/disk/unwritable/axp_correct.log",
"chars": 239,
"preview": "%FLS-F-NOREST: Flash could not be restored from flash.rom\nEmulator Failure: Runtime exception: pci0.15(ali_ide).disk0.0("
},
{
"path": "test/disk/unwritable/es40.cfg",
"chars": 522,
"preview": "sys0 = tsunami\n{\n memory.bits = 26;\n rom.srm = \"cl67srmrom.exe\";\n rom.decompressed = \"decompressed.rom\";\n rom.flash "
},
{
"path": "test/disk/unwritable/test.sh",
"chars": 958,
"preview": "#!/bin/bash\n\ntouch disk-unwritable.img\nchmod 400 disk-unwritable.img\n\n# Download the firmware\nif [[ ! -f \"cl67srmrom.exe"
},
{
"path": "test/rom/es40.cfg",
"chars": 379,
"preview": "sys0 = tsunami\n{\n memory.bits = 26;\n rom.srm = \"cl67srmrom.exe\";\n rom.decompressed = \"decompressed.rom\";\n rom.flash "
},
{
"path": "test/rom/test.ps1",
"chars": 1050,
"preview": "# Download the firmware\nInvoke-WebRequest -Uri 'http://raymii.org/s/inc/downloads/es40-srmon/cl67srmrom.exe' -OutFile 'c"
},
{
"path": "test/rom/test.sh",
"chars": 1008,
"preview": "#!/bin/bash\nexport LC_CTYPE=C\nexport LANG=C\nexport LC_ALL=C\n\n# Download the firmware\nwget 'http://raymii.org/s/inc/downl"
},
{
"path": "test/run",
"chars": 679,
"preview": "#!/bin/bash\nsuccess=0\n\nfunction message() {\n echo -n -e '\\033[1;36m' >&2\n echo $1 >&2\n echo -n -e '\\033[0m' >&2\n}\n\nfu"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the lenticularis39/axpbox GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 180 files (2.0 MB), approximately 542.9k tokens, and a symbol index with 543 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.