mirror of
https://github.com/thewesker/RASCSI.git
synced 2025-12-20 04:11:07 -05:00
Break up disk.h and disk.cpp to be smaller files (#22)
This commit is contained in:
@@ -9,15 +9,17 @@ CXX = $(CROSS_COMPILE)g++
|
|||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
# Debug CFLAGS
|
# Debug CFLAGS
|
||||||
CFLAGS = -DDISK_LOG -O0 -g -Wall -DDEBUG
|
CFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
|
||||||
CXXFLAGS = -DDISK_LOG -O0 -g -Wall -DDEBUG
|
CXXFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
|
||||||
BUILD_TYPE = Debug
|
BUILD_TYPE = Debug
|
||||||
else
|
else
|
||||||
# Release CFLAGS
|
# Release CFLAGS
|
||||||
CFLAGS ?= -O3 -Wall -Werror
|
CFLAGS += -O3 -Wall -Werror
|
||||||
CXXFLAGS ?= -O3 -Wall -Werror
|
CXXFLAGS += -O3 -Wall -Werror
|
||||||
BUILD_TYPE = Release
|
BUILD_TYPE = Release
|
||||||
endif
|
endif
|
||||||
|
CFLAGS += -iquote .
|
||||||
|
CXXFLAGS += -std=c++14 -iquote .
|
||||||
|
|
||||||
# If its not specified, build for STANDARD configuration
|
# If its not specified, build for STANDARD configuration
|
||||||
CONNECT_TYPE ?= STANDARD
|
CONNECT_TYPE ?= STANDARD
|
||||||
@@ -37,24 +39,31 @@ USR_LOCAL_BIN = /usr/local/bin
|
|||||||
MAN_PAGE_DIR = /usr/share/man/man1
|
MAN_PAGE_DIR = /usr/share/man/man1
|
||||||
DOC_DIR = ../../doc
|
DOC_DIR = ../../doc
|
||||||
|
|
||||||
|
OBJDIR := ./obj
|
||||||
|
BINDIR := ./bin
|
||||||
|
|
||||||
#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON)
|
#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON)
|
||||||
# Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed
|
# 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!
|
# for my specific use case. If you need them - add them back in!
|
||||||
BIN_ALL = $(RASCSI) $(RASCTL)
|
BIN_ALL = $(BINDIR)/$(RASCSI) $(BINDIR)/$(RASCTL)
|
||||||
|
|
||||||
|
|
||||||
SRC_RASCSI = \
|
SRC_RASCSI = \
|
||||||
rascsi.cpp \
|
rascsi.cpp \
|
||||||
scsi.cpp \
|
scsi.cpp \
|
||||||
disk.cpp \
|
|
||||||
gpiobus.cpp \
|
gpiobus.cpp \
|
||||||
ctapdriver.cpp \
|
|
||||||
cfilesystem.cpp \
|
|
||||||
filepath.cpp \
|
filepath.cpp \
|
||||||
fileio.cpp
|
fileio.cpp\
|
||||||
|
# os.cpp
|
||||||
|
# rasctl_command.cpp
|
||||||
|
# rascsi_mgr.cpp
|
||||||
|
# command_thread.cpp
|
||||||
|
SRC_RASCSI += $(notdir $(shell find ./controllers -name '*.cpp'))
|
||||||
|
SRC_RASCSI += $(notdir $(shell find ./devices -name '*.cpp'))
|
||||||
|
|
||||||
SRC_RASCTL = \
|
SRC_RASCTL = \
|
||||||
rasctl.cpp
|
rasctl.cpp
|
||||||
|
# rasctl_command.cpp
|
||||||
|
|
||||||
SRC_RASDUMP = \
|
SRC_RASDUMP = \
|
||||||
rasdump.cpp \
|
rasdump.cpp \
|
||||||
@@ -70,18 +79,31 @@ SRC_SASIDUMP = \
|
|||||||
filepath.cpp \
|
filepath.cpp \
|
||||||
fileio.cpp
|
fileio.cpp
|
||||||
|
|
||||||
OBJ_RASCSI := $(SRC_RASCSI:%.cpp=%.o)
|
vpath %.h ./ ./controllers ./devices
|
||||||
OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o)
|
vpath %.cpp ./ ./controllers ./devices
|
||||||
OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o)
|
vpath %.o ./$(OBJDIR)
|
||||||
OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=%.o)
|
vpath ./$(BINDIR)
|
||||||
OBJ_SCSIMON := $(SRC_SCSIMON:%.cpp=%.o)
|
|
||||||
|
|
||||||
|
OBJ_RASCSI := $(SRC_RASCSI:%.cpp=$(OBJDIR)/%.o)
|
||||||
|
OBJ_RASCTL := $(SRC_RASCTL:%.cpp=$(OBJDIR)/%.o)
|
||||||
|
OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=$(OBJDIR)/%.o)
|
||||||
|
OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=$(OBJDIR)/%.o)
|
||||||
|
OBJ_SCSIMON := $(SRC_SCSIMON:%.cpp=$(OBJDIR)/%.o)
|
||||||
#OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON)
|
#OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON)
|
||||||
OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP)
|
OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP)
|
||||||
|
|
||||||
%.o: %.cpp
|
$(OBJDIR) $(BINDIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp $(OBJDIR)
|
||||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# $(OBJDIR)/%.o: %.c
|
||||||
|
# $(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# %.o: %.cpp
|
||||||
|
# $(CXX) $(CXXFLAGS) -c $(OBJDIR)/$< -o $@
|
||||||
|
|
||||||
.DEFAULT_GOAL := all
|
.DEFAULT_GOAL := all
|
||||||
.PHONY: all ALL docs
|
.PHONY: all ALL docs
|
||||||
@@ -90,23 +112,25 @@ ALL: all
|
|||||||
|
|
||||||
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt
|
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt
|
||||||
|
|
||||||
$(RASCSI): $(OBJ_RASCSI)
|
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) $(BINDIR)
|
||||||
|
@echo -- Linking $(RASCSI)
|
||||||
$(CXX) -o $@ $(OBJ_RASCSI) -lpthread
|
$(CXX) -o $@ $(OBJ_RASCSI) -lpthread
|
||||||
|
|
||||||
$(RASCTL): $(OBJ_RASCTL)
|
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) $(BINDIR)
|
||||||
|
@echo -- Linking $(RASCTL)
|
||||||
$(CXX) -o $@ $(OBJ_RASCTL)
|
$(CXX) -o $@ $(OBJ_RASCTL)
|
||||||
|
|
||||||
$(RASDUMP): $(OBJ_RASDUMP)
|
$(RASDUMP): $(OBJ_RASDUMP) $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_RASDUMP)
|
$(CXX) -o $@ $(OBJ_RASDUMP)
|
||||||
|
|
||||||
$(SASIDUMP): $(OBJ_SASIDUMP)
|
$(SASIDUMP): $(OBJ_SASIDUMP) $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_SASIDUMP)
|
$(CXX) -o $@ $(OBJ_SASIDUMP)
|
||||||
|
|
||||||
$(SCSIMON): $(OBJ_SCSIMON)
|
$(SCSIMON): $(OBJ_SCSIMON) $(BINDIR)
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJ_ALL) $(BIN_ALL)
|
rm -rf $(OBJDIR) $(BINDIR)
|
||||||
|
|
||||||
run:
|
run:
|
||||||
sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK2.hda -ID6 /home/pi/marathon.iso
|
sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK2.hda -ID6 /home/pi/marathon.iso
|
||||||
|
|||||||
1999
src/raspberrypi/controllers/sasidev_ctrl.cpp
Normal file
1999
src/raspberrypi/controllers/sasidev_ctrl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
src/raspberrypi/controllers/sasidev_ctrl.h
Normal file
211
src/raspberrypi/controllers/sasidev_ctrl.h
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
1869
src/raspberrypi/controllers/scsidev_ctrl.cpp
Normal file
1869
src/raspberrypi/controllers/scsidev_ctrl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
142
src/raspberrypi/controllers/scsidev_ctrl.h
Normal file
142
src/raspberrypi/controllers/scsidev_ctrl.h
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
|
|
||||||
4794
src/raspberrypi/devices/cfilesystem.cpp
Normal file
4794
src/raspberrypi/devices/cfilesystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1184
src/raspberrypi/devices/cfilesystem.h
Normal file
1184
src/raspberrypi/devices/cfilesystem.h
Normal file
File diff suppressed because it is too large
Load Diff
209
src/raspberrypi/devices/ctapdriver.cpp
Normal file
209
src/raspberrypi/devices/ctapdriver.cpp
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Powered by XM6 TypeG Technology.
|
||||||
|
// Copyright (C) 2016-2020 GIMONS
|
||||||
|
//
|
||||||
|
// Imported NetBSD support and some optimisation patch by Rin Okuyama.
|
||||||
|
//
|
||||||
|
// [ TAP Driver ]
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
#include "xm6.h"
|
||||||
|
#include "ctapdriver.h"
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// コンストラクタ
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
CTapDriver::CTapDriver()
|
||||||
|
{
|
||||||
|
// 初期化
|
||||||
|
m_hTAP = -1;
|
||||||
|
memset(&m_MacAddr, 0, sizeof(m_MacAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// 初期化
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#ifdef __linux__
|
||||||
|
BOOL FASTCALL CTapDriver::Init()
|
||||||
|
{
|
||||||
|
char dev[IFNAMSIZ] = "ras0";
|
||||||
|
struct ifreq ifr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ASSERT(this);
|
||||||
|
|
||||||
|
// TAPデバイス初期化
|
||||||
|
if ((m_hTAP = open("/dev/net/tun", O_RDWR)) < 0) {
|
||||||
|
printf("Error: can't open tun\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFF_NO_PI for no extra packet information
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
|
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
|
||||||
|
if ((ret = ioctl(m_hTAP, TUNSETIFF, (void *)&ifr)) < 0) {
|
||||||
|
printf("Error: can't ioctl TUNSETIFF\n");
|
||||||
|
close(m_hTAP);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MACアドレス取得
|
||||||
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) {
|
||||||
|
printf("Error: can't ioctl SIOCGIFHWADDR\n");
|
||||||
|
close(m_hTAP);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MACアドレス保存
|
||||||
|
memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
#ifdef __NetBSD__
|
||||||
|
BOOL FASTCALL CTapDriver::Init()
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
struct ifaddrs *ifa, *a;
|
||||||
|
|
||||||
|
ASSERT(this);
|
||||||
|
|
||||||
|
// TAPデバイス初期化
|
||||||
|
if ((m_hTAP = open("/dev/tap", O_RDWR)) < 0) {
|
||||||
|
printf("Error: can't open tap\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// デバイス名取得
|
||||||
|
if (ioctl(m_hTAP, TAPGIFNAME, (void *)&ifr) < 0) {
|
||||||
|
printf("Error: can't ioctl TAPGIFNAME\n");
|
||||||
|
close(m_hTAP);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MACアドレス取得
|
||||||
|
if (getifaddrs(&ifa) == -1) {
|
||||||
|
printf("Error: can't getifaddrs\n");
|
||||||
|
close(m_hTAP);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
for (a = ifa; a != NULL; a = a->ifa_next)
|
||||||
|
if (strcmp(ifr.ifr_name, a->ifa_name) == 0 &&
|
||||||
|
a->ifa_addr->sa_family == AF_LINK)
|
||||||
|
break;
|
||||||
|
if (a == NULL) {
|
||||||
|
printf("Error: can't get MAC address\n");
|
||||||
|
close(m_hTAP);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MACアドレス保存
|
||||||
|
memcpy(m_MacAddr, LLADDR((struct sockaddr_dl *)a->ifa_addr),
|
||||||
|
sizeof(m_MacAddr));
|
||||||
|
freeifaddrs(ifa);
|
||||||
|
|
||||||
|
printf("Tap device : %s\n", ifr.ifr_name);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif // __NetBSD__
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// クリーンアップ
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void FASTCALL CTapDriver::Cleanup()
|
||||||
|
{
|
||||||
|
ASSERT(this);
|
||||||
|
|
||||||
|
// TAPデバイス解放
|
||||||
|
if (m_hTAP != -1) {
|
||||||
|
close(m_hTAP);
|
||||||
|
m_hTAP = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// MACアドレス取得
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void FASTCALL CTapDriver::GetMacAddr(BYTE *mac)
|
||||||
|
{
|
||||||
|
ASSERT(this);
|
||||||
|
ASSERT(mac);
|
||||||
|
|
||||||
|
memcpy(mac, m_MacAddr, sizeof(m_MacAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// 受信
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
int FASTCALL CTapDriver::Rx(BYTE *buf)
|
||||||
|
{
|
||||||
|
struct pollfd fds;
|
||||||
|
DWORD dwReceived;
|
||||||
|
|
||||||
|
ASSERT(this);
|
||||||
|
ASSERT(m_hTAP != -1);
|
||||||
|
|
||||||
|
// 受信可能なデータがあるか調べる
|
||||||
|
fds.fd = m_hTAP;
|
||||||
|
fds.events = POLLIN | POLLERR;
|
||||||
|
fds.revents = 0;
|
||||||
|
poll(&fds, 1, 0);
|
||||||
|
if (!(fds.revents & POLLIN)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 受信
|
||||||
|
dwReceived = read(m_hTAP, buf, ETH_FRAME_LEN);
|
||||||
|
if (dwReceived == (DWORD)-1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 受信が有効であれば
|
||||||
|
if (dwReceived > 0) {
|
||||||
|
// FCSを除く最小フレームサイズ(60バイト)にパディング
|
||||||
|
if (dwReceived < 60) {
|
||||||
|
memset(buf + dwReceived, 0, 60 - dwReceived);
|
||||||
|
dwReceived = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ダミーのFCSを付加する
|
||||||
|
memset(buf + dwReceived, 0, 4);
|
||||||
|
dwReceived += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// バイト数を返却
|
||||||
|
return dwReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// 送信
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
int FASTCALL CTapDriver::Tx(BYTE *buf, int len)
|
||||||
|
{
|
||||||
|
ASSERT(this);
|
||||||
|
ASSERT(m_hTAP != -1);
|
||||||
|
|
||||||
|
// 送信開始
|
||||||
|
return write(m_hTAP, buf, len);
|
||||||
|
}
|
||||||
53
src/raspberrypi/devices/ctapdriver.h
Normal file
53
src/raspberrypi/devices/ctapdriver.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Powered by XM6 TypeG Technology.
|
||||||
|
// Copyright (C) 2016-2020 GIMONS
|
||||||
|
//
|
||||||
|
// Imported NetBSD support and some optimisation patch by Rin Okuyama.
|
||||||
|
//
|
||||||
|
// [ TAP Driver ]
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(ctapdriver_h)
|
||||||
|
#define ctapdriver_h
|
||||||
|
|
||||||
|
#ifndef ETH_FRAME_LEN
|
||||||
|
#define ETH_FRAME_LEN 1514
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Tapドライバ
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
class CTapDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 基本ファンクション
|
||||||
|
CTapDriver();
|
||||||
|
// コンストラクタ
|
||||||
|
BOOL FASTCALL Init();
|
||||||
|
// 初期化
|
||||||
|
void FASTCALL Cleanup();
|
||||||
|
// クリーンアップ
|
||||||
|
void FASTCALL GetMacAddr(BYTE *mac);
|
||||||
|
// MACアドレス取得
|
||||||
|
int FASTCALL Rx(BYTE *buf);
|
||||||
|
// 受信
|
||||||
|
int FASTCALL Tx(BYTE *buf, int len);
|
||||||
|
// 送信
|
||||||
|
|
||||||
|
private:
|
||||||
|
BYTE m_MacAddr[6];
|
||||||
|
// MACアドレス
|
||||||
|
BOOL m_bTxValid;
|
||||||
|
// 送信有効フラグ
|
||||||
|
int m_hTAP;
|
||||||
|
// ディスクプリタ
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ctapdriver_h
|
||||||
2346
src/raspberrypi/devices/disk.cpp
Normal file
2346
src/raspberrypi/devices/disk.cpp
Normal file
File diff suppressed because it is too large
Load Diff
368
src/raspberrypi/devices/disk.h
Normal file
368
src/raspberrypi/devices/disk.h
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// X68000 EMULATOR "XM6"
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
164
src/raspberrypi/devices/sasihd.cpp
Normal file
164
src/raspberrypi/devices/sasihd.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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;
|
||||||
|
}
|
||||||
40
src/raspberrypi/devices/sasihd.h
Normal file
40
src/raspberrypi/devices/sasihd.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
1502
src/raspberrypi/devices/scsi_host_bridge.cpp
Normal file
1502
src/raspberrypi/devices/scsi_host_bridge.cpp
Normal file
File diff suppressed because it is too large
Load Diff
153
src/raspberrypi/devices/scsi_host_bridge.h
Normal file
153
src/raspberrypi/devices/scsi_host_bridge.h
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
1089
src/raspberrypi/devices/scsicd.cpp
Normal file
1089
src/raspberrypi/devices/scsicd.cpp
Normal file
File diff suppressed because it is too large
Load Diff
230
src/raspberrypi/devices/scsicd.h
Normal file
230
src/raspberrypi/devices/scsicd.h
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
268
src/raspberrypi/devices/scsihd.cpp
Normal file
268
src/raspberrypi/devices/scsihd.cpp
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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;
|
||||||
|
}
|
||||||
44
src/raspberrypi/devices/scsihd.h
Normal file
44
src/raspberrypi/devices/scsihd.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
93
src/raspberrypi/devices/scsihd_apple.cpp
Normal file
93
src/raspberrypi/devices/scsihd_apple.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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;
|
||||||
|
}
|
||||||
39
src/raspberrypi/devices/scsihd_apple.h
Normal file
39
src/raspberrypi/devices/scsihd_apple.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
295
src/raspberrypi/devices/scsihd_nec.cpp
Normal file
295
src/raspberrypi/devices/scsihd_nec.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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;
|
||||||
|
}
|
||||||
61
src/raspberrypi/devices/scsihd_nec.h
Normal file
61
src/raspberrypi/devices/scsihd_nec.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
|
||||||
|
};
|
||||||
421
src/raspberrypi/devices/scsimo.cpp
Normal file
421
src/raspberrypi/devices/scsimo.cpp
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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;
|
||||||
|
}
|
||||||
49
src/raspberrypi/devices/scsimo.h
Normal file
49
src/raspberrypi/devices/scsimo.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001-2006 PI.(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
@@ -11,6 +11,8 @@
|
|||||||
#if !defined(fileio_h)
|
#if !defined(fileio_h)
|
||||||
#define fileio_h
|
#define fileio_h
|
||||||
|
|
||||||
|
#include "filepath.h"
|
||||||
|
|
||||||
#ifdef BAREMETAL
|
#ifdef BAREMETAL
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#endif // BAREMETAL
|
#endif // BAREMETAL
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#if !defined(filepath_h)
|
#if !defined(filepath_h)
|
||||||
#define filepath_h
|
#define filepath_h
|
||||||
|
|
||||||
|
class Fileio;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// 定数定義
|
// 定数定義
|
||||||
|
|||||||
@@ -13,9 +13,19 @@
|
|||||||
#include "xm6.h"
|
#include "xm6.h"
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "fileio.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 "gpiobus.h"
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Constant declarations
|
// Constant declarations
|
||||||
|
|||||||
Reference in New Issue
Block a user