Merge pull request #95 from akuker/develop

Merge 21.05.1 changes to master
This commit is contained in:
akuker 2021-05-02 14:05:59 -05:00 committed by GitHub
commit 5548548708
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1871 additions and 1951 deletions

8
.gitignore vendored
View File

@ -1 +1,9 @@
venv venv
*.pyc
core
.idea/
.DS_Store
*.swp
__pycache__
src/web/current
src/oled_monitor/current

View File

@ -24,11 +24,11 @@ VIRTUAL_DRIVER_PATH=/home/pi/images
HFS_FORMAT=/usr/bin/hformat HFS_FORMAT=/usr/bin/hformat
HFDISK_BIN=/usr/bin/hfdisk HFDISK_BIN=/usr/bin/hfdisk
LIDO_DRIVER=~/RASCSI/lido-driver.img LIDO_DRIVER=~/RASCSI/lido-driver.img
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
function initialChecks() { function initialChecks() {
currentUser=$(whoami) currentUser=$(whoami)
if [ "pi" != $currentUser ]; then if [ "pi" != "$currentUser" ]; then
echo "You must use 'pi' user (current: $currentUser)" echo "You must use 'pi' user (current: $currentUser)"
exit 1 exit 1
fi fi
@ -40,10 +40,14 @@ function initialChecks() {
fi fi
} }
function installPackages() {
sudo apt-get update && sudo apt install git libspdlog-dev genisoimage python3 python3-venv nginx bridge-utils -y
}
# install all dependency packages for RaSCSI Service # install all dependency packages for RaSCSI Service
# compile and install RaSCSI Service # compile and install RaSCSI Service
function installRaScsi() { function installRaScsi() {
installPackages
sudo apt-get update && sudo apt-get install --yes git libspdlog-dev sudo apt-get update && sudo apt-get install --yes git libspdlog-dev
cd ~/RASCSI/src/raspberrypi cd ~/RASCSI/src/raspberrypi
@ -69,7 +73,7 @@ www-data ALL=NOPASSWD: /sbin/shutdown, /sbin/reboot
function stopOldWebInterface() { function stopOldWebInterface() {
APACHE_STATUS=$(sudo systemctl status apache2 &> /dev/null; echo $?) APACHE_STATUS=$(sudo systemctl status apache2 &> /dev/null; echo $?)
if [ $APACHE_STATUS -eq 0 ] ; then if [ "$APACHE_STATUS" -eq 0 ] ; then
echo "Stopping old Apache2 RaSCSI Web..." echo "Stopping old Apache2 RaSCSI Web..."
sudo systemctl disable apache2 sudo systemctl disable apache2
sudo systemctl stop apache2 sudo systemctl stop apache2
@ -79,7 +83,7 @@ function stopOldWebInterface() {
# install everything required to run an HTTP server (Nginx + Python Flask App) # install everything required to run an HTTP server (Nginx + Python Flask App)
function installRaScsiWebInterface() { function installRaScsiWebInterface() {
stopOldWebInterface stopOldWebInterface
sudo apt install genisoimage python3 python3-venv nginx -y installPackages
sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default
sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html
@ -99,12 +103,17 @@ function installRaScsiWebInterface() {
} }
function updateRaScsiGit() { function updateRaScsiGit() {
echo "Updating checked out branch $GIT_BRANCH"
cd ~/RASCSI cd ~/RASCSI
git pull git fetch origin
git stash
git rebase origin/$GIT_BRANCH
git stash apply
} }
function updateRaScsi() { function updateRaScsi() {
updateRaScsiGit updateRaScsiGit
installPackages
sudo systemctl stop rascsi sudo systemctl stop rascsi
cd ~/RASCSI/src/raspberrypi cd ~/RASCSI/src/raspberrypi
@ -241,8 +250,8 @@ function showMenu() {
choice=-1 choice=-1
until [ $choice -ge "0" ] && [ $choice -le "7" ]; do until [ $choice -ge "0" ] && [ $choice -le "7" ]; do
echo "Enter your choice (0-7) or CTRL-C to exit" echo -n "Enter your choice (0-7) or CTRL-C to exit: "
read choice read -r choice
done done

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python3
# #
# RaSCSI Updates: # RaSCSI Updates:
# Updates to output rascsi status to an OLED display # Updates to output rascsi status to an OLED display
@ -29,92 +29,57 @@
# THE SOFTWARE. # THE SOFTWARE.
import time import time
import os import os
import sys
import datetime import datetime
import board
#import Adafruit_GPIO.SPI as SPI import busio
import Adafruit_SSD1306 import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import subprocess import subprocess
WIDTH = 128
HEIGHT = 32 # Change to 64 if needed
BORDER = 5
# How long to delay between each update # How long to delay between each update
delay_time_ms = 250 delay_time_ms = 250
# Raspberry Pi pin configuration: # Define the Reset Pin
RST = None # on the PiOLED this pin isnt used oled_reset = None
# Note the following are only used with SPI:
DC = 23
SPI_PORT = 0
SPI_DEVICE = 0
# Beaglebone Black pin configuration: # init i2c
# RST = 'P9_12' i2c = board.I2C()
# Note the following are only used with SPI:
# DC = 'P9_15'
# SPI_PORT = 1
# SPI_DEVICE = 0
# 128x32 display with hardware I2C: # 128x32 display with hardware I2C:
disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C, reset=oled_reset)
# 128x64 display with hardware I2C: print ("Running with the following display:")
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) print (oled)
print ()
# Note you can change the I2C address by passing an i2c_address parameter like: print ("Will update the OLED display every " + str(delay_time_ms) + "ms (approximately)")
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C)
# Alternatively you can specify an explicit I2C bus number, for example
# with the 128x32 display you would use:
# disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, i2c_bus=2)
# 128x32 display with hardware SPI:
# disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))
# 128x64 display with hardware SPI:
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))
# Alternatively you can specify a software SPI implementation by providing
# digital GPIO pin numbers for all the required display pins. For example
# on a Raspberry Pi with the 128x32 display you might use:
# disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, sclk=18, din=25, cs=22)
print "Running with the following display:"
print disp
print
print "Will update the OLED display every " + str(delay_time_ms) + "ms (approximately)"
# Initialize library.
disp.begin()
# Clear display. # Clear display.
disp.clear() oled.fill(0)
disp.display() oled.show()
# Create blank image for drawing. # Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color. # Make sure to create image with mode '1' for 1-bit color.
width = disp.width image = Image.new("1", (oled.width, oled.height))
height = disp.height
image = Image.new('1', (width, height))
# Get drawing object to draw on image. # Get drawing object to draw on image.
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
# Draw a black filled box to clear the image. # Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0) draw.rectangle((0,0,WIDTH,HEIGHT), outline=0, fill=0)
# Draw some shapes. # Draw some shapes.
# First define some constants to allow easy resizing of shapes. # First define some constants to allow easy resizing of shapes.
padding = -2 padding = -2
top = padding top = padding
bottom = height-padding bottom = HEIGHT-padding
# Move left to right keeping track of the current x position for drawing shapes. # Move left to right keeping track of the current x position for drawing shapes.
x = 0 x = 0
# Load default font. # Load default font.
font = ImageFont.load_default() font = ImageFont.load_default()
@ -125,10 +90,10 @@ font = ImageFont.load_default()
while True: while True:
# Draw a black filled box to clear the image. # Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0) draw.rectangle((0,0,WIDTH,HEIGHT), outline=0, fill=0)
cmd = "rasctl -l" cmd = "rasctl -l"
rascsi_list = subprocess.check_output(cmd, shell=True) rascsi_list = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding)
y_pos = top y_pos = top
# Draw all of the meaningful data to the 'image' # Draw all of the meaningful data to the 'image'
@ -154,11 +119,12 @@ while True:
else: else:
output = "No image mounted!" output = "No image mounted!"
draw.text((x, y_pos), output, font=font, fill=255) draw.text((x, y_pos), output, font=font, fill=255)
y_pos = y_pos + 8 y_pos += 8
# If there is still room on the screen, we'll display the time. If there's not room it will just be clipped # If there is still room on the screen, we'll display the time. If there's not room it will just be clipped
draw.text((x, y_pos), datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"), font=font, fill=255) draw.text((x, y_pos), datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"), font=font, fill=255)
# Display image. # Display image.
disp.image(image) oled.image(image)
disp.display() oled.show()
time.sleep(1/delay_time_ms) time.sleep(1/delay_time_ms)

View File

@ -0,0 +1,14 @@
Adafruit-Blinka==6.3.2
adafruit-circuitpython-busdevice==5.0.6
adafruit-circuitpython-framebuf==1.4.6
adafruit-circuitpython-ssd1306==2.11.1
Adafruit-PlatformDetect==3.2.0
Adafruit-PureIO==1.1.8
Pillow==8.1.2
pkg-resources==0.0.0
pyftdi==0.52.9
pyserial==3.5
pyusb==1.1.1
rpi-ws281x==4.2.5
RPi.GPIO==0.7.0
sysv-ipc==1.1.0

76
src/oled_monitor/start.sh Executable file
View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -e
# set -x # Uncomment to Debug
cd $(dirname $0)
# verify packages installed
ERROR=0
if ! command -v dpkg -l i2c-tools &> /dev/null ; then
echo "i2c-tools could not be found"
echo "Run 'sudo apt install i2c-tools' to fix."
ERROR=1
fi
if ! command -v python3 &> /dev/null ; then
echo "python3 could not be found"
echo "Run 'sudo apt install python3' to fix."
ERROR=1
fi
# Dep to build Pillow
if ! dpkg -l python3-dev &> /dev/null; then
echo "python3-dev could not be found"
echo "Run 'sudo apt install python3-dev' to fix."
ERROR=1
fi
if ! dpkg -l libjpeg-dev &> /dev/null; then
echo "libjpeg-dev could not be found"
echo "Run 'sudo apt install libjpeg-dev' to fix."
ERROR=1
fi
if ! dpkg -l libpng-dev &> /dev/null; then
echo "libpng-dev could not be found"
echo "Run 'sudo apt install libpng-dev' to fix."
ERROR=1
fi
# Dep to build Pollow
if ! python3 -m venv --help &> /dev/null ; then
echo "venv could not be found"
echo "Run 'sudo apt install python3-venv' to fix."
ERROR=1
fi
if [ $ERROR = 1 ] ; then
echo
echo "Fix errors and re-run ./start.sh"
exit 1
fi
if ! i2cdetect -y 1 &> /dev/null ; then
echo "i2cdetect -y 1 did not find a screen."
exit 2
fi
if ! test -e venv; then
echo "Creating python venv for OLED Screen"
python3 -m venv venv
echo "Activating venv"
source venv/bin/activate
echo "Installing requirements.txt"
pip install -r requirements.txt
git rev-parse HEAD > current
fi
source venv/bin/activate
# Detect if someone updates - we need to re-run pip install.
if ! test -e current; then
git rev-parse > current
else
if [ "$(cat current)" != "$(git rev-parse HEAD)" ]; then
echo "New version detected, updating requirements.txt"
echo " This may take some time..."
pip install wheel
pip install -r requirements.txt
git rev-parse HEAD > current
fi
fi
echo "Starting OLED Screen..."
python3 rascsi_oled_monitor.py

View File

@ -37,10 +37,10 @@ SASIDEV::SASIDEV(Device *dev)
{ {
int i; int i;
#ifndef RASCSI #ifndef RASCSI
// Remember host device // Remember host device
host = dev; host = dev;
#endif // RASCSI #endif // RASCSI
// Work initialization // Work initialization
ctrl.phase = BUS::busfree; ctrl.phase = BUS::busfree;
@ -49,9 +49,9 @@ SASIDEV::SASIDEV(Device *dev)
memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd));
ctrl.status = 0x00; ctrl.status = 0x00;
ctrl.message = 0x00; ctrl.message = 0x00;
#ifdef RASCSI #ifdef RASCSI
ctrl.execstart = 0; ctrl.execstart = 0;
#endif // RASCSI #endif // RASCSI
ctrl.bufsize = 0x800; ctrl.bufsize = 0x800;
ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); ctrl.buffer = (BYTE *)malloc(ctrl.bufsize);
memset(ctrl.buffer, 0x00, ctrl.bufsize); memset(ctrl.buffer, 0x00, ctrl.bufsize);
@ -96,9 +96,9 @@ void FASTCALL SASIDEV::Reset()
ctrl.phase = BUS::busfree; ctrl.phase = BUS::busfree;
ctrl.status = 0x00; ctrl.status = 0x00;
ctrl.message = 0x00; ctrl.message = 0x00;
#ifdef RASCSI #ifdef RASCSI
ctrl.execstart = 0; ctrl.execstart = 0;
#endif // RASCSI #endif // RASCSI
memset(ctrl.buffer, 0x00, ctrl.bufsize); memset(ctrl.buffer, 0x00, ctrl.bufsize);
ctrl.blocks = 0; ctrl.blocks = 0;
ctrl.next = 0; ctrl.next = 0;
@ -301,9 +301,9 @@ BUS::phase_t FASTCALL SASIDEV::Process()
// For the monitor tool, we shouldn't need to reset. We're just logging information // For the monitor tool, we shouldn't need to reset. We're just logging information
// Reset // Reset
if (ctrl.bus->GetRST()) { if (ctrl.bus->GetRST()) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "RESET signal received"); Log(Log::Normal, "SASI - RESET signal received");
#endif // DISK_LOG #endif // DISK_LOG
// Reset the controller // Reset the controller
Reset(); Reset();
@ -371,9 +371,9 @@ void FASTCALL SASIDEV::BusFree()
// Phase change // Phase change
if (ctrl.phase != BUS::busfree) { if (ctrl.phase != BUS::busfree) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Bus free phase"); Log(Log::Normal, "SASI - Bus free phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::busfree; ctrl.phase = BUS::busfree;
@ -421,10 +421,9 @@ void FASTCALL SASIDEV::Selection()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SASI - Selection Phase ID=%d (with device)", ctrl.id);
"Selection Phase ID=%d (with device)", ctrl.id); #endif // DISK_LOG
#endif // DISK_LOG
// Phase change // Phase change
ctrl.phase = BUS::selection; ctrl.phase = BUS::selection;
@ -447,19 +446,19 @@ void FASTCALL SASIDEV::Selection()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::Command() void FASTCALL SASIDEV::Command()
{ {
#ifdef RASCSI #ifdef RASCSI
int count; int count;
int i; int i;
#endif // RASCSI #endif // RASCSI
ASSERT(this); ASSERT(this);
// Phase change // Phase change
if (ctrl.phase != BUS::command) { if (ctrl.phase != BUS::command) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Command Phase"); Log(Log::Normal, "SASI - Command Phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::command; ctrl.phase = BUS::command;
@ -474,7 +473,7 @@ void FASTCALL SASIDEV::Command()
ctrl.length = 6; ctrl.length = 6;
ctrl.blocks = 1; ctrl.blocks = 1;
#ifdef RASCSI #ifdef RASCSI
// Command reception handshake (10 bytes are automatically received at the first command) // Command reception handshake (10 bytes are automatically received at the first command)
count = ctrl.bus->CommandHandShake(ctrl.buffer); count = ctrl.bus->CommandHandShake(ctrl.buffer);
@ -506,13 +505,13 @@ void FASTCALL SASIDEV::Command()
// Execution Phase // Execution Phase
Execute(); Execute();
#else #else
// Request the command // Request the command
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
return; return;
#endif // RASCSI #endif // RASCSI
} }
#ifndef RASCSI #ifndef RASCSI
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Sent by the initiator // Sent by the initiator
@ -525,7 +524,7 @@ void FASTCALL SASIDEV::Command()
ReceiveNext(); ReceiveNext();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -537,9 +536,9 @@ void FASTCALL SASIDEV::Execute()
{ {
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Execution Phase Command %02X", ctrl.cmd[0]); Log(Log::Normal, "SASI - Execution Phase Command %02X", ctrl.cmd[0]);
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::execute; ctrl.phase = BUS::execute;
@ -547,9 +546,9 @@ void FASTCALL SASIDEV::Execute()
// Initialization for data transfer // Initialization for data transfer
ctrl.offset = 0; ctrl.offset = 0;
ctrl.blocks = 1; ctrl.blocks = 1;
#ifdef RASCSI #ifdef RASCSI
ctrl.execstart = SysTimer::GetTimerLow(); ctrl.execstart = SysTimer::GetTimerLow();
#endif // RASCSI #endif // RASCSI
// Process by command // Process by command
switch (ctrl.cmd[0]) { switch (ctrl.cmd[0]) {
@ -603,14 +602,25 @@ void FASTCALL SASIDEV::Execute()
CmdAssign(); CmdAssign();
return; return;
// RESERVE UNIT(16)
case 0x16:
CmdReserveUnit();
return;
// RELEASE UNIT(17)
case 0x17:
CmdReleaseUnit();
return;
// SPECIFY(SASIのみ) // SPECIFY(SASIのみ)
case 0xc2: case 0xc2:
CmdSpecify(); CmdSpecify();
return; return;
} }
// Unsupported command // Unsupported command
Log(Log::Warning, "Unsupported command $%02X", ctrl.cmd[0]); Log(Log::Warning, "SASI - Unsupported command $%02X", ctrl.cmd[0]);
CmdInvalid(); CmdInvalid();
} }
@ -621,17 +631,17 @@ void FASTCALL SASIDEV::Execute()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::Status() void FASTCALL SASIDEV::Status()
{ {
#ifdef RASCSI #ifdef RASCSI
DWORD min_exec_time; DWORD min_exec_time;
DWORD time; DWORD time;
#endif // RASCSI #endif // RASCSI
ASSERT(this); ASSERT(this);
// Phase change // Phase change
if (ctrl.phase != BUS::status) { if (ctrl.phase != BUS::status) {
#ifdef RASCSI #ifdef RASCSI
// Minimum execution time // Minimum execution time
if (ctrl.execstart > 0) { if (ctrl.execstart > 0) {
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
@ -643,11 +653,11 @@ void FASTCALL SASIDEV::Status()
} else { } else {
SysTimer::SleepUsec(5); SysTimer::SleepUsec(5);
} }
#endif // RASCSI #endif // RASCSI
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Status phase"); Log(Log::Normal, "SASI - Status phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::status; ctrl.phase = BUS::status;
@ -663,22 +673,22 @@ void FASTCALL SASIDEV::Status()
ctrl.blocks = 1; ctrl.blocks = 1;
ctrl.buffer[0] = (BYTE)ctrl.status; ctrl.buffer[0] = (BYTE)ctrl.status;
#ifndef RASCSI #ifndef RASCSI
// Request status // Request status
ctrl.bus->SetDAT(ctrl.buffer[0]); ctrl.bus->SetDAT(ctrl.buffer[0]);
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Status Phase $%02X", ctrl.status); Log(Log::Normal, "SASI - Status Phase $%02X", ctrl.status);
#endif // DISK_LOG #endif // DISK_LOG
#endif // RASCSI #endif // RASCSI
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
// Send // Send
Send(); Send();
#else #else
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Initiator received // Initiator received
@ -691,7 +701,7 @@ void FASTCALL SASIDEV::Status()
Send(); Send();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -706,9 +716,9 @@ void FASTCALL SASIDEV::MsgIn()
// Phase change // Phase change
if (ctrl.phase != BUS::msgin) { if (ctrl.phase != BUS::msgin) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Message in phase"); Log(Log::Normal, "SASI - Message in phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::msgin; ctrl.phase = BUS::msgin;
@ -723,22 +733,22 @@ void FASTCALL SASIDEV::MsgIn()
ASSERT(ctrl.blocks > 0); ASSERT(ctrl.blocks > 0);
ctrl.offset = 0; ctrl.offset = 0;
#ifndef RASCSI #ifndef RASCSI
// Request message // Request message
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Message in phase $%02X", ctrl.buffer[ctrl.offset]); Log(Log::Normal, "SASI - Message in phase $%02X", ctrl.buffer[ctrl.offset]);
#endif // DISK_LOG #endif // DISK_LOG
#endif // RASCSI #endif // RASCSI
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
//Send //Send
Send(); Send();
#else #else
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Initator received // Initator received
@ -751,7 +761,7 @@ void FASTCALL SASIDEV::MsgIn()
Send(); Send();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -761,10 +771,10 @@ void FASTCALL SASIDEV::MsgIn()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::DataIn() void FASTCALL SASIDEV::DataIn()
{ {
#ifdef RASCSI #ifdef RASCSI
DWORD min_exec_time; DWORD min_exec_time;
DWORD time; DWORD time;
#endif // RASCSI #endif // RASCSI
ASSERT(this); ASSERT(this);
ASSERT(ctrl.length >= 0); ASSERT(ctrl.length >= 0);
@ -772,7 +782,7 @@ void FASTCALL SASIDEV::DataIn()
// Phase change // Phase change
if (ctrl.phase != BUS::datain) { if (ctrl.phase != BUS::datain) {
#ifdef RASCSI #ifdef RASCSI
// Minimum execution time // Minimum execution time
if (ctrl.execstart > 0) { if (ctrl.execstart > 0) {
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
@ -782,7 +792,7 @@ void FASTCALL SASIDEV::DataIn()
} }
ctrl.execstart = 0; ctrl.execstart = 0;
} }
#endif // RASCSI #endif // RASCSI
// If the length is 0, go to the status phase // If the length is 0, go to the status phase
if (ctrl.length == 0) { if (ctrl.length == 0) {
@ -790,9 +800,9 @@ void FASTCALL SASIDEV::DataIn()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Data-in Phase"); Log(Log::Normal, "SASI - Data-in Phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::datain; ctrl.phase = BUS::datain;
@ -807,20 +817,20 @@ void FASTCALL SASIDEV::DataIn()
ASSERT(ctrl.blocks > 0); ASSERT(ctrl.blocks > 0);
ctrl.offset = 0; ctrl.offset = 0;
#ifndef RASCSI #ifndef RASCSI
// Assert the DAT signal // Assert the DAT signal
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
// Request data // Request data
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
// Send // Send
Send(); Send();
#else #else
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Initator received // Initator received
@ -833,7 +843,7 @@ void FASTCALL SASIDEV::DataIn()
Send(); Send();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -843,10 +853,10 @@ void FASTCALL SASIDEV::DataIn()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::DataOut() void FASTCALL SASIDEV::DataOut()
{ {
#ifdef RASCSI #ifdef RASCSI
DWORD min_exec_time; DWORD min_exec_time;
DWORD time; DWORD time;
#endif // RASCSI #endif // RASCSI
ASSERT(this); ASSERT(this);
ASSERT(ctrl.length >= 0); ASSERT(ctrl.length >= 0);
@ -854,7 +864,7 @@ void FASTCALL SASIDEV::DataOut()
// Phase change // Phase change
if (ctrl.phase != BUS::dataout) { if (ctrl.phase != BUS::dataout) {
#ifdef RASCSI #ifdef RASCSI
// Minimum execution time // Minimum execution time
if (ctrl.execstart > 0) { if (ctrl.execstart > 0) {
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
@ -864,7 +874,7 @@ void FASTCALL SASIDEV::DataOut()
} }
ctrl.execstart = 0; ctrl.execstart = 0;
} }
#endif // RASCSI #endif // RASCSI
// If the length is 0, go to the status phase // If the length is 0, go to the status phase
if (ctrl.length == 0) { if (ctrl.length == 0) {
@ -872,9 +882,9 @@ void FASTCALL SASIDEV::DataOut()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Data out phase"); Log(Log::Normal, "SASI - Data out phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::dataout; ctrl.phase = BUS::dataout;
@ -889,17 +899,17 @@ void FASTCALL SASIDEV::DataOut()
ASSERT(ctrl.blocks > 0); ASSERT(ctrl.blocks > 0);
ctrl.offset = 0; ctrl.offset = 0;
#ifndef RASCSI #ifndef RASCSI
// Request data // Request data
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
// Receive // Receive
Receive(); Receive();
#else #else
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Sent by the initiator // Sent by the initiator
@ -912,7 +922,7 @@ void FASTCALL SASIDEV::DataOut()
ReceiveNext(); ReceiveNext();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -945,9 +955,9 @@ void FASTCALL SASIDEV::Error()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Warning, "Error occured (going to status phase)"); Log(Log::Warning, "SASI - Error occured (going to status phase)");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -971,9 +981,9 @@ void FASTCALL SASIDEV::CmdTestUnitReady()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "TEST UNIT READY Command "); Log(Log::Normal, "SASI - TEST UNIT READY Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1006,9 +1016,9 @@ void FASTCALL SASIDEV::CmdRezero()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "REZERO UNIT Command "); Log(Log::Normal, "SASI - REZERO UNIT Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1040,9 +1050,9 @@ void FASTCALL SASIDEV::CmdRequestSense()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "REQUEST SENSE Command "); Log(Log::Normal, "SASI - REQUEST SENSE Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1055,9 +1065,9 @@ void FASTCALL SASIDEV::CmdRequestSense()
ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer); ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length > 0); ASSERT(ctrl.length > 0);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Sense key $%02X", ctrl.buffer[2]); Log(Log::Normal, "SASI - Sense key $%02X", ctrl.buffer[2]);
#endif // DISK_LOG #endif // DISK_LOG
// Read phase // Read phase
DataIn(); DataIn();
@ -1075,9 +1085,9 @@ void FASTCALL SASIDEV::CmdFormat()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "FORMAT UNIT Command "); Log(Log::Normal, "SASI - FORMAT UNIT Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1110,9 +1120,9 @@ void FASTCALL SASIDEV::CmdReassign()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "REASSIGN BLOCKS Command "); Log(Log::Normal, "SASI - REASSIGN BLOCKS Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1133,6 +1143,42 @@ void FASTCALL SASIDEV::CmdReassign()
Status(); Status();
} }
// The following commands RESERVE UNIT and RELEASE UNIT are not properly implemented.
// These commands are used in multi-initator environments which this project is not targeted at.
// For now, we simply reply with an OK. -phrax 2021-03-06
//---------------------------------------------------------------------------
//
// RESERVE UNIT(16)
//
//---------------------------------------------------------------------------
void FASTCALL SASIDEV::CmdReserveUnit()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SASI - RESERVE UNIT Command");
#endif // DISK_LOG
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// RELEASE UNIT(17)
//
//---------------------------------------------------------------------------
void FASTCALL SASIDEV::CmdReleaseUnit()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SASI - RELEASE UNIT Command");
#endif // DISK_LOG
// status phase
Status();
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// READ(6) // READ(6)
@ -1163,10 +1209,9 @@ void FASTCALL SASIDEV::CmdRead6()
ctrl.blocks = 0x100; ctrl.blocks = 0x100;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SASI - READ(6) command record=%06X blocks=%d", record, ctrl.blocks);
"READ(6) command record=%06X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG
#endif // DISK_LOG
// Command processing on drive // Command processing on drive
ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record);
@ -1213,10 +1258,9 @@ void FASTCALL SASIDEV::CmdWrite6()
ctrl.blocks = 0x100; ctrl.blocks = 0x100;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SASI - WRITE(6) command record=%06X blocks=%d", record, ctrl.blocks);
"WRITE(6) command record=%06X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG
#endif // DISK_LOG
// Command processing on drive // Command processing on drive
ctrl.length = ctrl.unit[lun]->WriteCheck(record); ctrl.length = ctrl.unit[lun]->WriteCheck(record);
@ -1245,9 +1289,9 @@ void FASTCALL SASIDEV::CmdSeek6()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "SEEK(6) Command "); Log(Log::Normal, "SASI - SEEK(6) Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1280,9 +1324,9 @@ void FASTCALL SASIDEV::CmdAssign()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "ASSIGN Command "); Log(Log::Normal, "SASI - ASSIGN Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1318,9 +1362,9 @@ void FASTCALL SASIDEV::CmdSpecify()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "SPECIFY Command "); Log(Log::Normal, "SASI - SPECIFY Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1355,9 +1399,9 @@ void FASTCALL SASIDEV::CmdInvalid()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Command not supported"); Log(Log::Normal, "SASI - Command not supported");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1383,16 +1427,16 @@ void FASTCALL SASIDEV::CmdInvalid()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::Send() void FASTCALL SASIDEV::Send()
{ {
#ifdef RASCSI #ifdef RASCSI
int len; int len;
#endif // RASCSI #endif // RASCSI
BOOL result; BOOL result;
ASSERT(this); ASSERT(this);
ASSERT(!ctrl.bus->GetREQ()); ASSERT(!ctrl.bus->GetREQ());
ASSERT(ctrl.bus->GetIO()); ASSERT(ctrl.bus->GetIO());
#ifdef RASCSI #ifdef RASCSI
// Check that the length isn't 0 // Check that the length isn't 0
if (ctrl.length != 0) { if (ctrl.length != 0) {
len = ctrl.bus->SendHandShake( len = ctrl.bus->SendHandShake(
@ -1409,7 +1453,7 @@ void FASTCALL SASIDEV::Send()
ctrl.length = 0; ctrl.length = 0;
return; return;
} }
#else #else
// Offset and Length // Offset and Length
ASSERT(ctrl.length >= 1); ASSERT(ctrl.length >= 1);
ctrl.offset++; ctrl.offset++;
@ -1422,7 +1466,7 @@ void FASTCALL SASIDEV::Send()
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
return; return;
} }
#endif // RASCSI #endif // RASCSI
// Remove block and initialize the result // Remove block and initialize the result
ctrl.blocks--; ctrl.blocks--;
@ -1435,9 +1479,9 @@ void FASTCALL SASIDEV::Send()
result = XferIn(ctrl.buffer); result = XferIn(ctrl.buffer);
//** printf("xfer in: %d \n",result); //** printf("xfer in: %d \n",result);
#ifndef RASCSI #ifndef RASCSI
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
#endif // RASCSI #endif // RASCSI
} }
} }
@ -1451,10 +1495,10 @@ void FASTCALL SASIDEV::Send()
if (ctrl.blocks != 0){ if (ctrl.blocks != 0){
ASSERT(ctrl.length > 0); ASSERT(ctrl.length > 0);
ASSERT(ctrl.offset == 0); ASSERT(ctrl.offset == 0);
#ifndef RASCSI #ifndef RASCSI
// Signal line operated by the target // Signal line operated by the target
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
@ -1538,9 +1582,9 @@ void FASTCALL SASIDEV::Receive()
// Command phase // Command phase
case BUS::command: case BUS::command:
ctrl.cmd[ctrl.offset] = data; ctrl.cmd[ctrl.offset] = data;
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Command phase $%02X", data); Log(Log::Normal, "SASI - Command phase $%02X", data);
#endif // DISK_LOG #endif // DISK_LOG
// Set the length again with the first data (offset 0) // Set the length again with the first data (offset 0)
if (ctrl.offset == 0) { if (ctrl.offset == 0) {
@ -1580,9 +1624,9 @@ void FASTCALL SASIDEV::Receive()
void FASTCALL SASIDEV::ReceiveNext() void FASTCALL SASIDEV::ReceiveNext()
#endif // RASCSI #endif // RASCSI
{ {
#ifdef RASCSI #ifdef RASCSI
int len; int len;
#endif // RASCSI #endif // RASCSI
BOOL result; BOOL result;
ASSERT(this); ASSERT(this);
@ -1591,7 +1635,7 @@ void FASTCALL SASIDEV::ReceiveNext()
ASSERT(!ctrl.bus->GetREQ()); ASSERT(!ctrl.bus->GetREQ());
ASSERT(!ctrl.bus->GetIO()); ASSERT(!ctrl.bus->GetIO());
#ifdef RASCSI #ifdef RASCSI
// Length != 0 if received // Length != 0 if received
if (ctrl.length != 0) { if (ctrl.length != 0) {
// Receive // Receive
@ -1609,7 +1653,7 @@ void FASTCALL SASIDEV::ReceiveNext()
ctrl.length = 0; ctrl.length = 0;
return; return;
} }
#else #else
// Offset and Length // Offset and Length
ASSERT(ctrl.length >= 1); ASSERT(ctrl.length >= 1);
ctrl.offset++; ctrl.offset++;
@ -1621,7 +1665,7 @@ void FASTCALL SASIDEV::ReceiveNext()
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
return; return;
} }
#endif // RASCSI #endif // RASCSI
// Remove the control block and initialize the result // Remove the control block and initialize the result
ctrl.blocks--; ctrl.blocks--;
@ -1648,22 +1692,22 @@ void FASTCALL SASIDEV::ReceiveNext()
if (ctrl.blocks != 0){ if (ctrl.blocks != 0){
ASSERT(ctrl.length > 0); ASSERT(ctrl.length > 0);
ASSERT(ctrl.offset == 0); ASSERT(ctrl.offset == 0);
#ifndef RASCSI #ifndef RASCSI
// Signal line operated by the target // Signal line operated by the target
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
// Move to the next phase // Move to the next phase
switch (ctrl.phase) { switch (ctrl.phase) {
#ifndef RASCSI #ifndef RASCSI
// Command phase // Command phase
case BUS::command: case BUS::command:
// Execution Phase // Execution Phase
Execute(); Execute();
break; break;
#endif // RASCSI #endif // RASCSI
// Data out phase // Data out phase
case BUS::dataout: case BUS::dataout:
@ -1856,7 +1900,7 @@ void FASTCALL SASIDEV::FlushUnit()
// Debug code related to Issue #2 on github, where we get an unhandled Model select when // Debug code related to Issue #2 on github, where we get an unhandled Model select when
// the mac is rebooted // the mac is rebooted
// https://github.com/akuker/RASCSI/issues/2 // https://github.com/akuker/RASCSI/issues/2
Log(Log::Warning, "Received \'Mode Select\'\n"); Log(Log::Warning, "SASI - Received \'Mode Select\'\n");
Log(Log::Warning, " Operation Code: [%02X]\n", ctrl.cmd[0]); Log(Log::Warning, " Operation Code: [%02X]\n", ctrl.cmd[0]);
Log(Log::Warning, " Logical Unit %01X, PF %01X, SP %01X [%02X]\n", ctrl.cmd[1] >> 5, 1 & (ctrl.cmd[1] >> 4), ctrl.cmd[1] & 1, ctrl.cmd[1]); Log(Log::Warning, " Logical Unit %01X, PF %01X, SP %01X [%02X]\n", ctrl.cmd[1] >> 5, 1 & (ctrl.cmd[1] >> 4), ctrl.cmd[1] & 1, ctrl.cmd[1]);
Log(Log::Warning, " Reserved: %02X\n", ctrl.cmd[2]); Log(Log::Warning, " Reserved: %02X\n", ctrl.cmd[2]);
@ -1868,13 +1912,13 @@ void FASTCALL SASIDEV::FlushUnit()
if (!ctrl.unit[lun]->ModeSelect( if (!ctrl.unit[lun]->ModeSelect(
ctrl.cmd, ctrl.buffer, ctrl.offset)) { ctrl.cmd, ctrl.buffer, ctrl.offset)) {
// MODE SELECT failed // MODE SELECT failed
Log(Log::Warning, "Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]); Log(Log::Warning, "SASI - Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]);
return; return;
} }
break; break;
default: default:
Log(Log::Warning, "Received an invalid flush command %02X!!!!!\n",ctrl.cmd[0]); Log(Log::Warning, "SASI - Received an invalid flush command %02X!!!!!\n",ctrl.cmd[0]);
ASSERT(FALSE); ASSERT(FALSE);
break; break;
} }
@ -1938,13 +1982,13 @@ void SASIDEV::GetPhaseStr(char *str)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...) void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...)
{ {
#if !defined(BAREMETAL) #if !defined(BAREMETAL)
#ifdef DISK_LOG #ifdef DISK_LOG
char buffer[0x200]; char buffer[0x200];
char buffer2[0x250]; char buffer2[0x250];
char buffer3[0x250]; char buffer3[0x250];
char phase_str[20]; char phase_str[20];
#endif #endif
va_list args; va_list args;
va_start(args, format); va_start(args, format);
@ -1953,15 +1997,15 @@ void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...)
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
#ifndef DISK_LOG #ifndef DISK_LOG
if (level == Log::Warning) { if (level == Log::Warning) {
return; return;
} }
#endif // DISK_LOG #endif // DISK_LOG
#endif // RASCSI #endif // RASCSI
#ifdef DISK_LOG #ifdef DISK_LOG
// format // format
vsprintf(buffer, format, args); vsprintf(buffer, format, args);
@ -1974,7 +2018,6 @@ void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...)
// convert now to string form // convert now to string form
char* dt = ctime(&now); char* dt = ctime(&now);
strcpy(buffer2, "["); strcpy(buffer2, "[");
strcat(buffer2, dt); strcat(buffer2, dt);
// Get rid of the carriage return // Get rid of the carriage return
@ -1987,13 +2030,12 @@ void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...)
strcat(buffer2,buffer3); strcat(buffer2,buffer3);
strcat(buffer2, buffer); strcat(buffer2, buffer);
// Log output // Log output
#ifdef RASCSI #ifdef RASCSI
printf("%s\n", buffer2); printf("%s\n", buffer2);
#else #else
host->GetVM()->GetLog()->Format(level, host, buffer); host->GetVM()->GetLog()->Format(level, host, buffer);
#endif // RASCSI #endif // RASCSI
#endif // BAREMETAL #endif // BAREMETAL
#endif // DISK_LOG #endif // DISK_LOG
} }

View File

@ -31,18 +31,17 @@
class SASIDEV class SASIDEV
{ {
public: public:
// Maximum number of logical units
enum { enum {
UnitMax = 8 UnitMax = 8 // Maximum number of logical units
}; };
#ifdef RASCSI #ifdef RASCSI
// For timing adjustments // For timing adjustments
enum { enum {
min_exec_time_sasi = 100, // SASI BOOT/FORMAT 30:NG 35:OK min_exec_time_sasi = 100, // SASI BOOT/FORMAT 30:NG 35:OK
min_exec_time_scsi = 50 min_exec_time_scsi = 50
}; };
#endif // RASCSI #endif // RASCSI
// Internal data definition // Internal data definition
typedef struct { typedef struct {
@ -56,10 +55,10 @@ public:
DWORD status; // Status data DWORD status; // Status data
DWORD message; // Message data DWORD message; // Message data
#ifdef RASCSI #ifdef RASCSI
// Run // Run
DWORD execstart; // Execution start time DWORD execstart; // Execution start time
#endif // RASCSI #endif // RASCSI
// Transfer // Transfer
BYTE *buffer; // Transfer data buffer BYTE *buffer; // Transfer data buffer
@ -70,142 +69,102 @@ public:
DWORD length; // Transfer remaining length DWORD length; // Transfer remaining length
// Logical unit // Logical unit
Disk *unit[UnitMax]; Disk *unit[UnitMax]; // Logical Unit
// Logical Unit
} ctrl_t; } ctrl_t;
public: public:
// Basic Functions // Basic Functions
#ifdef RASCSI #ifdef RASCSI
SASIDEV(); SASIDEV();
#else #else
SASIDEV(Device *dev);
#endif //RASCSI
// Constructor SASIDEV(Device *dev); // Constructor
virtual ~SASIDEV();
// Destructor #endif //RASCSI
virtual void FASTCALL Reset(); virtual ~SASIDEV(); // Destructor
// Device Reset virtual void FASTCALL Reset(); // Device Reset
#ifndef RASCSI
virtual BOOL FASTCALL Save(Fileio *fio, int ver); #ifndef RASCSI
// Save virtual BOOL FASTCALL Save(Fileio *fio, int ver); // Save
virtual BOOL FASTCALL Load(Fileio *fio, int ver); virtual BOOL FASTCALL Load(Fileio *fio, int ver); // Load
// Load #endif //RASCSI
#endif //RASCSI
// External API // External API
virtual BUS::phase_t FASTCALL Process(); virtual BUS::phase_t FASTCALL Process(); // Run
// Run
// Connect // Connect
void FASTCALL Connect(int id, BUS *sbus); void FASTCALL Connect(int id, BUS *sbus); // Controller connection
// Controller connection Disk* FASTCALL GetUnit(int no); // Get logical unit
Disk* FASTCALL GetUnit(int no); void FASTCALL SetUnit(int no, Disk *dev); // Logical unit setting
// Get logical unit BOOL FASTCALL HasUnit(); // Has a valid logical unit
void FASTCALL SetUnit(int no, Disk *dev);
// Logical unit setting
BOOL FASTCALL HasUnit();
// Has a valid logical unit
// Other // Other
BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} // Get the phase
// Get the phase #ifdef DISK_LOG
#ifdef DISK_LOG
// Function to get the current phase as a String. // Function to get the current phase as a String.
void FASTCALL GetPhaseStr(char *str); void FASTCALL GetPhaseStr(char *str);
#endif #endif
int FASTCALL GetID() {return ctrl.id;} int FASTCALL GetID() {return ctrl.id;} // Get the ID
// Get the ID void FASTCALL GetCTRL(ctrl_t *buffer); // Get the internal information
void FASTCALL GetCTRL(ctrl_t *buffer); ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } // Get the internal information address
// Get the internal information virtual BOOL FASTCALL IsSASI() const {return TRUE;} // SASI Check
ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } virtual BOOL FASTCALL IsSCSI() const {return FALSE;} // SCSI check
// Get the internal information address Disk* FASTCALL GetBusyUnit(); // Get the busy unit
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: protected:
// Phase processing // Phase processing
virtual void FASTCALL BusFree(); virtual void FASTCALL BusFree(); // Bus free phase
// Bus free phase virtual void FASTCALL Selection(); // Selection phase
virtual void FASTCALL Selection(); virtual void FASTCALL Command(); // Command phase
// Selection phase virtual void FASTCALL Execute(); // Execution phase
virtual void FASTCALL Command(); void FASTCALL Status(); // Status phase
// Command phase void FASTCALL MsgIn(); // Message in phase
virtual void FASTCALL Execute(); void FASTCALL DataIn(); // Data in phase
// Execution phase void FASTCALL DataOut(); // Data out phase
void FASTCALL Status(); virtual void FASTCALL Error(); // Common error handling
// 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 // commands
void FASTCALL CmdTestUnitReady(); void FASTCALL CmdTestUnitReady(); // TEST UNIT READY command
// TEST UNIT READY command void FASTCALL CmdRezero(); // REZERO UNIT command
void FASTCALL CmdRezero(); void FASTCALL CmdRequestSense(); // REQUEST SENSE command
// REZERO UNIT command void FASTCALL CmdFormat(); // FORMAT command
void FASTCALL CmdRequestSense(); void FASTCALL CmdReassign(); // REASSIGN BLOCKS command
// REQUEST SENSE command void FASTCALL CmdReserveUnit(); // RESERVE UNIT command
void FASTCALL CmdFormat(); void FASTCALL CmdReleaseUnit(); // RELEASE UNIT command
// FORMAT command void FASTCALL CmdRead6(); // READ(6) command
void FASTCALL CmdReassign(); void FASTCALL CmdWrite6(); // WRITE(6) command
// REASSIGN BLOCKS command void FASTCALL CmdSeek6(); // SEEK(6) command
void FASTCALL CmdRead6(); void FASTCALL CmdAssign(); // ASSIGN command
// READ(6) command void FASTCALL CmdSpecify(); // SPECIFY command
void FASTCALL CmdWrite6(); void FASTCALL CmdInvalid(); // Unsupported command
// 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(); virtual void FASTCALL Send(); // Send data
// Send data
#ifndef RASCSI #ifndef RASCSI
virtual void FASTCALL SendNext(); virtual void FASTCALL SendNext(); // Continue sending data
// Continue sending data #endif // RASCSI
#endif // RASCSI
virtual void FASTCALL Receive(); virtual void FASTCALL Receive(); // Receive data
// Receive data
#ifndef RASCSI #ifndef RASCSI
virtual void FASTCALL ReceiveNext(); virtual void FASTCALL ReceiveNext(); // Continue receiving data
// Continue receiving data #endif // RASCSI
#endif // RASCSI
BOOL FASTCALL XferIn(BYTE* buf); BOOL FASTCALL XferIn(BYTE* buf); // Data transfer IN
// Data transfer IN BOOL FASTCALL XferOut(BOOL cont); // Data transfer OUT
BOOL FASTCALL XferOut(BOOL cont);
// Data transfer OUT
// Special operations // Special operations
void FASTCALL FlushUnit(); void FASTCALL FlushUnit(); // Flush the logical unit
// Flush the logical unit
// Log // Log
void FASTCALL Log(Log::loglevel level, const char *format, ...); void FASTCALL Log(Log::loglevel level, const char *format, ...); // Log output
// Log output
protected: protected:
#ifndef RASCSI #ifndef RASCSI
Device *host; Device *host; // Host device
// Host device #endif // RASCSI
#endif // RASCSI ctrl_t ctrl; // Internal data
ctrl_t ctrl;
// Internal data
}; };

View File

@ -81,9 +81,9 @@ BUS::phase_t FASTCALL SCSIDEV::Process()
// Reset // Reset
if (ctrl.bus->GetRST()) { if (ctrl.bus->GetRST()) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "RESET信号受信"); Log(Log::Normal, "SCSI - RESET信号受信");
#endif // DISK_LOG #endif // DISK_LOG
// Reset the controller // Reset the controller
Reset(); Reset();
@ -162,9 +162,9 @@ void FASTCALL SCSIDEV::BusFree()
// Phase change // Phase change
if (ctrl.phase != BUS::busfree) { if (ctrl.phase != BUS::busfree) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Bus free phase"); Log(Log::Normal, "SCSI - Bus free phase");
#endif // DISK_LOG #endif // DISK_LOG
// Phase setting // Phase setting
ctrl.phase = BUS::busfree; ctrl.phase = BUS::busfree;
@ -215,10 +215,9 @@ void FASTCALL SCSIDEV::Selection()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - Selection Phase ID=%d (with device)", ctrl.id);
"Selection Phase ID=%d (with device)", ctrl.id); #endif // DISK_LOG
#endif // DISK_LOG
// Phase setting // Phase setting
ctrl.phase = BUS::selection; ctrl.phase = BUS::selection;
@ -248,9 +247,9 @@ void FASTCALL SCSIDEV::Execute()
{ {
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Execution phase command $%02X", ctrl.cmd[0]); Log(Log::Normal, "SCSI - Execution phase command $%02X", ctrl.cmd[0]);
#endif // DISK_LOG #endif // DISK_LOG
// Phase Setting // Phase Setting
ctrl.phase = BUS::execute; ctrl.phase = BUS::execute;
@ -258,9 +257,9 @@ void FASTCALL SCSIDEV::Execute()
// Initialization for data transfer // Initialization for data transfer
ctrl.offset = 0; ctrl.offset = 0;
ctrl.blocks = 1; ctrl.blocks = 1;
#ifdef RASCSI #ifdef RASCSI
ctrl.execstart = SysTimer::GetTimerLow(); ctrl.execstart = SysTimer::GetTimerLow();
#endif // RASCSI #endif // RASCSI
// Process by command // Process by command
switch (ctrl.cmd[0]) { switch (ctrl.cmd[0]) {
@ -314,6 +313,26 @@ void FASTCALL SCSIDEV::Execute()
CmdModeSelect(); CmdModeSelect();
return; return;
// RESERVE(6)
case 0x16:
CmdReserve6();
return;
// RESERVE(10)
case 0x56:
CmdReserve10();
return;
// RELEASE(6)
case 0x17:
CmdRelease6();
return;
// RELEASE(10)
case 0x57:
CmdRelease10();
return;
// MDOE SENSE // MDOE SENSE
case 0x1a: case 0x1a:
CmdModeSense(); CmdModeSense();
@ -412,7 +431,7 @@ void FASTCALL SCSIDEV::Execute()
} }
// No other support // No other support
Log(Log::Normal, "Unsupported command received: $%02X", ctrl.cmd[0]); Log(Log::Normal, "SCSI - Unsupported command received: $%02X", ctrl.cmd[0]);
CmdInvalid(); CmdInvalid();
} }
@ -428,11 +447,10 @@ void FASTCALL SCSIDEV::MsgOut()
// Phase change // Phase change
if (ctrl.phase != BUS::msgout) { if (ctrl.phase != BUS::msgout) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Message Out Phase"); Log(Log::Normal, "SCSI - Message Out Phase"); // Message out phase after selection
#endif // DISK_LOG #endif // DISK_LOG
// Message out phase after selection
// process the IDENTIFY message // process the IDENTIFY message
if (ctrl.phase == BUS::selection) { if (ctrl.phase == BUS::selection) {
scsi.atnmsg = TRUE; scsi.atnmsg = TRUE;
@ -453,17 +471,18 @@ void FASTCALL SCSIDEV::MsgOut()
ctrl.length = 1; ctrl.length = 1;
ctrl.blocks = 1; ctrl.blocks = 1;
#ifndef RASCSI #ifndef RASCSI
// Request message // Request message
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
#ifdef RASCSI #ifdef RASCSI
// Receive // Receive
Receive(); Receive();
#else #else
// Requesting // Requesting
if (ctrl.bus->GetREQ()) { if (ctrl.bus->GetREQ()) {
// Sent by the initiator // Sent by the initiator
@ -476,7 +495,7 @@ void FASTCALL SCSIDEV::MsgOut()
ReceiveNext(); ReceiveNext();
} }
} }
#endif // RASCSI #endif // RASCSI
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -507,9 +526,9 @@ void FASTCALL SCSIDEV::Error()
return; return;
} }
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Error (to status phase)"); Log(Log::Normal, "SCSI - Error (to status phase)");
#endif // DISK_LOG #endif // DISK_LOG
// Set status and message(CHECK CONDITION) // Set status and message(CHECK CONDITION)
ctrl.status = 0x02; ctrl.status = 0x02;
@ -539,9 +558,9 @@ void FASTCALL SCSIDEV::CmdInquiry()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "INQUIRY Command"); Log(Log::Normal, "SCSI - INQUIRY Command");
#endif // DISK_LOG #endif // DISK_LOG
// Find a valid unit // Find a valid unit
disk = NULL; disk = NULL;
@ -588,9 +607,9 @@ void FASTCALL SCSIDEV::CmdModeSelect()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "MODE SELECT Command"); Log(Log::Normal, "SCSI - MODE SELECT Command");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -611,6 +630,75 @@ void FASTCALL SCSIDEV::CmdModeSelect()
DataOut(); DataOut();
} }
// The following commands RESERVE(6), RESERVE(10), RELEASE(6) and RELEASE(10)
// are not properly implemented. These commands are used in multi-initator environments
// which this project is not targeted at. For now, we simply reply with an OK.
// -phrax 2021-03-06
//---------------------------------------------------------------------------
//
// RESERVE(6)
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::CmdReserve6()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SCSI - RESERVE(6) Command");
#endif // DISK_LOG
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// RESERVE(10)
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::CmdReserve10()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SCSI - RESERVE(10) Command");
#endif // DISK_LOG
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// RELEASE(6)
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::CmdRelease6()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SCSI - RELEASE(6) Command");
#endif // DISK_LOG
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// RELEASE(10)
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::CmdRelease10()
{
ASSERT(this);
#if defined(DISK_LOG)
Log(Log::Normal, "SCSI - RELEASE(10) Command");
#endif // DISK_LOG
// status phase
Status();
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// MODE SENSE // MODE SENSE
@ -622,9 +710,9 @@ void FASTCALL SCSIDEV::CmdModeSense()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "MODE SENSE Command "); Log(Log::Normal, "SCSI - MODE SENSE Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -637,8 +725,7 @@ void FASTCALL SCSIDEV::CmdModeSense()
ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer); ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length >= 0); ASSERT(ctrl.length >= 0);
if (ctrl.length == 0) { if (ctrl.length == 0) {
Log(Log::Warning, Log(Log::Warning,"SCSI - Not supported MODE SENSE page $%02X", ctrl.cmd[2]);
"Not supported MODE SENSE page $%02X", ctrl.cmd[2]);
// Failure (Error) // Failure (Error)
Error(); Error();
@ -661,9 +748,9 @@ void FASTCALL SCSIDEV::CmdStartStop()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "START STOP UNIT Command "); Log(Log::Normal, "SCSI - START STOP UNIT Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -696,9 +783,9 @@ void FASTCALL SCSIDEV::CmdSendDiag()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "SEND DIAGNOSTIC Command "); Log(Log::Normal, "SCSI - SEND DIAGNOSTIC Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -731,9 +818,9 @@ void FASTCALL SCSIDEV::CmdRemoval()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "PREVENT/ALLOW MEDIUM REMOVAL Command "); Log(Log::Normal, "SCSI - PREVENT/ALLOW MEDIUM REMOVAL Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -766,9 +853,9 @@ void FASTCALL SCSIDEV::CmdReadCapacity()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "READ CAPACITY Command "); Log(Log::Normal, "SCSI - READ CAPACITY Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -829,9 +916,9 @@ void FASTCALL SCSIDEV::CmdRead10()
ctrl.blocks <<= 8; ctrl.blocks <<= 8;
ctrl.blocks |= ctrl.cmd[8]; ctrl.blocks |= ctrl.cmd[8];
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "READ(10) command record=%08X block=%d", record, ctrl.blocks); Log(Log::Normal, "SCSI - READ(10) command record=%08X block=%d", record, ctrl.blocks);
#endif // DISK_LOG #endif // DISK_LOG
// Do not process 0 blocks // Do not process 0 blocks
if (ctrl.blocks == 0) { if (ctrl.blocks == 0) {
@ -891,10 +978,9 @@ void FASTCALL SCSIDEV::CmdWrite10()
ctrl.blocks <<= 8; ctrl.blocks <<= 8;
ctrl.blocks |= ctrl.cmd[8]; ctrl.blocks |= ctrl.cmd[8];
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - WRTIE(10) command record=%08X blocks=%d", record, ctrl.blocks);
"WRTIE(10) command record=%08X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG
#endif // DISK_LOG
// Do not process 0 blocks // Do not process 0 blocks
if (ctrl.blocks == 0) { if (ctrl.blocks == 0) {
@ -929,9 +1015,9 @@ void FASTCALL SCSIDEV::CmdSeek10()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "SEEK(10) Command "); Log(Log::Normal, "SCSI - SEEK(10) Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -984,10 +1070,9 @@ void FASTCALL SCSIDEV::CmdVerify()
ctrl.blocks <<= 8; ctrl.blocks <<= 8;
ctrl.blocks |= ctrl.cmd[8]; ctrl.blocks |= ctrl.cmd[8];
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - VERIFY command record=%08X blocks=%d", record, ctrl.blocks);
"VERIFY command record=%08X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG
#endif // DISK_LOG
// Do not process 0 blocks // Do not process 0 blocks
if (ctrl.blocks == 0) { if (ctrl.blocks == 0) {
@ -1057,12 +1142,11 @@ void FASTCALL SCSIDEV::CmdSynchronizeCache()
void FASTCALL SCSIDEV::CmdReadDefectData10() void FASTCALL SCSIDEV::CmdReadDefectData10()
{ {
DWORD lun; DWORD lun;
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "READ DEFECT DATA(10) Command "); Log(Log::Normal, "SCSI - READ DEFECT DATA(10) Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1092,7 +1176,6 @@ void FASTCALL SCSIDEV::CmdReadDefectData10()
void FASTCALL SCSIDEV::CmdReadToc() void FASTCALL SCSIDEV::CmdReadToc()
{ {
DWORD lun; DWORD lun;
ASSERT(this); ASSERT(this);
// Logical Unit // Logical Unit
@ -1218,9 +1301,9 @@ void FASTCALL SCSIDEV::CmdModeSelect10()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "MODE SELECT10 Command "); Log(Log::Normal, "SCSI - MODE SELECT10 Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1252,9 +1335,9 @@ void FASTCALL SCSIDEV::CmdModeSense10()
ASSERT(this); ASSERT(this);
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "MODE SENSE(10) Command "); Log(Log::Normal, "SCSI - MODE SENSE(10) Command ");
#endif // DISK_LOG #endif // DISK_LOG
// Logical Unit // Logical Unit
lun = (ctrl.cmd[1] >> 5) & 0x07; lun = (ctrl.cmd[1] >> 5) & 0x07;
@ -1267,8 +1350,7 @@ void FASTCALL SCSIDEV::CmdModeSense10()
ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer); ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length >= 0); ASSERT(ctrl.length >= 0);
if (ctrl.length == 0) { if (ctrl.length == 0) {
Log(Log::Warning, Log(Log::Warning,"SCSI - Not supported MODE SENSE(10) page $%02X", ctrl.cmd[2]);
"Not supported MODE SENSE(10) page $%02X", ctrl.cmd[2]);
// Failure (Error) // Failure (Error)
Error(); Error();
@ -1394,16 +1476,16 @@ void FASTCALL SCSIDEV::CmdSendMessage10()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SCSIDEV::Send() void FASTCALL SCSIDEV::Send()
{ {
#ifdef RASCSI #ifdef RASCSI
int len; int len;
#endif // RASCSI #endif // RASCSI
BOOL result; BOOL result;
ASSERT(this); ASSERT(this);
ASSERT(!ctrl.bus->GetREQ()); ASSERT(!ctrl.bus->GetREQ());
ASSERT(ctrl.bus->GetIO()); ASSERT(ctrl.bus->GetIO());
#ifdef RASCSI #ifdef RASCSI
//if Length! = 0, send //if Length! = 0, send
if (ctrl.length != 0) { if (ctrl.length != 0) {
len = ctrl.bus->SendHandShake( len = ctrl.bus->SendHandShake(
@ -1420,7 +1502,7 @@ void FASTCALL SCSIDEV::Send()
ctrl.length = 0; ctrl.length = 0;
return; return;
} }
#else #else
// offset and length // offset and length
ASSERT(ctrl.length >= 1); ASSERT(ctrl.length >= 1);
ctrl.offset++; ctrl.offset++;
@ -1433,7 +1515,7 @@ void FASTCALL SCSIDEV::Send()
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
return; return;
} }
#endif // RASCSI #endif // RASCSI
// Block subtraction, result initialization // Block subtraction, result initialization
ctrl.blocks--; ctrl.blocks--;
@ -1442,11 +1524,11 @@ void FASTCALL SCSIDEV::Send()
// Processing after data collection (read/data-in only) // Processing after data collection (read/data-in only)
if (ctrl.phase == BUS::datain) { if (ctrl.phase == BUS::datain) {
if (ctrl.blocks != 0) { if (ctrl.blocks != 0) {
// // set next buffer (set offset, length) // set next buffer (set offset, length)
result = XferIn(ctrl.buffer); result = XferIn(ctrl.buffer);
#ifndef RASCSI #ifndef RASCSI
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
#endif // RASCSI #endif // RASCSI
} }
} }
@ -1460,10 +1542,10 @@ void FASTCALL SCSIDEV::Send()
if (ctrl.blocks != 0){ if (ctrl.blocks != 0){
ASSERT(ctrl.length > 0); ASSERT(ctrl.length > 0);
ASSERT(ctrl.offset == 0); ASSERT(ctrl.offset == 0);
#ifndef RASCSI #ifndef RASCSI
// Signal line operated by the target // Signal line operated by the target
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
@ -1556,9 +1638,9 @@ void FASTCALL SCSIDEV::Receive()
// Command phase // Command phase
case BUS::command: case BUS::command:
ctrl.cmd[ctrl.offset] = data; ctrl.cmd[ctrl.offset] = data;
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Command phase $%02X", data); Log(Log::Normal, "SCSI - Command phase $%02X", data);
#endif // DISK_LOG #endif // DISK_LOG
// Set the length again with the first data (offset 0) // Set the length again with the first data (offset 0)
if (ctrl.offset == 0) { if (ctrl.offset == 0) {
@ -1572,9 +1654,9 @@ void FASTCALL SCSIDEV::Receive()
// Message out phase // Message out phase
case BUS::msgout: case BUS::msgout:
ctrl.message = data; ctrl.message = data;
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Message out phase $%02X", data); Log(Log::Normal, "SCSI - Message out phase $%02X", data);
#endif // DISK_LOG #endif // DISK_LOG
break; break;
// Data out phase // Data out phase
@ -1598,6 +1680,7 @@ void FASTCALL SCSIDEV::Receive()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FASTCALL SCSIDEV::Receive() void FASTCALL SCSIDEV::Receive()
#else #else
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Continue receiving data // Continue receiving data
@ -1606,9 +1689,9 @@ void FASTCALL SCSIDEV::Receive()
void FASTCALL SCSIDEV::ReceiveNext() void FASTCALL SCSIDEV::ReceiveNext()
#endif // RASCSI #endif // RASCSI
{ {
#ifdef RASCSI #ifdef RASCSI
int len; int len;
#endif // RASCSI #endif // RASCSI
BOOL result; BOOL result;
int i; int i;
BYTE data; BYTE data;
@ -1619,7 +1702,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
ASSERT(!ctrl.bus->GetREQ()); ASSERT(!ctrl.bus->GetREQ());
ASSERT(!ctrl.bus->GetIO()); ASSERT(!ctrl.bus->GetIO());
#ifdef RASCSI #ifdef RASCSI
// Length != 0 if received // Length != 0 if received
if (ctrl.length != 0) { if (ctrl.length != 0) {
// Receive // Receive
@ -1637,7 +1720,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
ctrl.length = 0;; ctrl.length = 0;;
return; return;
} }
#else #else
// Offset and Length // Offset and Length
ASSERT(ctrl.length >= 1); ASSERT(ctrl.length >= 1);
ctrl.offset++; ctrl.offset++;
@ -1649,7 +1732,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
return; return;
} }
#endif // RASCSI #endif // RASCSI
// Block subtraction, result initialization // Block subtraction, result initialization
ctrl.blocks--; ctrl.blocks--;
@ -1696,10 +1779,10 @@ void FASTCALL SCSIDEV::ReceiveNext()
if (ctrl.blocks != 0){ if (ctrl.blocks != 0){
ASSERT(ctrl.length > 0); ASSERT(ctrl.length > 0);
ASSERT(ctrl.offset == 0); ASSERT(ctrl.offset == 0);
#ifndef RASCSI #ifndef RASCSI
// Signal line operated by the target // Signal line operated by the target
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
@ -1707,7 +1790,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
switch (ctrl.phase) { switch (ctrl.phase) {
// Command phase // Command phase
case BUS::command: case BUS::command:
#ifdef RASCSI #ifdef RASCSI
// Command data transfer // Command data transfer
len = 6; len = 6;
if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) {
@ -1716,11 +1799,11 @@ void FASTCALL SCSIDEV::ReceiveNext()
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, "Command $%02X", ctrl.cmd[i]); Log(Log::Normal, "SCSI - Command $%02X", ctrl.cmd[i]);
#endif // DISK_LOG #endif // DISK_LOG
} }
#endif // RASCSI #endif // RASCSI
// Execution Phase // Execution Phase
Execute(); Execute();
@ -1734,10 +1817,10 @@ void FASTCALL SCSIDEV::ReceiveNext()
ctrl.offset = 0; ctrl.offset = 0;
ctrl.length = 1; ctrl.length = 1;
ctrl.blocks = 1; ctrl.blocks = 1;
#ifndef RASCSI #ifndef RASCSI
// Request message // Request message
ctrl.bus->SetREQ(TRUE); ctrl.bus->SetREQ(TRUE);
#endif // RASCSI #endif // RASCSI
return; return;
} }
@ -1750,20 +1833,18 @@ void FASTCALL SCSIDEV::ReceiveNext()
// ABORT // ABORT
if (data == 0x06) { if (data == 0x06) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - Message code ABORT $%02X", data);
"Message code ABORT $%02X", data); #endif // DISK_LOG
#endif // DISK_LOG
BusFree(); BusFree();
return; return;
} }
// BUS DEVICE RESET // BUS DEVICE RESET
if (data == 0x0C) { if (data == 0x0C) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - Message code BUS DEVICE RESET $%02X", data);
"Message code BUS DEVICE RESET $%02X", data); #endif // DISK_LOG
#endif // DISK_LOG
scsi.syncoffset = 0; scsi.syncoffset = 0;
BusFree(); BusFree();
return; return;
@ -1771,18 +1852,16 @@ void FASTCALL SCSIDEV::ReceiveNext()
// IDENTIFY // IDENTIFY
if (data >= 0x80) { if (data >= 0x80) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - Message code IDENTIFY $%02X", data);
"Message code IDENTIFY $%02X", data); #endif // DISK_LOG
#endif // DISK_LOG
} }
// Extended Message // Extended Message
if (data == 0x01) { if (data == 0x01) {
#if defined(DISK_LOG) #if defined(DISK_LOG)
Log(Log::Normal, Log(Log::Normal,"SCSI - Message code EXTENDED MESSAGE $%02X", data);
"Message code EXTENDED MESSAGE $%02X", data); #endif // DISK_LOG
#endif // DISK_LOG
// Check only when synchronous transfer is possible // Check only when synchronous transfer is possible
if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) {

View File

@ -43,100 +43,66 @@ public:
#ifdef RASCSI #ifdef RASCSI
SCSIDEV(); SCSIDEV();
#else #else
SCSIDEV(Device *dev); SCSIDEV(Device *dev); // Constructor
#endif // RASCSI #endif // RASCSI
// Constructor
void FASTCALL Reset(); void FASTCALL Reset(); // Device Reset
// Device Reset
// 外部API // 外部API
BUS::phase_t FASTCALL Process(); BUS::phase_t FASTCALL Process(); // Run
// Run
void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } // Synchronouse transfer enable setting
// Synchronouse transfer enable setting
// Other // Other
BOOL FASTCALL IsSASI() const {return FALSE;} BOOL FASTCALL IsSASI() const {return FALSE;} // SASI Check
// SASI Check BOOL FASTCALL IsSCSI() const {return TRUE;} // SCSI check
BOOL FASTCALL IsSCSI() const {return TRUE;}
// SCSI check
private: private:
// Phase // Phase
void FASTCALL BusFree(); void FASTCALL BusFree(); // Bus free phase
// Bus free phase void FASTCALL Selection(); // Selection phase
void FASTCALL Selection(); void FASTCALL Execute(); // Execution phase
// Selection phase void FASTCALL MsgOut(); // Message out phase
void FASTCALL Execute(); void FASTCALL Error(); // Common erorr handling
// Execution phase
void FASTCALL MsgOut();
// Message out phase
void FASTCALL Error();
// Common erorr handling
// commands // commands
void FASTCALL CmdInquiry(); void FASTCALL CmdInquiry(); // INQUIRY command
// INQUIRY command void FASTCALL CmdModeSelect(); // MODE SELECT command
void FASTCALL CmdModeSelect(); void FASTCALL CmdReserve6(); // RESERVE(6) command
// MODE SELECT command void FASTCALL CmdReserve10(); // RESERVE(10) command
void FASTCALL CmdModeSense(); void FASTCALL CmdRelease6(); // RELEASE(6) command
// MODE SENSE command void FASTCALL CmdRelease10(); // RELEASE(10) command
void FASTCALL CmdStartStop(); void FASTCALL CmdModeSense(); // MODE SENSE command
// START STOP UNIT command void FASTCALL CmdStartStop(); // START STOP UNIT command
void FASTCALL CmdSendDiag(); void FASTCALL CmdSendDiag(); // SEND DIAGNOSTIC command
// SEND DIAGNOSTIC command void FASTCALL CmdRemoval(); // PREVENT/ALLOW MEDIUM REMOVAL command
void FASTCALL CmdRemoval(); void FASTCALL CmdReadCapacity(); // READ CAPACITY command
// PREVENT/ALLOW MEDIUM REMOVAL command void FASTCALL CmdRead10(); // READ(10) command
void FASTCALL CmdReadCapacity(); void FASTCALL CmdWrite10(); // WRITE(10) command
// READ CAPACITY command void FASTCALL CmdSeek10(); // SEEK(10) command
void FASTCALL CmdRead10(); void FASTCALL CmdVerify(); // VERIFY command
// READ(10) command void FASTCALL CmdSynchronizeCache(); // SYNCHRONIZE CACHE command
void FASTCALL CmdWrite10(); void FASTCALL CmdReadDefectData10(); // READ DEFECT DATA(10) command
// WRITE(10) command void FASTCALL CmdReadToc(); // READ TOC command
void FASTCALL CmdSeek10(); void FASTCALL CmdPlayAudio10(); // PLAY AUDIO(10) command
// SEEK(10) command void FASTCALL CmdPlayAudioMSF(); // PLAY AUDIO MSF command
void FASTCALL CmdVerify(); void FASTCALL CmdPlayAudioTrack(); // PLAY AUDIO TRACK INDEX command
// VERIFY command void FASTCALL CmdModeSelect10(); // MODE SELECT(10) command
void FASTCALL CmdSynchronizeCache(); void FASTCALL CmdModeSense10(); // MODE SENSE(10) command
// SYNCHRONIZE CACHE command void FASTCALL CmdGetMessage10(); // GET MESSAGE(10) command
void FASTCALL CmdReadDefectData10(); void FASTCALL CmdSendMessage10(); // SEND MESSAGE(10) command
// 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(); void FASTCALL Send(); // Send data
// Send data #ifndef RASCSI
#ifndef RASCSI void FASTCALL SendNext(); // Continue sending data
void FASTCALL SendNext(); #endif // RASCSI
// Continue sending data void FASTCALL Receive(); // Receive data
#endif // RASCSI #ifndef RASCSI
void FASTCALL Receive(); void FASTCALL ReceiveNext(); // Continue receiving data
// Receive data #endif // RASCSI
#ifndef RASCSI BOOL FASTCALL XferMsg(DWORD msg); // Data transfer message
void FASTCALL ReceiveNext();
// Continue receiving data
#endif // RASCSI
BOOL FASTCALL XferMsg(DWORD msg);
// Data transfer message
scsi_t scsi; scsi_t scsi; // Internal data
// Internal data
}; };

View File

@ -328,41 +328,22 @@ Human68k側のファイル名は、ホスト側のファイルシステムの名
*/ */
enum { enum {
WINDRV_OPT_REMOVE = 0x00000001, WINDRV_OPT_REMOVE = 0x00000001, ///< Bit 0: ファイル削除処理 0:直接 1:ごみ箱
///< Bit 0: ファイル削除処理 0:直接 1:ごみ箱 WINDRV_OPT_ALPHABET = 0x00000020, ///< Bit 5: ファイル名比較 Alphabet区別 0:なし 1:あり 0:-C 1:+C
WINDRV_OPT_ALPHABET = 0x00000020, WINDRV_OPT_COMPARE_LENGTH = 0x00000040, ///< Bit 6: ファイル名比較 文字数(未実装) 0:18+3 1:8+3 0:+T 1:-T
///< Bit 5: ファイル名比較 Alphabet区別 0:なし 1:あり 0:-C 1:+C WINDRV_OPT_CONVERT_LENGTH = 0x00000080, ///< Bit 7: ファイル名変換 文字数 0:18+3 1:8+3 0:-A 1:+A
WINDRV_OPT_COMPARE_LENGTH = 0x00000040, WINDRV_OPT_CONVERT_SPACE = 0x00000100, ///< Bit 8: ファイル名変換 スペース 0:なし 1:'_'
///< Bit 6: ファイル名比較 文字数(未実装) 0:18+3 1:8+3 0:+T 1:-T WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, ///< Bit 9: ファイル名変換 無効な文字 0:なし 1:'_'
WINDRV_OPT_CONVERT_LENGTH = 0x00000080, WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, ///< Bit10: ファイル名変換 中間のハイフン 0:なし 1:'_'
///< Bit 7: ファイル名変換 文字数 0:18+3 1:8+3 0:-A 1:+A WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, ///< Bit11: ファイル名変換 先頭のハイフン 0:なし 1:'_'
WINDRV_OPT_CONVERT_PERIODS = 0x00001000, ///< Bit12: ファイル名変換 中間のピリオド 0:なし 1:'_'
WINDRV_OPT_CONVERT_SPACE = 0x00000100, WINDRV_OPT_CONVERT_PERIOD = 0x00002000, ///< Bit13: ファイル名変換 先頭のピリオド 0:なし 1:'_'
///< Bit 8: ファイル名変換 スペース 0:なし 1:'_' WINDRV_OPT_REDUCED_SPACE = 0x00010000, ///< Bit16: ファイル名短縮 スペース 0:なし 1:短縮
WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, WINDRV_OPT_REDUCED_BADCHAR = 0x00020000, ///< Bit17: ファイル名短縮 無効な文字 0:なし 1:短縮
///< Bit 9: ファイル名変換 無効な文字 0:なし 1:'_' WINDRV_OPT_REDUCED_HYPHENS = 0x00040000, ///< Bit18: ファイル名短縮 中間のハイフン 0:なし 1:短縮
WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, WINDRV_OPT_REDUCED_HYPHEN = 0x00080000, ///< Bit19: ファイル名短縮 先頭のハイフン 0:なし 1:短縮
///< Bit10: ファイル名変換 中間のハイフン 0:なし 1:'_' WINDRV_OPT_REDUCED_PERIODS = 0x00100000, ///< Bit20: ファイル名短縮 中間のピリオド 0:なし 1:短縮
WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, WINDRV_OPT_REDUCED_PERIOD = 0x00200000, ///< Bit21: ファイル名短縮 先頭のピリオド 0:なし 1:短縮
///< Bit11: ファイル名変換 先頭のハイフン 0:なし 1:'_'
WINDRV_OPT_CONVERT_PERIODS = 0x00001000,
///< Bit12: ファイル名変換 中間のピリオド 0:なし 1:'_'
WINDRV_OPT_CONVERT_PERIOD = 0x00002000,
///< Bit13: ファイル名変換 先頭のピリオド 0:なし 1:'_'
WINDRV_OPT_REDUCED_SPACE = 0x00010000,
///< Bit16: ファイル名短縮 スペース 0:なし 1:短縮
WINDRV_OPT_REDUCED_BADCHAR = 0x00020000,
///< Bit17: ファイル名短縮 無効な文字 0:なし 1:短縮
WINDRV_OPT_REDUCED_HYPHENS = 0x00040000,
///< Bit18: ファイル名短縮 中間のハイフン 0:なし 1:短縮
WINDRV_OPT_REDUCED_HYPHEN = 0x00080000,
///< Bit19: ファイル名短縮 先頭のハイフン 0:なし 1:短縮
WINDRV_OPT_REDUCED_PERIODS = 0x00100000,
///< Bit20: ファイル名短縮 中間のピリオド 0:なし 1:短縮
WINDRV_OPT_REDUCED_PERIOD = 0x00200000,
///< Bit21: ファイル名短縮 先頭のピリオド 0:なし 1:短縮
// Bit2430 ファイル重複防止マーク 0:自動 1127:文字 // Bit2430 ファイル重複防止マーク 0:自動 1127:文字
}; };
@ -373,12 +354,9 @@ enum {
(USBストレージとか) (USBストレージとか)
*/ */
enum { enum {
FSFLAG_WRITE_PROTECT = 0x00000001, FSFLAG_WRITE_PROTECT = 0x00000001, ///< Bit0: 強制書き込み禁止
///< Bit0: 強制書き込み禁止 FSFLAG_REMOVABLE = 0x00000002, ///< Bit1: 強制リムーバブルメディア
FSFLAG_REMOVABLE = 0x00000002, FSFLAG_MANUAL = 0x00000004, ///< Bit2: 強制手動イジェクト
///< Bit1: 強制リムーバブルメディア
FSFLAG_MANUAL = 0x00000004,
///< Bit2: 強制手動イジェクト
}; };
//=========================================================================== //===========================================================================
@ -393,17 +371,12 @@ enum {
class CRing { class CRing {
public: public:
// 基本ファンクション // 基本ファンクション
CRing() { Init(); } CRing() { Init(); } ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ ~CRing() { Remove(); } ///< デストラクタ final
~CRing() { Remove(); } void Init() { ASSERT(this); next = prev = this; } ///< 初期化
///< デストラクタ final
void Init() { ASSERT(this); next = prev = this; }
///< 初期化
CRing* Next() const { ASSERT(this); return next; } CRing* Next() const { ASSERT(this); return next; } ///< 次の要素を取得
///< 次の要素を取得 CRing* Prev() const { ASSERT(this); return prev; } ///< 前の要素を取得
CRing* Prev() const { ASSERT(this); return prev; }
///< 前の要素を取得
void Insert(CRing* pRoot) void Insert(CRing* pRoot)
{ {
@ -485,57 +458,39 @@ private:
class CHostFilename { class CHostFilename {
public: public:
// 基本ファンクション // 基本ファンクション
CHostFilename(); CHostFilename(); ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ static size_t Offset() { return offsetof(CHostFilename, m_szHost); } ///< オフセット位置取得
static size_t Offset() { return offsetof(CHostFilename, m_szHost); }
///< オフセット位置取得
void SetHost(const TCHAR* szHost); void SetHost(const TCHAR* szHost); ///< ホスト側の名称を設定
///< ホスト側の名称を設定 const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } ///< ホスト側の名称を取得
const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } void ConvertHuman(int nCount = -1); ///< Human68k側の名称を変換
///< ホスト側の名称を取得 void CopyHuman(const BYTE* szHuman); ///< Human68k側の名称を複製
void ConvertHuman(int nCount = -1); BOOL isReduce() const; ///< Human68k側の名称が加工されたか調査
///< Human68k側の名称を変換 BOOL isCorrect() const { ASSERT(this); return m_bCorrect; } ///< Human68k側のファイル名規則に合致しているか調査
void CopyHuman(const BYTE* szHuman); const BYTE* GetHuman() const { ASSERT(this); return m_szHuman; } ///< Human68kファイル名を取得
///< Human68k側の名称を複製 const BYTE* GetHumanLast() const
BOOL isReduce() const; { ASSERT(this); return m_pszHumanLast; } ///< Human68kファイル名を取得
///< Human68k側の名称が加工されたか調査 const BYTE* GetHumanExt() const { ASSERT(this); return m_pszHumanExt; }///< Human68kファイル名を取得
BOOL isCorrect() const { ASSERT(this); return m_bCorrect; } void SetEntryName(); ///< Human68kディレクトリエントリを設定
///< Human68k側のファイル名規則に合致しているか調査
const BYTE* GetHuman() const { ASSERT(this); return m_szHuman; }
///< Human68kファイル名を取得
const BYTE* GetHumanLast() const { ASSERT(this); return m_pszHumanLast; }
///< Human68kファイル名を取得
const BYTE* GetHumanExt() const { ASSERT(this); return m_pszHumanExt; }
///< Human68kファイル名を取得
void SetEntryName();
///< Human68kディレクトリエントリを設定
void SetEntryAttribute(BYTE nHumanAttribute) void SetEntryAttribute(BYTE nHumanAttribute)
{ ASSERT(this); m_dirHuman.attr = nHumanAttribute; } { ASSERT(this); m_dirHuman.attr = nHumanAttribute; } ///< Human68kディレクトリエントリを設定
///< Human68kディレクトリエントリを設定
void SetEntrySize(DWORD nHumanSize) void SetEntrySize(DWORD nHumanSize)
{ ASSERT(this); m_dirHuman.size = nHumanSize; } { ASSERT(this); m_dirHuman.size = nHumanSize; } ///< Human68kディレクトリエントリを設定
///< Human68kディレクトリエントリを設定
void SetEntryDate(WORD nHumanDate) void SetEntryDate(WORD nHumanDate)
{ ASSERT(this); m_dirHuman.date = nHumanDate; } { ASSERT(this); m_dirHuman.date = nHumanDate; } ///< Human68kディレクトリエントリを設定
///< Human68kディレクトリエントリを設定
void SetEntryTime(WORD nHumanTime) void SetEntryTime(WORD nHumanTime)
{ ASSERT(this); m_dirHuman.time = nHumanTime; } { ASSERT(this); m_dirHuman.time = nHumanTime; } ///< Human68kディレクトリエントリを設定
///< Human68kディレクトリエントリを設定
void SetEntryCluster(WORD nHumanCluster) void SetEntryCluster(WORD nHumanCluster)
{ ASSERT(this); m_dirHuman.cluster = nHumanCluster; } { ASSERT(this); m_dirHuman.cluster = nHumanCluster; } ///< Human68kディレクトリエントリを設定
///< Human68kディレクトリエントリを設定 const Human68k::dirent_t* GetEntry() const
const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } { ASSERT(this); return &m_dirHuman; } ///< Human68kディレクトリエントリを取得
///< Human68kディレクトリエントリを取得 BOOL CheckAttribute(DWORD nHumanAttribute) const; ///< Human68kディレクトリエントリの属性判定
BOOL CheckAttribute(DWORD nHumanAttribute) const;
///< Human68kディレクトリエントリの属性判定
BOOL isSameEntry(const Human68k::dirent_t* pdirHuman) const BOOL isSameEntry(const Human68k::dirent_t* pdirHuman) const
{ ASSERT(this); ASSERT(pdirHuman); return memcmp(&m_dirHuman, pdirHuman, sizeof(m_dirHuman)) == 0; } { ASSERT(this); ASSERT(pdirHuman); return memcmp(&m_dirHuman, pdirHuman, sizeof(m_dirHuman)) == 0; }
///< Human68kディレクトリエントリの一致判定 ///< Human68kディレクトリエントリの一致判定
// パス名操作 // パス名操作
static const BYTE* SeparateExt(const BYTE* szHuman); static const BYTE* SeparateExt(const BYTE* szHuman); ///< Human68kファイル名から拡張子を分離
///< Human68kファイル名から拡張子を分離
private: private:
static BYTE* CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast); static BYTE* CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast);
@ -588,62 +543,45 @@ public:
const ring_t* pos; ///< 次回検索を続行する位置 (識別ID一致時) const ring_t* pos; ///< 次回検索を続行する位置 (識別ID一致時)
Human68k::dirent_t entry; ///< 次回検索を続行するエントリ内容 Human68k::dirent_t entry; ///< 次回検索を続行するエントリ内容
void Clear() { count = 0; } void Clear() { count = 0; } ///< 初期化
///< 初期化
}; };
// 基本ファンクション // 基本ファンクション
CHostPath(); CHostPath(); ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ ~CHostPath(); ///< デストラクタ final
~CHostPath(); void Clean(); ///< 再利用のための初期化
///< デストラクタ final
void Clean();
///< 再利用のための初期化
void SetHuman(const BYTE* szHuman); void SetHuman(const BYTE* szHuman); ///< Human68k側の名称を直接指定する
///< Human68k側の名称を直接指定する void SetHost(const TCHAR* szHost); ///< ホスト側の名称を直接指定する
void SetHost(const TCHAR* szHost); BOOL isSameHuman(const BYTE* szHuman) const; ///< Human68k側の名称を比較する
///< ホスト側の名称を直接指定する BOOL isSameChild(const BYTE* szHuman) const; ///< Human68k側の名称を比較する
BOOL isSameHuman(const BYTE* szHuman) const; const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } ///< ホスト側の名称の獲得
///< Human68k側の名称を比較する
BOOL isSameChild(const BYTE* szHuman) const;
///< Human68k側の名称を比較する
const TCHAR* GetHost() const { ASSERT(this); return m_szHost; }
///< ホスト側の名称の獲得
const CHostFilename* FindFilename(const BYTE* szHuman, DWORD nHumanAttribute = Human68k::AT_ALL) const; const CHostFilename* FindFilename(const BYTE* szHuman, DWORD nHumanAttribute = Human68k::AT_ALL) const;
///< ファイル名を検索 ///< ファイル名を検索
const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const; const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const;
///< ファイル名を検索 (ワイルドカード対応) ///< ファイル名を検索 (ワイルドカード対応)
BOOL isRefresh(); BOOL isRefresh(); ///< ファイル変更が行なわれたか確認
///< ファイル変更が行なわれたか確認 void Refresh(); ///< ファイル再構成
void Refresh(); void Backup(); /// ホスト側のタイムスタンプを保存
///< ファイル再構成 void Restore() const; /// ホスト側のタイムスタンプを復元
void Backup(); void Release(); ///< 更新
/// ホスト側のタイムスタンプを保存
void Restore() const;
/// ホスト側のタイムスタンプを復元
void Release();
///< 更新
// CHostEntryが利用する外部API // CHostEntryが利用する外部API
static void InitId() { g_nId = 0; } static void InitId() { g_nId = 0; } ///< 識別ID生成用カウンタ初期化
///< 識別ID生成用カウンタ初期化
private: private:
static ring_t* Alloc(size_t nLength); static ring_t* Alloc(size_t nLength); ///< ファイル名領域確保
///< ファイル名領域確保 static void Free(ring_t* pRing); ///< ファイル名領域解放
static void Free(ring_t* pRing);
///< ファイル名領域解放
static int Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast); static int Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast);
///< 文字列比較 (ワイルドカード対応) ///< 文字列比較 (ワイルドカード対応)
CRing m_cRing; ///< CHostFilename連結用 CRing m_cRing; ///< CHostFilename連結用
#ifndef BAREMETAL #ifndef BAREMETAL
time_t m_tBackup; ///< 時刻復元用 time_t m_tBackup; ///< 時刻復元用
#else #else
WORD m_tBackupD; ///< 時刻復元用 WORD m_tBackupD; ///< 時刻復元用
WORD m_tBackupT; ///< 時刻復元用 WORD m_tBackupT; ///< 時刻復元用
#endif // BAREMETAL #endif // BAREMETAL
BOOL m_bRefresh; ///< 更新フラグ BOOL m_bRefresh; ///< 更新フラグ
DWORD m_nId; ///< 識別ID (値が変化した場合は更新を意味する) DWORD m_nId; ///< 識別ID (値が変化した場合は更新を意味する)
BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< 該当エントリのHuman68k内部名 BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< 該当エントリのHuman68k内部名
@ -676,58 +614,36 @@ private:
class CHostFiles { class CHostFiles {
public: public:
// 基本ファンクション // 基本ファンクション
CHostFiles() { SetKey(0); Init(); } CHostFiles() { SetKey(0); Init(); } ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ void Init(); ///< 初期化
void Init();
///< 初期化
void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } ///< 検索キー設定
///< 検索キー設定 BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } ///< 検索キー比較
BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } void SetPath(const Human68k::namests_t* pNamests); ///< パス名・ファイル名を内部で生成
///< 検索キー比較 BOOL isRootPath() const { return m_szHumanPath[1] == '\0'; } ///< ルートディレクトリ判定
void SetPath(const Human68k::namests_t* pNamests); void SetPathWildcard() { m_nHumanWildcard = 1; } ///< ワイルドカードによるファイル検索を有効化
///< パス名・ファイル名を内部で生成 void SetPathOnly() { m_nHumanWildcard = 0xFF; } ///< パス名のみを有効化
BOOL isRootPath() const { return m_szHumanPath[1] == '\0'; } BOOL isPathOnly() const { return m_nHumanWildcard == 0xFF; } ///< パス名のみ設定か判定
///< ルートディレクトリ判定
void SetPathWildcard() { m_nHumanWildcard = 1; }
///< ワイルドカードによるファイル検索を有効化
void SetPathOnly() { m_nHumanWildcard = 0xFF; }
///< パス名のみを有効化
BOOL isPathOnly() const { return m_nHumanWildcard == 0xFF; }
///< パス名のみ設定か判定
void SetAttribute(DWORD nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; } void SetAttribute(DWORD nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; }
///< 検索属性を設定 ///< 検索属性を設定
BOOL Find(DWORD nUnit, class CHostEntry* pEntry); BOOL Find(DWORD nUnit, class CHostEntry* pEntry); ///< Human68k側でファイルを検索しホスト側の情報を生成
///< Human68k側でファイルを検索しホスト側の情報を生成 const CHostFilename* Find(CHostPath* pPath); ///< ファイル名検索
const CHostFilename* Find(CHostPath* pPath); void SetEntry(const CHostFilename* pFilename); ///< Human68k側の検索結果保存
///< ファイル名検索 void SetResult(const TCHAR* szPath); ///< ホスト側の名称を設定
void SetEntry(const CHostFilename* pFilename); void AddResult(const TCHAR* szPath); ///< ホスト側の名称にファイル名を追加
///< Human68k側の検索結果保存 void AddFilename(); ///< ホスト側の名称にHuman68kの新規ファイル名を追加
void SetResult(const TCHAR* szPath);
///< ホスト側の名称を設定
void AddResult(const TCHAR* szPath);
///< ホスト側の名称にファイル名を追加
void AddFilename();
///< ホスト側の名称にHuman68kの新規ファイル名を追加
const TCHAR* GetPath() const { ASSERT(this); return m_szHostResult; } const TCHAR* GetPath() const { ASSERT(this); return m_szHostResult; } ///< ホスト側の名称を取得
///< ホスト側の名称を取得
const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; }///< Human68kディレクトリエントリを取得
///< Human68kディレクトリエントリを取得
DWORD GetAttribute() const { ASSERT(this); return m_dirHuman.attr; } DWORD GetAttribute() const { ASSERT(this); return m_dirHuman.attr; } ///< Human68k属性を取得
///< Human68k属性を取得 WORD GetDate() const { ASSERT(this); return m_dirHuman.date; } ///< Human68k日付を取得
WORD GetDate() const { ASSERT(this); return m_dirHuman.date; } WORD GetTime() const { ASSERT(this); return m_dirHuman.time; } ///< Human68k時刻を取得
///< Human68k日付を取得 DWORD GetSize() const { ASSERT(this); return m_dirHuman.size; } ///< Human68kファイルサイズを取得
WORD GetTime() const { ASSERT(this); return m_dirHuman.time; } const BYTE* GetHumanFilename() const { ASSERT(this); return m_szHumanFilename; }///< Human68kファイル名を取得
///< Human68k時刻を取得 const BYTE* GetHumanResult() const { ASSERT(this); return m_szHumanResult; } ///< Human68kファイル名検索結果を取得
DWORD GetSize() const { ASSERT(this); return m_dirHuman.size; } const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } ///< Human68kパス名を取得
///< Human68kファイルサイズを取得
const BYTE* GetHumanFilename() const { ASSERT(this); return m_szHumanFilename; }
///< Human68kファイル名を取得
const BYTE* GetHumanResult() const { ASSERT(this); return m_szHumanResult; }
///< Human68kファイル名検索結果を取得
const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; }
///< Human68kパス名を取得
private: private:
DWORD m_nKey; ///< Human68kのFILESバッファアドレス 0なら未使用 DWORD m_nKey; ///< Human68kのFILESバッファアドレス 0なら未使用
@ -751,20 +667,14 @@ class CHostFilesManager {
public: public:
#ifdef _DEBUG #ifdef _DEBUG
// 基本ファンクション // 基本ファンクション
~CHostFilesManager(); ~CHostFilesManager(); ///< デストラクタ final
///< デストラクタ final
#endif // _DEBUG #endif // _DEBUG
void Init(); void Init(); ///< 初期化 (ドライバ組込み時)
///< 初期化 (ドライバ組込み時) void Clean(); ///< 解放 (起動・リセット時)
void Clean();
///< 解放 (起動・リセット時)
CHostFiles* Alloc(DWORD nKey); CHostFiles* Alloc(DWORD nKey); ///< 確保
///< 確保 CHostFiles* Search(DWORD nKey); ///< 検索
CHostFiles* Search(DWORD nKey); void Free(CHostFiles* pFiles); ///< 解放
///< 検索
void Free(CHostFiles* pFiles);
///< 解放
private: private:
/// メモリ管理用 /// メモリ管理用
struct ring_t { struct ring_t {
@ -783,59 +693,39 @@ private:
class CHostFcb { class CHostFcb {
public: public:
// 基本ファンクション // 基本ファンクション
CHostFcb() { SetKey(0); Init(); } CHostFcb() { SetKey(0); Init(); } ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ ~CHostFcb() { Close(); } ///< デストラクタ final
~CHostFcb() { Close(); } void Init(); ///< 初期化
///< デストラクタ final
void Init();
///< 初期化
void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } ///< 検索キー設定
///< 検索キー設定 BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } ///< 検索キー比較
BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } void SetUpdate() { ASSERT(this); m_bUpdate = TRUE; } ///< 更新
///< 検索キー比較 BOOL isUpdate() const { ASSERT(this); return m_bUpdate; } ///< 更新状態取得
void SetUpdate() { ASSERT(this); m_bUpdate = TRUE; } BOOL SetMode(DWORD nHumanMode); ///< ファイルオープンモードを設定
///< 更新 void SetFilename(const TCHAR* szFilename); ///< ファイル名を設定
BOOL isUpdate() const { ASSERT(this); return m_bUpdate; } void SetHumanPath(const BYTE* szHumanPath); ///< Human68kパス名を設定
///< 更新状態取得 const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } ///< Human68kパス名を取得
BOOL SetMode(DWORD nHumanMode);
///< ファイルオープンモードを設定
void SetFilename(const TCHAR* szFilename);
///< ファイル名を設定
void SetHumanPath(const BYTE* szHumanPath);
///< Human68kパス名を設定
const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; }
///< Human68kパス名を取得
BOOL Create(Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce); BOOL Create(Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce); ///< ファイル作成
///< ファイル作成 BOOL Open(); ///< ファイルオープン
BOOL Open(); BOOL Rewind(DWORD nOffset); ///< ファイルシーク
///< ファイルオープン DWORD Read(BYTE* pBuffer, DWORD nSize); ///< ファイル読み込み
BOOL Rewind(DWORD nOffset); DWORD Write(const BYTE* pBuffer, DWORD nSize); ///< ファイル書き込み
///< ファイルシーク BOOL Truncate(); ///< ファイル切り詰め
DWORD Read(BYTE* pBuffer, DWORD nSize); DWORD Seek(DWORD nOffset, DWORD nHumanSeek); ///< ファイルシーク
///< ファイル読み込み BOOL TimeStamp(DWORD nHumanTime); ///< ファイル時刻設定
DWORD Write(const BYTE* pBuffer, DWORD nSize); BOOL Close(); ///< ファイルクローズ
///< ファイル書き込み
BOOL Truncate();
///< ファイル切り詰め
DWORD Seek(DWORD nOffset, DWORD nHumanSeek);
///< ファイルシーク
BOOL TimeStamp(DWORD nHumanTime);
///< ファイル時刻設定
BOOL Close();
///< ファイルクローズ
private: private:
DWORD m_nKey; ///< Human68kのFCBバッファアドレス (0なら未使用) DWORD m_nKey; ///< Human68kのFCBバッファアドレス (0なら未使用)
BOOL m_bUpdate; ///< 更新フラグ BOOL m_bUpdate; ///< 更新フラグ
#ifndef BAREMETAL #ifndef BAREMETAL
FILE* m_pFile; ///< ホスト側のファイルオブジェクト FILE* m_pFile; ///< ホスト側のファイルオブジェクト
const char* m_pszMode; ///< ホスト側のファイルオープンモード const char* m_pszMode; ///< ホスト側のファイルオープンモード
#else #else
FIL m_File; ///< ホスト側のファイルオブジェクト FIL m_File; ///< ホスト側のファイルオブジェクト
BYTE m_Mode; ///< ホスト側のファイルオープンモード BYTE m_Mode; ///< ホスト側のファイルオープンモード
#endif // BAREMETAL #endif // BAREMETAL
bool m_bFlag; ///< ホスト側のファイルオープンフラグ bool m_bFlag; ///< ホスト側のファイルオープンフラグ
BYTE m_szHumanPath[HUMAN68K_PATH_MAX]; BYTE m_szHumanPath[HUMAN68K_PATH_MAX];
///< Human68kのパス名 ///< Human68kのパス名
@ -849,22 +739,16 @@ private:
//=========================================================================== //===========================================================================
class CHostFcbManager { class CHostFcbManager {
public: public:
#ifdef _DEBUG #ifdef _DEBUG
// 基本ファンクション // 基本ファンクション
~CHostFcbManager(); ~CHostFcbManager(); ///< デストラクタ final
///< デストラクタ final #endif // _DEBUG
#endif // _DEBUG void Init(); ///< 初期化 (ドライバ組込み時)
void Init(); void Clean(); ///< 解放 (起動・リセット時)
///< 初期化 (ドライバ組込み時)
void Clean();
///< 解放 (起動・リセット時)
CHostFcb* Alloc(DWORD nKey); CHostFcb* Alloc(DWORD nKey); ///< 確保
///< 確保 CHostFcb* Search(DWORD nKey); ///< 検索
CHostFcb* Search(DWORD nKey); void Free(CHostFcb* p); ///< 解放
///< 検索
void Free(CHostFcb* p);
///< 解放
private: private:
/// メモリ管理用 /// メモリ管理用
@ -887,57 +771,33 @@ class CHostDrv
{ {
public: public:
// 基本ファンクション // 基本ファンクション
CHostDrv(); CHostDrv(); ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ ~CHostDrv(); ///< デストラクタ final
~CHostDrv(); void Init(const TCHAR* szBase, DWORD nFlag); ///< 初期化 (デバイス起動とロード)
///< デストラクタ final
void Init(const TCHAR* szBase, DWORD nFlag);
///< 初期化 (デバイス起動とロード)
BOOL isWriteProtect() const { ASSERT(this); return m_bWriteProtect; } BOOL isWriteProtect() const { ASSERT(this); return m_bWriteProtect; } ///< 書き込み禁止か?
///< 書き込み禁止か? BOOL isEnable() const { ASSERT(this); return m_bEnable; } ///< アクセス可能か?
BOOL isEnable() const { ASSERT(this); return m_bEnable; } BOOL isMediaOffline(); ///< メディアチェック
///< アクセス可能か? BYTE GetMediaByte() const; ///< メディアバイトの取得
BOOL isMediaOffline(); DWORD GetStatus() const; ///< ドライブ状態の取得
///< メディアチェック void SetEnable(BOOL bEnable); ///< メディア状態設定
BYTE GetMediaByte() const; BOOL CheckMedia(); ///< メディア交換チェック
///< メディアバイトの取得 void Update(); ///< メディア状態更新
DWORD GetStatus() const; void Eject(); ///< イジェクト
///< ドライブ状態の取得 void GetVolume(TCHAR* szLabel); ///< ボリュームラベルの取得
void SetEnable(BOOL bEnable); BOOL GetVolumeCache(TCHAR* szLabel) const; ///< キャッシュからボリュームラベルを取得
///< メディア状態設定 DWORD GetCapacity(Human68k::capacity_t* pCapacity); ///< 容量の取得
BOOL CheckMedia(); BOOL GetCapacityCache(Human68k::capacity_t* pCapacity) const; ///< キャッシュから容量を取得
///< メディア交換チェック
void Update();
///< メディア状態更新
void Eject();
///< イジェクト
void GetVolume(TCHAR* szLabel);
///< ボリュームラベルの取得
BOOL GetVolumeCache(TCHAR* szLabel) const;
///< キャッシュからボリュームラベルを取得
DWORD GetCapacity(Human68k::capacity_t* pCapacity);
///< 容量の取得
BOOL GetCapacityCache(Human68k::capacity_t* pCapacity) const;
///< キャッシュから容量を取得
// キャッシュ操作 // キャッシュ操作
void CleanCache(); void CleanCache(); ///< 全てのキャッシュを更新する
///< 全てのキャッシュを更新する void CleanCache(const BYTE* szHumanPath); ///< 指定されたパスのキャッシュを更新する
void CleanCache(const BYTE* szHumanPath); void CleanCacheChild(const BYTE* szHumanPath); ///< 指定されたパス以下のキャッシュを全て更新する
///< 指定されたパスのキャッシュを更新する void DeleteCache(const BYTE* szHumanPath); ///< 指定されたパスのキャッシュを削除する
void CleanCacheChild(const BYTE* szHumanPath); CHostPath* FindCache(const BYTE* szHuman); ///< 指定されたパスがキャッシュされているか検索する
///< 指定されたパス以下のキャッシュを全て更新する CHostPath* CopyCache(CHostFiles* pFiles); ///< キャッシュ情報を元に、ホスト側の名称を獲得する
void DeleteCache(const BYTE* szHumanPath); CHostPath* MakeCache(CHostFiles* pFiles); ///< ホスト側の名称の構築に必要な情報をすべて取得する
///< 指定されたパスのキャッシュを削除する BOOL Find(CHostFiles* pFiles); ///< ホスト側の名称を検索 (パス名+ファイル名(省略可)+属性)
CHostPath* FindCache(const BYTE* szHuman);
///< 指定されたパスがキャッシュされているか検索する
CHostPath* CopyCache(CHostFiles* pFiles);
///< キャッシュ情報を元に、ホスト側の名称を獲得する
CHostPath* MakeCache(CHostFiles* pFiles);
///< ホスト側の名称の構築に必要な情報をすべて取得する
BOOL Find(CHostFiles* pFiles);
///< ホスト側の名称を検索 (パス名+ファイル名(省略可)+属性)
private: private:
// パス名操作 // パス名操作
@ -972,54 +832,32 @@ private:
class CHostEntry { class CHostEntry {
public: public:
// 基本ファンクション // 基本ファンクション
CHostEntry(); CHostEntry(); ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ ~CHostEntry(); ///< デストラクタ final
~CHostEntry(); void Init(); ///< 初期化 (ドライバ組込み時)
///< デストラクタ final void Clean(); ///< 解放 (起動・リセット時)
void Init();
///< 初期化 (ドライバ組込み時)
void Clean();
///< 解放 (起動・リセット時)
// キャッシュ操作 // キャッシュ操作
void CleanCache(); void CleanCache(); ///< 全てのキャッシュを更新する
///< 全てのキャッシュを更新する void CleanCache(DWORD nUnit); ///< 指定されたユニットのキャッシュを更新する
void CleanCache(DWORD nUnit); void CleanCache(DWORD nUnit, const BYTE* szHumanPath); ///< 指定されたパスのキャッシュを更新する
///< 指定されたユニットのキャッシュを更新する void CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath); ///< 指定されたパス以下のキャッシュを全て更新する
void CleanCache(DWORD nUnit, const BYTE* szHumanPath); void DeleteCache(DWORD nUnit, const BYTE* szHumanPath); ///< 指定されたパスのキャッシュを削除する
///< 指定されたパスのキャッシュを更新する BOOL Find(DWORD nUnit, CHostFiles* pFiles); ///< ホスト側の名称を検索 (パス名+ファイル名(省略可)+属性)
void CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath); void ShellNotify(DWORD nEvent, const TCHAR* szPath); ///< ホスト側ファイルシステム状態変化通知
///< 指定されたパス以下のキャッシュを全て更新する
void DeleteCache(DWORD nUnit, const BYTE* szHumanPath);
///< 指定されたパスのキャッシュを削除する
BOOL Find(DWORD nUnit, CHostFiles* pFiles);
///< ホスト側の名称を検索 (パス名+ファイル名(省略可)+属性)
void ShellNotify(DWORD nEvent, const TCHAR* szPath);
///< ホスト側ファイルシステム状態変化通知
// ドライブオブジェクト操作 // ドライブオブジェクト操作
void SetDrv(DWORD nUnit, CHostDrv* pDrv); void SetDrv(DWORD nUnit, CHostDrv* pDrv); ///< ドライブ設定
///< ドライブ設定 BOOL isWriteProtect(DWORD nUnit) const; ///< 書き込み禁止か?
BOOL isWriteProtect(DWORD nUnit) const; BOOL isEnable(DWORD nUnit) const; ///< アクセス可能か?
///< 書き込み禁止か? BOOL isMediaOffline(DWORD nUnit); ///< メディアチェック
BOOL isEnable(DWORD nUnit) const; BYTE GetMediaByte(DWORD nUnit) const; ///< メディアバイトの取得
///< アクセス可能か? DWORD GetStatus(DWORD nUnit) const; ///< ドライブ状態の取得
BOOL isMediaOffline(DWORD nUnit); BOOL CheckMedia(DWORD nUnit); ///< メディア交換チェック
///< メディアチェック void Eject(DWORD nUnit); ///< イジェクト
BYTE GetMediaByte(DWORD nUnit) const; void GetVolume(DWORD nUnit, TCHAR* szLabel); ///< ボリュームラベルの取得
///< メディアバイトの取得 BOOL GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const; ///< キャッシュからボリュームラベルを取得
DWORD GetStatus(DWORD nUnit) const; DWORD GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); ///< 容量の取得
///< ドライブ状態の取得
BOOL CheckMedia(DWORD nUnit);
///< メディア交換チェック
void Eject(DWORD nUnit);
///< イジェクト
void GetVolume(DWORD nUnit, TCHAR* szLabel);
///< ボリュームラベルの取得
BOOL GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const;
///< キャッシュからボリュームラベルを取得
DWORD GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity);
///< 容量の取得
BOOL GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const; BOOL GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const;
///< キャッシュからクラスタサイズを取得 ///< キャッシュからクラスタサイズを取得
@ -1069,80 +907,54 @@ class CFileSys
{ {
public: public:
// 基本ファンクション // 基本ファンクション
CFileSys(); CFileSys(); ///< デフォルトコンストラクタ
///< デフォルトコンストラクタ virtual ~CFileSys() {}; ///< デストラクタ
virtual ~CFileSys() {};
///< デストラクタ
// 初期化・終了 // 初期化・終了
void Reset(); void Reset(); ///< リセット (全クローズ)
///< リセット (全クローズ) void Init(); ///< 初期化 (デバイス起動とロード)
void Init();
///< 初期化 (デバイス起動とロード)
// コマンドハンドラ // コマンドハンドラ
DWORD InitDevice(const Human68k::argument_t* pArgument); DWORD InitDevice(const Human68k::argument_t* pArgument); ///< $40 - デバイス起動
///< $40 - デバイス起動 int CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests); ///< $41 - ディレクトリチェック
int CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests); int MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests); ///< $42 - ディレクトリ作成
///< $41 - ディレクトリチェック int RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests); ///< $43 - ディレクトリ削除
int MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests);
///< $42 - ディレクトリ作成
int RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests);
///< $43 - ディレクトリ削除
int Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew); int Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew);
///< $44 - ファイル名変更 ///< $44 - ファイル名変更
int Delete(DWORD nUnit, const Human68k::namests_t* pNamests); int Delete(DWORD nUnit, const Human68k::namests_t* pNamests); ///< $45 - ファイル削除
///< $45 - ファイル削除
int Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute); int Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute);
///< $46 - ファイル属性取得/設定 ///< $46 - ファイル属性取得/設定
int Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles); int Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles);
///< $47 - ファイル検索 ///< $47 - ファイル検索
int NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles); int NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles); ///< $48 - ファイル次検索
///< $48 - ファイル次検索
int Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce); int Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce);
///< $49 - ファイル作成 ///< $49 - ファイル作成
int Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb); int Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb);
///< $4A - ファイルオープン ///< $4A - ファイルオープン
int Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb); int Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb); ///< $4B - ファイルクローズ
///< $4B - ファイルクローズ
int Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, DWORD nSize); int Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, DWORD nSize);
///< $4C - ファイル読み込み ///< $4C - ファイル読み込み
int Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, DWORD nSize); int Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, DWORD nSize);
///< $4D - ファイル書き込み ///< $4D - ファイル書き込み
int Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset); int Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset); ///< $4E - ファイルシーク
///< $4E - ファイルシーク
DWORD TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime); DWORD TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime);
///< $4F - ファイル時刻取得/設定 ///< $4F - ファイル時刻取得/設定
int GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); int GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); ///< $50 - 容量取得
///< $50 - 容量取得 int CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive); ///< $51 - ドライブ状態検査/制御
int CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive); int GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb); ///< $52 - DPB取得
///< $51 - ドライブ状態検査/制御 int DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize); ///< $53 - セクタ読み込み
int GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb); int DiskWrite(DWORD nUnit); ///< $54 - セクタ書き込み
///< $52 - DPB取得 int Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl); ///< $55 - IOCTRL
int DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize); int Flush(DWORD nUnit); ///< $56 - フラッシュ
///< $53 - セクタ読み込み int CheckMedia(DWORD nUnit); ///< $57 - メディア交換チェック
int DiskWrite(DWORD nUnit); int Lock(DWORD nUnit); ///< $58 - 排他制御
///< $54 - セクタ書き込み
int Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl);
///< $55 - IOCTRL
int Flush(DWORD nUnit);
///< $56 - フラッシュ
int CheckMedia(DWORD nUnit);
///< $57 - メディア交換チェック
int Lock(DWORD nUnit);
///< $58 - 排他制御
void SetOption(DWORD nOption); void SetOption(DWORD nOption); ///< オプション設定
///< オプション設定 DWORD GetOption() const { ASSERT(this); return m_nOption; } ///< オプション取得
DWORD GetOption() const { ASSERT(this); return m_nOption; } DWORD GetDefault() const { ASSERT(this); return m_nOptionDefault; } ///< デフォルトオプション取得
///< オプション取得 static DWORD GetFileOption() { return g_nOption; } ///< ファイル名変換オプション取得
DWORD GetDefault() const { ASSERT(this); return m_nOptionDefault; }
///< デフォルトオプション取得
static DWORD GetFileOption() { return g_nOption; }
///< ファイル名変換オプション取得
void ShellNotify(DWORD nEvent, const TCHAR* szPath) void ShellNotify(DWORD nEvent, const TCHAR* szPath)
{ ASSERT(this); m_cEntry.ShellNotify(nEvent, szPath); } { ASSERT(this); m_cEntry.ShellNotify(nEvent, szPath); } ///< ホスト側ファイルシステム状態変化通知
///< ホスト側ファイルシステム状態変化通知
/// 定数 /// 定数
enum { enum {
@ -1151,10 +963,8 @@ public:
private: private:
// 内部補助用 // 内部補助用
void InitOption(const Human68k::argument_t* pArgument); void InitOption(const Human68k::argument_t* pArgument); ///< オプション初期化
///< オプション初期化 BOOL FilesVolume(DWORD nUnit, Human68k::files_t* pFiles); ///< ボリュームラベル取得
BOOL FilesVolume(DWORD nUnit, Human68k::files_t* pFiles);
///< ボリュームラベル取得
DWORD m_nUnits; ///< 現在のドライブオブジェクト数 (レジューム毎に変化) DWORD m_nUnits; ///< 現在のドライブオブジェクト数 (レジューム毎に変化)
@ -1176,8 +986,7 @@ private:
///< 擬似セクタの指すファイル実体 ///< 擬似セクタの指すファイル実体
DWORD m_nFlag[DriveMax]; ///< ベースパス状態復元用の動作フラグ候補 DWORD m_nFlag[DriveMax]; ///< ベースパス状態復元用の動作フラグ候補
TCHAR m_szBase[DriveMax][FILEPATH_MAX]; TCHAR m_szBase[DriveMax][FILEPATH_MAX]; ///< ベースパス状態復元用の候補
///< ベースパス状態復元用の候補
static DWORD g_nOption; ///< ファイル名変換フラグ static DWORD g_nOption; ///< ファイル名変換フラグ
}; };

View File

@ -28,26 +28,17 @@ class CTapDriver
{ {
public: public:
// Basic Functionality // Basic Functionality
CTapDriver(); CTapDriver(); // Constructor
// Constructor BOOL FASTCALL Init(); // Initilization
BOOL FASTCALL Init(); void FASTCALL Cleanup(); // Cleanup
// Initilization void FASTCALL GetMacAddr(BYTE *mac); // Get Mac Address
void FASTCALL Cleanup(); int FASTCALL Rx(BYTE *buf); // Receive
// Cleanup int FASTCALL Tx(BYTE *buf, int len); // Send
void FASTCALL GetMacAddr(BYTE *mac);
// Get Mac Address
int FASTCALL Rx(BYTE *buf);
// Receive
int FASTCALL Tx(BYTE *buf, int len);
// Send
private: private:
BYTE m_MacAddr[6]; BYTE m_MacAddr[6]; // MAC Address
// MAC Address BOOL m_bTxValid; // Send Valid Flag
BOOL m_bTxValid; int m_hTAP; // File handle
// Send Valid Flag
int m_hTAP;
// File handle
}; };
#endif // ctapdriver_h #endif // ctapdriver_h

View File

@ -161,11 +161,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100));
if (dt.buffer == NULL) { if (dt.buffer == NULL) {
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512); posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512);
#else #else
dt.buffer = (BYTE *)malloc(length * sizeof(BYTE)); dt.buffer = (BYTE *)malloc(length * sizeof(BYTE));
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
dt.length = length; dt.length = length;
} }
@ -176,11 +176,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
// Reallocate if the buffer length is different // Reallocate if the buffer length is different
if (dt.length != (DWORD)length) { if (dt.length != (DWORD)length) {
free(dt.buffer); free(dt.buffer);
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512); posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512);
#else #else
dt.buffer = (BYTE *)malloc(length * sizeof(BYTE)); dt.buffer = (BYTE *)malloc(length * sizeof(BYTE));
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
dt.length = length; dt.length = length;
} }
@ -205,11 +205,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL)); memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL));
// Read from File // Read from File
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
if (!fio.OpenDIO(path, Fileio::ReadOnly)) { if (!fio.OpenDIO(path, Fileio::ReadOnly)) {
#else #else
if (!fio.Open(path, Fileio::ReadOnly)) { if (!fio.Open(path, Fileio::ReadOnly)) {
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
return FALSE; return FALSE;
} }
if (dt.raw) { if (dt.raw) {

View File

@ -94,34 +94,23 @@ public:
public: public:
// Basic Functions // Basic Functions
DiskTrack(); DiskTrack(); // Constructor
// Constructor virtual ~DiskTrack(); // Destructor
virtual ~DiskTrack(); void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE, off64_t imgoff = 0);// Initialization
// Destructor BOOL FASTCALL Load(const Filepath& path); // Load
void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE, BOOL FASTCALL Save(const Filepath& path); // Save
off64_t imgoff = 0);
// Initialization
BOOL FASTCALL Load(const Filepath& path);
// Load
BOOL FASTCALL Save(const Filepath& path);
// Save
// Read / Write // Read / Write
BOOL FASTCALL Read(BYTE *buf, int sec) const; BOOL FASTCALL Read(BYTE *buf, int sec) const; // Sector Read
// Sector Read BOOL FASTCALL Write(const BYTE *buf, int sec); // Sector Write
BOOL FASTCALL Write(const BYTE *buf, int sec);
// Sector Write
// Other // Other
int FASTCALL GetTrack() const { return dt.track; } int FASTCALL GetTrack() const { return dt.track; } // Get track
// Get track BOOL FASTCALL IsChanged() const { return dt.changed; } // Changed flag check
BOOL FASTCALL IsChanged() const { return dt.changed; }
// Changed flag check
private: private:
// Internal data // Internal data
disktrk_t dt; disktrk_t dt; // Internal data
// Internal data
}; };
//=========================================================================== //===========================================================================
@ -145,50 +134,31 @@ public:
public: public:
// Basic Functions // Basic Functions
DiskCache(const Filepath& path, int size, int blocks, DiskCache(const Filepath& path, int size, int blocks,off64_t imgoff = 0);// Constructor
off64_t imgoff = 0); virtual ~DiskCache(); // Destructor
// Constructor void FASTCALL SetRawMode(BOOL raw); // CD-ROM raw mode setting
virtual ~DiskCache();
// Destructor
void FASTCALL SetRawMode(BOOL raw);
// CD-ROM raw mode setting
// Access // Access
BOOL FASTCALL Save(); BOOL FASTCALL Save(); // Save and release all
// Save and release all BOOL FASTCALL Read(BYTE *buf, int block); // Sector Read
BOOL FASTCALL Read(BYTE *buf, int block); BOOL FASTCALL Write(const BYTE *buf, int block); // Sector Write
// Sector Read BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const; // Get cache information
BOOL FASTCALL Write(const BYTE *buf, int block);
// Sector Write
BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const;
// Get cache information
private: private:
// Internal Management // Internal Management
void FASTCALL Clear(); void FASTCALL Clear(); // Clear all tracks
// Clear all tracks DiskTrack* FASTCALL Assign(int track); // Load track
DiskTrack* FASTCALL Assign(int track); BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL); // Load track
// Load track void FASTCALL Update(); // Update serial number
BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL);
// Load track
void FASTCALL Update();
// Update serial number
// Internal data // Internal data
cache_t cache[CacheMax]; cache_t cache[CacheMax]; // Cache management
// Cache management DWORD serial; // Last serial number
DWORD serial; Filepath sec_path; // Path
// Last serial number int sec_size; // Sector size (8 or 9 or 11)
Filepath sec_path; int sec_blocks; // Blocks per sector
// Path BOOL cd_raw; // CD-ROM RAW mode
int sec_size; off64_t imgoffset; // Offset to actual data
// 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
}; };
//=========================================================================== //===========================================================================
@ -219,150 +189,86 @@ public:
public: public:
// Basic Functions // Basic Functions
Disk(); Disk(); // Constructor
// Constructor virtual ~Disk(); // Destructor
virtual ~Disk(); virtual void FASTCALL Reset(); // Device Reset
// Destructor #ifndef RASCSI
virtual void FASTCALL Reset(); virtual BOOL FASTCALL Save(Fileio *fio, int ver); // Save
// Device Reset virtual BOOL FASTCALL Load(Fileio *fio, int ver); // Load
#ifndef RASCSI #endif // RASCSI
virtual BOOL FASTCALL Save(Fileio *fio, int ver);
// Save
virtual BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// ID // ID
DWORD FASTCALL GetID() const { return disk.id; } DWORD FASTCALL GetID() const { return disk.id; } // Get media ID
// Get media ID BOOL FASTCALL IsNULL() const; // NULL check
BOOL FASTCALL IsNULL() const; BOOL FASTCALL IsSASI() const; // SASI Check
// NULL check BOOL FASTCALL IsSCSI() const; // SASI Check
BOOL FASTCALL IsSASI() const;
// SASI Check
BOOL FASTCALL IsSCSI() const;
// SASI Check
// Media Operations // Media Operations
virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
// Open void FASTCALL GetPath(Filepath& path) const; // Get the path
void FASTCALL GetPath(Filepath& path) const; void FASTCALL Eject(BOOL force); // Eject
// Get the path BOOL FASTCALL IsReady() const { return disk.ready; } // Ready check
void FASTCALL Eject(BOOL force); void FASTCALL WriteP(BOOL flag); // Set Write Protect flag
// Eject BOOL FASTCALL IsWriteP() const { return disk.writep; } // Get write protect flag
BOOL FASTCALL IsReady() const { return disk.ready; } BOOL FASTCALL IsReadOnly() const { return disk.readonly; } // Get read only flag
// Ready check BOOL FASTCALL IsRemovable() const { return disk.removable; } // Get is removable flag
void FASTCALL WriteP(BOOL flag); BOOL FASTCALL IsLocked() const { return disk.lock; } // Get locked status
// Set Write Protect flag BOOL FASTCALL IsAttn() const { return disk.attn; } // Get attention flag
BOOL FASTCALL IsWriteP() const { return disk.writep; } BOOL FASTCALL Flush(); // Flush the cache
// Get write protect flag void FASTCALL GetDisk(disk_t *buffer) const; // Get the internal data struct
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 // Properties
void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; } void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; } // LUN set
// LUN set DWORD FASTCALL GetLUN() { return disk.lun; } // LUN get
DWORD FASTCALL GetLUN() { return disk.lun; }
// LUN get
// commands // commands
virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);// INQUIRY command
// INQUIRY command virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); int FASTCALL SelectCheck(const DWORD *cdb); // SELECT check
// REQUEST SENSE command int FASTCALL SelectCheck10(const DWORD *cdb); // SELECT(10) check
int FASTCALL SelectCheck(const DWORD *cdb); virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);// MODE SELECT command
// SELECT check virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf); // MODE SENSE command
int FASTCALL SelectCheck10(const DWORD *cdb); virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf); // MODE SENSE(10) command
// SELECT(10) check int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf); // READ DEFECT DATA(10) command
virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
// MODE SELECT command BOOL FASTCALL Rezero(const DWORD *cdb); // REZERO command
virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf); BOOL FASTCALL Format(const DWORD *cdb); // FORMAT UNIT command
// MODE SENSE command BOOL FASTCALL Reassign(const DWORD *cdb); // REASSIGN UNIT command
virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf); virtual int FASTCALL Read(BYTE *buf, DWORD block); // READ command
// MODE SENSE(10) command int FASTCALL WriteCheck(DWORD block); // WRITE check
int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf); BOOL FASTCALL Write(const BYTE *buf, DWORD block); // WRITE command
// READ DEFECT DATA(10) command BOOL FASTCALL Seek(const DWORD *cdb); // SEEK command
virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb); BOOL FASTCALL Assign(const DWORD *cdb); // ASSIGN command
// TEST UNIT READY command BOOL FASTCALL Specify(const DWORD *cdb); // SPECIFY command
BOOL FASTCALL Rezero(const DWORD *cdb); BOOL FASTCALL StartStop(const DWORD *cdb); // START STOP UNIT command
// REZERO command BOOL FASTCALL SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
BOOL FASTCALL Format(const DWORD *cdb); BOOL FASTCALL Removal(const DWORD *cdb); // PREVENT/ALLOW MEDIUM REMOVAL command
// FORMAT UNIT command int FASTCALL ReadCapacity(const DWORD *cdb, BYTE *buf); // READ CAPACITY command
BOOL FASTCALL Reassign(const DWORD *cdb); BOOL FASTCALL Verify(const DWORD *cdb); // VERIFY command
// REASSIGN UNIT command virtual int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
virtual int FASTCALL Read(BYTE *buf, DWORD block); virtual BOOL FASTCALL PlayAudio(const DWORD *cdb); // PLAY AUDIO command
// READ command virtual BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); // PLAY AUDIO MSF command
int FASTCALL WriteCheck(DWORD block); virtual BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); // PLAY AUDIO TRACK command
// WRITE check void FASTCALL InvalidCmd() { disk.code = DISK_INVALIDCMD; } // Unsupported command
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 // Other
BOOL IsCacheWB() { return cache_wb; } BOOL IsCacheWB() { return cache_wb; } // Get cache writeback mode
// Get cache writeback mode void SetCacheWB(BOOL enable) { cache_wb = enable; } // Set cache writeback mode
void SetCacheWB(BOOL enable) { cache_wb = enable; }
// Set cache writeback mode
protected: protected:
// Internal processing // Internal processing
virtual int FASTCALL AddError(BOOL change, BYTE *buf); virtual int FASTCALL AddError(BOOL change, BYTE *buf); // Add error
// Add error virtual int FASTCALL AddFormat(BOOL change, BYTE *buf); // Add format
virtual int FASTCALL AddFormat(BOOL change, BYTE *buf); virtual int FASTCALL AddDrive(BOOL change, BYTE *buf); // Add drive
// Add format int FASTCALL AddOpt(BOOL change, BYTE *buf); // Add optical
virtual int FASTCALL AddDrive(BOOL change, BYTE *buf); int FASTCALL AddCache(BOOL change, BYTE *buf); // Add cache
// Add drive int FASTCALL AddCDROM(BOOL change, BYTE *buf); // Add CD-ROM
int FASTCALL AddOpt(BOOL change, BYTE *buf); int FASTCALL AddCDDA(BOOL change, BYTE *buf); // Add CD_DA
// Add optical virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special info
int FASTCALL AddCache(BOOL change, BYTE *buf); BOOL FASTCALL CheckReady(); // Check if ready
// 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 // Internal data
disk_t disk; disk_t disk; // Internal disk data
// Internal disk data Filepath diskpath; // File path (for GetPath)
Filepath diskpath; BOOL cache_wb; // Cache mode
// File path (for GetPath)
BOOL cache_wb;
// Cache mode
}; };

View File

@ -73,7 +73,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
size = fio.GetFileSize(); size = fio.GetFileSize();
fio.Close(); fio.Close();
#if defined(USE_MZ1F23_1024_SUPPORT) #if defined(USE_MZ1F23_1024_SUPPORT)
// MZ-2500/MZ-2800用 MZ-1F23(SASI 20M/セクタサイズ1024)専用 // MZ-2500/MZ-2800用 MZ-1F23(SASI 20M/セクタサイズ1024)専用
// 20M(22437888 BS=1024 C=21912) // 20M(22437888 BS=1024 C=21912)
if (size == 0x1566000) { if (size == 0x1566000) {
@ -84,9 +84,9 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
// Call the base class // Call the base class
return Disk::Open(path); return Disk::Open(path);
} }
#endif // USE_MZ1F23_1024_SUPPORT #endif // USE_MZ1F23_1024_SUPPORT
#if defined(REMOVE_FIXED_SASIHD_SIZE) #if defined(REMOVE_FIXED_SASIHD_SIZE)
// 256バイト単位であること // 256バイト単位であること
if (size & 0xff) { if (size & 0xff) {
return FALSE; return FALSE;
@ -101,7 +101,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
if (size > 512 * 1024 * 1024) { if (size > 512 * 1024 * 1024) {
return FALSE; return FALSE;
} }
#else #else
// 10MB, 20MB, 40MBのみ // 10MB, 20MB, 40MBのみ
switch (size) { switch (size) {
// 10MB(10441728 BS=256 C=40788) // 10MB(10441728 BS=256 C=40788)
@ -120,7 +120,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
default: default:
return FALSE; return FALSE;
} }
#endif // REMOVE_FIXED_SASIHD_SIZE #endif // REMOVE_FIXED_SASIHD_SIZE
// セクタサイズとブロック数 // セクタサイズとブロック数
disk.size = 8; disk.size = 8;

View File

@ -28,13 +28,10 @@ class SASIHD : public Disk
{ {
public: public:
// Basic Functions // Basic Functions
SASIHD(); SASIHD(); // Constructor
// Constructor void FASTCALL Reset(); // Reset
void FASTCALL Reset(); BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
// Reset
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands // commands
int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
// REQUEST SENSE command
}; };

View File

@ -37,7 +37,7 @@ SCSIBR::SCSIBR() : Disk()
// Host Bridge // Host Bridge
disk.id = MAKEID('S', 'C', 'B', 'R'); disk.id = MAKEID('S', 'C', 'B', 'R');
#if defined(RASCSI) && defined(__linux__) && !defined(BAREMETAL) #if defined(RASCSI) && defined(__linux__) && !defined(BAREMETAL)
// TAP Driver Generation // TAP Driver Generation
tap = new CTapDriver(); tap = new CTapDriver();
m_bTapEnable = tap->Init(); m_bTapEnable = tap->Init();
@ -51,7 +51,7 @@ SCSIBR::SCSIBR() : Disk()
// Packet reception flag OFF // Packet reception flag OFF
packet_enable = FALSE; packet_enable = FALSE;
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
// Create host file system // Create host file system
fs = new CFileSys(); fs = new CFileSys();
@ -65,13 +65,13 @@ SCSIBR::SCSIBR() : Disk()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
SCSIBR::~SCSIBR() SCSIBR::~SCSIBR()
{ {
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
// TAP driver release // TAP driver release
if (tap) { if (tap) {
tap->Cleanup(); tap->Cleanup();
delete tap; delete tap;
} }
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
// Release host file system // Release host file system
if (fs) { if (fs) {
@ -136,12 +136,12 @@ int FASTCALL SCSIBR::Inquiry(
// Optional function valid flag // Optional function valid flag
buf[36] = '0'; buf[36] = '0';
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
// TAP Enable // TAP Enable
if (m_bTapEnable) { if (m_bTapEnable) {
buf[37] = '1'; buf[37] = '1';
} }
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
// CFileSys Enable // CFileSys Enable
buf[38] = '1'; buf[38] = '1';
@ -182,27 +182,27 @@ int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
{ {
int type; int type;
int phase; int phase;
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
int func; int func;
int total_len; int total_len;
int i; int i;
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
ASSERT(this); ASSERT(this);
// Type // Type
type = cdb[2]; type = cdb[2];
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
// Function number // Function number
func = cdb[3]; func = cdb[3];
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
// Phase // Phase
phase = cdb[9]; phase = cdb[9];
switch (type) { switch (type) {
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
case 1: // Ethernet case 1: // Ethernet
// Do not process if TAP is invalid // Do not process if TAP is invalid
if (!m_bTapEnable) { if (!m_bTapEnable) {
@ -251,7 +251,7 @@ int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
return total_len; return total_len;
} }
break; break;
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
case 2: // Host Drive case 2: // Host Drive
switch (phase) { switch (phase) {
@ -305,7 +305,7 @@ BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
len |= cdb[8]; len |= cdb[8];
switch (type) { switch (type) {
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
case 1: // Ethernet case 1: // Ethernet
// Do not process if TAP is invalid // Do not process if TAP is invalid
if (!m_bTapEnable) { if (!m_bTapEnable) {
@ -322,7 +322,7 @@ BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
return TRUE; return TRUE;
} }
break; break;
#endif // RASCSI && !BAREMETAL #endif // RASCSI && !BAREMETAL
case 2: // Host drive case 2: // Host drive
switch (phase) { switch (phase) {

View File

@ -34,120 +34,68 @@ class SCSIBR : public Disk
{ {
public: public:
// Basic Functions // Basic Functions
SCSIBR(); SCSIBR(); // Constructor
// Constructor virtual ~SCSIBR(); // Destructor
virtual ~SCSIBR();
// Destructor
// commands // commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
// INQUIRY command BOOL FASTCALL TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
BOOL FASTCALL TestUnitReady(const DWORD *cdb); int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf); // GET MESSAGE10 command
// TEST UNIT READY command BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf); // SEND MESSAGE10 command
int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf);
// GET MESSAGE10 command
BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf);
// SEND MESSAGE10 command
private: private:
#if defined(RASCSI) && !defined(BAREMETAL) #if defined(RASCSI) && !defined(BAREMETAL)
int FASTCALL GetMacAddr(BYTE *buf); int FASTCALL GetMacAddr(BYTE *buf); // Get MAC address
// Get MAC address void FASTCALL SetMacAddr(BYTE *buf); // Set MAC address
void FASTCALL SetMacAddr(BYTE *buf); void FASTCALL ReceivePacket(); // Receive a packet
// Set MAC address void FASTCALL GetPacketBuf(BYTE *buf); // Get a packet
void FASTCALL ReceivePacket(); void FASTCALL SendPacket(BYTE *buf, int len); // Send a packet
// Receive a packet
void FASTCALL GetPacketBuf(BYTE *buf);
// Get a packet
void FASTCALL SendPacket(BYTE *buf, int len);
// Send a packet
CTapDriver *tap; CTapDriver *tap; // TAP driver
// TAP driver BOOL m_bTapEnable; // TAP valid flag
BOOL m_bTapEnable; BYTE mac_addr[6]; // MAC Addres
// TAP valid flag int packet_len; // Receive packet size
BYTE mac_addr[6]; BYTE packet_buf[0x1000]; // Receive packet buffer
// MAC Addres BOOL packet_enable; // Received packet valid
int packet_len; #endif // RASCSI && !BAREMETAL
// Receive packet size
BYTE packet_buf[0x1000]; int FASTCALL ReadFsResult(BYTE *buf); // Read filesystem (result code)
// Receive packet buffer int FASTCALL ReadFsOut(BYTE *buf); // Read filesystem (return data)
BOOL packet_enable; int FASTCALL ReadFsOpt(BYTE *buf); // Read file system (optional data)
// Received packet valid void FASTCALL WriteFs(int func, BYTE *buf); // File system write (execute)
#endif // RASCSI && !BAREMETAL void FASTCALL WriteFsOpt(BYTE *buf, int len); // File system write (optional data)
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 // Command handlers
void FASTCALL FS_InitDevice(BYTE *buf); void FASTCALL FS_InitDevice(BYTE *buf); // $40 - boot
// $40 - boot void FASTCALL FS_CheckDir(BYTE *buf); // $41 - directory check
void FASTCALL FS_CheckDir(BYTE *buf); void FASTCALL FS_MakeDir(BYTE *buf); // $42 - create directory
// $41 - directory check void FASTCALL FS_RemoveDir(BYTE *buf); // $43 - delete directory
void FASTCALL FS_MakeDir(BYTE *buf); void FASTCALL FS_Rename(BYTE *buf); // $44 - change filename
// $42 - create directory void FASTCALL FS_Delete(BYTE *buf); // $45 - delete file
void FASTCALL FS_RemoveDir(BYTE *buf); void FASTCALL FS_Attribute(BYTE *buf); // $46 - get/set file attributes
// $43 - delete directory void FASTCALL FS_Files(BYTE *buf); // $47 - file search
void FASTCALL FS_Rename(BYTE *buf); void FASTCALL FS_NFiles(BYTE *buf); // $48 - find next file
// $44 - change filename void FASTCALL FS_Create(BYTE *buf); // $49 - create file
void FASTCALL FS_Delete(BYTE *buf); void FASTCALL FS_Open(BYTE *buf); // $4A - open file
// $45 - delete file void FASTCALL FS_Close(BYTE *buf); // $4B - close file
void FASTCALL FS_Attribute(BYTE *buf); void FASTCALL FS_Read(BYTE *buf); // $4C - read file
// $46 - get/set file attributes void FASTCALL FS_Write(BYTE *buf); // $4D - write file
void FASTCALL FS_Files(BYTE *buf); void FASTCALL FS_Seek(BYTE *buf); // $4E - seek file
// $47 - file search void FASTCALL FS_TimeStamp(BYTE *buf); // $4F - get/set file time
void FASTCALL FS_NFiles(BYTE *buf); void FASTCALL FS_GetCapacity(BYTE *buf); // $50 - get capacity
// $48 - find next file void FASTCALL FS_CtrlDrive(BYTE *buf); // $51 - drive status check/control
void FASTCALL FS_Create(BYTE *buf); void FASTCALL FS_GetDPB(BYTE *buf); // $52 - get DPB
// $49 - create file void FASTCALL FS_DiskRead(BYTE *buf); // $53 - read sector
void FASTCALL FS_Open(BYTE *buf); void FASTCALL FS_DiskWrite(BYTE *buf); // $54 - write sector
// $4A - open file void FASTCALL FS_Ioctrl(BYTE *buf); // $55 - IOCTRL
void FASTCALL FS_Close(BYTE *buf); void FASTCALL FS_Flush(BYTE *buf); // $56 - flush cache
// $4B - close file void FASTCALL FS_CheckMedia(BYTE *buf); // $57 - check media
void FASTCALL FS_Read(BYTE *buf); void FASTCALL FS_Lock(BYTE *buf); // $58 - get exclusive control
// $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; CFileSys *fs; // File system accessor
// File system accessor DWORD fsresult; // File system access result code
DWORD fsresult; BYTE fsout[0x800]; // File system access result buffer
// File system access result code DWORD fsoutlen; // File system access result buffer size
BYTE fsout[0x800]; BYTE fsopt[0x1000000]; // File system access buffer
// File system access result buffer DWORD fsoptlen; // File system access buffer size
DWORD fsoutlen;
// File system access result buffer size
BYTE fsopt[0x1000000];
// File system access buffer
DWORD fsoptlen;
// File system access buffer size
}; };

View File

@ -36,50 +36,30 @@ class CDTrack
{ {
public: public:
// Basic Functions // Basic Functions
CDTrack(SCSICD *scsicd); CDTrack(SCSICD *scsicd); // Constructor
// Constructor virtual ~CDTrack(); // Destructor
virtual ~CDTrack(); BOOL FASTCALL Init(int track, DWORD first, DWORD last); // Initialization
// Destructor
BOOL FASTCALL Init(int track, DWORD first, DWORD last);
// Initialization
// Properties // Properties
void FASTCALL SetPath(BOOL cdda, const Filepath& path); void FASTCALL SetPath(BOOL cdda, const Filepath& path); // Set the path
// Set the path void FASTCALL GetPath(Filepath& path) const; // Get the path
void FASTCALL GetPath(Filepath& path) const; void FASTCALL AddIndex(int index, DWORD lba); // Add index
// Get the path DWORD FASTCALL GetFirst() const; // Get the start LBA
void FASTCALL AddIndex(int index, DWORD lba); DWORD FASTCALL GetLast() const; // Get the last LBA
// Add index DWORD FASTCALL GetBlocks() const; // Get the number of blocks
DWORD FASTCALL GetFirst() const; int FASTCALL GetTrackNo() const; // Get the track number
// Get the start LBA BOOL FASTCALL IsValid(DWORD lba) const; // Is this a valid LBA?
DWORD FASTCALL GetLast() const; BOOL FASTCALL IsAudio() const; // Is this an audio track?
// 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: private:
SCSICD *cdrom; SCSICD *cdrom; // Parent device
// Parent device BOOL valid; // Valid track
BOOL valid; int track_no; // Track number
// Valid track DWORD first_lba; // First LBA
int track_no; DWORD last_lba; // Last LBA
// Track number BOOL audio; // Audio track flag
DWORD first_lba; BOOL raw; // RAW data flag
// First LBA Filepath imgpath; // Image file path
DWORD last_lba;
// Last LBA
BOOL audio;
// Audio track flag
BOOL raw;
// RAW data flag
Filepath imgpath;
// Image file path
}; };
//=========================================================================== //===========================================================================
@ -91,47 +71,29 @@ class CDDABuf
{ {
public: public:
// Basic Functions // Basic Functions
CDDABuf(); CDDABuf(); // Constructor
// Constructor virtual ~CDDABuf(); // Destructor
virtual ~CDDABuf(); #if 0
// Destructor BOOL Init(); // Initialization
#if 0 BOOL FASTCALL Load(const Filepath& path); // Load
BOOL Init(); BOOL FASTCALL Save(const Filepath& path); // Save
// Initialization
BOOL FASTCALL Load(const Filepath& path);
// Load
BOOL FASTCALL Save(const Filepath& path);
// Save
// API // API
void FASTCALL Clear(); void FASTCALL Clear(); // Clear the buffer
// Clear the buffer BOOL FASTCALL Open(Filepath& path); // File specification
BOOL FASTCALL Open(Filepath& path); BOOL FASTCALL GetBuf(DWORD *buffer, int frames); // Get the buffer
// File specification BOOL FASTCALL IsValid(); // Check if Valid
BOOL FASTCALL GetBuf(DWORD *buffer, int frames); BOOL FASTCALL ReadReq(); // Read Request
// Get the buffer BOOL FASTCALL IsEnd() const; // Finish check
BOOL FASTCALL IsValid();
// Check if Valid
BOOL FASTCALL ReadReq();
// Read Request
BOOL FASTCALL IsEnd() const;
// Finish check
private: private:
Filepath wavepath; Filepath wavepath; // Wave path
// Wave path BOOL valid; // Open result (is it valid?)
BOOL valid; DWORD *buf; // Data buffer
// Open result (is it valid?) DWORD read; // Read pointer
DWORD *buf; DWORD write; // Write pointer
// Data buffer DWORD num; // Valid number of data
DWORD read; DWORD rest; // Remaining file size
// Read pointer
DWORD write;
// Write pointer
DWORD num;
// Valid number of data
DWORD rest;
// Remaining file size
#endif #endif
}; };
@ -150,81 +112,51 @@ public:
public: public:
// Basic Functions // Basic Functions
SCSICD(); SCSICD(); // Constructor
// Constructor virtual ~SCSICD(); // Destructor
virtual ~SCSICD(); BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
// Destructor #ifndef RASCSI
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); BOOL FASTCALL Load(Fileio *fio, int ver); // Load
// Open #endif // RASCSI
#ifndef RASCSI
BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// commands // commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
// INQUIRY command int FASTCALL Read(BYTE *buf, DWORD block); // READ command
int FASTCALL Read(BYTE *buf, DWORD block); int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
// READ command BOOL FASTCALL PlayAudio(const DWORD *cdb); // PLAY AUDIO command
int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); // PLAY AUDIO MSF command
// READ TOC command BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); // PLAY AUDIO TRACK 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 // CD-DA
BOOL FASTCALL NextFrame(); BOOL FASTCALL NextFrame(); // Frame notification
// Frame notification void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate); // Get CD-DA buffer
void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate);
// Get CD-DA buffer
// LBA-MSF変換 // LBA-MSF変換
void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const; void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const; // LBA→MSF conversion
// LBA→MSF conversion DWORD FASTCALL MSFtoLBA(const BYTE *msf) const; // MSF→LBA conversion
DWORD FASTCALL MSFtoLBA(const BYTE *msf) const;
// MSF→LBA conversion
private: private:
// Open // Open
BOOL FASTCALL OpenCue(const Filepath& path); BOOL FASTCALL OpenCue(const Filepath& path); // Open(CUE)
// Open(CUE) BOOL FASTCALL OpenIso(const Filepath& path); // Open(ISO)
BOOL FASTCALL OpenIso(const Filepath& path); BOOL FASTCALL OpenPhysical(const Filepath& path); // Open(Physical)
// Open(ISO) BOOL rawfile; // RAW flag
BOOL FASTCALL OpenPhysical(const Filepath& path);
// Open(Physical)
BOOL rawfile;
// RAW flag
// Track management // Track management
void FASTCALL ClearTrack(); void FASTCALL ClearTrack(); // Clear the track
// Clear the track int FASTCALL SearchTrack(DWORD lba) const; // Track search
int FASTCALL SearchTrack(DWORD lba) const; CDTrack* track[TrackMax]; // Track opbject references
// Track search int tracks; // Effective number of track objects
CDTrack* track[TrackMax]; int dataindex; // Current data track
// Track opbject references int audioindex; // Current audio track
int tracks;
// Effective number of track objects
int dataindex;
// Current data track
int audioindex;
// Current audio track
int frame; int frame; // Frame number
// Frame number
#if 0 #if 0
CDDABuf da_buf; CDDABuf da_buf; // CD-DA buffer
// CD-DA buffer int da_num; // Number of CD-DA tracks
int da_num; int da_cur; // CD-DA current track
// Number of CD-DA tracks int da_next; // CD-DA next track
int da_cur; BOOL da_req; // CD-DA data request
// CD-DA current track #endif
int da_next;
// CD-DA next track
BOOL da_req;
// CD-DA data request
#endif
}; };

View File

@ -28,17 +28,11 @@ class SCSIHD : public Disk
{ {
public: public:
// Basic Functions // Basic Functions
SCSIHD(); SCSIHD(); // Constructor
// Constructor void FASTCALL Reset(); // Reset
void FASTCALL Reset(); BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
// Reset
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands // commands
int FASTCALL Inquiry( int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); // MODE SELECT(6) command
// INQUIRY command
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
// MODE SELECT(6) command
}; };

View File

@ -26,14 +26,10 @@ class SCSIHD_APPLE : public SCSIHD
{ {
public: public:
// Basic Functions // Basic Functions
SCSIHD_APPLE(); SCSIHD_APPLE(); // Constructor
// Constructor
// commands // commands
int FASTCALL Inquiry( int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
// Internal processing // Internal processing
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
// Add vendor special page
}; };

View File

@ -26,36 +26,22 @@ class SCSIHD_NEC : public SCSIHD
{ {
public: public:
// Basic Functions // Basic Functions
SCSIHD_NEC(); SCSIHD_NEC(); // Constructor
// Constructor BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
// Open
// commands // commands
int FASTCALL Inquiry( int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
// INQUIRY command
// Internal processing // Internal processing
int FASTCALL AddError(BOOL change, BYTE *buf); int FASTCALL AddError(BOOL change, BYTE *buf); // Add error
// Add error int FASTCALL AddFormat(BOOL change, BYTE *buf); // Add format
int FASTCALL AddFormat(BOOL change, BYTE *buf); int FASTCALL AddDrive(BOOL change, BYTE *buf); // Add drive
// Add format
int FASTCALL AddDrive(BOOL change, BYTE *buf);
// Add drive
private: private:
int cylinders; int cylinders; // Number of cylinders
// Number of cylinders int heads; // Number of heads
int heads; int sectors; // Number of sectors
// Number of heads int sectorsize; // Sector size
int sectors; off64_t imgoffset; // Image offset
// Number of sectors off64_t imgsize; // Image size
int sectorsize;
// Sector size
off64_t imgoffset;
// Image offset
off64_t imgsize;
// Image size
}; };

View File

@ -28,22 +28,16 @@ class SCSIMO : public Disk
{ {
public: public:
// Basic Functions // Basic Functions
SCSIMO(); SCSIMO(); // Constructor
// Constructor BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); #ifndef RASCSI
// Open BOOL FASTCALL Load(Fileio *fio, int ver); // Load
#ifndef RASCSI #endif // RASCSI
BOOL FASTCALL Load(Fileio *fio, int ver);
// Load
#endif // RASCSI
// commands // commands
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
// INQUIRY command BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); // MODE SELECT(6) command
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
// MODE SELECT(6) command
// Internal processing // Internal processing
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
// Add vendor special page
}; };

View File

@ -7,39 +7,39 @@ from settings import *
def make_cd(file_path, file_type, file_creator): def make_cd(file_path, file_type, file_creator):
with open(file_path, "rb") as f: with open(file_path, "rb") as f:
file_bytes = f.read() file_bytes = f.read()
file_name = file_path.split('/')[-1] file_name = file_path.split("/")[-1]
file_suffix = file_name.split('.')[-1] file_suffix = file_name.split(".")[-1]
if file_type is None and file_creator is None: if file_type is None and file_creator is None:
if file_suffix.lower() == 'sea': if file_suffix.lower() == "sea":
file_type = '.sea' file_type = ".sea"
file_creator = 'APPL' file_creator = "APPL"
v = Volume() v = Volume()
v.name = "TestName" v.name = "TestName"
v['Folder'] = Folder() v["Folder"] = Folder()
v['Folder'][file_name] = File() v["Folder"][file_name] = File()
v['Folder'][file_name].data = file_bytes v["Folder"][file_name].data = file_bytes
v['Folder'][file_name].rsrc = b'' v["Folder"][file_name].rsrc = b""
if not (file_type is None and file_creator is None): if not (file_type is None and file_creator is None):
v['Folder'][file_name].type = bytearray(file_type) v["Folder"][file_name].type = bytearray(file_type)
v['Folder'][file_name].creator = bytearray(file_creator) v["Folder"][file_name].creator = bytearray(file_creator)
padding = (len(file_bytes) % 512) + (512 * 50) padding = (len(file_bytes) % 512) + (512 * 50)
print("mod", str(len(file_bytes) % 512)) print("mod", str(len(file_bytes) % 512))
print("padding " + str(padding)) print("padding " + str(padding))
print("len " + str(len(file_bytes))) print("len " + str(len(file_bytes)))
print("total " + str(len(file_bytes) + padding)) print("total " + str(len(file_bytes) + padding))
with open(base_dir + 'test.hda', 'wb') as f: with open(base_dir + "test.hda", "wb") as f:
flat = v.write( flat = v.write(
size=len(file_bytes) + padding, size=len(file_bytes) + padding,
align=512, # Allocation block alignment modulus (2048 for CDs) align=512, # Allocation block alignment modulus (2048 for CDs)
desktopdb=True, # Create a dummy Desktop Database to prevent a rebuild on boot desktopdb=True, # Create a dummy Desktop Database to prevent a rebuild on boot
bootable=False, # This requires a folder with a ZSYS and a FNDR file bootable=False, # This requires a folder with a ZSYS and a FNDR file
startapp=('Folder', file_name), # Path (as tuple) to an app to open at boot startapp=("Folder", file_name), # Path (as tuple) to an app to open at boot
) )
f.write(flat) f.write(flat)
return base_dir + 'test.hda' return base_dir + "test.hda"

View File

@ -5,8 +5,9 @@ import time
from ractl_cmds import attach_image from ractl_cmds import attach_image
from settings import * from settings import *
valid_file_types = ['*.hda', '*.iso', '*.cdr']
valid_file_types = r'|'.join([fnmatch.translate(x) for x in valid_file_types]) valid_file_types = ["*.hda", "*.iso", "*.cdr"]
valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_types])
def create_new_image(file_name, type, size): def create_new_image(file_name, type, size):
@ -15,8 +16,10 @@ def create_new_image(file_name, type, size):
else: else:
file_name = file_name + "." + type file_name = file_name + "." + type
return subprocess.run(["dd", "if=/dev/zero", "of=" + base_dir + file_name, "bs=1M", "count=" + size], return subprocess.run(
capture_output=True) ["dd", "if=/dev/zero", "of=" + base_dir + file_name, "bs=1M", "count=" + size],
capture_output=True,
)
def delete_image(file_name): def delete_image(file_name):
@ -30,18 +33,24 @@ def delete_image(file_name):
def unzip_file(file_name): def unzip_file(file_name):
import zipfile import zipfile
with zipfile.ZipFile(base_dir + file_name, 'r') as zip_ref:
with zipfile.ZipFile(base_dir + file_name, "r") as zip_ref:
zip_ref.extractall(base_dir) zip_ref.extractall(base_dir)
return True return True
def rascsi_service(action): def rascsi_service(action):
# start/stop/restart # start/stop/restart
return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 return (
subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode
== 0
)
def download_file_to_iso(scsi_id, url): def download_file_to_iso(scsi_id, url):
import urllib.request import urllib.request
file_name = url.split('/')[-1]
file_name = url.split("/")[-1]
tmp_ts = int(time.time()) tmp_ts = int(time.time())
tmp_dir = "/tmp/" + str(tmp_ts) + "/" tmp_dir = "/tmp/" + str(tmp_ts) + "/"
os.mkdir(tmp_dir) os.mkdir(tmp_dir)
@ -50,15 +59,18 @@ def download_file_to_iso(scsi_id, url):
urllib.request.urlretrieve(url, tmp_full_path) urllib.request.urlretrieve(url, tmp_full_path)
# iso_filename = make_cd(tmp_full_path, None, None) # not working yet # iso_filename = make_cd(tmp_full_path, None, None) # not working yet
iso_proc = subprocess.run(["genisoimage", "-hfs", "-o", iso_filename, tmp_full_path], capture_output=True) iso_proc = subprocess.run(
["genisoimage", "-hfs", "-o", iso_filename, tmp_full_path], capture_output=True
)
if iso_proc.returncode != 0: if iso_proc.returncode != 0:
return iso_proc return iso_proc
return attach_image(scsi_id, iso_filename, "cd") return attach_image(scsi_id, iso_filename, "SCCD")
def download_image(url): def download_image(url):
import urllib.request import urllib.request
file_name = url.split('/')[-1]
file_name = url.split("/")[-1]
full_path = base_dir + file_name full_path = base_dir + file_name
urllib.request.urlretrieve(url, full_path) urllib.request.urlretrieve(url, full_path)

12
src/web/mock/bin/brctl Normal file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Mock responses to rascsi-web
case $1 in
"show")
echo "rascsi_bridge 8000.dca632b05dd1 no eth0"
;;
**)
echo "default"
;;
esac

12
src/web/mock/bin/ip Normal file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Mock responses to rascsi-web
case $1 in
"link")
echo "link here"
;;
**)
echo "default"
;;
esac

View File

@ -3,7 +3,10 @@ import subprocess
def rascsi_service(action): def rascsi_service(action):
# start/stop/restart # start/stop/restart
return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 return (
subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode
== 0
)
def reboot_pi(): def reboot_pi():
@ -15,6 +18,14 @@ def shutdown_pi():
def running_version(): def running_version():
ra_web_version = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True).stdout.decode("utf-8").strip() ra_web_version = (
pi_version = subprocess.run(["uname", "-a"], capture_output=True).stdout.decode("utf-8").strip() subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True)
.stdout.decode("utf-8")
.strip()
)
pi_version = (
subprocess.run(["uname", "-a"], capture_output=True)
.stdout.decode("utf-8")
.strip()
)
return ra_web_version + " " + pi_version return ra_web_version + " " + pi_version

View File

@ -4,8 +4,9 @@ import subprocess
import re import re
from settings import * from settings import *
valid_file_types = ['*.hda', '*.iso', '*.cdr', '*.zip']
valid_file_types = r'|'.join([fnmatch.translate(x) for x in valid_file_types]) valid_file_types = ["*.hda", "*.iso", "*.cdr", "*.zip"]
valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_types])
# List of SCSI ID's you'd like to exclude - eg if you are on a Mac, the System is usually 7 # List of SCSI ID's you'd like to exclude - eg if you are on a Mac, the System is usually 7
EXCLUDE_SCSI_IDS = [7] EXCLUDE_SCSI_IDS = [7]
@ -20,19 +21,36 @@ def list_files():
for path, dirs, files in os.walk(base_dir): for path, dirs, files in os.walk(base_dir):
# Only list valid file types # Only list valid file types
files = [f for f in files if re.match(valid_file_types, f)] files = [f for f in files if re.match(valid_file_types, f)]
files_list.extend([ files_list.extend(
(os.path.join(path, file), [
(
os.path.join(path, file),
# TODO: move formatting to template # TODO: move formatting to template
'{:,.0f}'.format(os.path.getsize(os.path.join(path, file)) / float(1 << 20)) + " MB") "{:,.0f}".format(
for file in files]) os.path.getsize(os.path.join(path, file)) / float(1 << 20)
)
+ " MB",
)
for file in files
]
)
return files_list
def list_config_files():
files_list = []
for root, dirs, files in os.walk(base_dir):
for file in files:
if file.endswith(".csv"):
files_list.append(file)
return files_list return files_list
def get_valid_scsi_ids(devices): def get_valid_scsi_ids(devices):
invalid_list = EXCLUDE_SCSI_IDS.copy() invalid_list = EXCLUDE_SCSI_IDS.copy()
for device in devices: for device in devices:
if device['file'] != "NO MEDIA" and device['file'] != "-": if device["file"] != "NO MEDIA" and device["file"] != "-":
invalid_list.append(int(device['id'])) invalid_list.append(int(device["id"]))
valid_list = list(range(8)) valid_list = list(range(8))
for id in invalid_list: for id in invalid_list:
@ -46,19 +64,33 @@ def get_type(scsi_id):
return list_devices()[int(scsi_id)]["type"] return list_devices()[int(scsi_id)]["type"]
def attach_image(scsi_id, image, type): def attach_image(scsi_id, image, device_type):
if type == "cd" and get_type(scsi_id) == "SCCD": if device_type == "SCCD" and get_type(scsi_id) == "SCCD":
return insert(scsi_id, image) return insert(scsi_id, image)
elif device_type == "SCDP":
attach_daynaport(scsi_id)
else: else:
return subprocess.run(["rasctl", "-c", "attach", "-t", type, "-i", scsi_id, "-f", image], capture_output=True) if device_type == "SCCD":
device_type = "cd"
return subprocess.run(
["rasctl", "-c", "attach", "-t", device_type, "-i", scsi_id, "-f", image],
capture_output=True,
)
def detach_by_id(scsi_id): def detach_by_id(scsi_id):
return subprocess.run(["rasctl", "-c" "detach", "-i", scsi_id], capture_output=True) return subprocess.run(["rasctl", "-c" "detach", "-i", scsi_id], capture_output=True)
def detach_all():
for scsi_id in range(0, 7):
subprocess.run(["rasctl", "-c" "detach", "-i", str(scsi_id)])
def disconnect_by_id(scsi_id): def disconnect_by_id(scsi_id):
return subprocess.run(["rasctl", "-c", "disconnect", "-i", scsi_id], capture_output=True) return subprocess.run(
["rasctl", "-c", "disconnect", "-i", scsi_id], capture_output=True
)
def eject_by_id(scsi_id): def eject_by_id(scsi_id):
@ -66,33 +98,67 @@ def eject_by_id(scsi_id):
def insert(scsi_id, image): def insert(scsi_id, image):
return subprocess.run(["rasctl", "-i", scsi_id, "-c", "insert", "-f", image], capture_output=True) return subprocess.run(
["rasctl", "-i", scsi_id, "-c", "insert", "-f", image], capture_output=True
)
def attach_daynaport(scsi_id):
return subprocess.run(
["rasctl", "-i", scsi_id, "-c", "attach", "-t", "daynaport"],
capture_output=True,
)
def is_bridge_setup(interface):
process = subprocess.run(["brctl", "show"], capture_output=True)
output = process.stdout.decode("utf-8")
if "rascsi_bridge" in output and interface in output:
return True
return False
def daynaport_setup_bridge(interface):
return subprocess.run(
[f"{base_dir}../RASCSI/src/raspberrypi/setup_bridge.sh", interface],
capture_output=True,
)
def rascsi_service(action): def rascsi_service(action):
# start/stop/restart # start/stop/restart
return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 return (
subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode
== 0
)
def list_devices(): def list_devices():
device_list = [] device_list = []
for id in range(8): for id in range(8):
device_list.append({"id": str(id), "un": "-", "type": "-", "file": "-"}) device_list.append({"id": str(id), "un": "-", "type": "-", "file": "-"})
output = subprocess.run(["rasctl", "-l"], capture_output=True).stdout.decode("utf-8") output = subprocess.run(["rasctl", "-l"], capture_output=True).stdout.decode(
"utf-8"
)
for line in output.splitlines(): for line in output.splitlines():
# Valid line to process, continue # Valid line to process, continue
if not line.startswith("+") and \ if (
not line.startswith("| ID |") and \ not line.startswith("+")
(not line.startswith("No device is installed.") or line.startswith("No images currently attached.")) \ and not line.startswith("| ID |")
and len(line) > 0: and (
not line.startswith("No device is installed.")
or line.startswith("No images currently attached.")
)
and len(line) > 0
):
line.rstrip() line.rstrip()
device = {} device = {}
segments = line.split("|") segments = line.split("|")
if len(segments) > 4: if len(segments) > 4:
idx = int(segments[1].strip()) idx = int(segments[1].strip())
device_list[idx]["id"] = str(idx) device_list[idx]["id"] = str(idx)
device_list[idx]['un'] = segments[2].strip() device_list[idx]["un"] = segments[2].strip()
device_list[idx]['type'] = segments[3].strip() device_list[idx]["type"] = segments[3].strip()
device_list[idx]['file'] = segments[4].strip() device_list[idx]["file"] = segments[4].strip()
return device_list return device_list

View File

@ -1,4 +1,4 @@
import os import os
base_dir = os.getenv('BASE_DIR', "/home/pi/images/") base_dir = os.getenv("BASE_DIR", "/home/pi/images/")
MAX_FILE_SIZE = os.getenv('MAX_FILE_SIZE', 1024 * 1024 * 1024 * 2) # 2gb MAX_FILE_SIZE = os.getenv("MAX_FILE_SIZE", 1024 * 1024 * 1024 * 2) # 2gb

View File

@ -17,10 +17,26 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h2>Current RaSCSI Configuration</h2> <h2>Current RaSCSI Configuration</h2>
<form action="/config/load" method="post">
<select name="name" >
{% for config in config_files %}
<option value="{{config}}">{{config.replace(".csv", '')}}</option>
{% endfor %}
</select>
<input type="submit" value="Load" />
</form>
<form action="/config/save" method="post">
<input name="name" placeholder="default">
<input type="submit" value="Save" />
</form>
<form action="/scsi/detach_all" method="post" onsubmit="return confirm('Detach all SCSI Devices?')">
<input type="submit" value="Detach All" />
</form>
<table cellpadding="3" border="black"> <table cellpadding="3" border="black">
<tbody> <tbody>
<tr> <tr>
@ -103,7 +119,35 @@
</table> </table>
<hr/> <hr/>
<h2>Attach Ethernet Adapter</h2>
<p>Emulates a SCSI DaynaPORT Ethernet Adapter. Host drivers required.</p>
<table style="border: none">
<tr style="border: none">
<td style="border: none; vertical-align:top;">
<form action="/daynaport/attach" method="post">
<select name="scsi_id">
{% for id in scsi_ids %}
<option value="{{id}}">{{id}}</option>
{% endfor %}
</select>
<input type="submit" value="Attach" />
</form>
</td>
</tr>
<tr style="border: none">
<td style="border: none; vertical-align:top;">
{% if bridge_configured %}
<small>Bridge is currently configured!</small>
{% else %}
<form action="/daynaport/setup" method="post">
<input type="submit" value="Create Bridge" />
</form>
{% endif %}
</td>
</tr>
</table>
<hr/>
<h2>Upload File</h2> <h2>Upload File</h2>
<p>Uploads file to <tt>{{base_dir}}</tt>. Max file size is set to {{max_file_size / 1024 /1024 }}MB</p> <p>Uploads file to <tt>{{base_dir}}</tt>. Max file size is set to {{max_file_size / 1024 /1024 }}MB</p>
<table style="border: none"> <table style="border: none">
@ -183,7 +227,6 @@
</table> </table>
<hr/> <hr/>
<h2>Raspberry Pi Operations</h2> <h2>Raspberry Pi Operations</h2>
<table style="border: none"> <table style="border: none">
<tr style="border: none"> <tr style="border: none">

View File

@ -1,206 +1,298 @@
import os
from flask import Flask, render_template, request, flash, url_for, redirect, send_file from flask import Flask, render_template, request, flash, url_for, redirect, send_file
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from file_cmds import create_new_image, download_file_to_iso, delete_image, unzip_file, download_image from file_cmds import (
create_new_image,
download_file_to_iso,
delete_image,
unzip_file,
download_image,
)
from pi_cmds import shutdown_pi, reboot_pi, running_version, rascsi_service from pi_cmds import shutdown_pi, reboot_pi, running_version, rascsi_service
from ractl_cmds import attach_image, list_devices, is_active, list_files, detach_by_id, eject_by_id, get_valid_scsi_ids from ractl_cmds import (
attach_image,
list_devices,
is_active,
list_files,
detach_by_id,
eject_by_id,
get_valid_scsi_ids,
attach_daynaport,
is_bridge_setup,
daynaport_setup_bridge,
list_config_files,
detach_all,
)
from settings import * from settings import *
app = Flask(__name__) app = Flask(__name__)
@app.route('/')
@app.route("/")
def index(): def index():
devices = list_devices() devices = list_devices()
scsi_ids = get_valid_scsi_ids(devices) scsi_ids = get_valid_scsi_ids(devices)
return render_template('index.html', return render_template(
"index.html",
bridge_configured=is_bridge_setup("eth0"),
devices=devices, devices=devices,
active=is_active(), active=is_active(),
files=list_files(), files=list_files(),
config_files=list_config_files(),
base_dir=base_dir, base_dir=base_dir,
scsi_ids=scsi_ids, scsi_ids=scsi_ids,
max_file_size=MAX_FILE_SIZE, max_file_size=MAX_FILE_SIZE,
version=running_version()) version=running_version(),
)
@app.route('/logs')
@app.route("/config/save", methods=["POST"])
def config_save():
file_name = request.form.get("name") or "default"
file_name = f"{base_dir}{file_name}.csv"
import csv
with open(file_name, "w") as csv_file:
writer = csv.writer(csv_file)
for device in list_devices():
if device["type"] is not "-":
writer.writerow(device.values())
flash(f"Saved config to {file_name}!")
return redirect(url_for("index"))
@app.route("/config/load", methods=["POST"])
def config_load():
file_name = request.form.get("name") or "default.csv"
file_name = f"{base_dir}{file_name}"
detach_all()
import csv
with open(file_name) as csv_file:
config_reader = csv.reader(csv_file)
for row in config_reader:
image_name = row[3].replace("(WRITEPROTECT)", "")
attach_image(row[0], image_name, row[2])
flash(f"Loaded config from {file_name}!")
return redirect(url_for("index"))
@app.route("/logs")
def logs(): def logs():
import subprocess import subprocess
lines = request.args.get('lines') or "100"
lines = request.args.get("lines") or "100"
process = subprocess.run(["journalctl", "-n", lines], capture_output=True) process = subprocess.run(["journalctl", "-n", lines], capture_output=True)
if process.returncode == 0: if process.returncode == 0:
headers = { 'content-type':'text/plain' } headers = {"content-type": "text/plain"}
return process.stdout.decode("utf-8"), 200, headers return process.stdout.decode("utf-8"), 200, headers
else: else:
flash(u'Failed to get logs') flash("Failed to get logs")
flash(process.stdout.decode("utf-8"), 'stdout') flash(process.stdout.decode("utf-8"), "stdout")
flash(process.stderr.decode("utf-8"), 'stderr') flash(process.stderr.decode("utf-8"), "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/scsi/attach', methods=['POST']) @app.route("/daynaport/attach", methods=["POST"])
def daynaport_attach():
scsi_id = request.form.get("scsi_id")
process = attach_daynaport(scsi_id)
if process.returncode == 0:
flash(f"Attached DaynaPORT to SCSI id {scsi_id}!")
return redirect(url_for("index"))
else:
flash(f"Failed to attach DaynaPORT to SCSI id {scsi_id}!", "error")
flash(process.stdout.decode("utf-8"), "stdout")
flash(process.stderr.decode("utf-8"), "stderr")
return redirect(url_for("index"))
@app.route("/daynaport/setup", methods=["POST"])
def daynaport_setup():
# Future use for wifi
interface = request.form.get("interface") or "eth0"
process = daynaport_setup_bridge(interface)
if process.returncode == 0:
flash(f"Configured DaynaPORT bridge on {interface}!")
return redirect(url_for("index"))
else:
flash(f"Failed to configure DaynaPORT bridge on {interface}!", "error")
flash(process.stdout.decode("utf-8"), "stdout")
flash(process.stderr.decode("utf-8"), "stderr")
return redirect(url_for("index"))
@app.route("/scsi/attach", methods=["POST"])
def attach(): def attach():
file_name = request.form.get('file_name') file_name = request.form.get("file_name")
scsi_id = request.form.get('scsi_id') scsi_id = request.form.get("scsi_id")
# Validate image type by suffix # Validate image type by suffix
if file_name.lower().endswith('.iso') or file_name.lower().endswith('iso'): if file_name.lower().endswith(".iso") or file_name.lower().endswith("iso"):
image_type = "cd" image_type = "cd"
elif file_name.lower().endswith('.hda'): elif file_name.lower().endswith(".hda"):
image_type = "hd" image_type = "hd"
else: else:
flash(u'Unknown file type. Valid files are .iso, .hda, .cdr', 'error') flash("Unknown file type. Valid files are .iso, .hda, .cdr", "error")
return redirect(url_for('index')) return redirect(url_for("index"))
process = attach_image(scsi_id, file_name, image_type) process = attach_image(scsi_id, file_name, image_type)
if process.returncode == 0: if process.returncode == 0:
flash('Attached '+ file_name + " to scsi id " + scsi_id + "!") flash(f"Attached {file_name} to SCSI id {scsi_id}!")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u'Failed to attach '+ file_name + " to scsi id " + scsi_id + "!", 'error') flash(f"Failed to attach {file_name} to SCSI id {scsi_id}!", "error")
flash(process.stdout.decode("utf-8"), 'stdout') flash(process.stdout.decode("utf-8"), "stdout")
flash(process.stderr.decode("utf-8"), 'stderr') flash(process.stderr.decode("utf-8"), "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/scsi/detach', methods=['POST']) @app.route("/scsi/detach_all", methods=["POST"])
def detach_all_devices():
detach_all()
flash("Detached all SCSI devices!")
return redirect(url_for("index"))
@app.route("/scsi/detach", methods=["POST"])
def detach(): def detach():
scsi_id = request.form.get('scsi_id') scsi_id = request.form.get("scsi_id")
process = detach_by_id(scsi_id) process = detach_by_id(scsi_id)
if process.returncode == 0: if process.returncode == 0:
flash("Detached scsi id " + scsi_id + "!") flash("Detached SCSI id " + scsi_id + "!")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to detach scsi id " + scsi_id + "!", 'error') flash("Failed to detach SCSI id " + scsi_id + "!", "error")
flash(process.stdout, 'stdout') flash(process.stdout, "stdout")
flash(process.stderr, 'stderr') flash(process.stderr, "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/scsi/eject', methods=['POST']) @app.route("/scsi/eject", methods=["POST"])
def eject(): def eject():
scsi_id = request.form.get('scsi_id') scsi_id = request.form.get("scsi_id")
process = eject_by_id(scsi_id) process = eject_by_id(scsi_id)
if process.returncode == 0: if process.returncode == 0:
flash("Ejected scsi id " + scsi_id + "!") flash("Ejected scsi id " + scsi_id + "!")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to eject scsi id " + scsi_id + "!", 'error') flash("Failed to eject SCSI id " + scsi_id + "!", "error")
flash(process.stdout, 'stdout') flash(process.stdout, "stdout")
flash(process.stderr, 'stderr') flash(process.stderr, "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/pi/reboot', methods=['POST']) @app.route("/pi/reboot", methods=["POST"])
def restart(): def restart():
reboot_pi() reboot_pi()
flash("Restarting...") flash("Restarting...")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/rascsi/restart', methods=['POST']) @app.route("/rascsi/restart", methods=["POST"])
def rascsi_restart(): def rascsi_restart():
rascsi_service("restart") rascsi_service("restart")
flash("Restarting RaSCSI Service...") flash("Restarting RaSCSI Service...")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/pi/shutdown', methods=['POST']) @app.route("/pi/shutdown", methods=["POST"])
def shutdown(): def shutdown():
shutdown_pi() shutdown_pi()
flash("Shutting down...") flash("Shutting down...")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/files/download_to_iso', methods=['POST']) @app.route("/files/download_to_iso", methods=["POST"])
def download_file(): def download_file():
scsi_id = request.form.get('scsi_id') scsi_id = request.form.get("scsi_id")
url = request.form.get('url') url = request.form.get("url")
process = download_file_to_iso(scsi_id, url) process = download_file_to_iso(scsi_id, url)
if process.returncode == 0: if process.returncode == 0:
flash("File Downloaded") flash("File Downloaded")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to download file", 'error') flash("Failed to download file", "error")
flash(process.stdout, 'stdout') flash(process.stdout, "stdout")
flash(process.stderr, 'stderr') flash(process.stderr, "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/files/download_image', methods=['POST']) @app.route("/files/download_image", methods=["POST"])
def download_img(): def download_img():
url = request.form.get('url') url = request.form.get("url")
# TODO: error handling # TODO: error handling
download_image(url) download_image(url)
flash("File Downloaded") flash("File Downloaded")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/files/upload', methods=['POST']) @app.route("/files/upload", methods=["POST"])
def upload_file(): def upload_file():
if 'file' not in request.files: if "file" not in request.files:
flash('No file part', 'error') flash("No file part", "error")
return redirect(url_for('index')) return redirect(url_for("index"))
file = request.files['file'] file = request.files["file"]
if file: if file:
filename = secure_filename(file.filename) filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
return redirect(url_for('index', filename=filename)) return redirect(url_for("index", filename=filename))
@app.route('/files/create', methods=['POST']) @app.route("/files/create", methods=["POST"])
def create_file(): def create_file():
file_name = request.form.get('file_name') file_name = request.form.get("file_name")
size = request.form.get('size') size = request.form.get("size")
type = request.form.get('type') type = request.form.get("type")
process = create_new_image(file_name, type, size) process = create_new_image(file_name, type, size)
if process.returncode == 0: if process.returncode == 0:
flash("Drive created") flash("Drive created")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to create file", 'error') flash("Failed to create file", "error")
flash(process.stdout, 'stdout') flash(process.stdout, "stdout")
flash(process.stderr, 'stderr') flash(process.stderr, "stderr")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/files/download', methods=['POST']) @app.route("/files/download", methods=["POST"])
def download(): def download():
image = request.form.get('image') image = request.form.get("image")
return send_file(base_dir + image, as_attachment=True) return send_file(base_dir + image, as_attachment=True)
@app.route('/files/delete', methods=['POST']) @app.route("/files/delete", methods=["POST"])
def delete(): def delete():
image = request.form.get('image') image = request.form.get("image")
if delete_image(image): if delete_image(image):
flash("File " + image + " deleted") flash("File " + image + " deleted")
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to Delete " + image, 'error') flash("Failed to Delete " + image, "error")
return redirect(url_for('index')) return redirect(url_for("index"))
@app.route('/files/unzip', methods=['POST']) @app.route("/files/unzip", methods=["POST"])
def unzip(): def unzip():
image = request.form.get('image') image = request.form.get("image")
if unzip_file(image): if unzip_file(image):
flash("Unzipped file " + image) flash("Unzipped file " + image)
return redirect(url_for('index')) return redirect(url_for("index"))
else: else:
flash(u"Failed to unzip " + image, 'error') flash("Failed to unzip " + image, "error")
return redirect(url_for('index')) return redirect(url_for("index"))
if __name__ == "__main__": if __name__ == "__main__":
app.secret_key = 'rascsi_is_awesome_insecure_secret_key' app.secret_key = "rascsi_is_awesome_insecure_secret_key"
app.config['SESSION_TYPE'] = 'filesystem' app.config["SESSION_TYPE"] = "filesystem"
app.config['UPLOAD_FOLDER'] = base_dir app.config["UPLOAD_FOLDER"] = base_dir
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE app.config["MAX_CONTENT_LENGTH"] = MAX_FILE_SIZE
from waitress import serve from waitress import serve
serve(app, host="0.0.0.0", port=8080) serve(app, host="0.0.0.0", port=8080)

View File

@ -15,7 +15,7 @@ The ${service_name} Service Should be Running
The ${service_name} Service Should be Stopped The ${service_name} Service Should be Stopped
${lc_service_name}= Convert To Lower Case ${service_name} ${lc_service_name}= Convert To Lower Case ${service_name}
${output}= Execute Command systemctl status ${lc_service_name} ${output}= Execute Command systemctl status ${lc_service_name}
Should Contain ${output} Active: failed ignore_case=True Should Contain Any ${output} Active: failed Active: inactive ignore_case=True
The ${service_name} Service is Stopped The ${service_name} Service is Stopped
${lc_service_name}= Convert To Lower Case ${service_name} ${lc_service_name}= Convert To Lower Case ${service_name}