mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-02 11:41:34 +00:00
Merge in latest version of daynaport3
This commit is contained in:
commit
9c97e6ef83
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,3 +1,9 @@
|
|||
venv
|
||||
*.pyc
|
||||
core
|
||||
.idea/
|
||||
.DS_Store
|
||||
*.swp
|
||||
__pycache__
|
||||
src/web/current
|
||||
src/oled_monitor/current
|
||||
|
|
|
@ -24,11 +24,11 @@ VIRTUAL_DRIVER_PATH=/home/pi/images
|
|||
HFS_FORMAT=/usr/bin/hformat
|
||||
HFDISK_BIN=/usr/bin/hfdisk
|
||||
LIDO_DRIVER=~/RASCSI/lido-driver.img
|
||||
|
||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
function initialChecks() {
|
||||
currentUser=$(whoami)
|
||||
if [ "pi" != $currentUser ]; then
|
||||
if [ "pi" != "$currentUser" ]; then
|
||||
echo "You must use 'pi' user (current: $currentUser)"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -40,11 +40,14 @@ function initialChecks() {
|
|||
fi
|
||||
}
|
||||
|
||||
function installPackages() {
|
||||
sudo apt-get update && sudo apt install git libspdlog-dev libpcap-dev genisoimage python3 python3-venv nginx libpcap-dev -y
|
||||
}
|
||||
|
||||
# install all dependency packages for RaSCSI Service
|
||||
# compile and install RaSCSI Service
|
||||
function installRaScsi() {
|
||||
sudo apt-get update && sudo apt-get install --yes git libspdlog-dev
|
||||
installPackages
|
||||
|
||||
cd ~/RASCSI/src/raspberrypi
|
||||
make all CONNECT_TYPE=FULLSPEC
|
||||
|
@ -69,7 +72,7 @@ www-data ALL=NOPASSWD: /sbin/shutdown, /sbin/reboot
|
|||
|
||||
function stopOldWebInterface() {
|
||||
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..."
|
||||
sudo systemctl disable apache2
|
||||
sudo systemctl stop apache2
|
||||
|
@ -79,7 +82,7 @@ function stopOldWebInterface() {
|
|||
# install everything required to run an HTTP server (Nginx + Python Flask App)
|
||||
function installRaScsiWebInterface() {
|
||||
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/502.html /var/www/html/502.html
|
||||
|
@ -99,12 +102,17 @@ function installRaScsiWebInterface() {
|
|||
}
|
||||
|
||||
function updateRaScsiGit() {
|
||||
echo "Updating checked out branch $GIT_BRANCH"
|
||||
cd ~/RASCSI
|
||||
git pull
|
||||
git fetch origin
|
||||
git stash
|
||||
git rebase origin/$GIT_BRANCH
|
||||
git stash apply
|
||||
}
|
||||
|
||||
function updateRaScsi() {
|
||||
updateRaScsiGit
|
||||
installPackages
|
||||
sudo systemctl stop rascsi
|
||||
|
||||
cd ~/RASCSI/src/raspberrypi
|
||||
|
@ -241,8 +249,8 @@ function showMenu() {
|
|||
choice=-1
|
||||
|
||||
until [ $choice -ge "0" ] && [ $choice -le "7" ]; do
|
||||
echo "Enter your choice (0-7) or CTRL-C to exit"
|
||||
read choice
|
||||
echo -n "Enter your choice (0-7) or CTRL-C to exit: "
|
||||
read -r choice
|
||||
done
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# RaSCSI Updates:
|
||||
# Updates to output rascsi status to an OLED display
|
||||
|
@ -29,92 +29,57 @@
|
|||
# THE SOFTWARE.
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
#import Adafruit_GPIO.SPI as SPI
|
||||
import Adafruit_SSD1306
|
||||
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
from PIL import ImageFont
|
||||
|
||||
import board
|
||||
import busio
|
||||
import adafruit_ssd1306
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import subprocess
|
||||
|
||||
WIDTH = 128
|
||||
HEIGHT = 32 # Change to 64 if needed
|
||||
BORDER = 5
|
||||
|
||||
# How long to delay between each update
|
||||
delay_time_ms = 250
|
||||
|
||||
# Raspberry Pi pin configuration:
|
||||
RST = None # on the PiOLED this pin isnt used
|
||||
# Note the following are only used with SPI:
|
||||
DC = 23
|
||||
SPI_PORT = 0
|
||||
SPI_DEVICE = 0
|
||||
# Define the Reset Pin
|
||||
oled_reset = None
|
||||
|
||||
# Beaglebone Black pin configuration:
|
||||
# RST = 'P9_12'
|
||||
# Note the following are only used with SPI:
|
||||
# DC = 'P9_15'
|
||||
# SPI_PORT = 1
|
||||
# SPI_DEVICE = 0
|
||||
# init i2c
|
||||
i2c = board.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:
|
||||
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
|
||||
|
||||
# Note you can change the I2C address by passing an i2c_address parameter like:
|
||||
# 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()
|
||||
print ("Running with the following display:")
|
||||
print (oled)
|
||||
print ()
|
||||
print ("Will update the OLED display every " + str(delay_time_ms) + "ms (approximately)")
|
||||
|
||||
# Clear display.
|
||||
disp.clear()
|
||||
disp.display()
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
|
||||
# Create blank image for drawing.
|
||||
# Make sure to create image with mode '1' for 1-bit color.
|
||||
width = disp.width
|
||||
height = disp.height
|
||||
image = Image.new('1', (width, height))
|
||||
image = Image.new("1", (oled.width, oled.height))
|
||||
|
||||
# Get drawing object to draw on image.
|
||||
draw = ImageDraw.Draw(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.
|
||||
# First define some constants to allow easy resizing of shapes.
|
||||
padding = -2
|
||||
top = padding
|
||||
bottom = height-padding
|
||||
bottom = HEIGHT-padding
|
||||
# Move left to right keeping track of the current x position for drawing shapes.
|
||||
x = 0
|
||||
|
||||
|
||||
# Load default font.
|
||||
font = ImageFont.load_default()
|
||||
|
||||
|
@ -125,10 +90,10 @@ font = ImageFont.load_default()
|
|||
while True:
|
||||
|
||||
# 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"
|
||||
rascsi_list = subprocess.check_output(cmd, shell=True)
|
||||
rascsi_list = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding)
|
||||
|
||||
y_pos = top
|
||||
# Draw all of the meaningful data to the 'image'
|
||||
|
@ -146,19 +111,20 @@ while True:
|
|||
for line in rascsi_list.split('\n'):
|
||||
# Skip empty strings, divider lines and the header line...
|
||||
if (len(line) == 0) or line.startswith("+---") or line.startswith("| ID | UN"):
|
||||
continue
|
||||
else:
|
||||
if line.startswith("| "):
|
||||
fields = line.split('|')
|
||||
output = str.strip(fields[1]) + " " + str.strip(fields[3]) + " " + os.path.basename(str.strip(fields[4]))
|
||||
else:
|
||||
output = "No image mounted!"
|
||||
draw.text((x, y_pos), output, font=font, fill=255)
|
||||
y_pos = y_pos + 8
|
||||
continue
|
||||
else:
|
||||
if line.startswith("| "):
|
||||
fields = line.split('|')
|
||||
output = str.strip(fields[1]) + " " + str.strip(fields[3]) + " " + os.path.basename(str.strip(fields[4]))
|
||||
else:
|
||||
output = "No image mounted!"
|
||||
draw.text((x, y_pos), output, font=font, fill=255)
|
||||
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
|
||||
draw.text((x, y_pos), datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"), font=font, fill=255)
|
||||
|
||||
# Display image.
|
||||
disp.image(image)
|
||||
disp.display()
|
||||
oled.image(image)
|
||||
oled.show()
|
||||
time.sleep(1/delay_time_ms)
|
||||
|
|
14
src/oled_monitor/requirements.txt
Normal file
14
src/oled_monitor/requirements.txt
Normal 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
76
src/oled_monitor/start.sh
Executable 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
|
2
src/raspberrypi/.vscode/launch.json
vendored
2
src/raspberrypi/.vscode/launch.json
vendored
|
@ -26,4 +26,4 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
2
src/raspberrypi/.vscode/tasks.json
vendored
2
src/raspberrypi/.vscode/tasks.json
vendored
|
@ -16,4 +16,4 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,6 @@ SRC_RASCSI = \
|
|||
gpiobus.cpp \
|
||||
filepath.cpp \
|
||||
fileio.cpp\
|
||||
os.cpp\
|
||||
rascsi_version.cpp
|
||||
# os.cpp
|
||||
# rasctl_command.cpp
|
||||
|
@ -152,7 +151,7 @@ ALL: all
|
|||
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt
|
||||
|
||||
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread -lz
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread -lz -lpcap
|
||||
|
||||
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SASI device controller ]
|
||||
// [ SASI device controller ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "controllers/sasidev_ctrl.h"
|
||||
|
@ -39,10 +39,10 @@ SASIDEV::SASIDEV(Device *dev)
|
|||
{
|
||||
int i;
|
||||
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Remember host device
|
||||
host = dev;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Work initialization
|
||||
ctrl.phase = BUS::busfree;
|
||||
|
@ -51,10 +51,10 @@ SASIDEV::SASIDEV(Device *dev)
|
|||
memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd));
|
||||
ctrl.status = 0x00;
|
||||
ctrl.message = 0x00;
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
ctrl.execstart = 0;
|
||||
#endif // RASCSI
|
||||
ctrl.bufsize = ETH_FRAME_LEN + 16 + ETH_FCS_LEN;
|
||||
ctrl.bufsize = std::max(0x800, ETH_FRAME_LEN + 16 + ETH_FCS_LEN);
|
||||
ctrl.buffer = (BYTE *)malloc(ctrl.bufsize);
|
||||
memset(ctrl.buffer, 0x00, ctrl.bufsize);
|
||||
ctrl.blocks = 0;
|
||||
|
@ -98,9 +98,9 @@ void FASTCALL SASIDEV::Reset()
|
|||
ctrl.phase = BUS::busfree;
|
||||
ctrl.status = 0x00;
|
||||
ctrl.message = 0x00;
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
ctrl.execstart = 0;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
memset(ctrl.buffer, 0x00, ctrl.bufsize);
|
||||
ctrl.blocks = 0;
|
||||
ctrl.next = 0;
|
||||
|
@ -442,10 +442,10 @@ void FASTCALL SASIDEV::Selection()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::Command()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
int count;
|
||||
int i;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
ASSERT(this);
|
||||
|
||||
|
@ -467,7 +467,7 @@ void FASTCALL SASIDEV::Command()
|
|||
ctrl.length = 6;
|
||||
ctrl.blocks = 1;
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Command reception handshake (10 bytes are automatically received at the first command)
|
||||
count = ctrl.bus->CommandHandShake(ctrl.buffer);
|
||||
|
||||
|
@ -499,13 +499,13 @@ void FASTCALL SASIDEV::Command()
|
|||
|
||||
// Execution Phase
|
||||
Execute();
|
||||
#else
|
||||
#else
|
||||
// Request the command
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
return;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Requesting
|
||||
if (ctrl.bus->GetREQ()) {
|
||||
// Sent by the initiator
|
||||
|
@ -518,7 +518,7 @@ void FASTCALL SASIDEV::Command()
|
|||
ReceiveNext();
|
||||
}
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -538,9 +538,9 @@ void FASTCALL SASIDEV::Execute()
|
|||
// Initialization for data transfer
|
||||
ctrl.offset = 0;
|
||||
ctrl.blocks = 1;
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
ctrl.execstart = SysTimer::GetTimerLow();
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Process by command
|
||||
switch ((SCSIDEV::scsi_command)ctrl.cmd[0]) {
|
||||
|
@ -593,6 +593,16 @@ void FASTCALL SASIDEV::Execute()
|
|||
CmdAssign();
|
||||
return;
|
||||
|
||||
// RESERVE UNIT(16)
|
||||
case 0x16:
|
||||
CmdReserveUnit();
|
||||
return;
|
||||
|
||||
// RELEASE UNIT(17)
|
||||
case 0x17:
|
||||
CmdReleaseUnit();
|
||||
return;
|
||||
|
||||
// SPECIFY(SASIのみ)
|
||||
// This doesn't exist in the SCSI Spec, but was in the original RaSCSI code.
|
||||
// leaving it here for now....
|
||||
|
@ -615,17 +625,17 @@ void FASTCALL SASIDEV::Execute()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::Status()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
DWORD min_exec_time;
|
||||
DWORD time;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
ASSERT(this);
|
||||
|
||||
// Phase change
|
||||
if (ctrl.phase != BUS::status) {
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Minimum execution time
|
||||
if (ctrl.execstart > 0) {
|
||||
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
|
||||
|
@ -637,7 +647,7 @@ void FASTCALL SASIDEV::Status()
|
|||
} else {
|
||||
SysTimer::SleepUsec(5);
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
LOGTRACE("%s Status phase", __PRETTY_FUNCTION__);
|
||||
|
||||
|
@ -655,7 +665,7 @@ void FASTCALL SASIDEV::Status()
|
|||
ctrl.blocks = 1;
|
||||
ctrl.buffer[0] = (BYTE)ctrl.status;
|
||||
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Request status
|
||||
ctrl.bus->SetDAT(ctrl.buffer[0]);
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
|
@ -665,10 +675,10 @@ void FASTCALL SASIDEV::Status()
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Send
|
||||
Send();
|
||||
#else
|
||||
#else
|
||||
// Requesting
|
||||
if (ctrl.bus->GetREQ()) {
|
||||
// Initiator received
|
||||
|
@ -681,7 +691,7 @@ void FASTCALL SASIDEV::Status()
|
|||
Send();
|
||||
}
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -724,10 +734,10 @@ void FASTCALL SASIDEV::MsgIn()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::DataIn()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
DWORD min_exec_time;
|
||||
DWORD time;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
ASSERT(this);
|
||||
ASSERT(ctrl.length >= 0);
|
||||
|
@ -735,7 +745,7 @@ void FASTCALL SASIDEV::DataIn()
|
|||
// Phase change
|
||||
if (ctrl.phase != BUS::datain) {
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Minimum execution time
|
||||
if (ctrl.execstart > 0) {
|
||||
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
|
||||
|
@ -745,7 +755,7 @@ void FASTCALL SASIDEV::DataIn()
|
|||
}
|
||||
ctrl.execstart = 0;
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// If the length is 0, go to the status phase
|
||||
if (ctrl.length == 0) {
|
||||
|
@ -781,10 +791,10 @@ void FASTCALL SASIDEV::DataIn()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::DataOut()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
DWORD min_exec_time;
|
||||
DWORD time;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
ASSERT(this);
|
||||
ASSERT(ctrl.length >= 0);
|
||||
|
@ -792,7 +802,7 @@ void FASTCALL SASIDEV::DataOut()
|
|||
// Phase change
|
||||
if (ctrl.phase != BUS::dataout) {
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Minimum execution time
|
||||
if (ctrl.execstart > 0) {
|
||||
min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
|
||||
|
@ -802,7 +812,7 @@ void FASTCALL SASIDEV::DataOut()
|
|||
}
|
||||
ctrl.execstart = 0;
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// If the length is 0, go to the status phase
|
||||
if (ctrl.length == 0) {
|
||||
|
@ -825,17 +835,17 @@ void FASTCALL SASIDEV::DataOut()
|
|||
ASSERT(ctrl.blocks > 0);
|
||||
ctrl.offset = 0;
|
||||
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Request data
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Receive
|
||||
Receive();
|
||||
#else
|
||||
#else
|
||||
// Requesting
|
||||
if (ctrl.bus->GetREQ()) {
|
||||
// Sent by the initiator
|
||||
|
@ -848,7 +858,7 @@ void FASTCALL SASIDEV::DataOut()
|
|||
ReceiveNext();
|
||||
}
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1057,6 +1067,44 @@ void FASTCALL SASIDEV::CmdReassign()
|
|||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RESERVE UNIT(16)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::CmdReserveUnit()
|
||||
{
|
||||
ASSERT(this);
|
||||
LOGTRACE( "%s Reserve(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RELEASE UNIT(17)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::CmdReleaseUnit()
|
||||
{
|
||||
ASSERT(this);
|
||||
LOGTRACE( "%s Release(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// READ(6)
|
||||
|
@ -1373,9 +1421,9 @@ void FASTCALL SASIDEV::CmdInvalid()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SASIDEV::Send()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
int len;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
BOOL result;
|
||||
|
||||
ASSERT(this);
|
||||
|
@ -1385,7 +1433,7 @@ void FASTCALL SASIDEV::Send()
|
|||
// Check that the length isn't 0
|
||||
if (ctrl.length != 0) {
|
||||
len = ctrl.bus->SendHandShake(
|
||||
&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||
&ctrl.buffer[ctrl.offset], ctrl.length, BUS::SEND_NO_DELAY);
|
||||
|
||||
// If you can not send it all, move on to the status phase
|
||||
if (len != (int)ctrl.length) {
|
||||
|
@ -1416,7 +1464,7 @@ void FASTCALL SASIDEV::Send()
|
|||
LOGTRACE("%s processing after data collection", __PRETTY_FUNCTION__);
|
||||
#ifndef RASCSI
|
||||
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1431,10 +1479,10 @@ void FASTCALL SASIDEV::Send()
|
|||
if (ctrl.blocks != 0){
|
||||
ASSERT(ctrl.length > 0);
|
||||
ASSERT(ctrl.offset == 0);
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Signal line operated by the target
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1558,9 +1606,9 @@ void FASTCALL SASIDEV::Receive()
|
|||
void FASTCALL SASIDEV::ReceiveNext()
|
||||
#endif // RASCSI
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
int len;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
BOOL result;
|
||||
|
||||
ASSERT(this);
|
||||
|
@ -1569,7 +1617,7 @@ void FASTCALL SASIDEV::ReceiveNext()
|
|||
ASSERT(!ctrl.bus->GetREQ());
|
||||
ASSERT(!ctrl.bus->GetIO());
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Length != 0 if received
|
||||
if (ctrl.length != 0) {
|
||||
// Receive
|
||||
|
@ -1604,7 +1652,7 @@ void FASTCALL SASIDEV::ReceiveNext()
|
|||
ctrl.bus->SetREQ(TRUE);
|
||||
return;
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Remove the control block and initialize the result
|
||||
ctrl.blocks--;
|
||||
|
@ -1631,22 +1679,22 @@ void FASTCALL SASIDEV::ReceiveNext()
|
|||
if (ctrl.blocks != 0){
|
||||
ASSERT(ctrl.length > 0);
|
||||
ASSERT(ctrl.offset == 0);
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Signal line operated by the target
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to the next phase
|
||||
switch (ctrl.phase) {
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Command phase
|
||||
case BUS::command:
|
||||
// Execution Phase
|
||||
Execute();
|
||||
break;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Data out phase
|
||||
case BUS::dataout:
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SASI device controller ]
|
||||
// [ SASI device controller ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -31,18 +31,17 @@
|
|||
class SASIDEV
|
||||
{
|
||||
public:
|
||||
// Maximum number of logical units
|
||||
enum {
|
||||
UnitMax = 8
|
||||
UnitMax = 8 // Maximum number of logical units
|
||||
};
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// For timing adjustments
|
||||
enum {
|
||||
enum {
|
||||
min_exec_time_sasi = 100, // SASI BOOT/FORMAT 30:NG 35:OK
|
||||
min_exec_time_scsi = 50
|
||||
};
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Internal data definition
|
||||
typedef struct {
|
||||
|
@ -56,154 +55,113 @@ public:
|
|||
DWORD status; // Status data
|
||||
DWORD message; // Message data
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
// Run
|
||||
DWORD execstart; // Execution start time
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Transfer
|
||||
BYTE *buffer; // Transfer data buffer
|
||||
int bufsize; // Transfer data buffer size
|
||||
DWORD blocks; // Number of transfer block
|
||||
DWORD next; // Next record
|
||||
DWORD next; // Next record
|
||||
DWORD offset; // Transfer offset
|
||||
DWORD length; // Transfer remaining length
|
||||
|
||||
// Logical unit
|
||||
Disk *unit[UnitMax];
|
||||
// Logical Unit
|
||||
Disk *unit[UnitMax]; // Logical Unit
|
||||
} ctrl_t;
|
||||
|
||||
public:
|
||||
// Basic Functions
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
SASIDEV();
|
||||
#else
|
||||
SASIDEV(Device *dev);
|
||||
#endif //RASCSI
|
||||
#else
|
||||
|
||||
// Constructor
|
||||
virtual ~SASIDEV();
|
||||
// Destructor
|
||||
virtual void FASTCALL Reset();
|
||||
// Device Reset
|
||||
#ifndef RASCSI
|
||||
virtual BOOL FASTCALL Save(Fileio *fio, int ver);
|
||||
// Save
|
||||
virtual BOOL FASTCALL Load(Fileio *fio, int ver);
|
||||
// Load
|
||||
#endif //RASCSI
|
||||
SASIDEV(Device *dev); // Constructor
|
||||
|
||||
#endif //RASCSI
|
||||
virtual ~SASIDEV(); // Destructor
|
||||
virtual void FASTCALL Reset(); // Device Reset
|
||||
|
||||
#ifndef RASCSI
|
||||
virtual BOOL FASTCALL Save(Fileio *fio, int ver); // Save
|
||||
virtual BOOL FASTCALL Load(Fileio *fio, int ver); // Load
|
||||
#endif //RASCSI
|
||||
|
||||
// External API
|
||||
virtual BUS::phase_t FASTCALL Process();
|
||||
// Run
|
||||
virtual BUS::phase_t FASTCALL Process(); // Run
|
||||
|
||||
// Connect
|
||||
void FASTCALL Connect(int id, BUS *sbus);
|
||||
// Controller connection
|
||||
Disk* FASTCALL GetUnit(int no);
|
||||
// Get logical unit
|
||||
void FASTCALL SetUnit(int no, Disk *dev);
|
||||
// Logical unit setting
|
||||
BOOL FASTCALL HasUnit();
|
||||
// Has a valid logical unit
|
||||
void FASTCALL Connect(int id, BUS *sbus); // Controller connection
|
||||
Disk* FASTCALL GetUnit(int no); // Get logical unit
|
||||
void FASTCALL SetUnit(int no, Disk *dev); // Logical unit setting
|
||||
BOOL FASTCALL HasUnit(); // Has a valid logical unit
|
||||
|
||||
// Other
|
||||
BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;}
|
||||
// Get the phase
|
||||
#ifdef DISK_LOG
|
||||
// Function to get the current phase as a String.
|
||||
void FASTCALL GetPhaseStr(char *str);
|
||||
#endif
|
||||
BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} // Get the phase
|
||||
#ifdef DISK_LOG
|
||||
|
||||
int FASTCALL GetSCSIID() {return ctrl.m_scsi_id;}
|
||||
// Get the ID
|
||||
void FASTCALL GetCTRL(ctrl_t *buffer);
|
||||
// Get the internal information
|
||||
ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; }
|
||||
// Get the internal information address
|
||||
virtual BOOL FASTCALL IsSASI() const {return TRUE;}
|
||||
// SASI Check
|
||||
virtual BOOL FASTCALL IsSCSI() const {return FALSE;}
|
||||
// SCSI check
|
||||
Disk* FASTCALL GetBusyUnit();
|
||||
// Get the busy unit
|
||||
// Function to get the current phase as a String.
|
||||
void FASTCALL GetPhaseStr(char *str);
|
||||
#endif
|
||||
|
||||
int FASTCALL GetSCSIID() {return ctrl.m_scsi_id;} // Get the ID
|
||||
void FASTCALL GetCTRL(ctrl_t *buffer); // Get the internal information
|
||||
ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } // Get the internal information address
|
||||
virtual BOOL FASTCALL IsSASI() const {return TRUE;} // SASI Check
|
||||
virtual BOOL FASTCALL IsSCSI() const {return FALSE;} // SCSI check
|
||||
Disk* FASTCALL GetBusyUnit(); // Get the busy unit
|
||||
|
||||
protected:
|
||||
// Phase processing
|
||||
virtual void FASTCALL BusFree();
|
||||
// Bus free phase
|
||||
virtual void FASTCALL Selection();
|
||||
// Selection phase
|
||||
virtual void FASTCALL Command();
|
||||
// Command phase
|
||||
virtual void FASTCALL Execute();
|
||||
// Execution phase
|
||||
void FASTCALL Status();
|
||||
// Status phase
|
||||
void FASTCALL MsgIn();
|
||||
// Message in phase
|
||||
void FASTCALL DataIn();
|
||||
// Data in phase
|
||||
void FASTCALL DataOut();
|
||||
// Data out phase
|
||||
virtual void FASTCALL Error();
|
||||
// Common error handling
|
||||
virtual void FASTCALL BusFree(); // Bus free phase
|
||||
virtual void FASTCALL Selection(); // Selection phase
|
||||
virtual void FASTCALL Command(); // Command phase
|
||||
virtual void FASTCALL Execute(); // Execution phase
|
||||
void FASTCALL Status(); // Status phase
|
||||
void FASTCALL MsgIn(); // Message in phase
|
||||
void FASTCALL DataIn(); // Data in phase
|
||||
void FASTCALL DataOut(); // Data out phase
|
||||
virtual void FASTCALL Error(); // Common error handling
|
||||
|
||||
// commands
|
||||
void FASTCALL CmdTestUnitReady();
|
||||
// TEST UNIT READY command
|
||||
void FASTCALL CmdRezero();
|
||||
// REZERO UNIT command
|
||||
void FASTCALL CmdRequestSense();
|
||||
// REQUEST SENSE command
|
||||
void FASTCALL CmdFormat();
|
||||
// FORMAT command
|
||||
void FASTCALL CmdReassign();
|
||||
// REASSIGN BLOCKS command
|
||||
virtual void FASTCALL CmdRead6();
|
||||
// READ(6) command
|
||||
virtual void FASTCALL CmdWrite6();
|
||||
// WRITE(6) command
|
||||
void FASTCALL CmdSeek6();
|
||||
// SEEK(6) command
|
||||
void FASTCALL CmdAssign();
|
||||
// ASSIGN command
|
||||
void FASTCALL CmdSpecify();
|
||||
// SPECIFY command
|
||||
void FASTCALL CmdInvalid();
|
||||
// Unsupported command
|
||||
void FASTCALL DaynaPortWrite();
|
||||
// DaynaPort specific 'write' operation
|
||||
|
||||
void FASTCALL CmdTestUnitReady(); // TEST UNIT READY command
|
||||
void FASTCALL CmdRezero(); // REZERO UNIT command
|
||||
void FASTCALL CmdRequestSense(); // REQUEST SENSE command
|
||||
void FASTCALL CmdFormat(); // FORMAT command
|
||||
void FASTCALL CmdReassign(); // REASSIGN BLOCKS command
|
||||
void FASTCALL CmdReserveUnit(); // RESERVE UNIT command
|
||||
void FASTCALL CmdReleaseUnit(); // RELEASE UNIT command
|
||||
void FASTCALL CmdRead6(); // READ(6) command
|
||||
void FASTCALL CmdWrite6(); // WRITE(6) command
|
||||
void FASTCALL CmdSeek6(); // SEEK(6) command
|
||||
void FASTCALL CmdAssign(); // ASSIGN command
|
||||
void FASTCALL CmdSpecify(); // SPECIFY command
|
||||
void FASTCALL CmdInvalid(); // Unsupported command
|
||||
void FASTCALL DaynaPortWrite(); // DaynaPort specific 'write' operation
|
||||
// データ転送
|
||||
virtual void FASTCALL Send();
|
||||
// Send data
|
||||
#ifndef RASCSI
|
||||
virtual void FASTCALL SendNext();
|
||||
// Continue sending data
|
||||
#endif // RASCSI
|
||||
virtual void FASTCALL Receive();
|
||||
// Receive data
|
||||
#ifndef RASCSI
|
||||
virtual void FASTCALL ReceiveNext();
|
||||
// Continue receiving data
|
||||
#endif // RASCSI
|
||||
BOOL FASTCALL XferIn(BYTE* buf);
|
||||
// Data transfer IN
|
||||
BOOL FASTCALL XferOut(BOOL cont);
|
||||
// Data transfer OUT
|
||||
virtual void FASTCALL Send(); // Send data
|
||||
|
||||
#ifndef RASCSI
|
||||
virtual void FASTCALL SendNext(); // Continue sending data
|
||||
#endif // RASCSI
|
||||
|
||||
virtual void FASTCALL Receive(); // Receive data
|
||||
|
||||
#ifndef RASCSI
|
||||
virtual void FASTCALL ReceiveNext(); // Continue receiving data
|
||||
#endif // RASCSI
|
||||
|
||||
BOOL FASTCALL XferIn(BYTE* buf); // Data transfer IN
|
||||
BOOL FASTCALL XferOut(BOOL cont); // Data transfer OUT
|
||||
|
||||
// Special operations
|
||||
void FASTCALL FlushUnit();
|
||||
// Flush the logical unit
|
||||
void FASTCALL FlushUnit(); // Flush the logical unit
|
||||
|
||||
protected:
|
||||
#ifndef RASCSI
|
||||
Device *host;
|
||||
// Host device
|
||||
#endif // RASCSI
|
||||
|
||||
ctrl_t ctrl;
|
||||
// Internal data
|
||||
#ifndef RASCSI
|
||||
Device *host; // Host device
|
||||
#endif // RASCSI
|
||||
ctrl_t ctrl; // Internal data
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI device controller ]
|
||||
// [ SCSI device controller ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "log.h"
|
||||
|
@ -250,9 +250,9 @@ void FASTCALL SCSIDEV::Execute()
|
|||
// Initialization for data transfer
|
||||
ctrl.offset = 0;
|
||||
ctrl.blocks = 1;
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
ctrl.execstart = SysTimer::GetTimerLow();
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Process by command
|
||||
switch ((scsi_command)ctrl.cmd[0]) {
|
||||
|
@ -333,6 +333,30 @@ void FASTCALL SCSIDEV::Execute()
|
|||
CmdModeSelect();
|
||||
return;
|
||||
|
||||
// RESERVE(6)
|
||||
case eCmdReserve6:
|
||||
LOGDEBUG("++++ CMD ++++ %s Received eCmdReserve6", __PRETTY_FUNCTION__);
|
||||
CmdReserve6();
|
||||
return;
|
||||
|
||||
// RESERVE(10)
|
||||
case eCmdReserve10:
|
||||
LOGDEBUG("++++ CMD ++++ %s Received eCmdReserve10", __PRETTY_FUNCTION__);
|
||||
CmdReserve10();
|
||||
return;
|
||||
|
||||
// RELEASE(6)
|
||||
case eCmdRelease6:
|
||||
LOGDEBUG("++++ CMD ++++ %s Received eCmdRelease6", __PRETTY_FUNCTION__);
|
||||
CmdRelease6();
|
||||
return;
|
||||
|
||||
// RELEASE(10)
|
||||
case eCmdRelease10:
|
||||
LOGDEBUG("++++ CMD ++++ %s Received eCmdRelease10", __PRETTY_FUNCTION__);
|
||||
CmdRelease10();
|
||||
return;
|
||||
|
||||
// MODE SENSE
|
||||
case eCmdModeSense:
|
||||
LOGDEBUG("++++ CMD ++++ %s Received eCmdModeSense", __PRETTY_FUNCTION__);
|
||||
|
@ -454,8 +478,7 @@ void FASTCALL SCSIDEV::MsgOut()
|
|||
|
||||
LOGTRACE("Message Out Phase");
|
||||
|
||||
// Message out phase after selection
|
||||
// process the IDENTIFY message
|
||||
// process the IDENTIFY message
|
||||
if (ctrl.phase == BUS::selection) {
|
||||
scsi.atnmsg = TRUE;
|
||||
scsi.msc = 0;
|
||||
|
@ -475,10 +498,10 @@ void FASTCALL SCSIDEV::MsgOut()
|
|||
ctrl.length = 1;
|
||||
ctrl.blocks = 1;
|
||||
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Request message
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -613,6 +636,83 @@ void FASTCALL SCSIDEV::CmdModeSelect()
|
|||
DataOut();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RESERVE(6)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SCSIDEV::CmdReserve6()
|
||||
{
|
||||
ASSERT(this);
|
||||
|
||||
LOGTRACE( "%s Reserve(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RESERVE(10)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SCSIDEV::CmdReserve10()
|
||||
{
|
||||
ASSERT(this);
|
||||
LOGTRACE( "%s Reserve(10) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RELEASE(6)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SCSIDEV::CmdRelease6()
|
||||
{
|
||||
ASSERT(this);
|
||||
LOGTRACE( "%s Release(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RELEASE(10)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SCSIDEV::CmdRelease10()
|
||||
{
|
||||
ASSERT(this);
|
||||
LOGTRACE( "%s Release(10) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// MODE SENSE
|
||||
|
@ -1038,7 +1138,6 @@ void FASTCALL SCSIDEV::CmdSynchronizeCache()
|
|||
void FASTCALL SCSIDEV::CmdReadDefectData10()
|
||||
{
|
||||
DWORD lun;
|
||||
|
||||
ASSERT(this);
|
||||
|
||||
LOGTRACE( "%s READ DEFECT DATA(10) Command ", __PRETTY_FUNCTION__);
|
||||
|
@ -1071,7 +1170,6 @@ void FASTCALL SCSIDEV::CmdReadDefectData10()
|
|||
void FASTCALL SCSIDEV::CmdReadToc()
|
||||
{
|
||||
DWORD lun;
|
||||
|
||||
ASSERT(this);
|
||||
|
||||
// Logical Unit
|
||||
|
@ -1553,21 +1651,32 @@ void FASTCALL SCSIDEV::CmdEnableInterface()
|
|||
//---------------------------------------------------------------------------
|
||||
void FASTCALL SCSIDEV::Send()
|
||||
{
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
int len;
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
BOOL result;
|
||||
|
||||
ASSERT(this);
|
||||
ASSERT(!ctrl.bus->GetREQ());
|
||||
ASSERT(ctrl.bus->GetIO());
|
||||
|
||||
#ifdef RASCSI
|
||||
#ifdef RASCSI
|
||||
//if Length! = 0, send
|
||||
if (ctrl.length != 0) {
|
||||
LOGTRACE("%s sending handhake with offset %lu, length %lu", __PRETTY_FUNCTION__, ctrl.offset, ctrl.length);
|
||||
len = ctrl.bus->SendHandShake(
|
||||
&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||
|
||||
// The Daynaport needs to have a delay after the size/flags field
|
||||
// of the read response. In the MacOS driver, it looks like the
|
||||
// driver is doing two "READ" system calls.
|
||||
if (ctrl.unit[0]->GetID() == MAKEID('S', 'C', 'D', 'P')) {
|
||||
len = ((GPIOBUS*)ctrl.bus)->SendHandShake(
|
||||
&ctrl.buffer[ctrl.offset], ctrl.length, SCSIDaynaPort::DAYNAPORT_READ_HEADER_SZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ctrl.bus->SendHandShake(
|
||||
&ctrl.buffer[ctrl.offset], ctrl.length, BUS::SEND_NO_DELAY);
|
||||
}
|
||||
|
||||
// If you cannot send all, move to status phase
|
||||
if (len != (int)ctrl.length) {
|
||||
|
@ -1580,20 +1689,20 @@ void FASTCALL SCSIDEV::Send()
|
|||
ctrl.length = 0;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
// offset and length
|
||||
ASSERT(ctrl.length >= 1);
|
||||
ctrl.offset++;
|
||||
ctrl.length--;
|
||||
|
||||
// Immediately after ACK is asserted, if the data has been
|
||||
// set by SendNext, raise the request
|
||||
if (ctrl.length != 0) {
|
||||
// set by SendNext, raise the request
|
||||
if (ctrl.length != 0) {
|
||||
// Signal line operated by the target
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
return;
|
||||
}
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
|
||||
// Block subtraction, result initialization
|
||||
ctrl.blocks--;
|
||||
|
@ -1602,12 +1711,12 @@ void FASTCALL SCSIDEV::Send()
|
|||
// Processing after data collection (read/data-in only)
|
||||
if (ctrl.phase == BUS::datain) {
|
||||
if (ctrl.blocks != 0) {
|
||||
// // set next buffer (set offset, length)
|
||||
// set next buffer (set offset, length)
|
||||
result = XferIn(ctrl.buffer);
|
||||
LOGTRACE("%s processing after data collection. Blocks: %lu", __PRETTY_FUNCTION__, ctrl.blocks);
|
||||
#ifndef RASCSI
|
||||
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1622,10 +1731,10 @@ void FASTCALL SCSIDEV::Send()
|
|||
LOGTRACE("%s Continuing to send. blocks = %lu", __PRETTY_FUNCTION__, ctrl.blocks);
|
||||
ASSERT(ctrl.length > 0);
|
||||
ASSERT(ctrl.offset == 0);
|
||||
#ifndef RASCSI
|
||||
#ifndef RASCSI
|
||||
// Signal line operated by the target
|
||||
ctrl.bus->SetREQ(TRUE);
|
||||
#endif // RASCSI
|
||||
#endif // RASCSI
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1918,6 @@ void FASTCALL SCSIDEV::Receive()
|
|||
ctrl.offset = 0;
|
||||
ctrl.length = 1;
|
||||
ctrl.blocks = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI device controller ]
|
||||
// [ SCSI device controller ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -80,6 +80,8 @@ public:
|
|||
eCmdEnableInterface = 0x0E, // DaynaPort specific command
|
||||
eCmdInquiry = 0x12,
|
||||
eCmdModeSelect = 0x15,
|
||||
eCmdReserve6 = 0x16,
|
||||
eCmdRelease6 = 0x17,
|
||||
eCmdModeSense = 0x1A,
|
||||
eCmdStartStop = 0x1B,
|
||||
eCmdRcvDiag = 0x1C,
|
||||
|
@ -98,6 +100,8 @@ public:
|
|||
eCmdPlayAudioMSF = 0x47,
|
||||
eCmdPlayAudioTrack = 0x48,
|
||||
eCmdModeSelect10 = 0x55,
|
||||
eCmdReserve10 = 0x56,
|
||||
eCmdRelease10 = 0x57,
|
||||
eCmdModeSense10 = 0x5A,
|
||||
eCmdInvalid = 0xC2, // (SASI only/Suppress warning when using SxSI)
|
||||
eCmdSasiCmdAssign = 0x0e, // This isn't used by SCSI, and can probably be removed.
|
||||
|
@ -108,104 +112,66 @@ public:
|
|||
SCSIDEV();
|
||||
// Constructor
|
||||
|
||||
void FASTCALL Reset();
|
||||
// Device Reset
|
||||
void FASTCALL Reset(); // Device Reset
|
||||
|
||||
// 外部API
|
||||
BUS::phase_t FASTCALL Process();
|
||||
// Run
|
||||
BUS::phase_t FASTCALL Process(); // Run
|
||||
|
||||
void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; }
|
||||
// Synchronouse transfer enable setting
|
||||
void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } // Synchronouse transfer enable setting
|
||||
|
||||
// Other
|
||||
BOOL FASTCALL IsSASI() const {return FALSE;}
|
||||
// SASI Check
|
||||
BOOL FASTCALL IsSCSI() const {return TRUE;}
|
||||
// SCSI check
|
||||
BOOL FASTCALL IsSASI() const {return FALSE;} // SASI Check
|
||||
BOOL FASTCALL IsSCSI() const {return TRUE;} // SCSI check
|
||||
|
||||
private:
|
||||
// Phase
|
||||
void FASTCALL BusFree();
|
||||
// Bus free phase
|
||||
void FASTCALL Selection();
|
||||
// Selection phase
|
||||
void FASTCALL Execute();
|
||||
// Execution phase
|
||||
void FASTCALL MsgOut();
|
||||
// Message out phase
|
||||
void FASTCALL Error();
|
||||
// Common erorr handling
|
||||
void FASTCALL BusFree(); // Bus free phase
|
||||
void FASTCALL Selection(); // Selection phase
|
||||
void FASTCALL Execute(); // Execution phase
|
||||
void FASTCALL MsgOut(); // Message out phase
|
||||
void FASTCALL Error(); // Common erorr handling
|
||||
|
||||
// commands
|
||||
void FASTCALL CmdInquiry();
|
||||
// INQUIRY command
|
||||
void FASTCALL CmdModeSelect();
|
||||
// MODE SELECT command
|
||||
void FASTCALL CmdModeSense();
|
||||
// MODE SENSE command
|
||||
void FASTCALL CmdStartStop();
|
||||
// START STOP UNIT command
|
||||
void FASTCALL CmdSendDiag();
|
||||
// SEND DIAGNOSTIC command
|
||||
void FASTCALL CmdRemoval();
|
||||
// PREVENT/ALLOW MEDIUM REMOVAL command
|
||||
void FASTCALL CmdReadCapacity();
|
||||
// READ CAPACITY command
|
||||
void FASTCALL CmdRead10();
|
||||
// READ(10) command
|
||||
void FASTCALL CmdWrite10();
|
||||
// WRITE(10) command
|
||||
void FASTCALL CmdSeek10();
|
||||
// SEEK(10) command
|
||||
void FASTCALL CmdVerify();
|
||||
// VERIFY command
|
||||
void FASTCALL CmdSynchronizeCache();
|
||||
// SYNCHRONIZE CACHE command
|
||||
void FASTCALL CmdReadDefectData10();
|
||||
// READ DEFECT DATA(10) command
|
||||
void FASTCALL CmdReadToc();
|
||||
// READ TOC command
|
||||
void FASTCALL CmdPlayAudio10();
|
||||
// PLAY AUDIO(10) command
|
||||
void FASTCALL CmdPlayAudioMSF();
|
||||
// PLAY AUDIO MSF command
|
||||
void FASTCALL CmdPlayAudioTrack();
|
||||
// PLAY AUDIO TRACK INDEX command
|
||||
void FASTCALL CmdModeSelect10();
|
||||
// MODE SELECT(10) command
|
||||
void FASTCALL CmdModeSense10();
|
||||
// MODE SENSE(10) command
|
||||
void FASTCALL CmdGetMessage10();
|
||||
// GET MESSAGE(10) command
|
||||
void FASTCALL CmdSendMessage10();
|
||||
// SEND MESSAGE(10) command
|
||||
void FASTCALL CmdRetrieveStats();
|
||||
// DaynaPort specific command
|
||||
void FASTCALL CmdSetIfaceMode();
|
||||
// DaynaPort specific command
|
||||
void FASTCALL CmdSetMcastAddr();
|
||||
// DaynaPort specific command
|
||||
void FASTCALL CmdEnableInterface();
|
||||
// DaynaPort specific command
|
||||
void FASTCALL CmdInquiry(); // INQUIRY command
|
||||
void FASTCALL CmdModeSelect(); // MODE SELECT command
|
||||
void FASTCALL CmdReserve6(); // RESERVE(6) command
|
||||
void FASTCALL CmdReserve10(); // RESERVE(10) command
|
||||
void FASTCALL CmdRelease6(); // RELEASE(6) command
|
||||
void FASTCALL CmdRelease10(); // RELEASE(10) command
|
||||
void FASTCALL CmdModeSense(); // MODE SENSE command
|
||||
void FASTCALL CmdStartStop(); // START STOP UNIT command
|
||||
void FASTCALL CmdSendDiag(); // SEND DIAGNOSTIC command
|
||||
void FASTCALL CmdRemoval(); // PREVENT/ALLOW MEDIUM REMOVAL command
|
||||
void FASTCALL CmdReadCapacity(); // READ CAPACITY command
|
||||
void FASTCALL CmdRead10(); // READ(10) command
|
||||
void FASTCALL CmdWrite10(); // WRITE(10) command
|
||||
void FASTCALL CmdSeek10(); // SEEK(10) command
|
||||
void FASTCALL CmdVerify(); // VERIFY command
|
||||
void FASTCALL CmdSynchronizeCache(); // SYNCHRONIZE CACHE command
|
||||
void FASTCALL CmdReadDefectData10(); // READ DEFECT DATA(10) command
|
||||
void FASTCALL CmdReadToc(); // READ TOC command
|
||||
void FASTCALL CmdPlayAudio10(); // PLAY AUDIO(10) command
|
||||
void FASTCALL CmdPlayAudioMSF(); // PLAY AUDIO MSF command
|
||||
void FASTCALL CmdPlayAudioTrack(); // PLAY AUDIO TRACK INDEX command
|
||||
void FASTCALL CmdModeSelect10(); // MODE SELECT(10) command
|
||||
void FASTCALL CmdModeSense10(); // MODE SENSE(10) command
|
||||
void FASTCALL CmdGetMessage10(); // GET MESSAGE(10) command
|
||||
void FASTCALL CmdSendMessage10(); // SEND MESSAGE(10) command
|
||||
void FASTCALL CmdRetrieveStats(); // DaynaPort specific command
|
||||
void FASTCALL CmdSetIfaceMode(); // DaynaPort specific command
|
||||
void FASTCALL CmdSetMcastAddr(); // DaynaPort specific command
|
||||
void FASTCALL CmdEnableInterface(); // DaynaPort specific command
|
||||
// データ転送
|
||||
void FASTCALL Send(); // Send data
|
||||
#ifndef RASCSI
|
||||
void FASTCALL SendNext(); // Continue sending data
|
||||
#endif // RASCSI
|
||||
void FASTCALL Receive(); // Receive data
|
||||
#ifndef RASCSI
|
||||
void FASTCALL ReceiveNext(); // Continue receiving data
|
||||
#endif // RASCSI
|
||||
BOOL FASTCALL XferMsg(DWORD msg); // Data transfer message
|
||||
|
||||
// Data transfer
|
||||
void FASTCALL Send();
|
||||
// Send data
|
||||
#ifndef RASCSI
|
||||
void FASTCALL SendNext();
|
||||
// Continue sending data
|
||||
#endif // RASCSI
|
||||
void FASTCALL Receive();
|
||||
// Receive data
|
||||
#ifndef RASCSI
|
||||
void FASTCALL ReceiveNext();
|
||||
// Continue receiving data
|
||||
#endif // RASCSI
|
||||
BOOL FASTCALL XferMsg(DWORD msg);
|
||||
// Data transfer message
|
||||
|
||||
scsi_t scsi;
|
||||
// Internal data
|
||||
scsi_t scsi; // Internal data
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,12 +13,19 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#endif
|
||||
#include <zlib.h> // For crc32()
|
||||
#include "os.h"
|
||||
#include "xm6.h"
|
||||
#include "ctapdriver.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constructor
|
||||
|
@ -30,6 +37,8 @@ CTapDriver::CTapDriver()
|
|||
// Initialization
|
||||
m_hTAP = -1;
|
||||
memset(&m_MacAddr, 0, sizeof(m_MacAddr));
|
||||
m_pcap = NULL;
|
||||
m_pcap_dumper = NULL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -38,6 +47,43 @@ CTapDriver::CTapDriver()
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#ifdef __linux__
|
||||
|
||||
static BOOL br_setif(int br_socket_fd, const char* bridgename, const char* ifname, BOOL add) {
|
||||
struct ifreq ifr;
|
||||
ifr.ifr_ifindex = if_nametoindex(ifname);
|
||||
if (ifr.ifr_ifindex == 0) {
|
||||
LOGERROR("Error: can't if_nametoindex. Errno: %d %s", errno, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
strncpy(ifr.ifr_name, bridgename, IFNAMSIZ);
|
||||
if (ioctl(br_socket_fd, add ? SIOCBRADDIF : SIOCBRDELIF, &ifr) < 0) {
|
||||
LOGERROR("Error: can't ioctl %s. Errno: %d %s", add ? "SIOCBRADDIF" : "SIOCBRDELIF", errno, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL ip_link(int fd, const char* ifname, BOOL up) {
|
||||
struct ifreq ifr;
|
||||
int err;
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1); // Need to save room for null terminator
|
||||
err = ioctl(fd, SIOCGIFFLAGS, &ifr);
|
||||
if (err) {
|
||||
LOGERROR("Error: can't ioctl SIOCGIFFLAGS. Errno: %d %s", errno, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
ifr.ifr_flags &= ~IFF_UP;
|
||||
if (up) {
|
||||
ifr.ifr_flags |= IFF_UP;
|
||||
}
|
||||
err = ioctl(fd, SIOCSIFFLAGS, &ifr);
|
||||
if (err) {
|
||||
LOGERROR("Error: can't ioctl SIOCSIFFLAGS. Errno: %d %s", errno, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FASTCALL CTapDriver::Init()
|
||||
{
|
||||
LOGTRACE("%s",__PRETTY_FUNCTION__);
|
||||
|
@ -69,20 +115,78 @@ BOOL FASTCALL CTapDriver::Init()
|
|||
}
|
||||
LOGTRACE("return code from ioctl was %d", ret);
|
||||
|
||||
int ip_fd;
|
||||
if ((ip_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
LOGERROR("Error: can't open ip socket. Errno: %d %s", errno, strerror(errno));
|
||||
close(m_hTAP);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int br_socket_fd = -1;
|
||||
if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
|
||||
LOGERROR("Error: can't open bridge socket. Errno: %d %s", errno, strerror(errno));
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LOGTRACE("Going to see if the bridge is created");
|
||||
|
||||
// Check if the bridge is already created
|
||||
if (access("/sys/class/net/rascsi_bridge", F_OK) != 0) {
|
||||
LOGINFO("Creating the rascsi_bridge...");
|
||||
LOGDEBUG("brctl addbr rascsi_bridge");
|
||||
if ((ret = ioctl(br_socket_fd, SIOCBRADDBR, "rascsi_bridge")) < 0) {
|
||||
LOGERROR("Error: can't ioctl SIOCBRADDBR. Errno: %d %s", errno, strerror(errno));
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
LOGDEBUG("brctl addif rascsi_bridge eth0");
|
||||
if (!br_setif(br_socket_fd, "rascsi_bridge", "eth0", TRUE)) {
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
LOGDEBUG("ip link set dev rascsi_bridge up");
|
||||
if (!ip_link(ip_fd, "rascsi_bridge", TRUE)) {
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO("Note: rascsi_bridge already created");
|
||||
}
|
||||
|
||||
LOGDEBUG("ip link set ras0 up");
|
||||
ret = run_system_cmd("ip link set ras0 up");
|
||||
LOGTRACE("return code from ip link set ras0 up was %d", ret);
|
||||
|
||||
if (!ip_link(ip_fd, "ras0", TRUE)) {
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LOGDEBUG("brctl addif rascsi_bridge ras0");
|
||||
ret = run_system_cmd("brctl addif rascsi_bridge ras0");
|
||||
LOGTRACE("return code from brctl addif rascsi_bridge ras0 was %d", ret);
|
||||
|
||||
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", TRUE)) {
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get MAC address
|
||||
LOGTRACE("Getting the MAC address");
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) {
|
||||
LOGERROR("Error: can't ioctl SIOCGIFHWADDR. Errno: %d %s", errno, strerror(errno));
|
||||
close(m_hTAP);
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
return FALSE;
|
||||
}
|
||||
LOGTRACE("got the mac");
|
||||
|
@ -90,6 +194,10 @@ BOOL FASTCALL CTapDriver::Init()
|
|||
// Save MAC address
|
||||
memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr));
|
||||
LOGINFO("Tap device %s created", ifr.ifr_name);
|
||||
|
||||
close(ip_fd);
|
||||
close(br_socket_fd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif // __linux__
|
||||
|
@ -142,6 +250,22 @@ BOOL FASTCALL CTapDriver::Init()
|
|||
}
|
||||
#endif // __NetBSD__
|
||||
|
||||
BOOL FASTCALL CTapDriver::OpenDump(const Filepath& path) {
|
||||
if (m_pcap == NULL) {
|
||||
m_pcap = pcap_open_dead(DLT_EN10MB, 65535);
|
||||
}
|
||||
if (m_pcap_dumper != NULL) {
|
||||
pcap_dump_close(m_pcap_dumper);
|
||||
}
|
||||
m_pcap_dumper = pcap_dump_open(m_pcap, path.GetPath());
|
||||
if (m_pcap_dumper == NULL) {
|
||||
LOGERROR("Error: can't open pcap file: %s", pcap_geterr(m_pcap));
|
||||
return FALSE;
|
||||
}
|
||||
LOGTRACE("%s Opened %s for dumping", __PRETTY_FUNCTION__, path.GetPath());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Cleanup
|
||||
|
@ -150,13 +274,17 @@ BOOL FASTCALL CTapDriver::Init()
|
|||
void FASTCALL CTapDriver::Cleanup()
|
||||
{
|
||||
ASSERT(this);
|
||||
int result;
|
||||
|
||||
LOGDEBUG("brctl delif rascsi_bridge ras0");
|
||||
result = run_system_cmd("brctl delif rascsi_bridge ras0");
|
||||
if(result != EXIT_SUCCESS){
|
||||
LOGWARN("Warning: The brctl delif command failed.");
|
||||
LOGWARN("You may need to manually remove the ras0 tap device from the bridge");
|
||||
int br_socket_fd = -1;
|
||||
if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
|
||||
LOGERROR("Error: can't open bridge socket. Errno: %d %s", errno, strerror(errno));
|
||||
} else {
|
||||
LOGDEBUG("brctl delif rascsi_bridge ras0");
|
||||
if (!br_setif(br_socket_fd, "rascsi_bridge", "ras0", FALSE)) {
|
||||
LOGWARN("Warning: Removing ras0 from the bridge failed.");
|
||||
LOGWARN("You may need to manually remove the ras0 tap device from the bridge");
|
||||
}
|
||||
close(br_socket_fd);
|
||||
}
|
||||
|
||||
// Release TAP defice
|
||||
|
@ -164,6 +292,14 @@ void FASTCALL CTapDriver::Cleanup()
|
|||
close(m_hTAP);
|
||||
m_hTAP = -1;
|
||||
}
|
||||
|
||||
if (m_pcap_dumper != NULL) {
|
||||
pcap_dump_close(m_pcap_dumper);
|
||||
m_pcap_dumper = NULL;
|
||||
}
|
||||
if (m_pcap != NULL) {
|
||||
pcap_close(m_pcap);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -172,10 +308,11 @@ void FASTCALL CTapDriver::Cleanup()
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BOOL FASTCALL CTapDriver::Enable(){
|
||||
int result;
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
LOGDEBUG("%s: ip link set ras0 up", __PRETTY_FUNCTION__);
|
||||
result = run_system_cmd("ip link set ras0 up");
|
||||
return (result == EXIT_SUCCESS);
|
||||
BOOL result = ip_link(fd, "ras0", TRUE);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -184,10 +321,11 @@ BOOL FASTCALL CTapDriver::Enable(){
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BOOL FASTCALL CTapDriver::Disable(){
|
||||
int result;
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
LOGDEBUG("%s: ip link set ras0 down", __PRETTY_FUNCTION__);
|
||||
result = run_system_cmd("ip link set ras0 down");
|
||||
return (result == EXIT_SUCCESS);
|
||||
BOOL result = ip_link(fd, "ras0", FALSE);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -262,6 +400,7 @@ int FASTCALL CTapDriver::Rx(BYTE *buf)
|
|||
// Receive
|
||||
dwReceived = read(m_hTAP, buf, ETH_FRAME_LEN);
|
||||
if (dwReceived == (DWORD)-1) {
|
||||
LOGWARN("%s Error occured while receiving an packet", __PRETTY_FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -287,6 +426,16 @@ int FASTCALL CTapDriver::Rx(BYTE *buf)
|
|||
dwReceived += 4;
|
||||
}
|
||||
|
||||
if (m_pcap_dumper != NULL) {
|
||||
struct pcap_pkthdr h = {
|
||||
.caplen = dwReceived,
|
||||
.len = dwReceived,
|
||||
};
|
||||
gettimeofday(&h.ts, NULL);
|
||||
pcap_dump((u_char*)m_pcap_dumper, &h, buf);
|
||||
LOGTRACE("%s Dumped %d byte packet (first byte: %02x last byte: %02x)", __PRETTY_FUNCTION__, (unsigned int)dwReceived, buf[0], buf[dwReceived-1]);
|
||||
}
|
||||
|
||||
// Return the number of bytes
|
||||
return dwReceived;
|
||||
}
|
||||
|
@ -301,6 +450,16 @@ int FASTCALL CTapDriver::Tx(const BYTE *buf, int len)
|
|||
ASSERT(this);
|
||||
ASSERT(m_hTAP != -1);
|
||||
|
||||
if (m_pcap_dumper != NULL) {
|
||||
struct pcap_pkthdr h = {
|
||||
.caplen = (bpf_u_int32)len,
|
||||
.len = (bpf_u_int32)len,
|
||||
};
|
||||
gettimeofday(&h.ts, NULL);
|
||||
pcap_dump((u_char*)m_pcap_dumper, &h, buf);
|
||||
LOGTRACE("%s Dumped %d byte packet (first byte: %02x last byte: %02x)", __PRETTY_FUNCTION__, (unsigned int)h.len, buf[0], buf[h.len-1]);
|
||||
}
|
||||
|
||||
// Start sending
|
||||
return write(m_hTAP, buf, len);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#if !defined(ctapdriver_h)
|
||||
#define ctapdriver_h
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
#include "filepath.h"
|
||||
|
||||
#ifndef ETH_FRAME_LEN
|
||||
#define ETH_FRAME_LEN 1514
|
||||
#endif
|
||||
|
@ -29,35 +32,29 @@ class CTapDriver
|
|||
{
|
||||
public:
|
||||
// Basic Functionality
|
||||
CTapDriver();
|
||||
// Constructor
|
||||
BOOL FASTCALL Init();
|
||||
// Initilization
|
||||
void FASTCALL Cleanup();
|
||||
// Cleanup
|
||||
void FASTCALL GetMacAddr(BYTE *mac);
|
||||
// Get Mac Address
|
||||
int FASTCALL Rx(BYTE *buf);
|
||||
// Receive
|
||||
int FASTCALL Tx(const BYTE *buf, int len);
|
||||
// Send
|
||||
BOOL FASTCALL PendingPackets();
|
||||
// Check if there are IP packets available
|
||||
BOOL FASTCALL Enable();
|
||||
// Enable the ras0 interface
|
||||
BOOL FASTCALL Disable();
|
||||
// Disable the ras0 interface
|
||||
BOOL FASTCALL Flush();
|
||||
// Purge all of the packets that are waiting to be processed
|
||||
CTapDriver(); // Constructor
|
||||
BOOL FASTCALL Init(); // Initilization
|
||||
BOOL FASTCALL OpenDump(const Filepath& path);
|
||||
// Capture packets
|
||||
void FASTCALL Cleanup(); // Cleanup
|
||||
void FASTCALL GetMacAddr(BYTE *mac); // Get Mac Address
|
||||
int FASTCALL Rx(BYTE *buf); // Receive
|
||||
int FASTCALL Tx(const BYTE *buf, int len); // Send
|
||||
BOOL FASTCALL PendingPackets(); // Check if there are IP packets available
|
||||
BOOL FASTCALL Enable(); // Enable the ras0 interface
|
||||
BOOL FASTCALL Disable(); // Disable the ras0 interface
|
||||
BOOL FASTCALL Flush(); // Purge all of the packets that are waiting to be processed
|
||||
|
||||
private:
|
||||
BYTE m_MacAddr[6];
|
||||
// MAC Address
|
||||
BOOL m_bTxValid;
|
||||
// Send Valid Flag
|
||||
int m_hTAP;
|
||||
// File handle
|
||||
BYTE m_MacAddr[6]; // MAC Address
|
||||
BOOL m_bTxValid; // Send Valid Flag
|
||||
int m_hTAP; // File handle
|
||||
|
||||
BYTE m_garbage_buffer[ETH_FRAME_LEN];
|
||||
|
||||
pcap_t *m_pcap;
|
||||
pcap_dumper_t *m_pcap_dumper;
|
||||
|
||||
};
|
||||
|
||||
#endif // ctapdriver_h
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//
|
||||
// Imported sava's Anex86/T98Next image and MO format support patch.
|
||||
// Imported NetBSD support and some optimisation patch by Rin Okuyama.
|
||||
// Comments translated to english by akuker.
|
||||
// Comments translated to english by akuker.
|
||||
//
|
||||
// [ Disk ]
|
||||
//
|
||||
|
@ -161,11 +161,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
|
|||
ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100));
|
||||
|
||||
if (dt.buffer == NULL) {
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512);
|
||||
#else
|
||||
#else
|
||||
dt.buffer = (BYTE *)malloc(length * sizeof(BYTE));
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
dt.length = length;
|
||||
}
|
||||
|
||||
|
@ -176,11 +176,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
|
|||
// Reallocate if the buffer length is different
|
||||
if (dt.length != (DWORD)length) {
|
||||
free(dt.buffer);
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512);
|
||||
#else
|
||||
#else
|
||||
dt.buffer = (BYTE *)malloc(length * sizeof(BYTE));
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
dt.length = length;
|
||||
}
|
||||
|
||||
|
@ -205,11 +205,11 @@ BOOL FASTCALL DiskTrack::Load(const Filepath& path)
|
|||
memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL));
|
||||
|
||||
// Read from File
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
if (!fio.OpenDIO(path, Fileio::ReadOnly)) {
|
||||
#else
|
||||
#else
|
||||
if (!fio.Open(path, Fileio::ReadOnly)) {
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
return FALSE;
|
||||
}
|
||||
if (dt.raw) {
|
||||
|
@ -1701,7 +1701,7 @@ int FASTCALL Disk::AddFormat(BOOL change, BYTE *buf)
|
|||
buf[1] = 0x16;
|
||||
|
||||
// Show the number of bytes in the physical sector as changeable
|
||||
// (though it cannot be changed in practice)
|
||||
// (though it cannot be changed in practice)
|
||||
if (change) {
|
||||
buf[0xc] = 0xff;
|
||||
buf[0xd] = 0xff;
|
||||
|
@ -1863,7 +1863,7 @@ int FASTCALL Disk::AddCDDA(BOOL change, BYTE *buf)
|
|||
}
|
||||
|
||||
// Audio waits for operation completion and allows
|
||||
// PLAY across multiple tracks
|
||||
// PLAY across multiple tracks
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
// XM6i
|
||||
// Copyright (C) 2010-2015 isaki@NetBSD.org
|
||||
//
|
||||
// Imported sava's Anex86/T98Next image and MO format support patch.
|
||||
// Comments translated to english by akuker.
|
||||
// Imported sava's Anex86/T98Next image and MO format support patch.
|
||||
// Comments translated to english by akuker.
|
||||
//
|
||||
// [ Disk ]
|
||||
//
|
||||
|
@ -62,11 +62,11 @@
|
|||
|
||||
|
||||
#ifdef RASCSI
|
||||
#define BENDER_SIGNATURE "RaSCSI"
|
||||
#define BENDER_SIGNATURE "RaSCSI"
|
||||
// The following line was to mimic Apple's CDROM ID
|
||||
// #define BENDER_SIGNATURE "SONY "
|
||||
#else
|
||||
#define BENDER_SIGNATURE "XM6"
|
||||
#define BENDER_SIGNATURE "XM6"
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
@ -79,49 +79,38 @@ class DiskTrack
|
|||
public:
|
||||
// Internal data definition
|
||||
typedef struct {
|
||||
int track; // Track Number
|
||||
int size; // Sector Size(8 or 9)
|
||||
int sectors; // Number of sectors(<=0x100)
|
||||
DWORD length; // Data buffer length
|
||||
BYTE *buffer; // Data buffer
|
||||
BOOL init; // Is it initilized?
|
||||
BOOL changed; // Changed flag
|
||||
DWORD maplen; // Changed map length
|
||||
BOOL *changemap; // Changed map
|
||||
BOOL raw; // RAW mode flag
|
||||
off64_t imgoffset; // Offset to actual data
|
||||
int track; // Track Number
|
||||
int size; // Sector Size(8 or 9)
|
||||
int sectors; // Number of sectors(<=0x100)
|
||||
DWORD length; // Data buffer length
|
||||
BYTE *buffer; // Data buffer
|
||||
BOOL init; // Is it initilized?
|
||||
BOOL changed; // Changed flag
|
||||
DWORD maplen; // Changed map length
|
||||
BOOL *changemap; // Changed map
|
||||
BOOL raw; // RAW mode flag
|
||||
off64_t imgoffset; // Offset to actual data
|
||||
} disktrk_t;
|
||||
|
||||
public:
|
||||
// Basic Functions
|
||||
DiskTrack();
|
||||
// Constructor
|
||||
virtual ~DiskTrack();
|
||||
// Destructor
|
||||
void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE,
|
||||
off64_t imgoff = 0);
|
||||
// Initialization
|
||||
BOOL FASTCALL Load(const Filepath& path);
|
||||
// Load
|
||||
BOOL FASTCALL Save(const Filepath& path);
|
||||
// Save
|
||||
DiskTrack(); // Constructor
|
||||
virtual ~DiskTrack(); // Destructor
|
||||
void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE, off64_t imgoff = 0);// Initialization
|
||||
BOOL FASTCALL Load(const Filepath& path); // Load
|
||||
BOOL FASTCALL Save(const Filepath& path); // Save
|
||||
|
||||
// Read / Write
|
||||
BOOL FASTCALL Read(BYTE *buf, int sec) const;
|
||||
// Sector Read
|
||||
BOOL FASTCALL Write(const BYTE *buf, int sec);
|
||||
// Sector Write
|
||||
BOOL FASTCALL Read(BYTE *buf, int sec) const; // Sector Read
|
||||
BOOL FASTCALL Write(const BYTE *buf, int sec); // Sector Write
|
||||
|
||||
// Other
|
||||
int FASTCALL GetTrack() const { return dt.track; }
|
||||
// Get track
|
||||
BOOL FASTCALL IsChanged() const { return dt.changed; }
|
||||
// Changed flag check
|
||||
int FASTCALL GetTrack() const { return dt.track; } // Get track
|
||||
BOOL FASTCALL IsChanged() const { return dt.changed; } // Changed flag check
|
||||
|
||||
private:
|
||||
// Internal data
|
||||
disktrk_t dt;
|
||||
// Internal data
|
||||
disktrk_t dt; // Internal data
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
@ -134,61 +123,42 @@ class DiskCache
|
|||
public:
|
||||
// Internal data definition
|
||||
typedef struct {
|
||||
DiskTrack *disktrk; // Disk Track
|
||||
DWORD serial; // Serial
|
||||
DiskTrack *disktrk; // Disk Track
|
||||
DWORD serial; // Serial
|
||||
} cache_t;
|
||||
|
||||
// Number of caches
|
||||
enum {
|
||||
CacheMax = 16 // Number of tracks to cache
|
||||
CacheMax = 16 // Number of tracks to cache
|
||||
};
|
||||
|
||||
public:
|
||||
// Basic Functions
|
||||
DiskCache(const Filepath& path, int size, int blocks,
|
||||
off64_t imgoff = 0);
|
||||
// Constructor
|
||||
virtual ~DiskCache();
|
||||
// Destructor
|
||||
void FASTCALL SetRawMode(BOOL raw);
|
||||
// CD-ROM raw mode setting
|
||||
DiskCache(const Filepath& path, int size, int blocks,off64_t imgoff = 0);// Constructor
|
||||
virtual ~DiskCache(); // Destructor
|
||||
void FASTCALL SetRawMode(BOOL raw); // CD-ROM raw mode setting
|
||||
|
||||
// Access
|
||||
BOOL FASTCALL Save();
|
||||
// Save and release all
|
||||
BOOL FASTCALL Read(BYTE *buf, int block);
|
||||
// Sector Read
|
||||
BOOL FASTCALL Write(const BYTE *buf, int block);
|
||||
// Sector Write
|
||||
BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const;
|
||||
// Get cache information
|
||||
BOOL FASTCALL Save(); // Save and release all
|
||||
BOOL FASTCALL Read(BYTE *buf, int block); // Sector Read
|
||||
BOOL FASTCALL Write(const BYTE *buf, int block); // Sector Write
|
||||
BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const; // Get cache information
|
||||
|
||||
private:
|
||||
// Internal Management
|
||||
void FASTCALL Clear();
|
||||
// Clear all tracks
|
||||
DiskTrack* FASTCALL Assign(int track);
|
||||
// Load track
|
||||
BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL);
|
||||
// Load track
|
||||
void FASTCALL Update();
|
||||
// Update serial number
|
||||
void FASTCALL Clear(); // Clear all tracks
|
||||
DiskTrack* FASTCALL Assign(int track); // Load track
|
||||
BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL); // Load track
|
||||
void FASTCALL Update(); // Update serial number
|
||||
|
||||
// Internal data
|
||||
cache_t cache[CacheMax];
|
||||
// Cache management
|
||||
DWORD serial;
|
||||
// Last serial number
|
||||
Filepath sec_path;
|
||||
// Path
|
||||
int sec_size;
|
||||
// Sector size (8 or 9 or 11)
|
||||
int sec_blocks;
|
||||
// Blocks per sector
|
||||
BOOL cd_raw;
|
||||
// CD-ROM RAW mode
|
||||
off64_t imgoffset;
|
||||
// Offset to actual data
|
||||
cache_t cache[CacheMax]; // Cache management
|
||||
DWORD serial; // Last serial number
|
||||
Filepath sec_path; // Path
|
||||
int sec_size; // Sector size (8 or 9 or 11)
|
||||
int sec_blocks; // Blocks per sector
|
||||
BOOL cd_raw; // CD-ROM RAW mode
|
||||
off64_t imgoffset; // Offset to actual data
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
@ -201,173 +171,110 @@ class Disk
|
|||
public:
|
||||
// Internal data structure
|
||||
typedef struct {
|
||||
DWORD id; // Media ID
|
||||
BOOL ready; // Valid Disk
|
||||
BOOL writep; // Write protected
|
||||
BOOL readonly; // Read only
|
||||
BOOL removable; // Removable
|
||||
BOOL lock; // Locked
|
||||
BOOL attn; // Attention
|
||||
BOOL reset; // Reset
|
||||
int size; // Sector Size
|
||||
DWORD blocks; // Total number of sectors
|
||||
DWORD lun; // LUN
|
||||
DWORD code; // Status code
|
||||
DiskCache *dcache; // Disk cache
|
||||
off64_t imgoffset; // Offset to actual data
|
||||
DWORD id; // Media ID
|
||||
BOOL ready; // Valid Disk
|
||||
BOOL writep; // Write protected
|
||||
BOOL readonly; // Read only
|
||||
BOOL removable; // Removable
|
||||
BOOL lock; // Locked
|
||||
BOOL attn; // Attention
|
||||
BOOL reset; // Reset
|
||||
int size; // Sector Size
|
||||
DWORD blocks; // Total number of sectors
|
||||
DWORD lun; // LUN
|
||||
DWORD code; // Status code
|
||||
DiskCache *dcache; // Disk cache
|
||||
off64_t imgoffset; // Offset to actual data
|
||||
} disk_t;
|
||||
|
||||
public:
|
||||
// Basic Functions
|
||||
Disk();
|
||||
// Constructor
|
||||
virtual ~Disk();
|
||||
// Destructor
|
||||
virtual void FASTCALL Reset();
|
||||
// Device Reset
|
||||
#ifndef RASCSI
|
||||
virtual BOOL FASTCALL Save(Fileio *fio, int ver);
|
||||
// Save
|
||||
virtual BOOL FASTCALL Load(Fileio *fio, int ver);
|
||||
// Load
|
||||
#endif // RASCSI
|
||||
Disk(); // Constructor
|
||||
virtual ~Disk(); // Destructor
|
||||
virtual void FASTCALL Reset(); // Device Reset
|
||||
#ifndef RASCSI
|
||||
virtual BOOL FASTCALL Save(Fileio *fio, int ver); // Save
|
||||
virtual BOOL FASTCALL Load(Fileio *fio, int ver); // Load
|
||||
#endif // RASCSI
|
||||
|
||||
// ID
|
||||
DWORD FASTCALL GetID() const;
|
||||
// Get media ID
|
||||
BOOL FASTCALL IsNULL() const;
|
||||
// NULL check
|
||||
BOOL FASTCALL IsSASI() const;
|
||||
// SASI Check
|
||||
BOOL FASTCALL IsSCSI() const;
|
||||
// SASI Check
|
||||
DWORD FASTCALL GetID() const; // Get media ID
|
||||
BOOL FASTCALL IsNULL() const; // NULL check
|
||||
BOOL FASTCALL IsSASI() const; // SASI Check
|
||||
BOOL FASTCALL IsSCSI() const; // SASI Check
|
||||
|
||||
// Media Operations
|
||||
virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
void FASTCALL GetPath(Filepath& path) const;
|
||||
// Get the path
|
||||
void FASTCALL Eject(BOOL force);
|
||||
// Eject
|
||||
BOOL FASTCALL IsReady() const { return disk.ready; }
|
||||
// Ready check
|
||||
void FASTCALL WriteP(BOOL flag);
|
||||
// Set Write Protect flag
|
||||
BOOL FASTCALL IsWriteP() const { return disk.writep; }
|
||||
// Get write protect flag
|
||||
BOOL FASTCALL IsReadOnly() const { return disk.readonly; }
|
||||
// Get read only flag
|
||||
BOOL FASTCALL IsRemovable() const { return disk.removable; }
|
||||
// Get is removable flag
|
||||
BOOL FASTCALL IsLocked() const { return disk.lock; }
|
||||
// Get locked status
|
||||
BOOL FASTCALL IsAttn() const { return disk.attn; }
|
||||
// Get attention flag
|
||||
BOOL FASTCALL Flush();
|
||||
// Flush the cache
|
||||
void FASTCALL GetDisk(disk_t *buffer) const;
|
||||
// Get the internal data struct
|
||||
virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
void FASTCALL GetPath(Filepath& path) const; // Get the path
|
||||
void FASTCALL Eject(BOOL force); // Eject
|
||||
BOOL FASTCALL IsReady() const { return disk.ready; } // Ready check
|
||||
void FASTCALL WriteP(BOOL flag); // Set Write Protect flag
|
||||
BOOL FASTCALL IsWriteP() const { return disk.writep; } // Get write protect flag
|
||||
BOOL FASTCALL IsReadOnly() const { return disk.readonly; } // Get read only flag
|
||||
BOOL FASTCALL IsRemovable() const { return disk.removable; } // Get is removable flag
|
||||
BOOL FASTCALL IsLocked() const { return disk.lock; } // Get locked status
|
||||
BOOL FASTCALL IsAttn() const { return disk.attn; } // Get attention flag
|
||||
BOOL FASTCALL Flush(); // Flush the cache
|
||||
void FASTCALL GetDisk(disk_t *buffer) const; // Get the internal data struct
|
||||
|
||||
// Properties
|
||||
void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; }
|
||||
// LUN set
|
||||
DWORD FASTCALL GetLUN() { return disk.lun; }
|
||||
// LUN get
|
||||
void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; } // LUN set
|
||||
DWORD FASTCALL GetLUN() { return disk.lun; } // LUN get
|
||||
|
||||
// commands
|
||||
virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf);
|
||||
// REQUEST SENSE command
|
||||
int FASTCALL SelectCheck(const DWORD *cdb);
|
||||
// SELECT check
|
||||
int FASTCALL SelectCheck10(const DWORD *cdb);
|
||||
// SELECT(10) check
|
||||
virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
|
||||
// MODE SELECT command
|
||||
virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf);
|
||||
// MODE SENSE command
|
||||
virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf);
|
||||
// MODE SENSE(10) command
|
||||
int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf);
|
||||
// READ DEFECT DATA(10) command
|
||||
virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb);
|
||||
// TEST UNIT READY command
|
||||
BOOL FASTCALL Rezero(const DWORD *cdb);
|
||||
// REZERO command
|
||||
BOOL FASTCALL Format(const DWORD *cdb);
|
||||
// FORMAT UNIT command
|
||||
BOOL FASTCALL Reassign(const DWORD *cdb);
|
||||
// REASSIGN UNIT command
|
||||
virtual int FASTCALL Read(const DWORD *cdb, BYTE *buf, DWORD block);
|
||||
// READ command
|
||||
virtual int FASTCALL WriteCheck(DWORD block);
|
||||
// WRITE check
|
||||
virtual BOOL FASTCALL Write(const DWORD *cdb, 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();
|
||||
// Unsupported command
|
||||
virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);// INQUIRY command
|
||||
virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
|
||||
int FASTCALL SelectCheck(const DWORD *cdb); // SELECT check
|
||||
int FASTCALL SelectCheck10(const DWORD *cdb); // SELECT(10) check
|
||||
virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);// MODE SELECT command
|
||||
virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf); // MODE SENSE command
|
||||
virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf); // MODE SENSE(10) command
|
||||
int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf); // READ DEFECT DATA(10) command
|
||||
virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
|
||||
BOOL FASTCALL Rezero(const DWORD *cdb); // REZERO command
|
||||
BOOL FASTCALL Format(const DWORD *cdb); // FORMAT UNIT command
|
||||
BOOL FASTCALL Reassign(const DWORD *cdb); // REASSIGN UNIT command
|
||||
virtual int FASTCALL Read(const DWORD *cdb, BYTE *buf, DWORD block); // READ command
|
||||
virtual int FASTCALL WriteCheck(DWORD block); // WRITE check
|
||||
virtual BOOL FASTCALL Write(const DWORD *cdb, 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(); // Unsupported command
|
||||
|
||||
// Other
|
||||
BOOL FASTCALL IsCacheWB();
|
||||
// Get cache writeback mode
|
||||
void FASTCALL SetCacheWB(BOOL enable);
|
||||
// Set cache writeback mode
|
||||
BOOL FASTCALL IsCacheWB(); // Get cache writeback mode
|
||||
void FASTCALL SetCacheWB(BOOL enable); // Set cache writeback mode
|
||||
|
||||
protected:
|
||||
// Internal processing
|
||||
virtual int FASTCALL AddError(BOOL change, BYTE *buf);
|
||||
// Add error
|
||||
virtual int FASTCALL AddFormat(BOOL change, BYTE *buf);
|
||||
// Add format
|
||||
virtual int FASTCALL AddDrive(BOOL change, BYTE *buf);
|
||||
// Add drive
|
||||
int FASTCALL AddOpt(BOOL change, BYTE *buf);
|
||||
// Add optical
|
||||
int FASTCALL AddCache(BOOL change, BYTE *buf);
|
||||
// Add cache
|
||||
int FASTCALL AddCDROM(BOOL change, BYTE *buf);
|
||||
// Add CD-ROM
|
||||
int FASTCALL AddCDDA(BOOL change, BYTE *buf);
|
||||
// Add CD_DA
|
||||
virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
|
||||
// Add vendor special info
|
||||
BOOL FASTCALL CheckReady();
|
||||
// Check if ready
|
||||
virtual int FASTCALL AddError(BOOL change, BYTE *buf); // Add error
|
||||
virtual int FASTCALL AddFormat(BOOL change, BYTE *buf); // Add format
|
||||
virtual int FASTCALL AddDrive(BOOL change, BYTE *buf); // Add drive
|
||||
int FASTCALL AddOpt(BOOL change, BYTE *buf); // Add optical
|
||||
int FASTCALL AddCache(BOOL change, BYTE *buf); // Add cache
|
||||
int FASTCALL AddCDROM(BOOL change, BYTE *buf); // Add CD-ROM
|
||||
int FASTCALL AddCDDA(BOOL change, BYTE *buf); // Add CD_DA
|
||||
virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special info
|
||||
BOOL FASTCALL CheckReady(); // Check if ready
|
||||
|
||||
// Internal data
|
||||
disk_t disk;
|
||||
// Internal disk data
|
||||
Filepath diskpath;
|
||||
// File path (for GetPath)
|
||||
BOOL cache_wb;
|
||||
// Cache mode
|
||||
|
||||
char m_vendor_id[9]; // 8 characters + null
|
||||
char m_product_id[17]; // 16 characters + null
|
||||
char m_revision_lvl[5]; // 4 characters + null
|
||||
char m_serial_num[9]; // 8 characters + null
|
||||
|
||||
disk_t disk; // Internal disk data
|
||||
Filepath diskpath; // File path (for GetPath)
|
||||
BOOL cache_wb; // Cache mode
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SASI hard disk ]
|
||||
// [ SASI hard disk ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "sasihd.h"
|
||||
|
@ -73,7 +73,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
|
|||
size = fio.GetFileSize();
|
||||
fio.Close();
|
||||
|
||||
#if defined(USE_MZ1F23_1024_SUPPORT)
|
||||
#if defined(USE_MZ1F23_1024_SUPPORT)
|
||||
// MZ-2500/MZ-2800用 MZ-1F23(SASI 20M/セクタサイズ1024)専用
|
||||
// 20M(22437888 BS=1024 C=21912)
|
||||
if (size == 0x1566000) {
|
||||
|
@ -84,9 +84,9 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
|
|||
// Call the base class
|
||||
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バイト単位であること
|
||||
if (size & 0xff) {
|
||||
return FALSE;
|
||||
|
@ -101,7 +101,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
|
|||
if (size > 512 * 1024 * 1024) {
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
// 10MB, 20MB, 40MBのみ
|
||||
switch (size) {
|
||||
// 10MB(10441728 BS=256 C=40788)
|
||||
|
@ -120,7 +120,7 @@ BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/)
|
|||
default:
|
||||
return FALSE;
|
||||
}
|
||||
#endif // REMOVE_FIXED_SASIHD_SIZE
|
||||
#endif // REMOVE_FIXED_SASIHD_SIZE
|
||||
|
||||
// セクタサイズとブロック数
|
||||
disk.size = 8;
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SASI hard disk ]
|
||||
//
|
||||
|
@ -28,13 +28,10 @@ class SASIHD : public Disk
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SASIHD();
|
||||
// Constructor
|
||||
void FASTCALL Reset();
|
||||
// Reset
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
SASIHD(); // Constructor
|
||||
void FASTCALL Reset(); // Reset
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
|
||||
// commands
|
||||
int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf);
|
||||
// REQUEST SENSE command
|
||||
int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
|
||||
};
|
|
@ -106,6 +106,12 @@ SCSIDaynaPort::~SCSIDaynaPort()
|
|||
}
|
||||
}
|
||||
|
||||
BOOL FASTCALL SCSIDaynaPort::Open(const Filepath& path, BOOL attn)
|
||||
{
|
||||
LOGTRACE("SCSIDaynaPort Open");
|
||||
return m_tap->OpenDump(path);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// INQUIRY
|
||||
|
@ -222,14 +228,14 @@ int FASTCALL SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
|||
// The first 2 bytes are reserved for the length of the packet
|
||||
// The next 4 bytes are reserved for a flag field
|
||||
//rx_packet_size = m_tap->Rx(response->data);
|
||||
rx_packet_size = m_tap->Rx(&buf[m_read_header_size]);
|
||||
rx_packet_size = m_tap->Rx(&buf[DAYNAPORT_READ_HEADER_SZ]);
|
||||
|
||||
// If we didn't receive anything, return size of 0
|
||||
if(rx_packet_size <= 0){
|
||||
LOGTRACE("%s No packet received", __PRETTY_FUNCTION__);
|
||||
response->length = 0;
|
||||
response->flags = e_no_more_data;
|
||||
return m_read_header_size;
|
||||
return DAYNAPORT_READ_HEADER_SZ;
|
||||
}
|
||||
|
||||
LOGTRACE("%s Packet Sz %d (%08X) read: %d", __PRETTY_FUNCTION__, (unsigned int) rx_packet_size, (unsigned int) rx_packet_size, read_count);
|
||||
|
@ -238,23 +244,25 @@ int FASTCALL SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
|||
// being sent to the SCSI initiator.
|
||||
send_message_to_host = FALSE;
|
||||
|
||||
// Check if received packet destination MAC address matches the
|
||||
// DaynaPort MAC. For IP packets, the mac_address will be the first 6 bytes
|
||||
// of the data.
|
||||
if (memcmp(response->data, m_mac_addr, 6) == 0) {
|
||||
send_message_to_host = TRUE;
|
||||
}
|
||||
// The following doesn't seem to work with unicast messages. Temporarily removing the filtering
|
||||
// functionality.
|
||||
/////// // Check if received packet destination MAC address matches the
|
||||
/////// // DaynaPort MAC. For IP packets, the mac_address will be the first 6 bytes
|
||||
/////// // of the data.
|
||||
/////// if (memcmp(response->data, m_mac_addr, 6) == 0) {
|
||||
/////// send_message_to_host = TRUE;
|
||||
/////// }
|
||||
|
||||
// Check to see if this is a broadcast message
|
||||
if (memcmp(response->data, m_bcast_addr, 6) == 0) {
|
||||
send_message_to_host = TRUE;
|
||||
}
|
||||
/////// // Check to see if this is a broadcast message
|
||||
/////// if (memcmp(response->data, m_bcast_addr, 6) == 0) {
|
||||
/////// send_message_to_host = TRUE;
|
||||
/////// }
|
||||
|
||||
// Check to see if this is an AppleTalk Message
|
||||
if (memcmp(response->data, m_apple_talk_addr, 6) == 0) {
|
||||
|
||||
send_message_to_host = TRUE;
|
||||
}
|
||||
/////// // Check to see if this is an AppleTalk Message
|
||||
/////// if (memcmp(response->data, m_apple_talk_addr, 6) == 0) {
|
||||
/////// send_message_to_host = TRUE;
|
||||
/////// }
|
||||
send_message_to_host = TRUE;
|
||||
|
||||
// TODO: We should check to see if this message is in the multicast
|
||||
// configuration from SCSI command 0x0D
|
||||
|
@ -275,7 +283,7 @@ int FASTCALL SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
|||
{
|
||||
response->length = 0;
|
||||
response->flags = e_no_more_data;
|
||||
return m_read_header_size;
|
||||
return DAYNAPORT_READ_HEADER_SZ;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -304,7 +312,7 @@ int FASTCALL SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
|||
|
||||
// Return the packet size + 2 for the length + 4 for the flag field
|
||||
// The CRC was already appended by the ctapdriver
|
||||
return rx_packet_size + m_read_header_size;
|
||||
return rx_packet_size + DAYNAPORT_READ_HEADER_SZ;
|
||||
}
|
||||
// If we got to this point, there are still messages in the queue, so
|
||||
// we should loop back and get the next one.
|
||||
|
@ -312,7 +320,7 @@ int FASTCALL SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
|||
|
||||
response->length = 0;
|
||||
response->flags = e_no_more_data;
|
||||
return m_read_header_size;
|
||||
return DAYNAPORT_READ_HEADER_SZ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
// Constructor
|
||||
virtual ~SCSIDaynaPort();
|
||||
// Destructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Capture packets
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buffer, DWORD major, DWORD minor);
|
||||
|
@ -76,6 +78,11 @@ public:
|
|||
static const BYTE CMD_SCSILINK_SETMODE = 0x80;
|
||||
static const BYTE CMD_SCSILINK_SETMAC = 0x40;
|
||||
|
||||
// The READ response has a header which consists of:
|
||||
// 2 bytes - payload size
|
||||
// 4 bytes - status flags
|
||||
static const DWORD DAYNAPORT_READ_HEADER_SZ = 2 + 4;
|
||||
|
||||
private:
|
||||
typedef struct __attribute__((packed)) {
|
||||
BYTE operation_code;
|
||||
|
@ -188,12 +195,6 @@ private:
|
|||
static const BYTE m_bcast_addr[6];
|
||||
static const BYTE m_apple_talk_addr[6];
|
||||
|
||||
// The READ response has a header which consists of:
|
||||
// 2 bytes - payload size
|
||||
// 4 bytes - status flags
|
||||
// 1 byte - magic pad bit, that I don't know why it works.....
|
||||
const DWORD m_read_header_size = 2 + 4 + 1;
|
||||
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Host Bridge for the Sharp X68000 ]
|
||||
// [ SCSI Host Bridge for the Sharp X68000 ]
|
||||
//
|
||||
// Note: This requires a special driver on the host system and will only
|
||||
// work with the Sharp X68000 operating system.
|
||||
|
@ -37,7 +37,7 @@ SCSIBR::SCSIBR() : Disk()
|
|||
// Host Bridge
|
||||
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 = new CTapDriver();
|
||||
m_bTapEnable = tap->Init();
|
||||
|
@ -51,7 +51,7 @@ SCSIBR::SCSIBR() : Disk()
|
|||
|
||||
// Packet reception flag OFF
|
||||
packet_enable = FALSE;
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
// Create host file system
|
||||
fs = new CFileSys();
|
||||
|
@ -65,13 +65,13 @@ SCSIBR::SCSIBR() : Disk()
|
|||
//---------------------------------------------------------------------------
|
||||
SCSIBR::~SCSIBR()
|
||||
{
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
// TAP driver release
|
||||
if (tap) {
|
||||
tap->Cleanup();
|
||||
delete tap;
|
||||
}
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
// Release host file system
|
||||
if (fs) {
|
||||
|
@ -136,12 +136,12 @@ int FASTCALL SCSIBR::Inquiry(
|
|||
// Optional function valid flag
|
||||
buf[36] = '0';
|
||||
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
// TAP Enable
|
||||
if (m_bTapEnable) {
|
||||
buf[37] = '1';
|
||||
}
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
// CFileSys Enable
|
||||
buf[38] = '1';
|
||||
|
@ -182,27 +182,27 @@ int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
|||
{
|
||||
int type;
|
||||
int phase;
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
int func;
|
||||
int total_len;
|
||||
int i;
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
ASSERT(this);
|
||||
|
||||
// Type
|
||||
type = cdb[2];
|
||||
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
// Function number
|
||||
func = cdb[3];
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
// Phase
|
||||
phase = cdb[9];
|
||||
|
||||
switch (type) {
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
case 1: // Ethernet
|
||||
// Do not process if TAP is invalid
|
||||
if (!m_bTapEnable) {
|
||||
|
@ -251,7 +251,7 @@ int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
|||
return total_len;
|
||||
}
|
||||
break;
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
case 2: // Host Drive
|
||||
switch (phase) {
|
||||
|
@ -305,7 +305,7 @@ BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
|||
len |= cdb[8];
|
||||
|
||||
switch (type) {
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
case 1: // Ethernet
|
||||
// Do not process if TAP is invalid
|
||||
if (!m_bTapEnable) {
|
||||
|
@ -322,7 +322,7 @@ BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
|||
return TRUE;
|
||||
}
|
||||
break;
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
case 2: // Host drive
|
||||
switch (phase) {
|
||||
|
@ -1462,30 +1462,30 @@ void FASTCALL SCSIBR::WriteFs(int func, BYTE *buf)
|
|||
func &= 0x1f;
|
||||
switch (func) {
|
||||
case 0x00: return FS_InitDevice(buf); // $40 - start device
|
||||
case 0x01: return FS_CheckDir(buf); // $41 - directory check
|
||||
case 0x02: return FS_MakeDir(buf); // $42 - create directory
|
||||
case 0x01: return FS_CheckDir(buf); // $41 - directory check
|
||||
case 0x02: return FS_MakeDir(buf); // $42 - create directory
|
||||
case 0x03: return FS_RemoveDir(buf); // $43 - remove directory
|
||||
case 0x04: return FS_Rename(buf); // $44 - change file name
|
||||
case 0x05: return FS_Delete(buf); // $45 - delete file
|
||||
case 0x04: return FS_Rename(buf); // $44 - change file name
|
||||
case 0x05: return FS_Delete(buf); // $45 - delete file
|
||||
case 0x06: return FS_Attribute(buf); // $46 - Get/set file attribute
|
||||
case 0x07: return FS_Files(buf); // $47 - file search
|
||||
case 0x08: return FS_NFiles(buf); // $48 - next file search
|
||||
case 0x09: return FS_Create(buf); // $49 - create file
|
||||
case 0x0A: return FS_Open(buf); // $4A - File open
|
||||
case 0x0B: return FS_Close(buf); // $4B - File close
|
||||
case 0x0C: return FS_Read(buf); // $4C - read file
|
||||
case 0x0D: return FS_Write(buf); // $4D - write file
|
||||
case 0x0E: return FS_Seek(buf); // $4E - File seek
|
||||
case 0x07: return FS_Files(buf); // $47 - file search
|
||||
case 0x08: return FS_NFiles(buf); // $48 - next file search
|
||||
case 0x09: return FS_Create(buf); // $49 - create file
|
||||
case 0x0A: return FS_Open(buf); // $4A - File open
|
||||
case 0x0B: return FS_Close(buf); // $4B - File close
|
||||
case 0x0C: return FS_Read(buf); // $4C - read file
|
||||
case 0x0D: return FS_Write(buf); // $4D - write file
|
||||
case 0x0E: return FS_Seek(buf); // $4E - File seek
|
||||
case 0x0F: return FS_TimeStamp(buf); // $4F - Get/set file modification time
|
||||
case 0x10: return FS_GetCapacity(buf); // $50 - get capacity
|
||||
case 0x11: return FS_CtrlDrive(buf); // $51 - Drive control/state check
|
||||
case 0x12: return FS_GetDPB(buf); // $52 - Get DPB
|
||||
case 0x13: return FS_DiskRead(buf); // $53 - read sector
|
||||
case 0x12: return FS_GetDPB(buf); // $52 - Get DPB
|
||||
case 0x13: return FS_DiskRead(buf); // $53 - read sector
|
||||
case 0x14: return FS_DiskWrite(buf); // $54 - write sector
|
||||
case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL
|
||||
case 0x16: return FS_Flush(buf); // $56 - flush
|
||||
case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL
|
||||
case 0x16: return FS_Flush(buf); // $56 - flush
|
||||
case 0x17: return FS_CheckMedia(buf); // $57 - check media exchange
|
||||
case 0x18: return FS_Lock(buf); // $58 - exclusive control
|
||||
case 0x18: return FS_Lock(buf); // $58 - exclusive control
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Host Bridge for the Sharp X68000 ]
|
||||
// [ SCSI Host Bridge for the Sharp X68000 ]
|
||||
//
|
||||
// Note: This requires a special driver on the host system and will only
|
||||
// work with the Sharp X68000 operating system.
|
||||
|
@ -34,120 +34,68 @@ class SCSIBR : public Disk
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSIBR();
|
||||
// Constructor
|
||||
virtual ~SCSIBR();
|
||||
// Destructor
|
||||
SCSIBR(); // Constructor
|
||||
virtual ~SCSIBR(); // Destructor
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
BOOL FASTCALL TestUnitReady(const DWORD *cdb);
|
||||
// TEST UNIT READY command
|
||||
int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf);
|
||||
// GET MESSAGE10 command
|
||||
BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf);
|
||||
// SEND MESSAGE10 command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
BOOL FASTCALL TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
|
||||
int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf); // GET MESSAGE10 command
|
||||
BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf); // SEND MESSAGE10 command
|
||||
|
||||
private:
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
int FASTCALL GetMacAddr(BYTE *buf);
|
||||
// Get MAC address
|
||||
void FASTCALL SetMacAddr(BYTE *buf);
|
||||
// Set MAC address
|
||||
void FASTCALL ReceivePacket();
|
||||
// Receive a packet
|
||||
void FASTCALL GetPacketBuf(BYTE *buf);
|
||||
// Get a packet
|
||||
void FASTCALL SendPacket(BYTE *buf, int len);
|
||||
// Send a packet
|
||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
||||
int FASTCALL GetMacAddr(BYTE *buf); // Get MAC address
|
||||
void FASTCALL SetMacAddr(BYTE *buf); // Set MAC address
|
||||
void FASTCALL ReceivePacket(); // Receive a packet
|
||||
void FASTCALL GetPacketBuf(BYTE *buf); // Get a packet
|
||||
void FASTCALL SendPacket(BYTE *buf, int len); // Send a packet
|
||||
|
||||
CTapDriver *tap;
|
||||
// TAP driver
|
||||
BOOL m_bTapEnable;
|
||||
// TAP valid flag
|
||||
BYTE mac_addr[6];
|
||||
// MAC Addres
|
||||
int packet_len;
|
||||
// Receive packet size
|
||||
BYTE packet_buf[0x1000];
|
||||
// Receive packet buffer
|
||||
BOOL packet_enable;
|
||||
// Received packet valid
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
CTapDriver *tap; // TAP driver
|
||||
BOOL m_bTapEnable; // TAP valid flag
|
||||
BYTE mac_addr[6]; // MAC Addres
|
||||
int packet_len; // Receive packet size
|
||||
BYTE packet_buf[0x1000]; // Receive packet buffer
|
||||
BOOL packet_enable; // Received packet valid
|
||||
#endif // RASCSI && !BAREMETAL
|
||||
|
||||
int FASTCALL ReadFsResult(BYTE *buf); // Read filesystem (result code)
|
||||
int FASTCALL ReadFsOut(BYTE *buf); // Read filesystem (return data)
|
||||
int FASTCALL ReadFsOpt(BYTE *buf); // Read file system (optional data)
|
||||
void FASTCALL WriteFs(int func, BYTE *buf); // File system write (execute)
|
||||
void FASTCALL WriteFsOpt(BYTE *buf, int len); // File system write (optional data)
|
||||
|
||||
int FASTCALL ReadFsResult(BYTE *buf);
|
||||
// Read filesystem (result code)
|
||||
int FASTCALL ReadFsOut(BYTE *buf);
|
||||
// Read filesystem (return data)
|
||||
int FASTCALL ReadFsOpt(BYTE *buf);
|
||||
// Read file system (optional data)
|
||||
void FASTCALL WriteFs(int func, BYTE *buf);
|
||||
// File system write (execute)
|
||||
void FASTCALL WriteFsOpt(BYTE *buf, int len);
|
||||
// File system write (optional data)
|
||||
// Command handlers
|
||||
void FASTCALL FS_InitDevice(BYTE *buf);
|
||||
// $40 - boot
|
||||
void FASTCALL FS_CheckDir(BYTE *buf);
|
||||
// $41 - directory check
|
||||
void FASTCALL FS_MakeDir(BYTE *buf);
|
||||
// $42 - create directory
|
||||
void FASTCALL FS_RemoveDir(BYTE *buf);
|
||||
// $43 - delete directory
|
||||
void FASTCALL FS_Rename(BYTE *buf);
|
||||
// $44 - change filename
|
||||
void FASTCALL FS_Delete(BYTE *buf);
|
||||
// $45 - delete file
|
||||
void FASTCALL FS_Attribute(BYTE *buf);
|
||||
// $46 - get/set file attributes
|
||||
void FASTCALL FS_Files(BYTE *buf);
|
||||
// $47 - file search
|
||||
void FASTCALL FS_NFiles(BYTE *buf);
|
||||
// $48 - find next file
|
||||
void FASTCALL FS_Create(BYTE *buf);
|
||||
// $49 - create file
|
||||
void FASTCALL FS_Open(BYTE *buf);
|
||||
// $4A - open file
|
||||
void FASTCALL FS_Close(BYTE *buf);
|
||||
// $4B - close file
|
||||
void FASTCALL FS_Read(BYTE *buf);
|
||||
// $4C - read file
|
||||
void FASTCALL FS_Write(BYTE *buf);
|
||||
// $4D - write file
|
||||
void FASTCALL FS_Seek(BYTE *buf);
|
||||
// $4E - seek file
|
||||
void FASTCALL FS_TimeStamp(BYTE *buf);
|
||||
// $4F - get/set file time
|
||||
void FASTCALL FS_GetCapacity(BYTE *buf);
|
||||
// $50 - get capacity
|
||||
void FASTCALL FS_CtrlDrive(BYTE *buf);
|
||||
// $51 - drive status check/control
|
||||
void FASTCALL FS_GetDPB(BYTE *buf);
|
||||
// $52 - get DPB
|
||||
void FASTCALL FS_DiskRead(BYTE *buf);
|
||||
// $53 - read sector
|
||||
void FASTCALL FS_DiskWrite(BYTE *buf);
|
||||
// $54 - write sector
|
||||
void FASTCALL FS_Ioctrl(BYTE *buf);
|
||||
// $55 - IOCTRL
|
||||
void FASTCALL FS_Flush(BYTE *buf);
|
||||
// $56 - flush cache
|
||||
void FASTCALL FS_CheckMedia(BYTE *buf);
|
||||
// $57 - check media
|
||||
void FASTCALL FS_Lock(BYTE *buf);
|
||||
// $58 - get exclusive control
|
||||
void FASTCALL FS_InitDevice(BYTE *buf); // $40 - boot
|
||||
void FASTCALL FS_CheckDir(BYTE *buf); // $41 - directory check
|
||||
void FASTCALL FS_MakeDir(BYTE *buf); // $42 - create directory
|
||||
void FASTCALL FS_RemoveDir(BYTE *buf); // $43 - delete directory
|
||||
void FASTCALL FS_Rename(BYTE *buf); // $44 - change filename
|
||||
void FASTCALL FS_Delete(BYTE *buf); // $45 - delete file
|
||||
void FASTCALL FS_Attribute(BYTE *buf); // $46 - get/set file attributes
|
||||
void FASTCALL FS_Files(BYTE *buf); // $47 - file search
|
||||
void FASTCALL FS_NFiles(BYTE *buf); // $48 - find next file
|
||||
void FASTCALL FS_Create(BYTE *buf); // $49 - create file
|
||||
void FASTCALL FS_Open(BYTE *buf); // $4A - open file
|
||||
void FASTCALL FS_Close(BYTE *buf); // $4B - close file
|
||||
void FASTCALL FS_Read(BYTE *buf); // $4C - read file
|
||||
void FASTCALL FS_Write(BYTE *buf); // $4D - write file
|
||||
void FASTCALL FS_Seek(BYTE *buf); // $4E - seek file
|
||||
void FASTCALL FS_TimeStamp(BYTE *buf); // $4F - get/set file time
|
||||
void FASTCALL FS_GetCapacity(BYTE *buf); // $50 - get capacity
|
||||
void FASTCALL FS_CtrlDrive(BYTE *buf); // $51 - drive status check/control
|
||||
void FASTCALL FS_GetDPB(BYTE *buf); // $52 - get DPB
|
||||
void FASTCALL FS_DiskRead(BYTE *buf); // $53 - read sector
|
||||
void FASTCALL FS_DiskWrite(BYTE *buf); // $54 - write sector
|
||||
void FASTCALL FS_Ioctrl(BYTE *buf); // $55 - IOCTRL
|
||||
void FASTCALL FS_Flush(BYTE *buf); // $56 - flush cache
|
||||
void FASTCALL FS_CheckMedia(BYTE *buf); // $57 - check media
|
||||
void FASTCALL FS_Lock(BYTE *buf); // $58 - get exclusive control
|
||||
|
||||
CFileSys *fs;
|
||||
// File system accessor
|
||||
DWORD fsresult;
|
||||
// File system access result code
|
||||
BYTE fsout[0x800];
|
||||
// File system access result buffer
|
||||
DWORD fsoutlen;
|
||||
// File system access result buffer size
|
||||
BYTE fsopt[0x1000000];
|
||||
// File system access buffer
|
||||
DWORD fsoptlen;
|
||||
// File system access buffer size
|
||||
CFileSys *fs; // File system accessor
|
||||
DWORD fsresult; // File system access result code
|
||||
BYTE fsout[0x800]; // File system access result buffer
|
||||
DWORD fsoutlen; // File system access result buffer size
|
||||
BYTE fsopt[0x1000000]; // File system access buffer
|
||||
DWORD fsoptlen; // File system access buffer size
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -36,50 +36,30 @@ class CDTrack
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
CDTrack(SCSICD *scsicd);
|
||||
// Constructor
|
||||
virtual ~CDTrack();
|
||||
// Destructor
|
||||
BOOL FASTCALL Init(int track, DWORD first, DWORD last);
|
||||
// Initialization
|
||||
CDTrack(SCSICD *scsicd); // Constructor
|
||||
virtual ~CDTrack(); // Destructor
|
||||
BOOL FASTCALL Init(int track, DWORD first, DWORD last); // Initialization
|
||||
|
||||
// Properties
|
||||
void FASTCALL SetPath(BOOL cdda, const Filepath& path);
|
||||
// Set the path
|
||||
void FASTCALL GetPath(Filepath& path) const;
|
||||
// Get the path
|
||||
void FASTCALL AddIndex(int index, DWORD lba);
|
||||
// Add index
|
||||
DWORD FASTCALL GetFirst() const;
|
||||
// Get the start LBA
|
||||
DWORD FASTCALL GetLast() const;
|
||||
// Get the last LBA
|
||||
DWORD FASTCALL GetBlocks() const;
|
||||
// Get the number of blocks
|
||||
int FASTCALL GetTrackNo() const;
|
||||
// Get the track number
|
||||
BOOL FASTCALL IsValid(DWORD lba) const;
|
||||
// Is this a valid LBA?
|
||||
BOOL FASTCALL IsAudio() const;
|
||||
// Is this an audio track?
|
||||
void FASTCALL SetPath(BOOL cdda, const Filepath& path); // Set the path
|
||||
void FASTCALL GetPath(Filepath& path) const; // Get the path
|
||||
void FASTCALL AddIndex(int index, DWORD lba); // Add index
|
||||
DWORD FASTCALL GetFirst() const; // Get the start LBA
|
||||
DWORD FASTCALL GetLast() const; // Get the last LBA
|
||||
DWORD FASTCALL GetBlocks() const; // Get the number of blocks
|
||||
int FASTCALL GetTrackNo() const; // Get the track number
|
||||
BOOL FASTCALL IsValid(DWORD lba) const; // Is this a valid LBA?
|
||||
BOOL FASTCALL IsAudio() const; // Is this an audio track?
|
||||
|
||||
private:
|
||||
SCSICD *cdrom;
|
||||
// Parent device
|
||||
BOOL valid;
|
||||
// Valid track
|
||||
int track_no;
|
||||
// Track number
|
||||
DWORD first_lba;
|
||||
// First LBA
|
||||
DWORD last_lba;
|
||||
// Last LBA
|
||||
BOOL audio;
|
||||
// Audio track flag
|
||||
BOOL raw;
|
||||
// RAW data flag
|
||||
Filepath imgpath;
|
||||
// Image file path
|
||||
SCSICD *cdrom; // Parent device
|
||||
BOOL valid; // Valid track
|
||||
int track_no; // Track number
|
||||
DWORD first_lba; // First LBA
|
||||
DWORD last_lba; // Last LBA
|
||||
BOOL audio; // Audio track flag
|
||||
BOOL raw; // RAW data flag
|
||||
Filepath imgpath; // Image file path
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
@ -91,47 +71,29 @@ class CDDABuf
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
CDDABuf();
|
||||
// Constructor
|
||||
virtual ~CDDABuf();
|
||||
// Destructor
|
||||
#if 0
|
||||
BOOL Init();
|
||||
// Initialization
|
||||
BOOL FASTCALL Load(const Filepath& path);
|
||||
// Load
|
||||
BOOL FASTCALL Save(const Filepath& path);
|
||||
// Save
|
||||
CDDABuf(); // Constructor
|
||||
virtual ~CDDABuf(); // Destructor
|
||||
#if 0
|
||||
BOOL Init(); // Initialization
|
||||
BOOL FASTCALL Load(const Filepath& path); // Load
|
||||
BOOL FASTCALL Save(const Filepath& path); // Save
|
||||
|
||||
// API
|
||||
void FASTCALL Clear();
|
||||
// Clear the buffer
|
||||
BOOL FASTCALL Open(Filepath& path);
|
||||
// File specification
|
||||
BOOL FASTCALL GetBuf(DWORD *buffer, int frames);
|
||||
// Get the buffer
|
||||
BOOL FASTCALL IsValid();
|
||||
// Check if Valid
|
||||
BOOL FASTCALL ReadReq();
|
||||
// Read Request
|
||||
BOOL FASTCALL IsEnd() const;
|
||||
// Finish check
|
||||
void FASTCALL Clear(); // Clear the buffer
|
||||
BOOL FASTCALL Open(Filepath& path); // File specification
|
||||
BOOL FASTCALL GetBuf(DWORD *buffer, int frames); // Get the buffer
|
||||
BOOL FASTCALL IsValid(); // Check if Valid
|
||||
BOOL FASTCALL ReadReq(); // Read Request
|
||||
BOOL FASTCALL IsEnd() const; // Finish check
|
||||
|
||||
private:
|
||||
Filepath wavepath;
|
||||
// Wave path
|
||||
BOOL valid;
|
||||
// Open result (is it valid?)
|
||||
DWORD *m_buf;
|
||||
// Data buffer
|
||||
DWORD read;
|
||||
// Read pointer
|
||||
DWORD write;
|
||||
// Write pointer
|
||||
DWORD num;
|
||||
// Valid number of data
|
||||
DWORD rest;
|
||||
// Remaining file size
|
||||
Filepath wavepath; // Wave path
|
||||
BOOL valid; // Open result (is it valid?)
|
||||
DWORD *buf; // Data buffer
|
||||
DWORD read; // Read pointer
|
||||
DWORD write; // Write pointer
|
||||
DWORD num; // Valid number of data
|
||||
DWORD rest; // Remaining file size
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -145,88 +107,59 @@ class SCSICD : public Disk
|
|||
public:
|
||||
// Number of tracks
|
||||
enum {
|
||||
TrackMax = 96 // Maximum number of tracks
|
||||
TrackMax = 96 // Maximum number of tracks
|
||||
};
|
||||
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSICD();
|
||||
// Constructor
|
||||
virtual ~SCSICD();
|
||||
// Destructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
#ifndef RASCSI
|
||||
BOOL FASTCALL Load(Fileio *fio, int ver);
|
||||
// Load
|
||||
#endif // RASCSI
|
||||
SCSICD(); // Constructor
|
||||
virtual ~SCSICD(); // Destructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
#ifndef RASCSI
|
||||
BOOL FASTCALL Load(Fileio *fio, int ver); // Load
|
||||
#endif // RASCSI
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
int FASTCALL Read(const DWORD *cdb, BYTE *buf, DWORD block) override;
|
||||
// READ command
|
||||
int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf);
|
||||
// READ TOC command
|
||||
BOOL FASTCALL PlayAudio(const DWORD *cdb);
|
||||
// PLAY AUDIO command
|
||||
BOOL FASTCALL PlayAudioMSF(const DWORD *cdb);
|
||||
// PLAY AUDIO MSF command
|
||||
BOOL FASTCALL PlayAudioTrack(const DWORD *cdb);
|
||||
// PLAY AUDIO TRACK command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
int FASTCALL Read(const DWORD *cdb, BYTE *buf, DWORD block) override; // READ command
|
||||
int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
|
||||
BOOL FASTCALL PlayAudio(const DWORD *cdb); // PLAY AUDIO command
|
||||
BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); // PLAY AUDIO MSF command
|
||||
BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); // PLAY AUDIO TRACK command
|
||||
|
||||
// CD-DA
|
||||
BOOL FASTCALL NextFrame();
|
||||
// Frame notification
|
||||
void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate);
|
||||
// Get CD-DA buffer
|
||||
BOOL FASTCALL NextFrame(); // Frame notification
|
||||
void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate); // Get CD-DA buffer
|
||||
|
||||
// LBA-MSF Conversion
|
||||
void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const;
|
||||
// LBA→MSF conversion
|
||||
DWORD FASTCALL MSFtoLBA(const BYTE *msf) const;
|
||||
// MSF→LBA conversion
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
|
||||
// Add vendor special page
|
||||
void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const; // LBA→MSF conversion
|
||||
DWORD FASTCALL MSFtoLBA(const BYTE *msf) const; // MSF→LBA conversion
|
||||
|
||||
// Vendor-specific functions
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
|
||||
|
||||
private:
|
||||
// Open
|
||||
BOOL FASTCALL OpenCue(const Filepath& path);
|
||||
// Open(CUE)
|
||||
BOOL FASTCALL OpenIso(const Filepath& path);
|
||||
// Open(ISO)
|
||||
BOOL FASTCALL OpenPhysical(const Filepath& path);
|
||||
// Open(Physical)
|
||||
BOOL rawfile;
|
||||
// RAW flag
|
||||
BOOL FASTCALL OpenCue(const Filepath& path); // Open(CUE)
|
||||
BOOL FASTCALL OpenIso(const Filepath& path); // Open(ISO)
|
||||
BOOL FASTCALL OpenPhysical(const Filepath& path); // Open(Physical)
|
||||
BOOL rawfile; // RAW flag
|
||||
|
||||
// Track management
|
||||
void FASTCALL ClearTrack();
|
||||
// Clear the track
|
||||
int FASTCALL SearchTrack(DWORD lba) const;
|
||||
// Track search
|
||||
CDTrack* track[TrackMax];
|
||||
// Track opbject references
|
||||
int tracks;
|
||||
// Effective number of track objects
|
||||
int dataindex;
|
||||
// Current data track
|
||||
int audioindex;
|
||||
// Current audio track
|
||||
void FASTCALL ClearTrack(); // Clear the track
|
||||
int FASTCALL SearchTrack(DWORD lba) const; // Track search
|
||||
CDTrack* track[TrackMax]; // Track opbject references
|
||||
int tracks; // Effective number of track objects
|
||||
int dataindex; // Current data track
|
||||
int audioindex; // Current audio track
|
||||
|
||||
int frame;
|
||||
// Frame number
|
||||
int frame; // Frame number
|
||||
|
||||
#if 0
|
||||
CDDABuf da_buf;
|
||||
// CD-DA buffer
|
||||
int da_num;
|
||||
// Number of CD-DA tracks
|
||||
int da_cur;
|
||||
// CD-DA current track
|
||||
int da_next;
|
||||
// CD-DA next track
|
||||
BOOL da_req;
|
||||
// CD-DA data request
|
||||
#endif
|
||||
#if 0
|
||||
CDDABuf da_buf; // CD-DA buffer
|
||||
int da_num; // Number of CD-DA tracks
|
||||
int da_cur; // CD-DA current track
|
||||
int da_next; // CD-DA next track
|
||||
BOOL da_req; // CD-DA data request
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI hard disk ]
|
||||
// [ SCSI hard disk ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "scsihd.h"
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI hard disk ]
|
||||
//
|
||||
|
@ -28,17 +28,11 @@ class SCSIHD : public Disk
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSIHD();
|
||||
// Constructor
|
||||
void FASTCALL Reset();
|
||||
// Reset
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
SCSIHD(); // Constructor
|
||||
void FASTCALL Reset(); // Reset
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(
|
||||
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
|
||||
// MODE SELECT(6) command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); // MODE SELECT(6) command
|
||||
};
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
// [ SCSI Hard Disk for Apple Macintosh ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -26,14 +26,10 @@ class SCSIHD_APPLE : public SCSIHD
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSIHD_APPLE();
|
||||
// Constructor
|
||||
SCSIHD_APPLE(); // Constructor
|
||||
// commands
|
||||
int FASTCALL Inquiry(
|
||||
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
|
||||
// Internal processing
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
|
||||
// Add vendor special page
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
|
||||
};
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI NEC "Genuine" Hard Disk]
|
||||
// [ SCSI NEC "Genuine" Hard Disk]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI NEC "Genuine" Hard Disk]
|
||||
// [ SCSI NEC "Genuine" Hard Disk]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -26,36 +26,22 @@ class SCSIHD_NEC : public SCSIHD
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSIHD_NEC();
|
||||
// Constructor
|
||||
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
SCSIHD_NEC(); // Constructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(
|
||||
const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
|
||||
// Internal processing
|
||||
int FASTCALL AddError(BOOL change, BYTE *buf);
|
||||
// Add error
|
||||
int FASTCALL AddFormat(BOOL change, BYTE *buf);
|
||||
// Add format
|
||||
int FASTCALL AddDrive(BOOL change, BYTE *buf);
|
||||
// Add drive
|
||||
int FASTCALL AddError(BOOL change, BYTE *buf); // Add error
|
||||
int FASTCALL AddFormat(BOOL change, BYTE *buf); // Add format
|
||||
int FASTCALL AddDrive(BOOL change, BYTE *buf); // Add drive
|
||||
|
||||
private:
|
||||
int cylinders;
|
||||
// Number of cylinders
|
||||
int heads;
|
||||
// Number of heads
|
||||
int sectors;
|
||||
// Number of sectors
|
||||
int sectorsize;
|
||||
// Sector size
|
||||
off64_t imgoffset;
|
||||
// Image offset
|
||||
off64_t imgsize;
|
||||
// Image size
|
||||
int cylinders; // Number of cylinders
|
||||
int heads; // Number of heads
|
||||
int sectors; // Number of sectors
|
||||
int sectorsize; // Sector size
|
||||
off64_t imgoffset; // Image offset
|
||||
off64_t imgsize; // Image size
|
||||
};
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Magneto-Optical Disk]
|
||||
// [ SCSI Magneto-Optical Disk]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) akuker
|
||||
// Copyright (C) akuker
|
||||
//
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
// Licensed under the BSD 3-Clause License.
|
||||
// See LICENSE file in the project root folder.
|
||||
//
|
||||
// [ SCSI Magneto-Optical Disk]
|
||||
// [ SCSI Magneto-Optical Disk]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
@ -28,22 +28,16 @@ class SCSIMO : public Disk
|
|||
{
|
||||
public:
|
||||
// Basic Functions
|
||||
SCSIMO();
|
||||
// Constructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
|
||||
// Open
|
||||
#ifndef RASCSI
|
||||
BOOL FASTCALL Load(Fileio *fio, int ver);
|
||||
// Load
|
||||
#endif // RASCSI
|
||||
SCSIMO(); // Constructor
|
||||
BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); // Open
|
||||
#ifndef RASCSI
|
||||
BOOL FASTCALL Load(Fileio *fio, int ver); // Load
|
||||
#endif // RASCSI
|
||||
|
||||
// commands
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
|
||||
// INQUIRY command
|
||||
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
|
||||
// MODE SELECT(6) command
|
||||
int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); // INQUIRY command
|
||||
BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); // MODE SELECT(6) command
|
||||
|
||||
// Internal processing
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
|
||||
// Add vendor special page
|
||||
int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
|
||||
};
|
|
@ -1109,7 +1109,7 @@ int FASTCALL GPIOBUS::ReceiveHandShake(BYTE *buf, int count)
|
|||
// Data transmission handshake
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count)
|
||||
int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count, int delay_after_bytes)
|
||||
{
|
||||
int i;
|
||||
BOOL ret;
|
||||
|
@ -1120,6 +1120,11 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count)
|
|||
|
||||
if (actmode == TARGET) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if(i==delay_after_bytes){
|
||||
LOGTRACE("%s DELAYING for 100us after %d bytes", __PRETTY_FUNCTION__, (int)delay_after_bytes);
|
||||
SysTimer::SleepUsec(100);
|
||||
}
|
||||
|
||||
// Set the DATA signals
|
||||
SetDAT(*buf);
|
||||
|
||||
|
@ -1158,6 +1163,11 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count)
|
|||
phase = Aquire() & GPIO_MCI;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
if(i==delay_after_bytes){
|
||||
SysTimer::SleepUsec(100);
|
||||
}
|
||||
|
||||
// Set the DATA signals
|
||||
SetDAT(*buf);
|
||||
|
||||
|
|
|
@ -564,7 +564,7 @@ public:
|
|||
// Command receive handshake
|
||||
int FASTCALL ReceiveHandShake(BYTE *buf, int count);
|
||||
// Data receive handshake
|
||||
int FASTCALL SendHandShake(BYTE *buf, int count);
|
||||
int FASTCALL SendHandShake(BYTE *buf, int count, int delay_after_bytes);
|
||||
// Data transmission handshake
|
||||
|
||||
static BUS::phase_t FASTCALL GetPhaseRaw(DWORD raw_data);
|
||||
|
@ -645,7 +645,7 @@ private:
|
|||
DWORD signals; // All bus signals
|
||||
|
||||
#if defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
|
||||
struct gpioevent_request selevreq; // SEL signal event request
|
||||
struct gpioevent_request selevreq = {}; // SEL signal event request
|
||||
|
||||
int epfd; // epoll file descriptor
|
||||
#endif // USE_SEL_EVENT_ENABLE && !BAREMETAL
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
// Copyright (C) 2020-2021 akuker
|
||||
//
|
||||
// [ OS related definitions ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Run system command and wait for it to finish
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int run_system_cmd(const char* command)
|
||||
{
|
||||
pid_t pid;
|
||||
int result;
|
||||
int status = 0;
|
||||
pid=fork();
|
||||
if(pid == 0){
|
||||
result = system(command);
|
||||
exit(result);
|
||||
}
|
||||
waitpid(pid, &status, 0);
|
||||
return status;
|
||||
}
|
|
@ -155,7 +155,4 @@ typedef const char *LPCSTR;
|
|||
#define xstrcasecmp strcasecmp
|
||||
#define xstrncasecmp strncasecmp
|
||||
|
||||
// Run system command and wait for it to finish
|
||||
extern int run_system_cmd(const char* command);
|
||||
|
||||
#endif // os_h
|
||||
|
|
7
src/raspberrypi/os_integration/dhcpcd.conf.patch
Normal file
7
src/raspberrypi/os_integration/dhcpcd.conf.patch
Normal file
|
@ -0,0 +1,7 @@
|
|||
--- dhcpcd_orig.conf 2021-02-26 17:32:14.065284400 -0600
|
||||
+++ dhcpcd.conf 2021-02-26 17:32:30.925039567 -0600
|
||||
@@ -58,3 +58,4 @@
|
||||
#interface eth0
|
||||
#fallback static_eth0
|
||||
#
|
||||
+denyinterfaces eth0
|
13
src/raspberrypi/os_integration/rascsi_bridge
Normal file
13
src/raspberrypi/os_integration/rascsi_bridge
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Defines the 'rascsi_bridge' bridge that connects the RaSCSI network
|
||||
# interface (ex DaynaPort SCSI/Link) to the outside world.
|
||||
#
|
||||
# Depending upon your system configuration, you may need to update this
|
||||
# file to change 'eth0' to your Ethernet interface
|
||||
#
|
||||
# This file should be place in /etc/network/interfaces.d
|
||||
|
||||
auto rascsi_bridge
|
||||
iface rascsi_bridge inet dhcp
|
||||
bridge_ports eth0
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
#include "rascsi_version.h"
|
||||
#include "rasctl.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||
#include <spdlog/async.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -57,6 +59,7 @@ FATFS fatfs; // FatFS
|
|||
#else
|
||||
int monsocket; // Monitor Socket
|
||||
pthread_t monthread; // Monitor Thread
|
||||
pthread_mutex_t ctrl_mutex; // Semaphore for the ctrl array
|
||||
static void *MonThread(void *param);
|
||||
#endif // BAREMETAL
|
||||
|
||||
|
@ -126,7 +129,13 @@ BOOL Init()
|
|||
|
||||
#ifndef BAREMETAL
|
||||
struct sockaddr_in server;
|
||||
int yes;
|
||||
int yes, result;
|
||||
|
||||
result = pthread_mutex_init(&ctrl_mutex,NULL);
|
||||
if(result != EXIT_SUCCESS){
|
||||
LOGERROR("Unable to create a mutex. Err code: %d",result);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create socket for monitor
|
||||
monsocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
@ -228,6 +237,8 @@ void Cleanup()
|
|||
if (monsocket >= 0) {
|
||||
close(monsocket);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&ctrl_mutex);
|
||||
#endif // BAREMETAL
|
||||
}
|
||||
|
||||
|
@ -342,6 +353,9 @@ void MapControler(FILE *fp, Disk **map)
|
|||
int sasi_num;
|
||||
int scsi_num;
|
||||
|
||||
// Take ownership of the ctrl data structure
|
||||
pthread_mutex_lock(&ctrl_mutex);
|
||||
|
||||
// Replace the changed unit
|
||||
for (i = 0; i < CtrlMax; i++) {
|
||||
for (j = 0; j < UnitNum; j++) {
|
||||
|
@ -442,6 +456,7 @@ void MapControler(FILE *fp, Disk **map)
|
|||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&ctrl_mutex);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -543,7 +558,7 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
|
|||
}
|
||||
|
||||
// drive checks files
|
||||
if (type <= rasctl_dev_scsi_hd || (type <= rasctl_dev_cd && xstrcasecmp(file, "-") != 0)) {
|
||||
if (type <= rasctl_dev_scsi_hd || ((type <= rasctl_dev_cd || type == rasctl_dev_daynaport) && xstrcasecmp(file, "-") != 0)) {
|
||||
// Set the Path
|
||||
filepath.SetPath(file);
|
||||
|
||||
|
@ -911,13 +926,15 @@ bool ParseArgument(int argc, char* argv[])
|
|||
|| has_suffix(path, ".hdi")
|
||||
|| has_suffix(path, ".hda")
|
||||
|| has_suffix(path, ".nhd")) {
|
||||
type = 0;
|
||||
type = rasctl_dev_sasi_hd;
|
||||
} else if (has_suffix(path, ".mos")) {
|
||||
type = 2;
|
||||
type = rasctl_dev_mo;
|
||||
} else if (has_suffix(path, ".iso")) {
|
||||
type = 3;
|
||||
type = rasctl_dev_cd;
|
||||
} else if (xstrcasecmp(path, "bridge") == 0) {
|
||||
type = 4;
|
||||
type = rasctl_dev_br;
|
||||
} else if (xstrcasecmp(path, "daynaport") == 0) {
|
||||
type = rasctl_dev_daynaport;
|
||||
} else {
|
||||
// Cannot determine the file type
|
||||
fprintf(stderr,
|
||||
|
@ -1110,6 +1127,9 @@ int main(int argc, char* argv[])
|
|||
#endif // BAREMETAL
|
||||
|
||||
spdlog::set_level(spdlog::level::trace);
|
||||
// Create a thread-safe stdout logger to process the log messages
|
||||
auto logger = spdlog::stdout_color_mt("rascsi stdout logger");
|
||||
|
||||
LOGTRACE("Entering the function %s with %d arguments", __PRETTY_FUNCTION__, argc);
|
||||
// Output the Banner
|
||||
Banner(argc, argv);
|
||||
|
@ -1205,6 +1225,8 @@ int main(int argc, char* argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&ctrl_mutex);
|
||||
|
||||
// Notify all controllers
|
||||
data = bus->GetDAT();
|
||||
for (i = 0; i < CtrlMax; i++) {
|
||||
|
@ -1225,6 +1247,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
// Return to bus monitoring if the selection phase has not started
|
||||
if (phase != BUS::selection) {
|
||||
pthread_mutex_unlock(&ctrl_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1247,6 +1270,8 @@ int main(int argc, char* argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&ctrl_mutex);
|
||||
|
||||
|
||||
#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
|
||||
// Set the scheduling priority back to normal
|
||||
|
|
|
@ -125,7 +125,7 @@ public:
|
|||
// コマンド受信ハンドシェイク
|
||||
virtual int FASTCALL ReceiveHandShake(BYTE *buf, int count) = 0;
|
||||
// データ受信ハンドシェイク
|
||||
virtual int FASTCALL SendHandShake(BYTE *buf, int count) = 0;
|
||||
virtual int FASTCALL SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
||||
// データ送信ハンドシェイク
|
||||
|
||||
|
||||
|
@ -133,6 +133,8 @@ public:
|
|||
// Get SCSI input signal value
|
||||
virtual void FASTCALL SetSignal(int pin, BOOL ast) = 0;
|
||||
// Set SCSI output signal value
|
||||
static const int SEND_NO_DELAY = -1;
|
||||
// Passed into SendHandShake when we don't want to delay
|
||||
protected:
|
||||
phase_t m_current_phase = phase_t::reserved;
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
sudo brctl addbr rascsi_bridge
|
||||
sudo brctl addif rascsi_bridge eth0
|
||||
sudo ip link set dev rascsi_bridge up
|
||||
|
||||
echo Bridge config:
|
||||
brctl show
|
|
@ -7,39 +7,39 @@ from settings import *
|
|||
def make_cd(file_path, file_type, file_creator):
|
||||
with open(file_path, "rb") as f:
|
||||
file_bytes = f.read()
|
||||
file_name = file_path.split('/')[-1]
|
||||
file_suffix = file_name.split('.')[-1]
|
||||
file_name = file_path.split("/")[-1]
|
||||
file_suffix = file_name.split(".")[-1]
|
||||
|
||||
if file_type is None and file_creator is None:
|
||||
if file_suffix.lower() == 'sea':
|
||||
file_type = '.sea'
|
||||
file_creator = 'APPL'
|
||||
if file_suffix.lower() == "sea":
|
||||
file_type = ".sea"
|
||||
file_creator = "APPL"
|
||||
|
||||
v = Volume()
|
||||
v.name = "TestName"
|
||||
|
||||
v['Folder'] = Folder()
|
||||
v["Folder"] = Folder()
|
||||
|
||||
v['Folder'][file_name] = File()
|
||||
v['Folder'][file_name].data = file_bytes
|
||||
v['Folder'][file_name].rsrc = b''
|
||||
v["Folder"][file_name] = File()
|
||||
v["Folder"][file_name].data = file_bytes
|
||||
v["Folder"][file_name].rsrc = b""
|
||||
if not (file_type is None and file_creator is None):
|
||||
v['Folder'][file_name].type = bytearray(file_type)
|
||||
v['Folder'][file_name].creator = bytearray(file_creator)
|
||||
v["Folder"][file_name].type = bytearray(file_type)
|
||||
v["Folder"][file_name].creator = bytearray(file_creator)
|
||||
|
||||
padding = (len(file_bytes) % 512) + (512 * 50)
|
||||
print("mod", str(len(file_bytes) % 512))
|
||||
print("padding " + str(padding))
|
||||
print("len " + str(len(file_bytes)))
|
||||
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(
|
||||
size=len(file_bytes) + padding,
|
||||
align=512, # Allocation block alignment modulus (2048 for CDs)
|
||||
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
|
||||
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)
|
||||
|
||||
return base_dir + 'test.hda'
|
||||
return base_dir + "test.hda"
|
||||
|
|
|
@ -5,8 +5,9 @@ import time
|
|||
|
||||
from ractl_cmds import attach_image
|
||||
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):
|
||||
|
@ -15,8 +16,10 @@ def create_new_image(file_name, type, size):
|
|||
else:
|
||||
file_name = file_name + "." + type
|
||||
|
||||
return subprocess.run(["dd", "if=/dev/zero", "of=" + base_dir + file_name, "bs=1M", "count=" + size],
|
||||
capture_output=True)
|
||||
return subprocess.run(
|
||||
["dd", "if=/dev/zero", "of=" + base_dir + file_name, "bs=1M", "count=" + size],
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
|
||||
def delete_image(file_name):
|
||||
|
@ -30,18 +33,24 @@ def delete_image(file_name):
|
|||
|
||||
def unzip_file(file_name):
|
||||
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)
|
||||
return True
|
||||
|
||||
|
||||
def rascsi_service(action):
|
||||
# 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):
|
||||
import urllib.request
|
||||
file_name = url.split('/')[-1]
|
||||
|
||||
file_name = url.split("/")[-1]
|
||||
tmp_ts = int(time.time())
|
||||
tmp_dir = "/tmp/" + str(tmp_ts) + "/"
|
||||
os.mkdir(tmp_dir)
|
||||
|
@ -50,15 +59,18 @@ def download_file_to_iso(scsi_id, url):
|
|||
|
||||
urllib.request.urlretrieve(url, tmp_full_path)
|
||||
# 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:
|
||||
return iso_proc
|
||||
return attach_image(scsi_id, iso_filename, "cd")
|
||||
return attach_image(scsi_id, iso_filename, "SCCD")
|
||||
|
||||
|
||||
def download_image(url):
|
||||
import urllib.request
|
||||
file_name = url.split('/')[-1]
|
||||
|
||||
file_name = url.split("/")[-1]
|
||||
full_path = base_dir + file_name
|
||||
|
||||
urllib.request.urlretrieve(url, full_path)
|
||||
|
|
12
src/web/mock/bin/brctl
Normal file
12
src/web/mock/bin/brctl
Normal 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
12
src/web/mock/bin/ip
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Mock responses to rascsi-web
|
||||
case $1 in
|
||||
"link")
|
||||
echo "link here"
|
||||
;;
|
||||
|
||||
**)
|
||||
echo "default"
|
||||
;;
|
||||
esac
|
|
@ -3,7 +3,10 @@ import subprocess
|
|||
|
||||
def rascsi_service(action):
|
||||
# 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():
|
||||
|
@ -15,6 +18,14 @@ def shutdown_pi():
|
|||
|
||||
|
||||
def running_version():
|
||||
ra_web_version = 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()
|
||||
ra_web_version = (
|
||||
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
|
||||
|
|
|
@ -4,8 +4,9 @@ import subprocess
|
|||
import re
|
||||
|
||||
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
|
||||
EXCLUDE_SCSI_IDS = [7]
|
||||
|
||||
|
@ -20,19 +21,36 @@ def list_files():
|
|||
for path, dirs, files in os.walk(base_dir):
|
||||
# Only list valid file types
|
||||
files = [f for f in files if re.match(valid_file_types, f)]
|
||||
files_list.extend([
|
||||
(os.path.join(path, file),
|
||||
# TODO: move formatting to template
|
||||
'{:,.0f}'.format(os.path.getsize(os.path.join(path, file)) / float(1 << 20)) + " MB")
|
||||
for file in files])
|
||||
files_list.extend(
|
||||
[
|
||||
(
|
||||
os.path.join(path, file),
|
||||
# TODO: move formatting to template
|
||||
"{:,.0f}".format(
|
||||
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
|
||||
|
||||
|
||||
def get_valid_scsi_ids(devices):
|
||||
invalid_list = EXCLUDE_SCSI_IDS.copy()
|
||||
for device in devices:
|
||||
if device['file'] != "NO MEDIA" and device['file'] != "-":
|
||||
invalid_list.append(int(device['id']))
|
||||
if device["file"] != "NO MEDIA" and device["file"] != "-":
|
||||
invalid_list.append(int(device["id"]))
|
||||
|
||||
valid_list = list(range(8))
|
||||
for id in invalid_list:
|
||||
|
@ -46,19 +64,33 @@ def get_type(scsi_id):
|
|||
return list_devices()[int(scsi_id)]["type"]
|
||||
|
||||
|
||||
def attach_image(scsi_id, image, type):
|
||||
if type == "cd" and get_type(scsi_id) == "SCCD":
|
||||
def attach_image(scsi_id, image, device_type):
|
||||
if device_type == "SCCD" and get_type(scsi_id) == "SCCD":
|
||||
return insert(scsi_id, image)
|
||||
elif device_type == "SCDP":
|
||||
attach_daynaport(scsi_id)
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
|
@ -66,33 +98,67 @@ def eject_by_id(scsi_id):
|
|||
|
||||
|
||||
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):
|
||||
# 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():
|
||||
device_list = []
|
||||
for id in range(8):
|
||||
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():
|
||||
# Valid line to process, continue
|
||||
if not line.startswith("+") and \
|
||||
not line.startswith("| ID |") and \
|
||||
(not line.startswith("No device is installed.") or line.startswith("No images currently attached.")) \
|
||||
and len(line) > 0:
|
||||
if (
|
||||
not line.startswith("+")
|
||||
and not line.startswith("| ID |")
|
||||
and (
|
||||
not line.startswith("No device is installed.")
|
||||
or line.startswith("No images currently attached.")
|
||||
)
|
||||
and len(line) > 0
|
||||
):
|
||||
line.rstrip()
|
||||
device = {}
|
||||
segments = line.split("|")
|
||||
if len(segments) > 4:
|
||||
idx = int(segments[1].strip())
|
||||
device_list[idx]["id"] = str(idx)
|
||||
device_list[idx]['un'] = segments[2].strip()
|
||||
device_list[idx]['type'] = segments[3].strip()
|
||||
device_list[idx]['file'] = segments[4].strip()
|
||||
device_list[idx]["un"] = segments[2].strip()
|
||||
device_list[idx]["type"] = segments[3].strip()
|
||||
device_list[idx]["file"] = segments[4].strip()
|
||||
|
||||
return device_list
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import os
|
||||
|
||||
base_dir = os.getenv('BASE_DIR', "/home/pi/images/")
|
||||
MAX_FILE_SIZE = os.getenv('MAX_FILE_SIZE', 1024 * 1024 * 1024 * 2) # 2gb
|
||||
base_dir = os.getenv("BASE_DIR", "/home/pi/images/")
|
||||
MAX_FILE_SIZE = os.getenv("MAX_FILE_SIZE", 1024 * 1024 * 1024 * 2) # 2gb
|
||||
|
|
|
@ -17,10 +17,26 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<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">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -103,7 +119,35 @@
|
|||
</table>
|
||||
|
||||
<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>
|
||||
<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">
|
||||
|
@ -183,7 +227,6 @@
|
|||
</table>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h2>Raspberry Pi Operations</h2>
|
||||
<table style="border: none">
|
||||
<tr style="border: none">
|
||||
|
|
288
src/web/web.py
288
src/web/web.py
|
@ -1,206 +1,298 @@
|
|||
import os
|
||||
|
||||
from flask import Flask, render_template, request, flash, url_for, redirect, send_file
|
||||
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 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 *
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
devices = list_devices()
|
||||
scsi_ids = get_valid_scsi_ids(devices)
|
||||
return render_template('index.html',
|
||||
devices=devices,
|
||||
active=is_active(),
|
||||
files=list_files(),
|
||||
base_dir=base_dir,
|
||||
scsi_ids=scsi_ids,
|
||||
max_file_size=MAX_FILE_SIZE,
|
||||
version=running_version())
|
||||
return render_template(
|
||||
"index.html",
|
||||
bridge_configured=is_bridge_setup("eth0"),
|
||||
devices=devices,
|
||||
active=is_active(),
|
||||
files=list_files(),
|
||||
config_files=list_config_files(),
|
||||
base_dir=base_dir,
|
||||
scsi_ids=scsi_ids,
|
||||
max_file_size=MAX_FILE_SIZE,
|
||||
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():
|
||||
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)
|
||||
|
||||
if process.returncode == 0:
|
||||
headers = { 'content-type':'text/plain' }
|
||||
headers = {"content-type": "text/plain"}
|
||||
return process.stdout.decode("utf-8"), 200, headers
|
||||
else:
|
||||
flash(u'Failed to get logs')
|
||||
flash(process.stdout.decode("utf-8"), 'stdout')
|
||||
flash(process.stderr.decode("utf-8"), 'stderr')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to get logs")
|
||||
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'])
|
||||
@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():
|
||||
file_name = request.form.get('file_name')
|
||||
scsi_id = request.form.get('scsi_id')
|
||||
file_name = request.form.get("file_name")
|
||||
scsi_id = request.form.get("scsi_id")
|
||||
|
||||
# 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"
|
||||
elif file_name.lower().endswith('.hda'):
|
||||
elif file_name.lower().endswith(".hda"):
|
||||
image_type = "hd"
|
||||
else:
|
||||
flash(u'Unknown file type. Valid files are .iso, .hda, .cdr', 'error')
|
||||
return redirect(url_for('index'))
|
||||
flash("Unknown file type. Valid files are .iso, .hda, .cdr", "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
process = attach_image(scsi_id, file_name, image_type)
|
||||
if process.returncode == 0:
|
||||
flash('Attached '+ file_name + " to scsi id " + scsi_id + "!")
|
||||
return redirect(url_for('index'))
|
||||
flash(f"Attached {file_name} to SCSI id {scsi_id}!")
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u'Failed to attach '+ file_name + " 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'))
|
||||
flash(f"Failed to attach {file_name} 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('/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():
|
||||
scsi_id = request.form.get('scsi_id')
|
||||
scsi_id = request.form.get("scsi_id")
|
||||
process = detach_by_id(scsi_id)
|
||||
if process.returncode == 0:
|
||||
flash("Detached scsi id " + scsi_id + "!")
|
||||
return redirect(url_for('index'))
|
||||
flash("Detached SCSI id " + scsi_id + "!")
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to detach scsi id " + scsi_id + "!", 'error')
|
||||
flash(process.stdout, 'stdout')
|
||||
flash(process.stderr, 'stderr')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to detach SCSI id " + scsi_id + "!", "error")
|
||||
flash(process.stdout, "stdout")
|
||||
flash(process.stderr, "stderr")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route('/scsi/eject', methods=['POST'])
|
||||
@app.route("/scsi/eject", methods=["POST"])
|
||||
def eject():
|
||||
scsi_id = request.form.get('scsi_id')
|
||||
scsi_id = request.form.get("scsi_id")
|
||||
process = eject_by_id(scsi_id)
|
||||
if process.returncode == 0:
|
||||
flash("Ejected scsi id " + scsi_id + "!")
|
||||
return redirect(url_for('index'))
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to eject scsi id " + scsi_id + "!", 'error')
|
||||
flash(process.stdout, 'stdout')
|
||||
flash(process.stderr, 'stderr')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to eject SCSI id " + scsi_id + "!", "error")
|
||||
flash(process.stdout, "stdout")
|
||||
flash(process.stderr, "stderr")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route('/pi/reboot', methods=['POST'])
|
||||
@app.route("/pi/reboot", methods=["POST"])
|
||||
def restart():
|
||||
reboot_pi()
|
||||
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():
|
||||
rascsi_service("restart")
|
||||
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():
|
||||
shutdown_pi()
|
||||
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():
|
||||
scsi_id = request.form.get('scsi_id')
|
||||
url = request.form.get('url')
|
||||
scsi_id = request.form.get("scsi_id")
|
||||
url = request.form.get("url")
|
||||
process = download_file_to_iso(scsi_id, url)
|
||||
if process.returncode == 0:
|
||||
flash("File Downloaded")
|
||||
return redirect(url_for('index'))
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to download file", 'error')
|
||||
flash(process.stdout, 'stdout')
|
||||
flash(process.stderr, 'stderr')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to download file", "error")
|
||||
flash(process.stdout, "stdout")
|
||||
flash(process.stderr, "stderr")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route('/files/download_image', methods=['POST'])
|
||||
@app.route("/files/download_image", methods=["POST"])
|
||||
def download_img():
|
||||
url = request.form.get('url')
|
||||
url = request.form.get("url")
|
||||
# TODO: error handling
|
||||
download_image(url)
|
||||
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():
|
||||
if 'file' not in request.files:
|
||||
flash('No file part', 'error')
|
||||
return redirect(url_for('index'))
|
||||
file = request.files['file']
|
||||
if "file" not in request.files:
|
||||
flash("No file part", "error")
|
||||
return redirect(url_for("index"))
|
||||
file = request.files["file"]
|
||||
if file:
|
||||
filename = secure_filename(file.filename)
|
||||
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
|
||||
return redirect(url_for('index', filename=filename))
|
||||
file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
|
||||
return redirect(url_for("index", filename=filename))
|
||||
|
||||
|
||||
@app.route('/files/create', methods=['POST'])
|
||||
@app.route("/files/create", methods=["POST"])
|
||||
def create_file():
|
||||
file_name = request.form.get('file_name')
|
||||
size = request.form.get('size')
|
||||
type = request.form.get('type')
|
||||
file_name = request.form.get("file_name")
|
||||
size = request.form.get("size")
|
||||
type = request.form.get("type")
|
||||
|
||||
process = create_new_image(file_name, type, size)
|
||||
if process.returncode == 0:
|
||||
flash("Drive created")
|
||||
return redirect(url_for('index'))
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to create file", 'error')
|
||||
flash(process.stdout, 'stdout')
|
||||
flash(process.stderr, 'stderr')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to create file", "error")
|
||||
flash(process.stdout, "stdout")
|
||||
flash(process.stderr, "stderr")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route('/files/download', methods=['POST'])
|
||||
@app.route("/files/download", methods=["POST"])
|
||||
def download():
|
||||
image = request.form.get('image')
|
||||
image = request.form.get("image")
|
||||
return send_file(base_dir + image, as_attachment=True)
|
||||
|
||||
|
||||
@app.route('/files/delete', methods=['POST'])
|
||||
@app.route("/files/delete", methods=["POST"])
|
||||
def delete():
|
||||
image = request.form.get('image')
|
||||
image = request.form.get("image")
|
||||
if delete_image(image):
|
||||
flash("File " + image + " deleted")
|
||||
return redirect(url_for('index'))
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to Delete " + image, 'error')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to Delete " + image, "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route('/files/unzip', methods=['POST'])
|
||||
@app.route("/files/unzip", methods=["POST"])
|
||||
def unzip():
|
||||
image = request.form.get('image')
|
||||
image = request.form.get("image")
|
||||
|
||||
if unzip_file(image):
|
||||
flash("Unzipped file " + image)
|
||||
return redirect(url_for('index'))
|
||||
return redirect(url_for("index"))
|
||||
else:
|
||||
flash(u"Failed to unzip " + image, 'error')
|
||||
return redirect(url_for('index'))
|
||||
flash("Failed to unzip " + image, "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.secret_key = 'rascsi_is_awesome_insecure_secret_key'
|
||||
app.config['SESSION_TYPE'] = 'filesystem'
|
||||
app.config['UPLOAD_FOLDER'] = base_dir
|
||||
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
||||
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE
|
||||
app.secret_key = "rascsi_is_awesome_insecure_secret_key"
|
||||
app.config["SESSION_TYPE"] = "filesystem"
|
||||
app.config["UPLOAD_FOLDER"] = base_dir
|
||||
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
|
||||
app.config["MAX_CONTENT_LENGTH"] = MAX_FILE_SIZE
|
||||
|
||||
from waitress import serve
|
||||
|
||||
serve(app, host="0.0.0.0", port=8080)
|
||||
|
|
Loading…
Reference in New Issue
Block a user