merge in latest trunk

This commit is contained in:
akuker
2020-09-11 09:52:39 -05:00
323 changed files with 845083 additions and 11071 deletions

View File

@@ -1,4 +1,3 @@
*.o
*.bak
*.HDA
*.save
@@ -6,9 +5,10 @@
*.layout
*.log
rascsi
scsishark
scsimon
rasctl
sasidump
rasdump
log.*
obj
bin

27
src/raspberrypi/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,27 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/rascsi",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

14
src/raspberrypi/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"files.associations": {
"cstddef": "cpp",
"array": "cpp",
"chrono": "cpp",
"functional": "cpp",
"istream": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp"
}
}

19
src/raspberrypi/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "g++ build active file",
"command": "make",
"args": ["all", "DEBUG=1"],
"options": {
"cwd": "${workspaceFolder}/"
},
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -1,21 +1,43 @@
.DEFAULT_GOAL: all
CC = gcc
CXX = g++
## Optional build flags:
## ARCH=arm : Specify which target platform you're compiling
## for. This will default to arm, which is typical
## on a Raspberry Pi.
## CROSS_COMPILE=arm-linux-gnueabihf- : Specify which compiler
## toolchain to use. This will default to arm-linux-
## gnueabihf-, which is typical on a Raspberry Pi.
## To cross compile on a x86_64 system set these to:
## ARM=x86_64 CROSS_COMPILE=x86_64-linux-gnu-cpp
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
## DEBUG=1 : A Debug build includes the debugger symbols
## and disables compiler optimization. Typically,
## this is only used by developers.
DEBUG ?= 0
ifeq ($(DEBUG), 1)
# Debug CFLAGS
CFLAGS = -DDISK_LOG -O0 -g -Wall -DDEBUG
CXXFLAGS = -DDISK_LOG -O0 -g -Wall -DDEBUG
CFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
CXXFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
BUILD_TYPE = Debug
else
# Release CFLAGS
CFLAGS ?= -O3 -Wall -Werror
CXXFLAGS ?= -O3 -Wall -Werror
CFLAGS += -O3 -Wall -Werror
CXXFLAGS += -O3 -Wall -Werror
BUILD_TYPE = Release
endif
CFLAGS += -iquote . -MD -MP
CXXFLAGS += -std=c++14 -iquote . -MD -MP
## CONNECT_TYPE=STANDARD : Specify the type of RaSCSI board type
## that you are using. The typical options are
## STANDARD or FULLSPEC. The default is STANDARD
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
## * NEED TO SPECIFY
# If its not specified, build for STANDARD configuration
CONNECT_TYPE ?= STANDARD
@@ -30,25 +52,36 @@ RASDUMP = rasdump
SASIDUMP = sasidump
SCSISHARK = scsishark
SYSTEMD_CONF = /etc/systemd/system/rascsi.service
RSYSLOG_CONF = /etc/rsyslog.d/rascsi.conf
RSYSLOG_LOG = /var/log/rascsi.log
USR_LOCAL_BIN = /usr/local/bin
MAN_PAGE_DIR = /usr/share/man/man1
DOC_DIR = ../../doc
OS_FILES = ./os_integration
OBJDIR := ./obj/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]')
BINDIR := ./bin/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]')
#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON)
# Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed
# for my specific use case. If you need them - add them back in!
BIN_ALL = $(RASCSI) $(RASCTL) $(SCSISHARK)
BIN_ALL = $(BINDIR)/$(RASCSI) $(BINDIR)/$(RASCTL)
SRC_RASCSI = \
rascsi.cpp \
scsi.cpp \
disk.cpp \
gpiobus.cpp \
ctapdriver.cpp \
cfilesystem.cpp \
filepath.cpp \
fileio.cpp
fileio.cpp\
# os.cpp
# rasctl_command.cpp
# rascsi_mgr.cpp
# command_thread.cpp
SRC_RASCSI += $(shell find ./controllers -name '*.cpp')
SRC_RASCSI += $(shell find ./devices -name '*.cpp')
SRC_SCSISHARK = \
scsishark.cpp \
@@ -62,6 +95,7 @@ SRC_SCSISHARK = \
SRC_RASCTL = \
rasctl.cpp
# rasctl_command.cpp
SRC_RASDUMP = \
rasdump.cpp \
@@ -77,19 +111,37 @@ SRC_SASIDUMP = \
filepath.cpp \
fileio.cpp
OBJ_RASCSI := $(SRC_RASCSI:%.cpp=%.o)
OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o)
OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o)
OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=%.o)
OBJ_SCSISHARK := $(SRC_SCSISHARK:%.cpp=%.o)
vpath %.h ./ ./controllers ./devices
vpath %.cpp ./ ./controllers ./devices
vpath %.o ./$(OBJDIR)
vpath ./$(BINDIR)
OBJ_RASCSI := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI:%.cpp=%.o)))
OBJ_RASCTL := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL:%.cpp=%.o)))
OBJ_RASDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASDUMP:%.cpp=%.o)))
OBJ_SASIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SASIDUMP:%.cpp=%.o)))
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
#OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON)
OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSISHARK)
%.o: %.cpp
# The following will include all of the auto-generated dependency files (*.d)
# if they exist. This will trigger a rebuild of a source file if a header changes
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI) $(OBJ_RASCTL))
-include $(ALL_DEPS)
$(OBJDIR) $(BINDIR):
echo "-- Creating directory $@"
mkdir -p $@
$(OBJDIR)/%.o: %.cpp | $(OBJDIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
## Build Targets:
## all : Rebuild all of the executable files and re-generate
## the text versions of the manpages
## docs : Re-generate the text versions of the man pages
.DEFAULT_GOAL := all
.PHONY: all ALL docs
all: $(BIN_ALL) docs
@@ -97,40 +149,83 @@ ALL: all
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt
$(RASCSI): $(OBJ_RASCSI)
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread
$(RASCTL): $(OBJ_RASCTL)
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)
$(RASDUMP): $(OBJ_RASDUMP)
$(RASDUMP): $(OBJ_RASDUMP) $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP)
$(SASIDUMP): $(OBJ_SASIDUMP)
$(SASIDUMP): $(OBJ_SASIDUMP) $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SASIDUMP)
$(SCSISHARK): $(OBJ_SCSISHARK)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSISHARK) -lpthread
$(SCSIMON): $(OBJ_SCSIMON) $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
## clean : Remove all of the object files, intermediate
## compiler files and executable files
.PHONY: clean
clean:
rm -f $(OBJ_ALL) $(BIN_ALL)
rm -rf $(OBJDIR) $(BINDIR)
## run : Launches RaSCSI using some pre-defined drive
## images. Useful for debugging when you're building
## and re-launching over and over.
.PHONY: run
run:
sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK2.hda -ID6 /home/pi/marathon.iso
sudo $(BINDIR)/$(RASCSI) -ID1 /home/pi/HARDDISK2.hda -ID6 /home/pi/marathon.iso
install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1
sudo cp $(RASCTL) $(USR_LOCAL_BIN)
sudo cp $(RASCSI) $(USR_LOCAL_BIN)
## install : Copies all of the man pages to the correct location
## Copies the binaries to a global install location
## Configures the Systemd and RSyslog services to auto-run RaSCSI
## * This target needs to be run with sudo (ex: sudo make install)
## * Before running this, you need to stop the rascsi service if
## * it is already running:
## * sudo systemctl stop rascsi
## * After running this, you will need to reboot or run:
## * sudo systemctl daemon-reload
## * sudo systemctl restart rsyslog
## * sudo systemctl enable rascsi
## * sudo systemctl start rascsi
.PHONY: install
install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1 $(USR_LOCAL_BIN)/$(RASCTL) $(USR_LOCAL_BIN)/$(RASCSI) $(SYSTEMD_CONF) $(RSYSLOG_CONF) $(RSYSLOG_LOG)
@echo "-- Done installing!"
$(USR_LOCAL_BIN)% : $(BINDIR)/%
@echo "-- Copying $@"
cp $< $@
$(MAN_PAGE_DIR)/%.1 : $(DOC_DIR)/%.1
sudo cp $< $@
@echo "-- Copying $@"
cp $< $@
$(DOC_DIR)/%_man_page.txt : $(DOC_DIR)/%.1
@echo "!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!" > $@
@echo "!! ------ The native file is $(notdir $<). Re-run 'make docs' after updating\n\n" >> $@
man -l $< | col -bx >> $@
$(SYSTEMD_CONF) : $(OS_FILES)/$(notdir $(SYSTEMD_CONF))
@echo "-- Copying $@"
cp $< $@
$(RSYSLOG_CONF) : $(OS_FILES)/$(notdir $(RSYSLOG_CONF))
@echo "-- Copying $@"
cp $< $@
$(RSYSLOG_LOG) :
@echo "-- Creating $@"
touch /var/log/rascsi.log
chown root:adm /var/log/rascsi.log
## help : Lists information about how to use the makefile
# The help rule is based upon the approach from:
# https://swcarpentry.github.io/make-novice/08-self-doc/index.html
.PHONY: help
help : Makefile
@sed -n 's/^##//p' $<
## Debug : Same as 'all'. Useful when using a debugger.
.PHONY: Debug
Debug: all
.PHONY: Debug-scsishark
Debug-scsishark: $(SCSISHARK)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SASI device controller ]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "scsi.h"
#include "fileio.h"
#include "devices/disk.h"
#include "log.h"
#include "xm6.h"
//===========================================================================
//
// SASI Controller
//
//===========================================================================
class SASIDEV
{
public:
// Maximum number of logical units
enum {
UnitMax = 8
};
#ifdef RASCSI
// For timing adjustments
enum {
min_exec_time_sasi = 100, // SASI BOOT/FORMAT 30:NG 35:OK
min_exec_time_scsi = 50
};
#endif // RASCSI
// Internal data definition
typedef struct {
// 全般
BUS::phase_t phase; // Transition phase
int id; // Controller ID (0-7)
BUS *bus; // Bus
// commands
DWORD cmd[10]; // Command data
DWORD status; // Status data
DWORD message; // Message data
#ifdef RASCSI
// Run
DWORD execstart; // Execution start time
#endif // RASCSI
// Transfer
BYTE *buffer; // Transfer data buffer
int bufsize; // Transfer data buffer size
DWORD blocks; // Number of transfer block
DWORD next; // Next record
DWORD offset; // Transfer offset
DWORD length; // Transfer remaining length
// Logical unit
Disk *unit[UnitMax];
// Logical Unit
} ctrl_t;
public:
// Basic Functions
#ifdef RASCSI
SASIDEV();
#else
SASIDEV(Device *dev);
#endif //RASCSI
// Constructor
virtual ~SASIDEV();
// Destructor
virtual void FASTCALL Reset();
// Device Reset
#ifndef RASCSI
virtual BOOL FASTCALL Save(Fileio *fio, int ver);
// Save
virtual BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif //RASCSI
// External API
virtual BUS::phase_t FASTCALL Process();
// Run
// Connect
void FASTCALL Connect(int id, BUS *sbus);
// Controller connection
Disk* FASTCALL GetUnit(int no);
// Get logical unit
void FASTCALL SetUnit(int no, Disk *dev);
// Logical unit setting
BOOL FASTCALL HasUnit();
// Has a valid logical unit
// Other
BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;}
// Get the phase
#ifdef DISK_LOG
// Function to get the current phase as a String.
void FASTCALL GetPhaseStr(char *str);
#endif
int FASTCALL GetID() {return ctrl.id;}
// Get the ID
void FASTCALL GetCTRL(ctrl_t *buffer);
// Get the internal information
ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; }
// Get the internal information address
virtual BOOL FASTCALL IsSASI() const {return TRUE;}
// SASI Check
virtual BOOL FASTCALL IsSCSI() const {return FALSE;}
// SCSI check
Disk* FASTCALL GetBusyUnit();
// Get the busy unit
protected:
// Phase processing
virtual void FASTCALL BusFree();
// Bus free phase
virtual void FASTCALL Selection();
// Selection phase
virtual void FASTCALL Command();
// Command phase
virtual void FASTCALL Execute();
// Execution phase
void FASTCALL Status();
// Status phase
void FASTCALL MsgIn();
// Message in phase
void FASTCALL DataIn();
// Data in phase
void FASTCALL DataOut();
// Data out phase
virtual void FASTCALL Error();
// Common error handling
// commands
void FASTCALL CmdTestUnitReady();
// TEST UNIT READY command
void FASTCALL CmdRezero();
// REZERO UNIT command
void FASTCALL CmdRequestSense();
// REQUEST SENSE command
void FASTCALL CmdFormat();
// FORMAT command
void FASTCALL CmdReassign();
// REASSIGN BLOCKS command
void FASTCALL CmdRead6();
// READ(6) command
void FASTCALL CmdWrite6();
// WRITE(6) command
void FASTCALL CmdSeek6();
// SEEK(6) command
void FASTCALL CmdAssign();
// ASSIGN command
void FASTCALL CmdSpecify();
// SPECIFY command
void FASTCALL CmdInvalid();
// Unsupported command
// データ転送
virtual void FASTCALL Send();
// Send data
#ifndef RASCSI
virtual void FASTCALL SendNext();
// Continue sending data
#endif // RASCSI
virtual void FASTCALL Receive();
// Receive data
#ifndef RASCSI
virtual void FASTCALL ReceiveNext();
// Continue receiving data
#endif // RASCSI
BOOL FASTCALL XferIn(BYTE* buf);
// Data transfer IN
BOOL FASTCALL XferOut(BOOL cont);
// Data transfer OUT
// Special operations
void FASTCALL FlushUnit();
// Flush the logical unit
// Log
void FASTCALL Log(Log::loglevel level, const char *format, ...);
// Log output
protected:
#ifndef RASCSI
Device *host;
// Host device
#endif // RASCSI
ctrl_t ctrl;
// Internal data
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI device controller ]
//
//---------------------------------------------------------------------------
#pragma once
#include "controllers/sasidev_ctrl.h"
//===========================================================================
//
// SCSI Device (Interits SASI device)
//
//===========================================================================
class SCSIDEV : public SASIDEV
{
public:
// Internal data definition
typedef struct {
// Synchronous transfer
BOOL syncenable; // Synchronous transfer possible
int syncperiod; // Synchronous transfer period
int syncoffset; // Synchronous transfer offset
int syncack; // Number of synchronous transfer ACKs
// ATN message
BOOL atnmsg;
int msc;
BYTE msb[256];
} scsi_t;
public:
// Basic Functions
#ifdef RASCSI
SCSIDEV();
#else
SCSIDEV(Device *dev);
#endif // RASCSI
// Constructor
void FASTCALL Reset();
// Device Reset
// 外部API
BUS::phase_t FASTCALL Process();
// Run
void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; }
// Synchronouse transfer enable setting
// Other
BOOL FASTCALL IsSASI() const {return FALSE;}
// SASI Check
BOOL FASTCALL IsSCSI() const {return TRUE;}
// SCSI check
private:
// Phase
void FASTCALL BusFree();
// Bus free phase
void FASTCALL Selection();
// Selection phase
void FASTCALL Execute();
// Execution phase
void FASTCALL MsgOut();
// Message out phase
void FASTCALL Error();
// Common erorr handling
// commands
void FASTCALL CmdInquiry();
// INQUIRY command
void FASTCALL CmdModeSelect();
// MODE SELECT command
void FASTCALL CmdModeSense();
// MODE SENSE command
void FASTCALL CmdStartStop();
// START STOP UNIT command
void FASTCALL CmdSendDiag();
// SEND DIAGNOSTIC command
void FASTCALL CmdRemoval();
// PREVENT/ALLOW MEDIUM REMOVAL command
void FASTCALL CmdReadCapacity();
// READ CAPACITY command
void FASTCALL CmdRead10();
// READ(10) command
void FASTCALL CmdWrite10();
// WRITE(10) command
void FASTCALL CmdSeek10();
// SEEK(10) command
void FASTCALL CmdVerify();
// VERIFY command
void FASTCALL CmdSynchronizeCache();
// SYNCHRONIZE CACHE command
void FASTCALL CmdReadDefectData10();
// READ DEFECT DATA(10) command
void FASTCALL CmdReadToc();
// READ TOC command
void FASTCALL CmdPlayAudio10();
// PLAY AUDIO(10) command
void FASTCALL CmdPlayAudioMSF();
// PLAY AUDIO MSF command
void FASTCALL CmdPlayAudioTrack();
// PLAY AUDIO TRACK INDEX command
void FASTCALL CmdModeSelect10();
// MODE SELECT(10) command
void FASTCALL CmdModeSense10();
// MODE SENSE(10) command
void FASTCALL CmdGetMessage10();
// GET MESSAGE(10) command
void FASTCALL CmdSendMessage10();
// SEND MESSAGE(10) command
// データ転送
void FASTCALL Send();
// Send data
#ifndef RASCSI
void FASTCALL SendNext();
// Continue sending data
#endif // RASCSI
void FASTCALL Receive();
// Receive data
#ifndef RASCSI
void FASTCALL ReceiveNext();
// Continue receiving data
#endif // RASCSI
BOOL FASTCALL XferMsg(DWORD msg);
// Data transfer message
scsi_t scsi;
// Internal data
};

View File

@@ -76,6 +76,7 @@ static void convert(char const *src, char const *dest,
const char *inbuf, char *outbuf, size_t outsize)
#endif
{
#ifndef __APPLE__
iconv_t cd;
size_t in;
size_t out;
@@ -97,6 +98,7 @@ static void convert(char const *src, char const *dest,
iconv_close(cd);
*outbuf = '\0';
#endif //ifndef __macintosh__
}
#else
// Newlibの中にiconvが含まれてなかったので無変換
@@ -4548,7 +4550,7 @@ int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl)
case 2:
switch (pIoctrl->param) {
case -1:
case (DWORD)-1:
// メディア再認識
m_cEntry.isMediaOffline(nUnit);
return 0;
@@ -4560,17 +4562,17 @@ int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl)
}
break;
case -1:
case (DWORD)-1:
// 常駐判定
memcpy(pIoctrl->buffer, "WindrvXM", 8);
return 0;
case -2:
case (DWORD)-2:
// オプション設定
SetOption(pIoctrl->param);
return 0;
case -3:
case (DWORD)-3:
// オプション獲得
pIoctrl->param = GetOption();
return 0;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,368 @@
//---------------------------------------------------------------------------
//
// X68000 EMULATOR "XM6"
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
//
// XM6i
// Copyright (C) 2010-2015 isaki@NetBSD.org
//
// Imported sava's Anex86/T98Next image and MO format support patch.
// Comments translated to english by akuker.
//
// [ Disk ]
//
//---------------------------------------------------------------------------
#pragma once
#include "xm6.h"
#include "log.h"
#include "scsi.h"
#include "filepath.h"
//---------------------------------------------------------------------------
//
// Error definition (sense code returned by REQUEST SENSE)
//
// MSB Reserved (0x00)
// Sense Key
// Additional Sense Code (ASC)
// LSB Additional Sense Code Qualifier(ASCQ)
//
//---------------------------------------------------------------------------
#define DISK_NOERROR 0x00000000 // NO ADDITIONAL SENSE INFO.
#define DISK_DEVRESET 0x00062900 // POWER ON OR RESET OCCURED
#define DISK_NOTREADY 0x00023a00 // MEDIUM NOT PRESENT
#define DISK_ATTENTION 0x00062800 // MEDIUM MAY HAVE CHANGED
#define DISK_PREVENT 0x00045302 // MEDIUM REMOVAL PREVENTED
#define DISK_READFAULT 0x00031100 // UNRECOVERED READ ERROR
#define DISK_WRITEFAULT 0x00030300 // PERIPHERAL DEVICE WRITE FAULT
#define DISK_WRITEPROTECT 0x00042700 // WRITE PROTECTED
#define DISK_MISCOMPARE 0x000e1d00 // MISCOMPARE DURING VERIFY
#define DISK_INVALIDCMD 0x00052000 // INVALID COMMAND OPERATION CODE
#define DISK_INVALIDLBA 0x00052100 // LOGICAL BLOCK ADDR. OUT OF RANGE
#define DISK_INVALIDCDB 0x00052400 // INVALID FIELD IN CDB
#define DISK_INVALIDLUN 0x00052500 // LOGICAL UNIT NOT SUPPORTED
#define DISK_INVALIDPRM 0x00052600 // INVALID FIELD IN PARAMETER LIST
#define DISK_INVALIDMSG 0x00054900 // INVALID MESSAGE ERROR
#define DISK_PARAMLEN 0x00051a00 // PARAMETERS LIST LENGTH ERROR
#define DISK_PARAMNOT 0x00052601 // PARAMETERS NOT SUPPORTED
#define DISK_PARAMVALUE 0x00052602 // PARAMETERS VALUE INVALID
#define DISK_PARAMSAVE 0x00053900 // SAVING PARAMETERS NOT SUPPORTED
#define DISK_NODEFECT 0x00010000 // DEFECT LIST NOT FOUND
#if 0
#define DISK_AUDIOPROGRESS 0x00??0011 // AUDIO PLAY IN PROGRESS
#define DISK_AUDIOPAUSED 0x00??0012 // AUDIO PLAY PAUSED
#define DISK_AUDIOSTOPPED 0x00??0014 // AUDIO PLAY STOPPED DUE TO ERROR
#define DISK_AUDIOCOMPLETE 0x00??0013 // AUDIO PLAY SUCCESSFULLY COMPLETED
#endif
#ifdef RASCSI
#define BENDER_SIGNATURE "RaSCSI"
// The following line was to mimic Apple's CDROM ID
// #define BENDER_SIGNATURE "SONY "
#else
#define BENDER_SIGNATURE "XM6"
#endif
//===========================================================================
//
// Disk Track
//
//===========================================================================
class DiskTrack
{
public:
// Internal data definition
typedef struct {
int track; // Track Number
int size; // Sector Size(8 or 9)
int sectors; // Number of sectors(<=0x100)
DWORD length; // Data buffer length
BYTE *buffer; // Data buffer
BOOL init; // Is it initilized?
BOOL changed; // Changed flag
DWORD maplen; // Changed map length
BOOL *changemap; // Changed map
BOOL raw; // RAW mode flag
off64_t imgoffset; // Offset to actual data
} disktrk_t;
public:
// Basic Functions
DiskTrack();
// Constructor
virtual ~DiskTrack();
// Destructor
void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE,
off64_t imgoff = 0);
// Initialization
BOOL FASTCALL Load(const Filepath& path);
// Load
BOOL FASTCALL Save(const Filepath& path);
// Save
// Read / Write
BOOL FASTCALL Read(BYTE *buf, int sec) const;
// Sector Read
BOOL FASTCALL Write(const BYTE *buf, int sec);
// Sector Write
// Other
int FASTCALL GetTrack() const { return dt.track; }
// Get track
BOOL FASTCALL IsChanged() const { return dt.changed; }
// Changed flag check
private:
// Internal data
disktrk_t dt;
// Internal data
};
//===========================================================================
//
// Disk Cache
//
//===========================================================================
class DiskCache
{
public:
// Internal data definition
typedef struct {
DiskTrack *disktrk; // Disk Track
DWORD serial; // Serial
} cache_t;
// Number of caches
enum {
CacheMax = 16 // Number of tracks to cache
};
public:
// Basic Functions
DiskCache(const Filepath& path, int size, int blocks,
off64_t imgoff = 0);
// Constructor
virtual ~DiskCache();
// Destructor
void FASTCALL SetRawMode(BOOL raw);
// CD-ROM raw mode setting
// Access
BOOL FASTCALL Save();
// Save and release all
BOOL FASTCALL Read(BYTE *buf, int block);
// Sector Read
BOOL FASTCALL Write(const BYTE *buf, int block);
// Sector Write
BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const;
// Get cache information
private:
// Internal Management
void FASTCALL Clear();
// Clear all tracks
DiskTrack* FASTCALL Assign(int track);
// Load track
BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL);
// Load track
void FASTCALL Update();
// Update serial number
// Internal data
cache_t cache[CacheMax];
// Cache management
DWORD serial;
// Last serial number
Filepath sec_path;
// Path
int sec_size;
// Sector size (8 or 9 or 11)
int sec_blocks;
// Blocks per sector
BOOL cd_raw;
// CD-ROM RAW mode
off64_t imgoffset;
// Offset to actual data
};
//===========================================================================
//
// Disk
//
//===========================================================================
class Disk
{
public:
// Internal data structure
typedef struct {
DWORD id; // Media ID
BOOL ready; // Valid Disk
BOOL writep; // Write protected
BOOL readonly; // Read only
BOOL removable; // Removable
BOOL lock; // Locked
BOOL attn; // Attention
BOOL reset; // Reset
int size; // Sector Size
DWORD blocks; // Total number of sectors
DWORD lun; // LUN
DWORD code; // Status code
DiskCache *dcache; // Disk cache
off64_t imgoffset; // Offset to actual data
} disk_t;
public:
// Basic Functions
Disk();
// Constructor
virtual ~Disk();
// Destructor
virtual void FASTCALL Reset();
// Device Reset
#ifndef RASCSI
virtual BOOL FASTCALL Save(Fileio *fio, int ver);
// Save
virtual BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// ID
DWORD FASTCALL GetID() const { return disk.id; }
// Get media ID
BOOL FASTCALL IsNULL() const;
// NULL check
BOOL FASTCALL IsSASI() const;
// SASI Check
BOOL FASTCALL IsSCSI() const;
// SASI Check
// Media Operations
virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
void FASTCALL GetPath(Filepath& path) const;
// Get the path
void FASTCALL Eject(BOOL force);
// Eject
BOOL FASTCALL IsReady() const { return disk.ready; }
// Ready check
void FASTCALL WriteP(BOOL flag);
// Set Write Protect flag
BOOL FASTCALL IsWriteP() const { return disk.writep; }
// Get write protect flag
BOOL FASTCALL IsReadOnly() const { return disk.readonly; }
// Get read only flag
BOOL FASTCALL IsRemovable() const { return disk.removable; }
// Get is removable flag
BOOL FASTCALL IsLocked() const { return disk.lock; }
// Get locked status
BOOL FASTCALL IsAttn() const { return disk.attn; }
// Get attention flag
BOOL FASTCALL Flush();
// Flush the cache
void FASTCALL GetDisk(disk_t *buffer) const;
// Get the internal data struct
// Properties
void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; }
// LUN set
DWORD FASTCALL GetLUN() { return disk.lun; }
// LUN get
// commands
virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf);
// REQUEST SENSE command
int FASTCALL SelectCheck(const DWORD *cdb);
// SELECT check
int FASTCALL SelectCheck10(const DWORD *cdb);
// SELECT(10) check
virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
// MODE SELECT command
virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf);
// MODE SENSE command
virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf);
// MODE SENSE(10) command
int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf);
// READ DEFECT DATA(10) command
virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb);
// TEST UNIT READY command
BOOL FASTCALL Rezero(const DWORD *cdb);
// REZERO command
BOOL FASTCALL Format(const DWORD *cdb);
// FORMAT UNIT command
BOOL FASTCALL Reassign(const DWORD *cdb);
// REASSIGN UNIT command
virtual int FASTCALL Read(BYTE *buf, DWORD block);
// READ command
int FASTCALL WriteCheck(DWORD block);
// WRITE check
BOOL FASTCALL Write(const BYTE *buf, DWORD block);
// WRITE command
BOOL FASTCALL Seek(const DWORD *cdb);
// SEEK command
BOOL FASTCALL Assign(const DWORD *cdb);
// ASSIGN command
BOOL FASTCALL Specify(const DWORD *cdb);
// SPECIFY command
BOOL FASTCALL StartStop(const DWORD *cdb);
// START STOP UNIT command
BOOL FASTCALL SendDiag(const DWORD *cdb);
// SEND DIAGNOSTIC command
BOOL FASTCALL Removal(const DWORD *cdb);
// PREVENT/ALLOW MEDIUM REMOVAL command
int FASTCALL ReadCapacity(const DWORD *cdb, BYTE *buf);
// READ CAPACITY command
BOOL FASTCALL Verify(const DWORD *cdb);
// VERIFY command
virtual int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf);
// READ TOC command
virtual BOOL FASTCALL PlayAudio(const DWORD *cdb);
// PLAY AUDIO command
virtual BOOL FASTCALL PlayAudioMSF(const DWORD *cdb);
// PLAY AUDIO MSF command
virtual BOOL FASTCALL PlayAudioTrack(const DWORD *cdb);
// PLAY AUDIO TRACK command
void FASTCALL InvalidCmd() { disk.code = DISK_INVALIDCMD; }
// Unsupported command
// Other
BOOL IsCacheWB() { return cache_wb; }
// Get cache writeback mode
void SetCacheWB(BOOL enable) { cache_wb = enable; }
// Set cache writeback mode
protected:
// Internal processing
virtual int FASTCALL AddError(BOOL change, BYTE *buf);
// Add error
virtual int FASTCALL AddFormat(BOOL change, BYTE *buf);
// Add format
virtual int FASTCALL AddDrive(BOOL change, BYTE *buf);
// Add drive
int FASTCALL AddOpt(BOOL change, BYTE *buf);
// Add optical
int FASTCALL AddCache(BOOL change, BYTE *buf);
// Add cache
int FASTCALL AddCDROM(BOOL change, BYTE *buf);
// Add CD-ROM
int FASTCALL AddCDDA(BOOL change, BYTE *buf);
// Add CD_DA
virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
// Add vendor special info
BOOL FASTCALL CheckReady();
// Check if ready
// Internal data
disk_t disk;
// Internal disk data
Filepath diskpath;
// File path (for GetPath)
BOOL cache_wb;
// Cache mode
};

View File

@@ -0,0 +1,164 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SASI hard disk ]
//
//---------------------------------------------------------------------------
#include "sasihd.h"
#include "xm6.h"
#include "fileio.h"
//===========================================================================
//
// SASI Hard Disk
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SASIHD::SASIHD() : Disk()
{
// SASI ハードディスク
disk.id = MAKEID('S', 'A', 'H', 'D');
}
//---------------------------------------------------------------------------
//
// リセット
//
//---------------------------------------------------------------------------
void FASTCALL SASIHD::Reset()
{
// ロック状態解除、アテンション解除
disk.lock = FALSE;
disk.attn = FALSE;
// Resetなし、コードをクリア
disk.reset = FALSE;
disk.code = 0x00;
}
//---------------------------------------------------------------------------
//
// オープン
//
//---------------------------------------------------------------------------
BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
{
Fileio fio;
off64_t size;
ASSERT(this);
ASSERT(!disk.ready);
// Open as read-only
if (!fio.Open(path, Fileio::ReadOnly)) {
return FALSE;
}
// Get file size
size = fio.GetFileSize();
fio.Close();
#if defined(USE_MZ1F23_1024_SUPPORT)
// MZ-2500/MZ-2800用 MZ-1F23(SASI 20M/セクタサイズ1024)専用
// 20M(22437888 BS=1024 C=21912)
if (size == 0x1566000) {
// セクタサイズとブロック数
disk.size = 10;
disk.blocks = (DWORD)(size >> 10);
// Call the base class
return Disk::Open(path);
}
#endif // USE_MZ1F23_1024_SUPPORT
#if defined(REMOVE_FIXED_SASIHD_SIZE)
// 256バイト単位であること
if (size & 0xff) {
return FALSE;
}
// 10MB以上
if (size < 0x9f5400) {
return FALSE;
}
// 512MB程度に制限しておく
if (size > 512 * 1024 * 1024) {
return FALSE;
}
#else
// 10MB, 20MB, 40MBのみ
switch (size) {
// 10MB(10441728 BS=256 C=40788)
case 0x9f5400:
break;
// 20MB(20748288 BS=256 C=81048)
case 0x13c9800:
break;
// 40MB(41496576 BS=256 C=162096)
case 0x2793000:
break;
// Other(サポートしない)
default:
return FALSE;
}
#endif // REMOVE_FIXED_SASIHD_SIZE
// セクタサイズとブロック数
disk.size = 8;
disk.blocks = (DWORD)(size >> 8);
// Call the base class
return Disk::Open(path);
}
//---------------------------------------------------------------------------
//
// REQUEST SENSE
//
//---------------------------------------------------------------------------
int FASTCALL SASIHD::RequestSense(const DWORD *cdb, BYTE *buf)
{
int size;
ASSERT(this);
ASSERT(cdb);
ASSERT(buf);
// サイズ決定
size = (int)cdb[4];
ASSERT((size >= 0) && (size < 0x100));
// サイズ0のときに4バイト転送する(Shugart Associates System Interface仕様)
if (size == 0) {
size = 4;
}
// SASIは非拡張フォーマットに固定
memset(buf, 0, size);
buf[0] = (BYTE)(disk.code >> 16);
buf[1] = (BYTE)(disk.lun << 5);
// コードをクリア
disk.code = 0x00;
return size;
}

View File

@@ -0,0 +1,40 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SASI hard disk ]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "disk.h"
#include "filepath.h"
//===========================================================================
//
// SASI Hard Disk
//
//===========================================================================
class SASIHD : public Disk
{
public:
// Basic Functions
SASIHD();
// Constructor
void FASTCALL Reset();
// Reset
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands
int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf);
// REQUEST SENSE command
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Host Bridge for the Sharp X68000 ]
//
// Note: This requires a special driver on the host system and will only
// work with the Sharp X68000 operating system.
//---------------------------------------------------------------------------
#pragma once
#include "xm6.h"
#include "os.h"
#include "disk.h"
//===========================================================================
//
// SCSI Host Bridge
//
//===========================================================================
#if defined(RASCSI) && !defined(BAREMETAL)
class CTapDriver;
#endif // RASCSI && !BAREMETAL
class CFileSys;
class SCSIBR : public Disk
{
public:
// Basic Functions
SCSIBR();
// Constructor
virtual ~SCSIBR();
// Destructor
// commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
BOOL FASTCALL TestUnitReady(const DWORD *cdb);
// TEST UNIT READY command
int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf);
// GET MESSAGE10 command
BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf);
// SEND MESSAGE10 command
private:
#if defined(RASCSI) && !defined(BAREMETAL)
int FASTCALL GetMacAddr(BYTE *buf);
// Get MAC address
void FASTCALL SetMacAddr(BYTE *buf);
// Set MAC address
void FASTCALL ReceivePacket();
// Receive a packet
void FASTCALL GetPacketBuf(BYTE *buf);
// Get a packet
void FASTCALL SendPacket(BYTE *buf, int len);
// Send a packet
CTapDriver *tap;
// TAP driver
BOOL m_bTapEnable;
// TAP valid flag
BYTE mac_addr[6];
// MAC Addres
int packet_len;
// Receive packet size
BYTE packet_buf[0x1000];
// Receive packet buffer
BOOL packet_enable;
// Received packet valid
#endif // RASCSI && !BAREMETAL
int FASTCALL ReadFsResult(BYTE *buf);
// Read filesystem (result code)
int FASTCALL ReadFsOut(BYTE *buf);
// Read filesystem (return data)
int FASTCALL ReadFsOpt(BYTE *buf);
// Read file system (optional data)
void FASTCALL WriteFs(int func, BYTE *buf);
// File system write (execute)
void FASTCALL WriteFsOpt(BYTE *buf, int len);
// File system write (optional data)
// Command handlers
void FASTCALL FS_InitDevice(BYTE *buf);
// $40 - boot
void FASTCALL FS_CheckDir(BYTE *buf);
// $41 - directory check
void FASTCALL FS_MakeDir(BYTE *buf);
// $42 - create directory
void FASTCALL FS_RemoveDir(BYTE *buf);
// $43 - delete directory
void FASTCALL FS_Rename(BYTE *buf);
// $44 - change filename
void FASTCALL FS_Delete(BYTE *buf);
// $45 - delete file
void FASTCALL FS_Attribute(BYTE *buf);
// $46 - get/set file attributes
void FASTCALL FS_Files(BYTE *buf);
// $47 - file search
void FASTCALL FS_NFiles(BYTE *buf);
// $48 - find next file
void FASTCALL FS_Create(BYTE *buf);
// $49 - create file
void FASTCALL FS_Open(BYTE *buf);
// $4A - open file
void FASTCALL FS_Close(BYTE *buf);
// $4B - close file
void FASTCALL FS_Read(BYTE *buf);
// $4C - read file
void FASTCALL FS_Write(BYTE *buf);
// $4D - write file
void FASTCALL FS_Seek(BYTE *buf);
// $4E - seek file
void FASTCALL FS_TimeStamp(BYTE *buf);
// $4F - get/set file time
void FASTCALL FS_GetCapacity(BYTE *buf);
// $50 - get capacity
void FASTCALL FS_CtrlDrive(BYTE *buf);
// $51 - drive status check/control
void FASTCALL FS_GetDPB(BYTE *buf);
// $52 - get DPB
void FASTCALL FS_DiskRead(BYTE *buf);
// $53 - read sector
void FASTCALL FS_DiskWrite(BYTE *buf);
// $54 - write sector
void FASTCALL FS_Ioctrl(BYTE *buf);
// $55 - IOCTRL
void FASTCALL FS_Flush(BYTE *buf);
// $56 - flush cache
void FASTCALL FS_CheckMedia(BYTE *buf);
// $57 - check media
void FASTCALL FS_Lock(BYTE *buf);
// $58 - get exclusive control
CFileSys *fs;
// File system accessor
DWORD fsresult;
// File system access result code
BYTE fsout[0x800];
// File system access result buffer
DWORD fsoutlen;
// File system access result buffer size
BYTE fsopt[0x1000000];
// File system access buffer
DWORD fsoptlen;
// File system access buffer size
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,230 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Hard Disk for Apple Macintosh ]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "disk.h"
#include "filepath.h"
//---------------------------------------------------------------------------
//
// Class precedence definition
//
//---------------------------------------------------------------------------
class SCSICD;
//===========================================================================
//
// CD-ROM Track
//
//===========================================================================
class CDTrack
{
public:
// Basic Functions
CDTrack(SCSICD *scsicd);
// Constructor
virtual ~CDTrack();
// Destructor
BOOL FASTCALL Init(int track, DWORD first, DWORD last);
// Initialization
// Properties
void FASTCALL SetPath(BOOL cdda, const Filepath& path);
// Set the path
void FASTCALL GetPath(Filepath& path) const;
// Get the path
void FASTCALL AddIndex(int index, DWORD lba);
// Add index
DWORD FASTCALL GetFirst() const;
// Get the start LBA
DWORD FASTCALL GetLast() const;
// Get the last LBA
DWORD FASTCALL GetBlocks() const;
// Get the number of blocks
int FASTCALL GetTrackNo() const;
// Get the track number
BOOL FASTCALL IsValid(DWORD lba) const;
// Is this a valid LBA?
BOOL FASTCALL IsAudio() const;
// Is this an audio track?
private:
SCSICD *cdrom;
// Parent device
BOOL valid;
// Valid track
int track_no;
// Track number
DWORD first_lba;
// First LBA
DWORD last_lba;
// Last LBA
BOOL audio;
// Audio track flag
BOOL raw;
// RAW data flag
Filepath imgpath;
// Image file path
};
//===========================================================================
//
// CD-DA Buffer
//
//===========================================================================
class CDDABuf
{
public:
// Basic Functions
CDDABuf();
// Constructor
virtual ~CDDABuf();
// Destructor
#if 0
BOOL Init();
// Initialization
BOOL FASTCALL Load(const Filepath& path);
// Load
BOOL FASTCALL Save(const Filepath& path);
// Save
// API
void FASTCALL Clear();
// Clear the buffer
BOOL FASTCALL Open(Filepath& path);
// File specification
BOOL FASTCALL GetBuf(DWORD *buffer, int frames);
// Get the buffer
BOOL FASTCALL IsValid();
// Check if Valid
BOOL FASTCALL ReadReq();
// Read Request
BOOL FASTCALL IsEnd() const;
// Finish check
private:
Filepath wavepath;
// Wave path
BOOL valid;
// Open result (is it valid?)
DWORD *buf;
// Data buffer
DWORD read;
// Read pointer
DWORD write;
// Write pointer
DWORD num;
// Valid number of data
DWORD rest;
// Remaining file size
#endif
};
//===========================================================================
//
// SCSI CD-ROM
//
//===========================================================================
class SCSICD : public Disk
{
public:
// Number of tracks
enum {
TrackMax = 96 // Maximum number of tracks
};
public:
// Basic Functions
SCSICD();
// Constructor
virtual ~SCSICD();
// Destructor
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
#ifndef RASCSI
BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
int FASTCALL Read(BYTE *buf, DWORD block);
// READ command
int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf);
// READ TOC command
BOOL FASTCALL PlayAudio(const DWORD *cdb);
// PLAY AUDIO command
BOOL FASTCALL PlayAudioMSF(const DWORD *cdb);
// PLAY AUDIO MSF command
BOOL FASTCALL PlayAudioTrack(const DWORD *cdb);
// PLAY AUDIO TRACK command
// CD-DA
BOOL FASTCALL NextFrame();
// Frame notification
void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate);
// Get CD-DA buffer
// LBA-MSF変換
void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const;
// LBA→MSF conversion
DWORD FASTCALL MSFtoLBA(const BYTE *msf) const;
// MSF→LBA conversion
private:
// Open
BOOL FASTCALL OpenCue(const Filepath& path);
// Open(CUE)
BOOL FASTCALL OpenIso(const Filepath& path);
// Open(ISO)
BOOL FASTCALL OpenPhysical(const Filepath& path);
// Open(Physical)
BOOL rawfile;
// RAW flag
// Track management
void FASTCALL ClearTrack();
// Clear the track
int FASTCALL SearchTrack(DWORD lba) const;
// Track search
CDTrack* track[TrackMax];
// Track opbject references
int tracks;
// Effective number of track objects
int dataindex;
// Current data track
int audioindex;
// Current audio track
int frame;
// Frame number
#if 0
CDDABuf da_buf;
// CD-DA buffer
int da_num;
// Number of CD-DA tracks
int da_cur;
// CD-DA current track
int da_next;
// CD-DA next track
BOOL da_req;
// CD-DA data request
#endif
};

View File

@@ -0,0 +1,268 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI hard disk ]
//
//---------------------------------------------------------------------------
#include "scsihd.h"
#include "xm6.h"
#include "fileio.h"
//===========================================================================
//
// SCSI Hard Disk
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSIHD::SCSIHD() : Disk()
{
// SCSI Hard Disk
disk.id = MAKEID('S', 'C', 'H', 'D');
}
//---------------------------------------------------------------------------
//
// Reset
//
//---------------------------------------------------------------------------
void FASTCALL SCSIHD::Reset()
{
// Unlock and release attention
disk.lock = FALSE;
disk.attn = FALSE;
// No reset, clear code
disk.reset = FALSE;
disk.code = 0x00;
}
//---------------------------------------------------------------------------
//
// Open
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIHD::Open(const Filepath& path, BOOL /*attn*/)
{
Fileio fio;
off64_t size;
ASSERT(this);
ASSERT(!disk.ready);
// read open required
if (!fio.Open(path, Fileio::ReadOnly)) {
return FALSE;
}
// Get file size
size = fio.GetFileSize();
fio.Close();
// Must be 512 bytes
if (size & 0x1ff) {
return FALSE;
}
// 10MB or more
if (size < 0x9f5400) {
return FALSE;
}
// 2TB according to xm6i
// There is a similar one in wxw/wxw_cfg.cpp
if (size > 2LL * 1024 * 1024 * 1024 * 1024) {
return FALSE;
}
// sector size and number of blocks
disk.size = 9;
disk.blocks = (DWORD)(size >> 9);
// Call base class
return Disk::Open(path);
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD::Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor)
{
char vendor[32];
char product[32];
char rev[32];
int size;
ASSERT(this);
ASSERT(cdb);
ASSERT(buf);
ASSERT(cdb[0] == 0x12);
// EVPD check
if (cdb[1] & 0x01) {
disk.code = DISK_INVALIDCDB;
return 0;
}
// Ready check (Error if no image file)
if (!disk.ready) {
disk.code = DISK_NOTREADY;
return 0;
}
// Basic data
// buf[0] ... Direct Access Device
// buf[2] ... SCSI-2 compliant command system
// buf[3] ... SCSI-2 compliant Inquiry response
// buf[4] ... Inquiry additional data
memset(buf, 0, 8);
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
if (((cdb[1] >> 5) & 0x07) != disk.lun) {
buf[0] = 0x7f;
}
buf[2] = 0x02;
buf[3] = 0x02;
buf[4] = 122 + 3; // Value close to real HDD
// Fill with blanks
memset(&buf[8], 0x20, buf[4] - 3);
// Determine vendor name/product name
sprintf(vendor, BENDER_SIGNATURE);
size = disk.blocks >> 11;
if (size < 300)
sprintf(product, "PRODRIVE LPS%dS", size);
else if (size < 600)
sprintf(product, "MAVERICK%dS", size);
else if (size < 800)
sprintf(product, "LIGHTNING%dS", size);
else if (size < 1000)
sprintf(product, "TRAILBRAZER%dS", size);
else if (size < 2000)
sprintf(product, "FIREBALL%dS", size);
else
sprintf(product, "FBSE%d.%dS", size / 1000, (size % 1000) / 100);
// Vendor name
memcpy(&buf[8], vendor, strlen(vendor));
// Product name
memcpy(&buf[16], product, strlen(product));
// Revision
sprintf(rev, "0%01d%01d%01d",
(int)major, (int)(minor >> 4), (int)(minor & 0x0f));
memcpy(&buf[32], rev, 4);
// Size of data that can be returned
size = (buf[4] + 5);
// Limit if the other buffer is small
if (size > (int)cdb[4]) {
size = (int)cdb[4];
}
// Success
disk.code = DISK_NOERROR;
return size;
}
//---------------------------------------------------------------------------
//
// MODE SELECT
// *Not affected by disk.code
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
{
BYTE page;
int size;
ASSERT(this);
ASSERT(buf);
ASSERT(length >= 0);
// PF
if (cdb[1] & 0x10) {
// Mode Parameter header
if (length >= 12) {
// Check the block length bytes
size = 1 << disk.size;
if (buf[9] != (BYTE)(size >> 16) ||
buf[10] != (BYTE)(size >> 8) ||
buf[11] != (BYTE)size) {
// currently does not allow changing sector length
disk.code = DISK_INVALIDPRM;
return FALSE;
}
buf += 12;
length -= 12;
}
// Parsing the page
while (length > 0) {
// Get page
page = buf[0];
switch (page) {
// format device
case 0x03:
// check the number of bytes in the physical sector
size = 1 << disk.size;
if (buf[0xc] != (BYTE)(size >> 8) ||
buf[0xd] != (BYTE)size) {
// currently does not allow changing sector length
disk.code = DISK_INVALIDPRM;
return FALSE;
}
break;
// CD-ROM Parameters
// According to the SONY CDU-541 manual, Page code 8 is supposed
// to set the Logical Block Adress Format, as well as the
// inactivity timer multiplier
case 0x08:
// Debug code for Issue #2:
// https://github.com/akuker/RASCSI/issues/2
printf("[Unhandled page code] Received mode page code 8 with total length %d\n ", length);
for (int i = 0; i<length; i++)
{
printf("%02X ", buf[i]);
}
printf("\n");
break;
// Other page
default:
printf("Unknown Mode Select page code received: %02X\n",page);
break;
}
// Advance to the next page
size = buf[1] + 2;
length -= size;
buf += size;
}
}
// Do not generate an error for the time being (MINIX)
disk.code = DISK_NOERROR;
return TRUE;
}

View File

@@ -0,0 +1,44 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI hard disk ]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "disk.h"
#include "filepath.h"
//===========================================================================
//
// SCSI Hard Disk
//
//===========================================================================
class SCSIHD : public Disk
{
public:
// Basic Functions
SCSIHD();
// Constructor
void FASTCALL Reset();
// Reset
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands
int FASTCALL Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
// MODE SELECT(6) command
};

View File

@@ -0,0 +1,93 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Hard Disk for Apple Macintosh ]
//
//---------------------------------------------------------------------------
#include "scsihd_apple.h"
//===========================================================================
//
// SCSI hard disk (Macintosh Apple genuine)
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSIHD_APPLE::SCSIHD_APPLE() : SCSIHD()
{
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_APPLE::Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor)
{
int size;
char vendor[32];
char product[32];
// Call the base class
size = SCSIHD::Inquiry(cdb, buf, major, minor);
// End if there is an error in the base class
if (size == 0) {
return 0;
}
// Vendor name
sprintf(vendor, " SEAGATE");
memcpy(&buf[8], vendor, strlen(vendor));
// Product name
sprintf(product, " ST225N");
memcpy(&buf[16], product, strlen(product));
return size;
}
//---------------------------------------------------------------------------
//
// Add Vendor special page
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_APPLE::AddVendor(int page, BOOL change, BYTE *buf)
{
ASSERT(this);
ASSERT(buf);
// Page code 48
if ((page != 0x30) && (page != 0x3f)) {
return 0;
}
// Set the message length
buf[0] = 0x30;
buf[1] = 0x1c;
// No changeable area
if (change) {
return 30;
}
// APPLE COMPUTER, INC.
memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20);
return 30;
}

View File

@@ -0,0 +1,39 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Hard Disk for Apple Macintosh ]
//
//---------------------------------------------------------------------------
#pragma once
#include "scsihd.h"
//===========================================================================
//
// SCSI Hard Disk(Genuine Apple Macintosh)
//
//===========================================================================
class SCSIHD_APPLE : public SCSIHD
{
public:
// Basic Functions
SCSIHD_APPLE();
// Constructor
// commands
int FASTCALL Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
// Internal processing
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
// Add vendor special page
};

View File

@@ -0,0 +1,295 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI NEC "Genuine" Hard Disk]
//
//---------------------------------------------------------------------------
#include "scsihd_nec.h"
#include "fileio.h"
//===========================================================================
//
// SCSI hard disk (PC-9801-55 NEC genuine /Anex86/T98Next)
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSIHD_NEC::SCSIHD_NEC() : SCSIHD()
{
// ワーク初期化
cylinders = 0;
heads = 0;
sectors = 0;
sectorsize = 0;
imgoffset = 0;
imgsize = 0;
}
//---------------------------------------------------------------------------
//
// リトルエンディアンと想定したワードを取り出す
//
//---------------------------------------------------------------------------
static inline WORD getWordLE(const BYTE *b)
{
return ((WORD)(b[1]) << 8) | b[0];
}
//---------------------------------------------------------------------------
//
// リトルエンディアンと想定したロングワードを取り出す
//
//---------------------------------------------------------------------------
static inline DWORD getDwordLE(const BYTE *b)
{
return ((DWORD)(b[3]) << 24) | ((DWORD)(b[2]) << 16) |
((DWORD)(b[1]) << 8) | b[0];
}
//---------------------------------------------------------------------------
//
// オープン
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIHD_NEC::Open(const Filepath& path, BOOL /*attn*/)
{
Fileio fio;
off64_t size;
BYTE hdr[512];
LPCTSTR ext;
ASSERT(this);
ASSERT(!disk.ready);
// Open as read-only
if (!fio.Open(path, Fileio::ReadOnly)) {
return FALSE;
}
// Get file size
size = fio.GetFileSize();
// ヘッダー読み込み
if (size >= (off64_t)sizeof(hdr)) {
if (!fio.Read(hdr, sizeof(hdr))) {
fio.Close();
return FALSE;
}
}
fio.Close();
// 512バイト単位であること
if (size & 0x1ff) {
return FALSE;
}
// 10MB以上
if (size < 0x9f5400) {
return FALSE;
}
// xm6iに準じて2TB
// よく似たものが wxw/wxw_cfg.cpp にもある
if (size > 2LL * 1024 * 1024 * 1024 * 1024) {
return FALSE;
}
// 拡張子別にパラメータを決定
ext = path.GetFileExt();
if (xstrcasecmp(ext, _T(".HDN")) == 0) {
// デフォルト設定としてセクタサイズ512,セクタ数25,ヘッド数8を想定
imgoffset = 0;
imgsize = size;
sectorsize = 512;
sectors = 25;
heads = 8;
cylinders = (int)(size >> 9);
cylinders >>= 3;
cylinders /= 25;
} else if (xstrcasecmp(ext, _T(".HDI")) == 0) { // Anex86 HD image?
imgoffset = getDwordLE(&hdr[4 + 4]);
imgsize = getDwordLE(&hdr[4 + 4 + 4]);
sectorsize = getDwordLE(&hdr[4 + 4 + 4 + 4]);
sectors = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4]);
heads = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4]);
cylinders = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4 + 4]);
} else if (xstrcasecmp(ext, _T(".NHD")) == 0 &&
memcmp(hdr, "T98HDDIMAGE.R0\0", 15) == 0) { // T98Next HD image?
imgoffset = getDwordLE(&hdr[0x10 + 0x100]);
cylinders = getDwordLE(&hdr[0x10 + 0x100 + 4]);
heads = getWordLE(&hdr[0x10 + 0x100 + 4 + 4]);
sectors = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2]);
sectorsize = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2 + 2]);
imgsize = (off64_t)cylinders * heads * sectors * sectorsize;
}
// セクタサイズは256または512をサポート
if (sectorsize != 256 && sectorsize != 512) {
return FALSE;
}
// イメージサイズの整合性チェック
if (imgoffset + imgsize > size || (imgsize % sectorsize != 0)) {
return FALSE;
}
// セクタサイズ
for(disk.size = 16; disk.size > 0; --(disk.size)) {
if ((1 << disk.size) == sectorsize)
break;
}
if (disk.size <= 0 || disk.size > 16) {
return FALSE;
}
// ブロック数
disk.blocks = (DWORD)(imgsize >> disk.size);
disk.imgoffset = imgoffset;
// Call the base class
return Disk::Open(path);
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_NEC::Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor)
{
int size;
// 基底クラス
size = SCSIHD::Inquiry(cdb, buf, major, minor);
// 基底クラスでエラーなら終了
if (size == 0) {
return 0;
}
// SCSI1相当に変更
buf[2] = 0x01;
buf[3] = 0x01;
// Replace Vendor name
buf[8] = 'N';
buf[9] = 'E';
buf[10] = 'C';
return size;
}
//---------------------------------------------------------------------------
//
// エラーページ追加
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_NEC::AddError(BOOL change, BYTE *buf)
{
ASSERT(this);
ASSERT(buf);
// Set the message length
buf[0] = 0x01;
buf[1] = 0x06;
// No changeable area
if (change) {
return 8;
}
// リトライカウントは0、リミットタイムは装置内部のデフォルト値を使用
return 8;
}
//---------------------------------------------------------------------------
//
// フォーマットページ追加
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_NEC::AddFormat(BOOL change, BYTE *buf)
{
int size;
ASSERT(this);
ASSERT(buf);
// Set the message length
buf[0] = 0x80 | 0x03;
buf[1] = 0x16;
// 物理セクタのバイト数は変更可能に見せる(実際には変更できないが)
if (change) {
buf[0xc] = 0xff;
buf[0xd] = 0xff;
return 24;
}
if (disk.ready) {
// 1ゾーンのトラック数を設定(PC-9801-55はこの値を見ているようだ)
buf[0x2] = (BYTE)(heads >> 8);
buf[0x3] = (BYTE)heads;
// 1トラックのセクタ数を設定
buf[0xa] = (BYTE)(sectors >> 8);
buf[0xb] = (BYTE)sectors;
// 物理セクタのバイト数を設定
size = 1 << disk.size;
buf[0xc] = (BYTE)(size >> 8);
buf[0xd] = (BYTE)size;
}
// リムーバブル属性を設定(昔の名残)
if (disk.removable) {
buf[20] = 0x20;
}
return 24;
}
//---------------------------------------------------------------------------
//
// ドライブページ追加
//
//---------------------------------------------------------------------------
int FASTCALL SCSIHD_NEC::AddDrive(BOOL change, BYTE *buf)
{
ASSERT(this);
ASSERT(buf);
// Set the message length
buf[0] = 0x04;
buf[1] = 0x12;
// No changeable area
if (change) {
return 20;
}
if (disk.ready) {
// シリンダ数を設定
buf[0x2] = (BYTE)(cylinders >> 16);
buf[0x3] = (BYTE)(cylinders >> 8);
buf[0x4] = (BYTE)cylinders;
// ヘッド数を設定
buf[0x5] = (BYTE)heads;
}
return 20;
}

View File

@@ -0,0 +1,61 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI NEC "Genuine" Hard Disk]
//
//---------------------------------------------------------------------------
#pragma once
#include "scsihd.h"
//===========================================================================
//
// SCSI hard disk (PC-9801-55 NEC genuine /Anex86/T98Next)
//
//===========================================================================
class SCSIHD_NEC : public SCSIHD
{
public:
// Basic Functions
SCSIHD_NEC();
// Constructor
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands
int FASTCALL Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
// Internal processing
int FASTCALL AddError(BOOL change, BYTE *buf);
// Add error
int FASTCALL AddFormat(BOOL change, BYTE *buf);
// Add format
int FASTCALL AddDrive(BOOL change, BYTE *buf);
// Add drive
private:
int cylinders;
// Number of cylinders
int heads;
// Number of heads
int sectors;
// Number of sectors
int sectorsize;
// Sector size
off64_t imgoffset;
// Image offset
off64_t imgsize;
// Image size
};

View File

@@ -0,0 +1,421 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Magneto-Optical Disk]
//
//---------------------------------------------------------------------------
#include "scsimo.h"
#include "xm6.h"
#include "fileio.h"
//===========================================================================
//
// SCSI magneto-optical disk
//
//===========================================================================
//---------------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------------
SCSIMO::SCSIMO() : Disk()
{
// SCSI magneto-optical disk
disk.id = MAKEID('S', 'C', 'M', 'O');
// Set as removable
disk.removable = TRUE;
}
//---------------------------------------------------------------------------
//
// Open
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIMO::Open(const Filepath& path, BOOL attn)
{
Fileio fio;
off64_t size;
ASSERT(this);
ASSERT(!disk.ready);
// Open as read-only
if (!fio.Open(path, Fileio::ReadOnly)) {
return FALSE;
}
// Get file size
size = fio.GetFileSize();
fio.Close();
switch (size) {
// 128MB
case 0x797f400:
disk.size = 9;
disk.blocks = 248826;
break;
// 230MB
case 0xd9eea00:
disk.size = 9;
disk.blocks = 446325;
break;
// 540MB
case 0x1fc8b800:
disk.size = 9;
disk.blocks = 1041500;
break;
// 640MB
case 0x25e28000:
disk.size = 11;
disk.blocks = 310352;
break;
// Other (this is an error)
default:
return FALSE;
}
// Call the base class
Disk::Open(path);
// Attention if ready
if (disk.ready && attn) {
disk.attn = TRUE;
}
return TRUE;
}
#ifndef RASCSI
//---------------------------------------------------------------------------
//
// Load
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIMO::Load(Fileio *fio, int ver)
{
DWORD sz;
disk_t buf;
DWORD padding;
Filepath path;
ASSERT(this);
ASSERT(fio);
ASSERT(ver >= 0x0200);
// Prior to version 2.03, the disk was not saved
if (ver <= 0x0202) {
return TRUE;
}
// load size, match
if (!fio->Read(&sz, sizeof(sz))) {
return FALSE;
}
if (sz != 52) {
return FALSE;
}
// load into buffer
PROP_IMPORT(fio, buf.id);
PROP_IMPORT(fio, buf.ready);
PROP_IMPORT(fio, buf.writep);
PROP_IMPORT(fio, buf.readonly);
PROP_IMPORT(fio, buf.removable);
PROP_IMPORT(fio, buf.lock);
PROP_IMPORT(fio, buf.attn);
PROP_IMPORT(fio, buf.reset);
PROP_IMPORT(fio, buf.size);
PROP_IMPORT(fio, buf.blocks);
PROP_IMPORT(fio, buf.lun);
PROP_IMPORT(fio, buf.code);
PROP_IMPORT(fio, padding);
// Load path
if (!path.Load(fio, ver)) {
return FALSE;
}
// Always eject
Eject(TRUE);
// Move only if IDs match
if (disk.id != buf.id) {
// Not MO at the time of save. Maintain eject status
return TRUE;
}
// Re-try opening
if (!Open(path, FALSE)) {
// Cannot reopen. Maintain eject status
return TRUE;
}
// Disk cache is created in Open. Move property only
if (!disk.readonly) {
disk.writep = buf.writep;
}
disk.lock = buf.lock;
disk.attn = buf.attn;
disk.reset = buf.reset;
disk.lun = buf.lun;
disk.code = buf.code;
// loaded successfully
return TRUE;
}
#endif // RASCSI
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int FASTCALL SCSIMO::Inquiry(
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor)
{
int size;
char rev[32];
ASSERT(this);
ASSERT(cdb);
ASSERT(buf);
ASSERT(cdb[0] == 0x12);
// EVPD check
if (cdb[1] & 0x01) {
disk.code = DISK_INVALIDCDB;
return FALSE;
}
// 基本データ
// buf[0] ... Optical Memory Device
// buf[1] ... Removable
// buf[2] ... SCSI-2 compliant command system
// buf[3] ... SCSI-2 compliant Inquiry response
// buf[4] ... Inquiry additional data
memset(buf, 0, 8);
buf[0] = 0x07;
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
if (((cdb[1] >> 5) & 0x07) != disk.lun) {
buf[0] = 0x7f;
}
buf[1] = 0x80;
buf[2] = 0x02;
buf[3] = 0x02;
buf[4] = 36 - 5; // required
// Fill with blanks
memset(&buf[8], 0x20, buf[4] - 3);
// Vendor name
memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE));
// Product name
memcpy(&buf[16], "M2513A", 6);
// Revision (XM6 version number)
sprintf(rev, "0%01d%01d%01d",
(int)major, (int)(minor >> 4), (int)(minor & 0x0f));
memcpy(&buf[32], rev, 4);
// Size return data
size = (buf[4] + 5);
// Limit the size if the buffer is too small
if (size > (int)cdb[4]) {
size = (int)cdb[4];
}
// Success
disk.code = DISK_NOERROR;
return size;
}
//---------------------------------------------------------------------------
//
// MODE SELECT
// *Not affected by disk.code
//
//---------------------------------------------------------------------------
BOOL FASTCALL SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
{
int page;
int size;
ASSERT(this);
ASSERT(buf);
ASSERT(length >= 0);
// PF
if (cdb[1] & 0x10) {
// Mode Parameter header
if (length >= 12) {
// Check the block length (in bytes)
size = 1 << disk.size;
if (buf[9] != (BYTE)(size >> 16) ||
buf[10] != (BYTE)(size >> 8) || buf[11] != (BYTE)size) {
// Currently does not allow changing sector length
disk.code = DISK_INVALIDPRM;
return FALSE;
}
buf += 12;
length -= 12;
}
// Parsing the page
while (length > 0) {
// Get the page
page = buf[0];
switch (page) {
// format device
case 0x03:
// Check the number of bytes in the physical sector
size = 1 << disk.size;
if (buf[0xc] != (BYTE)(size >> 8) ||
buf[0xd] != (BYTE)size) {
// Currently does not allow changing sector length
disk.code = DISK_INVALIDPRM;
return FALSE;
}
break;
// vendor unique format
case 0x20:
// just ignore, for now
break;
// Other page
default:
break;
}
// Advance to the next page
size = buf[1] + 2;
length -= size;
buf += size;
}
}
// Do not generate an error for the time being (MINIX)
disk.code = DISK_NOERROR;
return TRUE;
}
//---------------------------------------------------------------------------
//
// Vendor Unique Format Page 20h (MO)
//
//---------------------------------------------------------------------------
int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf)
{
ASSERT(this);
ASSERT(buf);
// Page code 20h
if ((page != 0x20) && (page != 0x3f)) {
return 0;
}
// Set the message length
buf[0] = 0x20;
buf[1] = 0x0a;
// No changeable area
if (change) {
return 12;
}
/*
mode page code 20h - Vendor Unique Format Page
format mode XXh type 0
information: http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-lpg28560-1.pdf
offset description
02h format mode
03h type of format (0)
04~07h size of user band (total sectors?)
08~09h size of spare band (spare sectors?)
0A~0Bh number of bands
actual value of each 3.5inches optical medium (grabbed by Fujitsu M2513EL)
128M 230M 540M 640M
---------------------------------------------------
size of user band 3CBFAh 6CF75h FE45Ch 4BC50h
size of spare band 0400h 0401h 08CAh 08C4h
number of bands 0001h 000Ah 0012h 000Bh
further information: http://r2089.blog36.fc2.com/blog-entry-177.html
*/
if (disk.ready) {
unsigned spare = 0;
unsigned bands = 0;
if (disk.size == 9) switch (disk.blocks) {
// 128MB
case 248826:
spare = 1024;
bands = 1;
break;
// 230MB
case 446325:
spare = 1025;
bands = 10;
break;
// 540MB
case 1041500:
spare = 2250;
bands = 18;
break;
}
if (disk.size == 11) switch (disk.blocks) {
// 640MB
case 310352:
spare = 2244;
bands = 11;
break;
// 1.3GB (lpproj: not tested with real device)
case 605846:
spare = 4437;
bands = 18;
break;
}
buf[2] = 0; // format mode
buf[3] = 0; // type of format
buf[4] = (BYTE)(disk.blocks >> 24);
buf[5] = (BYTE)(disk.blocks >> 16);
buf[6] = (BYTE)(disk.blocks >> 8);
buf[7] = (BYTE)disk.blocks;
buf[8] = (BYTE)(spare >> 8);
buf[9] = (BYTE)spare;
buf[10] = (BYTE)(bands >> 8);
buf[11] = (BYTE)bands;
}
return 12;
}

View File

@@ -0,0 +1,49 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Magneto-Optical Disk]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "disk.h"
#include "filepath.h"
//===========================================================================
//
// SCSI magneto-optical disk
//
//===========================================================================
class SCSIMO : public Disk
{
public:
// Basic Functions
SCSIMO();
// Constructor
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
#ifndef RASCSI
BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
// MODE SELECT(6) command
// Internal processing
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
// Add vendor special page
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,8 @@
#if !defined(fileio_h)
#define fileio_h
#include "filepath.h"
#ifdef BAREMETAL
#include "ff.h"
#endif // BAREMETAL

View File

@@ -11,6 +11,8 @@
#if !defined(filepath_h)
#define filepath_h
class Fileio;
//---------------------------------------------------------------------------
//
// 定数定義

BIN
src/raspberrypi/foo.hda Normal file

Binary file not shown.

View File

@@ -144,6 +144,10 @@ GPIOBUS::~GPIOBUS()
//---------------------------------------------------------------------------
BOOL FASTCALL GPIOBUS::Init(mode_e mode)
{
#if defined(__x86_64__) || defined(__X86__)
// When we're running on x86, there is no hardware to talk to, so just return.
return true;
#else
void *map;
int i;
int j;
@@ -379,6 +383,8 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
SetControl(PIN_ENB, ENB_ON);
return TRUE;
#endif // ifdef __x86_64__ || __X86__
}
//---------------------------------------------------------------------------
@@ -388,6 +394,9 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
//---------------------------------------------------------------------------
void FASTCALL GPIOBUS::Cleanup()
{
#if defined(__x86_64__) || defined(__X86__)
return;
#else
int i;
int pin;
@@ -419,6 +428,7 @@ void FASTCALL GPIOBUS::Cleanup()
// Set drive strength back to 8mA
DrvConfig(3);
#endif // ifdef __x86_64__ || __X86__
}
//---------------------------------------------------------------------------
@@ -428,6 +438,9 @@ void FASTCALL GPIOBUS::Cleanup()
//---------------------------------------------------------------------------
void FASTCALL GPIOBUS::Reset()
{
#if defined(__x86_64__) || defined(__X86__)
return;
#else
int i;
int j;
@@ -506,6 +519,7 @@ void FASTCALL GPIOBUS::Reset()
// Initialize all signals
signals = 0;
#endif // ifdef __x86_64__ || __X86__
}
//---------------------------------------------------------------------------
@@ -515,6 +529,9 @@ void FASTCALL GPIOBUS::Reset()
//---------------------------------------------------------------------------
DWORD FASTCALL GPIOBUS::Aquire()
{
#if defined(__x86_64__) || defined(__X86__)
return 0;
#else
signals = *level;
#if SIGNAL_CONTROL_MODE < 2
@@ -523,6 +540,7 @@ DWORD FASTCALL GPIOBUS::Aquire()
#endif // SIGNAL_CONTROL_MODE
return signals;
#endif // ifdef __x86_64__ || __X86__
}
//---------------------------------------------------------------------------

View File

@@ -0,0 +1,2 @@
if $programname == 'RASCSI' then /var/log/rascsi.log
& stop

View File

@@ -0,0 +1,19 @@
[Unit]
Description=RaSCSI service
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/local/bin/rascsi
# Example: If you want to automatically attach a hard disk at startup, change
# the ExecStart line to:
# ExecStart=/usr/local/bin/rascsi -ID1 /home/pi/images/harddisk.hda
ExecStop=/usr/local/bin/rasctl -stop
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=RASCSI
[Install]
WantedBy=multi-user.target

14
src/raspberrypi/rascsi.1 Normal file
View File

@@ -0,0 +1,14 @@
.TH rascsi 1
.SH NAME
rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
.SH SYNOPSIS
.B rascsi
[\fB\-HDn\fR \fIfile\fR] ...
.SH DESCRIPTION
.B corrupt
modifies files by toggling a randomly chosen bit.
.SH OPTIONS
.TP
.BR \-n ", " \-\-bits =\fIBITS\fR
Set the number of bits to modify.
Default is one bit.

View File

@@ -13,10 +13,20 @@
#include "xm6.h"
#include "filepath.h"
#include "fileio.h"
#include "disk.h"
#include "devices/disk.h"
#include "devices/sasihd.h"
#include "devices/scsihd.h"
#include "devices/scsihd_apple.h"
#include "devices/scsihd_nec.h"
#include "devices/scsicd.h"
#include "devices/scsimo.h"
#include "devices/scsi_host_bridge.h"
#include "controllers/scsidev_ctrl.h"
#include "controllers/sasidev_ctrl.h"
#include "gpiobus.h"
#include "spdlog/spdlog.h"
//---------------------------------------------------------------------------
//
// Constant declarations
@@ -607,20 +617,24 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
return TRUE;
}
bool has_suffix(const char* string, const char* suffix) {
int string_len = strlen(string);
int suffix_len = strlen(suffix);
return (string_len >= suffix_len)
&& (xstrcasecmp(string + (string_len - suffix_len), suffix) == 0);
}
//---------------------------------------------------------------------------
//
// Argument Parsing
//
//---------------------------------------------------------------------------
BOOL ParseArgument(int argc, char* argv[])
{
#ifdef BAREMETAL
BOOL ParseConfig(int argc, char* argv[])
{
FRESULT fr;
FIL fp;
char line[512];
#else
int i;
#endif // BAREMETAL
int id;
int un;
int type;
@@ -629,7 +643,6 @@ BOOL ParseArgument(int argc, char* argv[])
int len;
char *ext;
#ifdef BAREMETAL
// Mount the SD card
fr = f_mount(&fatfs, "", 1);
if (fr != FR_OK) {
@@ -642,19 +655,10 @@ BOOL ParseArgument(int argc, char* argv[])
if (fr != FR_OK) {
return FALSE;
}
#else
// If the ID and path are not specified, the processing is interrupted
if (argc < 3) {
return TRUE;
}
i = 1;
argc--;
#endif // BAREMETAL
// Start Decoding
while (TRUE) {
#ifdef BAREMETAL
// Get one Line
memset(line, 0x00, sizeof(line));
if (f_gets(line, sizeof(line) -1, &fp) == NULL) {
@@ -670,16 +674,8 @@ BOOL ParseArgument(int argc, char* argv[])
line[len - 1] = '\0';
len--;
}
#else
if (argc < 2) {
break;
}
argc -= 2;
#endif // BAREMETAL
// Get the ID and Path
#ifdef BAREMETAL
argID = &line[0];
argPath = &line[4];
line[3] = '\0';
@@ -688,18 +684,6 @@ BOOL ParseArgument(int argc, char* argv[])
if (argID[0] == '\0' || argPath[0] == '\0') {
continue;
}
#else
argID = argv[i++];
argPath = argv[i++];
// Check if the argument is invalid
if (argID[0] != '-') {
FPRT(stderr,
"Error : Invalid argument(-IDn or -HDn) [%s]\n", argID);
goto parse_error;
}
argID++;
#endif // BAREMETAL
if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) {
// ID or ID Format
@@ -739,9 +723,7 @@ BOOL ParseArgument(int argc, char* argv[])
// The ID unit is good - create the id and unit number
id = ((argID[3] - '0') + 10) / UnitNum;
un = ((argID[3] - '0') + 10) % UnitNum;
#ifdef BAREMETAL
argPath++;
#endif // BAREMETAL
} else {
FPRT(stderr,
"Error : Invalid argument(IDn or HDn) [%s]\n", argID);
@@ -811,10 +793,8 @@ BOOL ParseArgument(int argc, char* argv[])
}
}
#ifdef BAREMETAL
// Close the configuration file
f_close(&fp);
#endif // BAREMETAL
// Display the device list
ListDevice(stdout);
@@ -823,13 +803,102 @@ BOOL ParseArgument(int argc, char* argv[])
parse_error:
#ifdef BAREMETAL
// Close the configuration file
f_close(&fp);
#endif // BAREMETAL
return FALSE;
}
#else
bool ParseArgument(int argc, char* argv[])
{
int id = -1;
bool is_sasi = false;
int max_id = 7;
int opt;
while ((opt = getopt(argc, argv, "-IiHhD:d:")) != -1) {
switch (opt) {
case 'I':
case 'i':
is_sasi = false;
max_id = 7;
id = -1;
continue;
case 'H':
case 'h':
is_sasi = true;
max_id = 15;
id = -1;
continue;
case 'D':
case 'd': {
char* end;
id = strtol(optarg, &end, 10);
if (*end || (id < 0) || (max_id < id)) {
fprintf(stderr, "%s: invalid %s (0-%d)\n",
optarg, is_sasi ? "HD" : "ID", max_id);
return false;
}
continue;
}
default:
return false;
case 1:
break;
}
if (id < 0) {
fprintf(stderr, "%s: ID not specified\n", optarg);
return false;
} else if (disk[id] && !disk[id]->IsNULL()) {
fprintf(stderr, "%d: duplicate ID\n", id);
return false;
}
char* path = optarg;
int type = -1;
if (has_suffix(path, ".hdf")
|| has_suffix(path, ".hds")
|| has_suffix(path, ".hdn")
|| has_suffix(path, ".hdi")
|| has_suffix(path, ".hda")
|| has_suffix(path, ".nhd")) {
type = 0;
} else if (has_suffix(path, ".mos")) {
type = 2;
} else if (has_suffix(path, ".iso")) {
type = 3;
} else if (xstrcasecmp(path, "bridge") == 0) {
type = 4;
} else {
// Cannot determine the file type
fprintf(stderr,
"%s: unknown file extension\n", path);
return false;
}
int un = 0;
if (is_sasi) {
un = id % UnitNum;
id /= UnitNum;
}
// Execute the command
if (!ProcessCmd(stderr, id, un, 0, type, path)) {
return false;
}
id = -1;
}
// Display the device list
ListDevice(stdout);
return true;
}
#endif // BAREMETAL
#ifndef BAREMETAL
//---------------------------------------------------------------------------
@@ -1014,13 +1083,19 @@ int main(int argc, char* argv[])
#ifdef BAREMETAL
// BUSY assert (to hold the host side)
bus->SetBSY(TRUE);
#endif
// Argument parsing
if (!ParseConfig(argc, argv)) {
ret = EINVAL;
goto err_exit;
}
#else
// Argument parsing
if (!ParseArgument(argc, argv)) {
ret = EINVAL;
goto err_exit;
}
#endif
#ifdef BAREMETAL
// Release the busy signal

14
src/raspberrypi/rasctl.1 Normal file
View File

@@ -0,0 +1,14 @@
.TH rascsi 1
.SH NAME
rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
.SH SYNOPSIS
.B rascsi
[\fB\-HDn\fR \fIfile\fR] ...
.SH DESCRIPTION
.B corrupt
modifies files by toggling a randomly chosen bit.
.SH OPTIONS
.TP
.BR \-n ", " \-\-bits =\fIBITS\fR
Set the number of bits to modify.
Default is one bit.

View File

@@ -39,7 +39,7 @@ BOOL SendCommand(char *buf)
// Send the command
fp = fdopen(fd, "r+");
setvbuf(fp, NULL, _IONBF, 0);
fprintf(fp, buf);
fputs(buf, fp);
// Receive the message
while (1) {