mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-26 07:29:31 +00:00
Merge branch 'develop' into bug_335_cache_fix_selectable
This commit is contained in:
commit
401ecc5118
|
@ -73,7 +73,7 @@ The rascsi server port, default is 6868.
|
||||||
.BR \-r\fI " " \fIRESERVED_IDS
|
.BR \-r\fI " " \fIRESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve.
|
Comma-separated list of IDs to reserve.
|
||||||
.BR \-p\fI " " \fITYPE
|
.BR \-p\fI " " \fITYPE
|
||||||
The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP). If no type is specified for devices that support an image file, rascsi tries to derive the type from the file extension.
|
The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP, SCHS). If no type is specified for devices that support an image file, rascsi tries to derive the type from the file extension.
|
||||||
.TP
|
.TP
|
||||||
.BR \-v\fI " " \fI
|
.BR \-v\fI " " \fI
|
||||||
Display the rascsi version.
|
Display the rascsi version.
|
||||||
|
@ -84,7 +84,7 @@ Overrides the default locale for client-faces error messages. The client can ove
|
||||||
.BR \-ID\fIn[:u] " " \fIFILE
|
.BR \-ID\fIn[:u] " " \fIFILE
|
||||||
n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0.
|
n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0.
|
||||||
.IP
|
.IP
|
||||||
FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP) a dummy name must be provided.
|
FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP, SCHS) a dummy name must be provided.
|
||||||
.TP
|
.TP
|
||||||
.BR \-HD\fIn[:u] " " \fIFILE
|
.BR \-HD\fIn[:u] " " \fIFILE
|
||||||
n is the SASI ID number (0-15). The effective SASI ID is calculated as n/2, the effective SASI LUN is calculated is the remainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1).
|
n is the SASI ID number (0-15). The effective SASI ID is calculated as n/2, the effective SASI LUN is calculated is the remainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1).
|
||||||
|
@ -101,7 +101,7 @@ Launch RaSCSI with an Apple hard drive image as ID 0 and a CD-ROM as ID 2
|
||||||
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
|
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
|
||||||
|
|
||||||
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw device file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter as ID 6:
|
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw device file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter as ID 6:
|
||||||
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
|
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp daynaport
|
||||||
|
|
||||||
To create an empty, 100MB HD image, use the following command:
|
To create an empty, 100MB HD image, use the following command:
|
||||||
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||||
|
|
|
@ -93,9 +93,9 @@ OPTIONS
|
||||||
-r RESERVED_IDS
|
-r RESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve. -p TYPE The optional
|
Comma-separated list of IDs to reserve. -p TYPE The optional
|
||||||
case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
|
case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
|
||||||
SCBR, SCDP). If no type is specified for devices that support an
|
SCBR, SCDP, SCHS). If no type is specified for devices that sup‐
|
||||||
image file, rascsi tries to derive the type from the file exten‐
|
port an image file, rascsi tries to derive the type from the
|
||||||
sion.
|
file extension.
|
||||||
|
|
||||||
-v Display the rascsi version.
|
-v Display the rascsi version.
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ OPTIONS
|
||||||
(logical unit). The default LUN is 0.
|
(logical unit). The default LUN is 0.
|
||||||
|
|
||||||
FILE is the name of the image file to use for the SCSI device.
|
FILE is the name of the image file to use for the SCSI device.
|
||||||
For devices that do not support an image file (SCBR, SCDP) a
|
For devices that do not support an image file (SCBR, SCDP, SCHS)
|
||||||
dummy name must be provided.
|
a dummy name must be provided.
|
||||||
|
|
||||||
-HDn[:u] FILE
|
-HDn[:u] FILE
|
||||||
n is the SASI ID number (0-15). The effective SASI ID is calcu‐
|
n is the SASI ID number (0-15). The effective SASI ID is calcu‐
|
||||||
|
@ -133,7 +133,7 @@ EXAMPLES
|
||||||
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de‐
|
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de‐
|
||||||
vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter
|
vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter
|
||||||
as ID 6:
|
as ID 6:
|
||||||
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
|
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp daynaport
|
||||||
|
|
||||||
To create an empty, 100MB HD image, use the following command:
|
To create an empty, 100MB HD image, use the following command:
|
||||||
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||||
|
|
|
@ -148,7 +148,8 @@ Specifies the device type. This type overrides the type derived from the file ex
|
||||||
cd: CD-ROM
|
cd: CD-ROM
|
||||||
mo: Magneto-Optical disk
|
mo: Magneto-Optical disk
|
||||||
bridge: Bridge device (Only applicable to the Sharp X68000)
|
bridge: Bridge device (Only applicable to the Sharp X68000)
|
||||||
daynaport: DaynaPORT network adapter
|
daynaport: DaynaPort network adapter
|
||||||
|
services: Host services device
|
||||||
.TP
|
.TP
|
||||||
.BR \-n\fI " " \fIVENDOR:PRODUCT:REVISION
|
.BR \-n\fI " " \fIVENDOR:PRODUCT:REVISION
|
||||||
The vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is automatically applied. Once set the name of a device cannot be changed.
|
The vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is automatically applied. Once set the name of a device cannot be changed.
|
||||||
|
|
|
@ -128,7 +128,8 @@ OPTIONS
|
||||||
cd: CD-ROM
|
cd: CD-ROM
|
||||||
mo: Magneto-Optical disk
|
mo: Magneto-Optical disk
|
||||||
bridge: Bridge device (Only applicable to the Sharp X68000)
|
bridge: Bridge device (Only applicable to the Sharp X68000)
|
||||||
daynaport: DaynaPORT network adapter
|
daynaport: DaynaPort network adapter
|
||||||
|
services: Host services device
|
||||||
|
|
||||||
-n VENDOR:PRODUCT:REVISION
|
-n VENDOR:PRODUCT:REVISION
|
||||||
The vendor, product and revision for the device, to be returned
|
The vendor, product and revision for the device, to be returned
|
||||||
|
|
|
@ -7,6 +7,7 @@ from os import getcwd
|
||||||
WORK_DIR = getcwd()
|
WORK_DIR = getcwd()
|
||||||
|
|
||||||
REMOVABLE_DEVICE_TYPES = ("SCCD", "SCRM", "SCMO")
|
REMOVABLE_DEVICE_TYPES = ("SCCD", "SCRM", "SCMO")
|
||||||
|
NETWORK_DEVICE_TYPES = ("SCDP", "SCBR")
|
||||||
|
|
||||||
# There may be a more elegant way to get the HOME dir of the user that installed RaSCSI
|
# There may be a more elegant way to get the HOME dir of the user that installed RaSCSI
|
||||||
HOME_DIR = "/".join(WORK_DIR.split("/")[0:3])
|
HOME_DIR = "/".join(WORK_DIR.split("/")[0:3])
|
||||||
|
|
|
@ -9,7 +9,7 @@ $ python3 -m venv venv
|
||||||
$ source venv/bin/activate
|
$ source venv/bin/activate
|
||||||
# Install requirements
|
# Install requirements
|
||||||
$ pip3 install -r requirements.txt
|
$ pip3 install -r requirements.txt
|
||||||
$ python3 src/rascsi_oled_monitor.py
|
$ PYTHONPATH=$PWD/src:$(dirname $PWD)/common/src python3 src/rascsi_oled_monitor.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
@ -20,7 +20,7 @@ The script takes two positional parameters:
|
||||||
|
|
||||||
Ex.
|
Ex.
|
||||||
```
|
```
|
||||||
$ python3 rascsi_oled_monitor.py 180 64
|
$ python3 rascsi_oled_monitor.py --rotation 180 --height 64
|
||||||
```
|
```
|
||||||
|
|
||||||
_Note:_ Both parameters must be passed for the script to read them. Ordering is also important.
|
_Note:_ Both parameters must be passed for the script to read them. Ordering is also important.
|
||||||
|
|
|
@ -43,6 +43,11 @@ from pi_cmds import get_ip_and_host
|
||||||
from rascsi.ractl_cmds import RaCtlCmds
|
from rascsi.ractl_cmds import RaCtlCmds
|
||||||
from rascsi.socket_cmds import SocketCmds
|
from rascsi.socket_cmds import SocketCmds
|
||||||
|
|
||||||
|
from rascsi.common_settings import (
|
||||||
|
REMOVABLE_DEVICE_TYPES,
|
||||||
|
NETWORK_DEVICE_TYPES,
|
||||||
|
)
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="RaSCSI OLED Monitor script")
|
parser = argparse.ArgumentParser(description="RaSCSI OLED Monitor script")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--rotation",
|
"--rotation",
|
||||||
|
@ -174,20 +179,17 @@ def formatted_output():
|
||||||
output.append("Permission denied!")
|
output.append("Permission denied!")
|
||||||
elif rascsi_list:
|
elif rascsi_list:
|
||||||
for line in rascsi_list:
|
for line in rascsi_list:
|
||||||
if line["device_type"] in ("SCCD", "SCRM", "SCMO"):
|
if line["device_type"] in REMOVABLE_DEVICE_TYPES:
|
||||||
# Print image file name only when there is an image attached
|
# Print image file name only when there is an image attached
|
||||||
if line["file"]:
|
if line["file"]:
|
||||||
output.append(f"{line['id']} {line['device_type'][2:4]} "
|
output.append(f"{line['id']} {line['device_type'][2:4]} "
|
||||||
f"{line['file']} {line['status']}")
|
f"{line['file']} {line['status']}")
|
||||||
else:
|
else:
|
||||||
output.append(f"{line['id']} {line['device_type'][2:4]} {line['status']}")
|
output.append(f"{line['id']} {line['device_type'][2:4]} {line['status']}")
|
||||||
# Special handling for the DaynaPort device
|
# Special handling for network devices
|
||||||
elif line["device_type"] == "SCDP":
|
elif line["device_type"] in NETWORK_DEVICE_TYPES:
|
||||||
output.append(f"{line['id']} {line['device_type'][2:4]} {line['vendor']} "
|
output.append(f"{line['id']} {line['device_type'][2:4]} {line['vendor']} "
|
||||||
f"{line['product']}")
|
f"{line['product']}")
|
||||||
# Special handling for the Host Bridge device
|
|
||||||
elif line["device_type"] == "SCBR":
|
|
||||||
output.append(f"{line['id']} {line['device_type'][2:4]} {line['product']}")
|
|
||||||
# Print only the Vendor/Product info if it's not generic RaSCSI
|
# Print only the Vendor/Product info if it's not generic RaSCSI
|
||||||
elif line["vendor"] not in "RaSCSI":
|
elif line["vendor"] not in "RaSCSI":
|
||||||
output.append(f"{line['id']} {line['device_type'][2:4]} {line['file']} "
|
output.append(f"{line['id']} {line['device_type'][2:4]} {line['file']} "
|
||||||
|
|
|
@ -57,7 +57,7 @@ def extend_device_names(device_types):
|
||||||
Takes a (list) of (str) device_types with the four letter device acronyms
|
Takes a (list) of (str) device_types with the four letter device acronyms
|
||||||
Returns a (dict) of device_type:device_name mappings of localized device names
|
Returns a (dict) of device_type:device_name mappings of localized device names
|
||||||
"""
|
"""
|
||||||
mapped_device_types = []
|
mapped_device_types = {}
|
||||||
for device_type in device_types:
|
for device_type in device_types:
|
||||||
if device_type is "SAHD":
|
if device_type is "SAHD":
|
||||||
device_name = _("SASI Hard Drive")
|
device_name = _("SASI Hard Drive")
|
||||||
|
@ -75,6 +75,6 @@ def extend_device_names(device_types):
|
||||||
device_name = _("DaynaPORT SCSI/Link")
|
device_name = _("DaynaPORT SCSI/Link")
|
||||||
else:
|
else:
|
||||||
device_name = _("Unknown Device")
|
device_name = _("Unknown Device")
|
||||||
mapped_device_types.append({device_type: device_name})
|
mapped_device_types[device_type] = device_name
|
||||||
|
|
||||||
return mapped_device_types
|
return mapped_device_types
|
||||||
|
|
|
@ -260,27 +260,19 @@
|
||||||
<input name="unit" type="number" size="2" value="0" min="0" max="31">
|
<input name="unit" type="number" size="2" value="0" min="0" max="31">
|
||||||
{% if file["detected_type"] != "UNDEFINED" %}
|
{% if file["detected_type"] != "UNDEFINED" %}
|
||||||
<input name="type" type="hidden" value="{{ file['detected_type'] }}">
|
<input name="type" type="hidden" value="{{ file['detected_type'] }}">
|
||||||
{% for device in device_types %}
|
{{ file['detected_type_name'] }}
|
||||||
{% for key, value in device.items() %}
|
|
||||||
{% if file["detected_type"] == key %}
|
|
||||||
{{ value }}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<select name="type">
|
<select name="type">
|
||||||
<option selected value="">
|
<option selected disabled value="">
|
||||||
{{ _("Type") }}
|
{{ _("Select device type") }}
|
||||||
</option>
|
</option>
|
||||||
{% for device in device_types %}
|
{% for key, value in device_types.items() %}
|
||||||
{% for key, value in device.items() %}
|
{% if key not in NETWORK_DEVICE_TYPES %}
|
||||||
{% if key not in ("SCBR", "SCDP") %}
|
|
||||||
<option value="{{ key }}">
|
<option value="{{ key }}">
|
||||||
{{ value }}
|
{{ value }}
|
||||||
</option>
|
</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
|
||||||
</select>
|
</select>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type="submit" value="{{ _("Attach") }}">
|
<input type="submit" value="{{ _("Attach") }}">
|
||||||
|
@ -310,7 +302,7 @@
|
||||||
{{ _("Attach Network Adapter") }}
|
{{ _("Attach Network Adapter") }}
|
||||||
</summary>
|
</summary>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{{ _("Emulates either a <a href=\"%(url1)s\">SCSI DaynaPORT Ethernet Adapter</a>, or an <a href=\"%(url2)s\">X68000 Host Bridge</a>.", url1="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link", url2="https://github.com/akuker/RASCSI/wiki/X68000#Host_File_System_driver") }}
|
<li>{{ _("Emulates either a <a href=\"%(url1)s\">DaynaPORT SCSI/Link Ethernet Adapter</a>, or an <a href=\"%(url2)s\">X68000 Host Bridge</a>.", url1="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link", url2="https://github.com/akuker/RASCSI/wiki/X68000#Host_File_System_driver") }}
|
||||||
</li>
|
</li>
|
||||||
<li>{{ _("If you have a DHCP setup, choose only the interface you have configured the bridge with. You can ignore the Static IP fields when attaching.") }}</li>
|
<li>{{ _("If you have a DHCP setup, choose only the interface you have configured the bridge with. You can ignore the Static IP fields when attaching.") }}</li>
|
||||||
<li>{{ _("Configure the network bridge by running easyinstall.sh, or follow the <a href=\"%(url)s\">manual steps in the wiki</a>.", url="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link#manual-setup") }}
|
<li>{{ _("Configure the network bridge by running easyinstall.sh, or follow the <a href=\"%(url)s\">manual steps in the wiki</a>.", url="https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link#manual-setup") }}
|
||||||
|
@ -337,12 +329,15 @@
|
||||||
<input name="mask" type="number" size="2" placeholder="24" min="16" max="30">
|
<input name="mask" type="number" size="2" placeholder="24" min="16" max="30">
|
||||||
<label for="type">{{ _("Type:") }}</label>
|
<label for="type">{{ _("Type:") }}</label>
|
||||||
<select name="type">
|
<select name="type">
|
||||||
<option selected value="SCDP">
|
{% for type in NETWORK_DEVICE_TYPES %}
|
||||||
{{ _("DaynaPORT") }}
|
<option value="{{ type }}">
|
||||||
</option>
|
{% for key, value in device_types.items() %}
|
||||||
<option value="SCBR">
|
{% if key == type %}
|
||||||
{{ _("Host Bridge") }}
|
{{ value }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
</option>
|
</option>
|
||||||
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<label for="scsi_id">{{ _("SCSI ID:") }}</label>
|
<label for="scsi_id">{{ _("SCSI ID:") }}</label>
|
||||||
<select name="scsi_id">
|
<select name="scsi_id">
|
||||||
|
|
|
@ -54,6 +54,7 @@ from rascsi.common_settings import (
|
||||||
CONFIG_FILE_SUFFIX,
|
CONFIG_FILE_SUFFIX,
|
||||||
PROPERTIES_SUFFIX,
|
PROPERTIES_SUFFIX,
|
||||||
REMOVABLE_DEVICE_TYPES,
|
REMOVABLE_DEVICE_TYPES,
|
||||||
|
NETWORK_DEVICE_TYPES,
|
||||||
RESERVATIONS,
|
RESERVATIONS,
|
||||||
)
|
)
|
||||||
from rascsi.ractl_cmds import RaCtlCmds
|
from rascsi.ractl_cmds import RaCtlCmds
|
||||||
|
@ -115,10 +116,17 @@ def index():
|
||||||
image_files = file_cmds.list_images()
|
image_files = file_cmds.list_images()
|
||||||
config_files = file_cmds.list_config_files()
|
config_files = file_cmds.list_config_files()
|
||||||
|
|
||||||
sorted_image_files = sorted(image_files["files"], key=lambda x: x["name"].lower())
|
|
||||||
sorted_config_files = sorted(config_files, key=lambda x: x.lower())
|
|
||||||
mapped_device_types = extend_device_names(device_types["device_types"])
|
mapped_device_types = extend_device_names(device_types["device_types"])
|
||||||
|
|
||||||
|
extended_image_files = []
|
||||||
|
for image in image_files["files"]:
|
||||||
|
if image["detected_type"] is not "UNDEFINED":
|
||||||
|
image["detected_type_name"] = mapped_device_types[image["detected_type"]]
|
||||||
|
extended_image_files.append(image)
|
||||||
|
|
||||||
|
sorted_image_files = sorted(extended_image_files, key=lambda x: x["name"].lower())
|
||||||
|
sorted_config_files = sorted(config_files, key=lambda x: x.lower())
|
||||||
|
|
||||||
attached_images = []
|
attached_images = []
|
||||||
units = 0
|
units = 0
|
||||||
# If there are more than 0 logical unit numbers, display in the Web UI
|
# If there are more than 0 logical unit numbers, display in the Web UI
|
||||||
|
@ -181,6 +189,7 @@ def index():
|
||||||
ARCHIVE_FILE_SUFFIX=ARCHIVE_FILE_SUFFIX,
|
ARCHIVE_FILE_SUFFIX=ARCHIVE_FILE_SUFFIX,
|
||||||
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
|
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
|
||||||
REMOVABLE_DEVICE_TYPES=REMOVABLE_DEVICE_TYPES,
|
REMOVABLE_DEVICE_TYPES=REMOVABLE_DEVICE_TYPES,
|
||||||
|
NETWORK_DEVICE_TYPES=NETWORK_DEVICE_TYPES,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ void SASIDEV::Connect(int id, BUS *bus)
|
||||||
// Set the logical unit
|
// Set the logical unit
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SASIDEV::SetUnit(int no, Disk *dev)
|
void SASIDEV::SetUnit(int no, Device *dev)
|
||||||
{
|
{
|
||||||
ASSERT(no < UnitMax);
|
ASSERT(no < UnitMax);
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ void SASIDEV::CmdTestUnitReady()
|
||||||
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->TestUnitReady(this);
|
((Disk *)ctrl.device)->TestUnitReady(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -678,7 +678,7 @@ void SASIDEV::CmdRezero()
|
||||||
LOGTRACE( "%s REZERO UNIT Command ", __PRETTY_FUNCTION__);
|
LOGTRACE( "%s REZERO UNIT Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->Rezero(this);
|
((Disk *)ctrl.device)->Rezero(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -691,7 +691,7 @@ void SASIDEV::CmdRequestSense()
|
||||||
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->RequestSense(this);
|
((Disk *)ctrl.device)->RequestSense(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -704,7 +704,7 @@ void SASIDEV::CmdFormat()
|
||||||
LOGTRACE( "%s FORMAT UNIT Command ", __PRETTY_FUNCTION__);
|
LOGTRACE( "%s FORMAT UNIT Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->FormatUnit(this);
|
((Disk *)ctrl.device)->FormatUnit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -717,7 +717,7 @@ void SASIDEV::CmdReassignBlocks()
|
||||||
LOGTRACE("%s REASSIGN BLOCKS Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s REASSIGN BLOCKS Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->ReassignBlocks(this);
|
((Disk *)ctrl.device)->ReassignBlocks(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -777,7 +777,7 @@ void SASIDEV::CmdRead6()
|
||||||
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
|
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.length = ctrl.device->Read(ctrl.cmd, ctrl.buffer, record);
|
ctrl.length = ((Disk *)ctrl.device)->Read(ctrl.cmd, ctrl.buffer, record);
|
||||||
if (ctrl.length <= 0) {
|
if (ctrl.length <= 0) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
|
@ -812,7 +812,7 @@ void SASIDEV::CmdWrite6()
|
||||||
LOGTRACE("%s WRITE(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (WORD)record, (WORD)ctrl.blocks);
|
LOGTRACE("%s WRITE(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (WORD)record, (WORD)ctrl.blocks);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.length = ctrl.device->WriteCheck(record);
|
ctrl.length = ((Disk *)ctrl.device)->WriteCheck(record);
|
||||||
if (ctrl.length <= 0) {
|
if (ctrl.length <= 0) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
|
@ -836,7 +836,7 @@ void SASIDEV::CmdSeek6()
|
||||||
LOGTRACE("%s SEEK(6) Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s SEEK(6) Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
ctrl.device->Seek6(this);
|
((Disk *)ctrl.device)->Seek6(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -849,7 +849,7 @@ void SASIDEV::CmdAssign()
|
||||||
LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
bool status = ctrl.device->CheckReady();
|
bool status = ((Disk *)ctrl.device)->CheckReady();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
|
@ -873,7 +873,7 @@ void SASIDEV::CmdSpecify()
|
||||||
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
bool status = ctrl.device->CheckReady();
|
bool status = ((Disk *)ctrl.device)->CheckReady();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
|
@ -1086,7 +1086,7 @@ bool SASIDEV::XferIn(BYTE *buf)
|
||||||
case eCmdRead10:
|
case eCmdRead10:
|
||||||
case eCmdRead16:
|
case eCmdRead16:
|
||||||
// Read from disk
|
// Read from disk
|
||||||
ctrl.length = ctrl.unit[lun]->Read(ctrl.cmd, buf, ctrl.next);
|
ctrl.length = ((Disk *)ctrl.unit[lun])->Read(ctrl.cmd, buf, ctrl.next);
|
||||||
ctrl.next++;
|
ctrl.next++;
|
||||||
|
|
||||||
// If there is an error, go to the status phase
|
// If there is an error, go to the status phase
|
||||||
|
@ -1124,7 +1124,7 @@ bool SASIDEV::XferOut(bool cont)
|
||||||
if (!ctrl.unit[lun]) {
|
if (!ctrl.unit[lun]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Disk *device = ctrl.unit[lun];
|
Disk *device = (Disk *)ctrl.unit[lun];
|
||||||
|
|
||||||
switch (ctrl.cmd[0]) {
|
switch (ctrl.cmd[0]) {
|
||||||
case SASIDEV::eCmdModeSelect6:
|
case SASIDEV::eCmdModeSelect6:
|
||||||
|
@ -1220,7 +1220,8 @@ void SASIDEV::FlushUnit()
|
||||||
if (!ctrl.unit[lun]) {
|
if (!ctrl.unit[lun]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Disk *device = ctrl.unit[lun];
|
|
||||||
|
Disk *disk = (Disk *)ctrl.unit[lun];
|
||||||
|
|
||||||
// WRITE system only
|
// WRITE system only
|
||||||
switch ((SASIDEV::sasi_command)ctrl.cmd[0]) {
|
switch ((SASIDEV::sasi_command)ctrl.cmd[0]) {
|
||||||
|
@ -1248,7 +1249,7 @@ void SASIDEV::FlushUnit()
|
||||||
LOGWARN(" Reserved: %02X\n",(WORD)ctrl.cmd[5]);
|
LOGWARN(" Reserved: %02X\n",(WORD)ctrl.cmd[5]);
|
||||||
LOGWARN(" Ctrl Len: %08X\n",(WORD)ctrl.length);
|
LOGWARN(" Ctrl Len: %08X\n",(WORD)ctrl.length);
|
||||||
|
|
||||||
if (!device->ModeSelect(
|
if (!disk->ModeSelect(
|
||||||
ctrl.cmd, ctrl.buffer, ctrl.offset)) {
|
ctrl.cmd, ctrl.buffer, ctrl.offset)) {
|
||||||
// MODE SELECT failed
|
// MODE SELECT failed
|
||||||
LOGWARN("Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]);
|
LOGWARN("Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -123,10 +124,10 @@ public:
|
||||||
DWORD length; // Transfer remaining length
|
DWORD length; // Transfer remaining length
|
||||||
|
|
||||||
// Logical unit
|
// Logical unit
|
||||||
Disk *unit[UnitMax];
|
Device *unit[UnitMax];
|
||||||
|
|
||||||
// The current device
|
// The current device
|
||||||
Disk *device;
|
Device *device;
|
||||||
|
|
||||||
// The LUN from the IDENTIFY message
|
// The LUN from the IDENTIFY message
|
||||||
int lun;
|
int lun;
|
||||||
|
@ -143,8 +144,8 @@ public:
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
void Connect(int id, BUS *sbus); // Controller connection
|
void Connect(int id, BUS *sbus); // Controller connection
|
||||||
Disk* GetUnit(int no); // Get logical unit
|
Device* GetUnit(int no); // Get logical unit
|
||||||
void SetUnit(int no, Disk *dev); // Logical unit setting
|
void SetUnit(int no, Device *dev); // Logical unit setting
|
||||||
bool HasUnit(); // Has a valid logical unit
|
bool HasUnit(); // Has a valid logical unit
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
SCSIDEV::SCSIDEV() : SASIDEV()
|
SCSIDEV::SCSIDEV() : SASIDEV()
|
||||||
{
|
{
|
||||||
|
shutdown_mode = NONE;
|
||||||
|
|
||||||
// Synchronous transfer work initialization
|
// Synchronous transfer work initialization
|
||||||
scsi.syncenable = FALSE;
|
scsi.syncenable = FALSE;
|
||||||
scsi.syncperiod = 50;
|
scsi.syncperiod = 50;
|
||||||
|
@ -153,6 +155,22 @@ void SCSIDEV::BusFree()
|
||||||
|
|
||||||
ctrl.lun = -1;
|
ctrl.lun = -1;
|
||||||
|
|
||||||
|
// When the bus is free RaSCSI or the Pi may be shut down
|
||||||
|
switch(shutdown_mode) {
|
||||||
|
case RASCSI:
|
||||||
|
LOGINFO("RaSCSI shutdown requested");
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PI:
|
||||||
|
LOGINFO("Raspberry Pi shutdown requested");
|
||||||
|
system("init 0");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +239,7 @@ void SCSIDEV::Execute()
|
||||||
ctrl.execstart = SysTimer::GetTimerLow();
|
ctrl.execstart = SysTimer::GetTimerLow();
|
||||||
|
|
||||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
|
if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) {
|
||||||
ctrl.status = 0;
|
ctrl.status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +247,8 @@ void SCSIDEV::Execute()
|
||||||
|
|
||||||
int lun = GetEffectiveLun();
|
int lun = GetEffectiveLun();
|
||||||
if (!ctrl.unit[lun]) {
|
if (!ctrl.unit[lun]) {
|
||||||
if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdInquiry && (SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
|
if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdInquiry &&
|
||||||
|
(ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) {
|
||||||
LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
|
LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
|
||||||
|
|
||||||
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
||||||
|
@ -247,7 +266,7 @@ void SCSIDEV::Execute()
|
||||||
ctrl.device = ctrl.unit[lun];
|
ctrl.device = ctrl.unit[lun];
|
||||||
|
|
||||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
|
if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) {
|
||||||
ctrl.device->SetStatusCode(0);
|
ctrl.device->SetStatusCode(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,10 +277,10 @@ void SCSIDEV::Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
|
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
|
||||||
if ((SCSIDEV::scsi_command)ctrl.cmd[0] == eCmdInquiry && !ctrl.unit[lun]) {
|
if ((ScsiDefs::scsi_command)ctrl.cmd[0] == ScsiDefs::eCmdInquiry && !ctrl.unit[lun]) {
|
||||||
lun = GetEffectiveLun();
|
lun = GetEffectiveLun();
|
||||||
|
|
||||||
LOGDEBUG("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId());
|
LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId());
|
||||||
|
|
||||||
ctrl.buffer[0] = 0x7f;
|
ctrl.buffer[0] = 0x7f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,51 +25,12 @@
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
class SCSIDEV : public SASIDEV
|
class SCSIDEV : public SASIDEV
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum scsi_command : int {
|
|
||||||
eCmdTestUnitReady = 0x00,
|
enum rascsi_shutdown_mode {
|
||||||
eCmdRezero = 0x01,
|
NONE,
|
||||||
eCmdRequestSense = 0x03,
|
RASCSI,
|
||||||
eCmdFormat = 0x04,
|
PI
|
||||||
eCmdReassign = 0x07,
|
|
||||||
eCmdRead6 = 0x08,
|
|
||||||
eCmdRetrieveStats = 0x09, // DaynaPort specific command
|
|
||||||
eCmdWrite6 = 0x0A,
|
|
||||||
eCmdSeek6 = 0x0B,
|
|
||||||
eCmdSetIfaceMode = 0x0C, // DaynaPort specific command
|
|
||||||
eCmdSetMcastAddr = 0x0D, // DaynaPort specific command
|
|
||||||
eCmdEnableInterface = 0x0E, // DaynaPort specific command
|
|
||||||
eCmdInquiry = 0x12,
|
|
||||||
eCmdModeSelect6 = 0x15,
|
|
||||||
eCmdReserve6 = 0x16,
|
|
||||||
eCmdRelease6 = 0x17,
|
|
||||||
eCmdModeSense6 = 0x1A,
|
|
||||||
eCmdStartStop = 0x1B,
|
|
||||||
eCmdSendDiag = 0x1D,
|
|
||||||
eCmdRemoval = 0x1E,
|
|
||||||
eCmdReadCapacity10 = 0x25,
|
|
||||||
eCmdRead10 = 0x28,
|
|
||||||
eCmdWrite10 = 0x2A,
|
|
||||||
eCmdSeek10 = 0x2B,
|
|
||||||
eCmdVerify10 = 0x2F,
|
|
||||||
eCmdSynchronizeCache10 = 0x35,
|
|
||||||
eCmdReadDefectData10 = 0x37,
|
|
||||||
eCmdReadLong10 = 0x3E,
|
|
||||||
eCmdWriteLong10 = 0x3F,
|
|
||||||
eCmdReadToc = 0x43,
|
|
||||||
eCmdGetEventStatusNotification = 0x4A,
|
|
||||||
eCmdModeSelect10 = 0x55,
|
|
||||||
eCmdReserve10 = 0x56,
|
|
||||||
eCmdRelease10 = 0x57,
|
|
||||||
eCmdModeSense10 = 0x5A,
|
|
||||||
eCmdRead16 = 0x88,
|
|
||||||
eCmdWrite16 = 0x8A,
|
|
||||||
eCmdVerify16 = 0x8F,
|
|
||||||
eCmdSynchronizeCache16 = 0x91,
|
|
||||||
eCmdReadCapacity16_ReadLong16 = 0x9E,
|
|
||||||
eCmdWriteLong16 = 0x9F,
|
|
||||||
eCmdReportLuns = 0xA0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Internal data definition
|
// Internal data definition
|
||||||
|
@ -86,7 +47,6 @@ public:
|
||||||
BYTE msb[256];
|
BYTE msb[256];
|
||||||
} scsi_t;
|
} scsi_t;
|
||||||
|
|
||||||
public:
|
|
||||||
// Basic Functions
|
// Basic Functions
|
||||||
SCSIDEV();
|
SCSIDEV();
|
||||||
~SCSIDEV();
|
~SCSIDEV();
|
||||||
|
@ -103,6 +63,8 @@ public:
|
||||||
void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
|
void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
|
||||||
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION) override; // Common error handling
|
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION) override; // Common error handling
|
||||||
|
|
||||||
|
void ShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Phase
|
// Phase
|
||||||
|
@ -122,5 +84,7 @@ private:
|
||||||
bool XferMsg(DWORD msg);
|
bool XferMsg(DWORD msg);
|
||||||
|
|
||||||
scsi_t scsi; // Internal data
|
scsi_t scsi; // Internal data
|
||||||
|
|
||||||
|
rascsi_shutdown_mode shutdown_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "cfilesystem.h"
|
#include "cfilesystem.h"
|
||||||
#include "../rascsi.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include <zlib.h> // For crc32()
|
#include <zlib.h> // For crc32()
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "../rascsi.h"
|
|
||||||
#include "ctapdriver.h"
|
#include "ctapdriver.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
|
@ -29,7 +29,7 @@ Device::Device(const string& type)
|
||||||
ready = false;
|
ready = false;
|
||||||
reset = false;
|
reset = false;
|
||||||
attn = false;
|
attn = false;
|
||||||
supported_luns = 1;
|
supported_luns = 32;
|
||||||
protectable = false;
|
protectable = false;
|
||||||
write_protected = false;
|
write_protected = false;
|
||||||
read_only = false;
|
read_only = false;
|
||||||
|
|
|
@ -162,6 +162,7 @@ public:
|
||||||
const string GetPaddedName() const;
|
const string GetPaddedName() const;
|
||||||
|
|
||||||
bool SupportsParams() const { return supports_params; }
|
bool SupportsParams() const { return supports_params; }
|
||||||
|
bool SupportsFile() const { return !supports_params; }
|
||||||
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
|
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
|
||||||
const map<string, string> GetParams() const { return params; }
|
const map<string, string> GetParams() const { return params; }
|
||||||
const string GetParam(const string&);
|
const string GetParam(const string&);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "host_services.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace rascsi_interface;
|
using namespace rascsi_interface;
|
||||||
|
@ -31,8 +32,6 @@ DeviceFactory::DeviceFactory()
|
||||||
sector_sizes[SCMO] = { 512, 1024, 2048, 4096 };
|
sector_sizes[SCMO] = { 512, 1024, 2048, 4096 };
|
||||||
// Some old Sun CD-ROM drives support 512 bytes per sector
|
// Some old Sun CD-ROM drives support 512 bytes per sector
|
||||||
sector_sizes[SCCD] = { 512, 2048};
|
sector_sizes[SCCD] = { 512, 2048};
|
||||||
sector_sizes[SCBR] = {};
|
|
||||||
sector_sizes[SCDP] = {};
|
|
||||||
|
|
||||||
// 128 MB, 512 bytes per sector, 248826 sectors
|
// 128 MB, 512 bytes per sector, 248826 sectors
|
||||||
geometries[SCMO][0x797f400] = make_pair(512, 248826);
|
geometries[SCMO][0x797f400] = make_pair(512, 248826);
|
||||||
|
@ -42,12 +41,6 @@ DeviceFactory::DeviceFactory()
|
||||||
geometries[SCMO][0x1fc8b800] = make_pair(512, 1041500);
|
geometries[SCMO][0x1fc8b800] = make_pair(512, 1041500);
|
||||||
// 640 MB, 20248 bytes per sector, 310352 sectors
|
// 640 MB, 20248 bytes per sector, 310352 sectors
|
||||||
geometries[SCMO][0x25e28000] = make_pair(2048, 310352);
|
geometries[SCMO][0x25e28000] = make_pair(2048, 310352);
|
||||||
geometries[SAHD] = {};
|
|
||||||
geometries[SCHD] = {};
|
|
||||||
geometries[SCRM] = {};
|
|
||||||
geometries[SCCD] = {};
|
|
||||||
geometries[SCBR] = {};
|
|
||||||
geometries[SCDP] = {};
|
|
||||||
|
|
||||||
string network_interfaces;
|
string network_interfaces;
|
||||||
for (const auto& network_interface : GetNetworkInterfaces()) {
|
for (const auto& network_interface : GetNetworkInterfaces()) {
|
||||||
|
@ -57,11 +50,6 @@ DeviceFactory::DeviceFactory()
|
||||||
network_interfaces += network_interface;
|
network_interfaces += network_interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
default_params[SAHD] = {};
|
|
||||||
default_params[SCHD] = {};
|
|
||||||
default_params[SCRM] = {};
|
|
||||||
default_params[SCMO] = {};
|
|
||||||
default_params[SCCD] = {};
|
|
||||||
default_params[SCBR]["interfaces"] = network_interfaces;
|
default_params[SCBR]["interfaces"] = network_interfaces;
|
||||||
default_params[SCDP]["interfaces"] = network_interfaces;
|
default_params[SCDP]["interfaces"] = network_interfaces;
|
||||||
|
|
||||||
|
@ -107,6 +95,9 @@ PbDeviceType DeviceFactory::GetTypeForFile(const string& filename)
|
||||||
else if (filename == "daynaport") {
|
else if (filename == "daynaport") {
|
||||||
return SCDP;
|
return SCDP;
|
||||||
}
|
}
|
||||||
|
else if (filename == "services") {
|
||||||
|
return SCHS;
|
||||||
|
}
|
||||||
|
|
||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +137,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
device->SetProduct("FIREBALL");
|
device->SetProduct("FIREBALL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
device->SetProtectable(true);
|
device->SetProtectable(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
break;
|
break;
|
||||||
|
@ -154,7 +144,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
|
|
||||||
case SCRM:
|
case SCRM:
|
||||||
device = new SCSIHD(true);
|
device = new SCSIHD(true);
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
device->SetProtectable(true);
|
device->SetProtectable(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
|
@ -165,7 +154,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
|
|
||||||
case SCMO:
|
case SCMO:
|
||||||
device = new SCSIMO();
|
device = new SCSIMO();
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
device->SetProtectable(true);
|
device->SetProtectable(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
|
@ -177,7 +165,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
|
|
||||||
case SCCD:
|
case SCCD:
|
||||||
device = new SCSICD();
|
device = new SCSICD();
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
device->SetReadOnly(true);
|
device->SetReadOnly(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
|
@ -188,7 +175,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
|
|
||||||
case SCBR:
|
case SCBR:
|
||||||
device = new SCSIBR();
|
device = new SCSIBR();
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
device->SetProduct("SCSI HOST BRIDGE");
|
device->SetProduct("SCSI HOST BRIDGE");
|
||||||
device->SupportsParams(true);
|
device->SupportsParams(true);
|
||||||
device->SetDefaultParams(default_params[SCBR]);
|
device->SetDefaultParams(default_params[SCBR]);
|
||||||
|
@ -196,7 +182,6 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
|
|
||||||
case SCDP:
|
case SCDP:
|
||||||
device = new SCSIDaynaPort();
|
device = new SCSIDaynaPort();
|
||||||
device->SetSupportedLuns(32);
|
|
||||||
// Since this is an emulation for a specific device the full INQUIRY data have to be set accordingly
|
// Since this is an emulation for a specific device the full INQUIRY data have to be set accordingly
|
||||||
device->SetVendor("Dayna");
|
device->SetVendor("Dayna");
|
||||||
device->SetProduct("SCSI/Link");
|
device->SetProduct("SCSI/Link");
|
||||||
|
@ -205,6 +190,13 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||||
device->SetDefaultParams(default_params[SCDP]);
|
device->SetDefaultParams(default_params[SCDP]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCHS:
|
||||||
|
device = new HostServices();
|
||||||
|
// Since this is an emulation for a specific device the full INQUIRY data have to be set accordingly
|
||||||
|
device->SetVendor("RaSCSI");
|
||||||
|
device->SetProduct("Host Services");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,18 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "controllers/sasidev_ctrl.h"
|
|
||||||
#include "device_factory.h"
|
#include "device_factory.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
|
#include "mode_page_device.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "../rascsi.h"
|
#include "../rascsi.h"
|
||||||
#include "file_access/file_access_factory.h"
|
#include "file_access/file_access_factory.h"
|
||||||
|
|
||||||
Disk::Disk(const std::string id) : Device(id), ScsiPrimaryCommands(), ScsiBlockCommands()
|
Disk::Disk(const std::string id) : ModePageDevice(id), ScsiBlockCommands()
|
||||||
{
|
{
|
||||||
|
disks.insert(this);
|
||||||
|
|
||||||
// Work initialization
|
// Work initialization
|
||||||
configured_sector_size = 0;
|
configured_sector_size = 0;
|
||||||
disk.size = 0;
|
disk.size = 0;
|
||||||
|
@ -33,42 +35,34 @@ Disk::Disk(const std::string id) : Device(id), ScsiPrimaryCommands(), ScsiBlockC
|
||||||
disk.dcache = NULL;
|
disk.dcache = NULL;
|
||||||
disk.image_offset = 0;
|
disk.image_offset = 0;
|
||||||
|
|
||||||
AddCommand(SCSIDEV::eCmdTestUnitReady, "TestUnitReady", &Disk::TestUnitReady);
|
AddCommand(ScsiDefs::eCmdRezero, "Rezero", &Disk::Rezero);
|
||||||
AddCommand(SCSIDEV::eCmdRezero, "Rezero", &Disk::Rezero);
|
AddCommand(ScsiDefs::eCmdFormat, "FormatUnit", &Disk::FormatUnit);
|
||||||
AddCommand(SCSIDEV::eCmdRequestSense, "RequestSense", &Disk::RequestSense);
|
AddCommand(ScsiDefs::eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks);
|
||||||
AddCommand(SCSIDEV::eCmdFormat, "FormatUnit", &Disk::FormatUnit);
|
AddCommand(ScsiDefs::eCmdRead6, "Read6", &Disk::Read6);
|
||||||
AddCommand(SCSIDEV::eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks);
|
AddCommand(ScsiDefs::eCmdWrite6, "Write6", &Disk::Write6);
|
||||||
AddCommand(SCSIDEV::eCmdRead6, "Read6", &Disk::Read6);
|
AddCommand(ScsiDefs::eCmdSeek6, "Seek6", &Disk::Seek6);
|
||||||
AddCommand(SCSIDEV::eCmdWrite6, "Write6", &Disk::Write6);
|
AddCommand(ScsiDefs::eCmdReserve6, "Reserve6", &Disk::Reserve6);
|
||||||
AddCommand(SCSIDEV::eCmdSeek6, "Seek6", &Disk::Seek6);
|
AddCommand(ScsiDefs::eCmdRelease6, "Release6", &Disk::Release6);
|
||||||
AddCommand(SCSIDEV::eCmdInquiry, "Inquiry", &Disk::Inquiry);
|
AddCommand(ScsiDefs::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit);
|
||||||
AddCommand(SCSIDEV::eCmdModeSelect6, "ModeSelect6", &Disk::ModeSelect6);
|
AddCommand(ScsiDefs::eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic);
|
||||||
AddCommand(SCSIDEV::eCmdReserve6, "Reserve6", &Disk::Reserve6);
|
AddCommand(ScsiDefs::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval);
|
||||||
AddCommand(SCSIDEV::eCmdRelease6, "Release6", &Disk::Release6);
|
AddCommand(ScsiDefs::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10);
|
||||||
AddCommand(SCSIDEV::eCmdModeSense6, "ModeSense6", &Disk::ModeSense6);
|
AddCommand(ScsiDefs::eCmdRead10, "Read10", &Disk::Read10);
|
||||||
AddCommand(SCSIDEV::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit);
|
AddCommand(ScsiDefs::eCmdWrite10, "Write10", &Disk::Write10);
|
||||||
AddCommand(SCSIDEV::eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic);
|
AddCommand(ScsiDefs::eCmdReadLong10, "ReadLong10", &Disk::ReadLong10);
|
||||||
AddCommand(SCSIDEV::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval);
|
AddCommand(ScsiDefs::eCmdWriteLong10, "WriteLong10", &Disk::WriteLong10);
|
||||||
AddCommand(SCSIDEV::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10);
|
AddCommand(ScsiDefs::eCmdWriteLong16, "WriteLong16", &Disk::WriteLong16);
|
||||||
AddCommand(SCSIDEV::eCmdRead10, "Read10", &Disk::Read10);
|
AddCommand(ScsiDefs::eCmdSeek10, "Seek10", &Disk::Seek10);
|
||||||
AddCommand(SCSIDEV::eCmdWrite10, "Write10", &Disk::Write10);
|
AddCommand(ScsiDefs::eCmdVerify10, "Verify10", &Disk::Verify10);
|
||||||
AddCommand(SCSIDEV::eCmdReadLong10, "ReadLong10", &Disk::ReadLong10);
|
AddCommand(ScsiDefs::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10);
|
||||||
AddCommand(SCSIDEV::eCmdWriteLong10, "WriteLong10", &Disk::WriteLong10);
|
AddCommand(ScsiDefs::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16);
|
||||||
AddCommand(SCSIDEV::eCmdWriteLong16, "WriteLong16", &Disk::WriteLong16);
|
AddCommand(ScsiDefs::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10);
|
||||||
AddCommand(SCSIDEV::eCmdSeek10, "Seek10", &Disk::Seek10);
|
AddCommand(ScsiDefs::eCmdReserve10, "Reserve10", &Disk::Reserve10);
|
||||||
AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Verify10);
|
AddCommand(ScsiDefs::eCmdRelease10, "Release10", &Disk::Release10);
|
||||||
AddCommand(SCSIDEV::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10);
|
AddCommand(ScsiDefs::eCmdRead16, "Read16", &Disk::Read16);
|
||||||
AddCommand(SCSIDEV::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16);
|
AddCommand(ScsiDefs::eCmdWrite16, "Write16", &Disk::Write16);
|
||||||
AddCommand(SCSIDEV::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10);
|
AddCommand(ScsiDefs::eCmdVerify16, "Verify16", &Disk::Verify16);
|
||||||
AddCommand(SCSIDEV::eCmdModeSelect10, "ModeSelect10", &Disk::ModeSelect10);
|
AddCommand(ScsiDefs::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16);
|
||||||
AddCommand(SCSIDEV::eCmdReserve10, "Reserve10", &Disk::Reserve10);
|
|
||||||
AddCommand(SCSIDEV::eCmdRelease10, "Release10", &Disk::Release10);
|
|
||||||
AddCommand(SCSIDEV::eCmdModeSense10, "ModeSense10", &Disk::ModeSense10);
|
|
||||||
AddCommand(SCSIDEV::eCmdRead16, "Read16", &Disk::Read16);
|
|
||||||
AddCommand(SCSIDEV::eCmdWrite16, "Write16", &Disk::Write16);
|
|
||||||
AddCommand(SCSIDEV::eCmdVerify16, "Verify16", &Disk::Verify16);
|
|
||||||
AddCommand(SCSIDEV::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16);
|
|
||||||
AddCommand(SCSIDEV::eCmdReportLuns, "ReportLuns", &Disk::ReportLuns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Disk::~Disk()
|
Disk::~Disk()
|
||||||
|
@ -90,9 +84,11 @@ Disk::~Disk()
|
||||||
for (auto const& command : commands) {
|
for (auto const& command : commands) {
|
||||||
delete command.second;
|
delete command.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disks.erase(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (Disk::*execute)(SASIDEV *))
|
void Disk::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (Disk::*execute)(SASIDEV *))
|
||||||
{
|
{
|
||||||
commands[opcode] = new command_t(name, execute);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
@ -101,8 +97,8 @@ bool Disk::Dispatch(SCSIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl = controller->GetCtrl();
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
if (commands.count(static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
@ -111,8 +107,10 @@ bool Disk::Dispatch(SCSIDEV *controller)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown command
|
LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[0]);
|
||||||
return false;
|
|
||||||
|
// The base class handles the less specific commands
|
||||||
|
return ModePageDevice::Dispatch(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -148,16 +146,6 @@ void Disk::Open(const Filepath& path)
|
||||||
SetLocked(false);
|
SetLocked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::TestUnitReady(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
if (!CheckReady()) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->Status();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::Rezero(SASIDEV *controller)
|
void Disk::Rezero(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!CheckReady()) {
|
if (!CheckReady()) {
|
||||||
|
@ -168,28 +156,6 @@ void Disk::Rezero(SASIDEV *controller)
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::RequestSense(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
int lun = controller->GetEffectiveLun();
|
|
||||||
|
|
||||||
// Note: According to the SCSI specs the LUN handling for REQUEST SENSE non-existing LUNs do *not* result
|
|
||||||
// in CHECK CONDITION. Only the Sense Key and ASC are set in order to signal the non-existing LUN.
|
|
||||||
if (!ctrl->unit[lun]) {
|
|
||||||
// LUN 0 can be assumed to be present (required to call RequestSense() below)
|
|
||||||
lun = 0;
|
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
|
||||||
ctrl->status = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl->length = ctrl->unit[lun]->RequestSense(ctrl->cmd, ctrl->buffer);
|
|
||||||
ASSERT(ctrl->length > 0);
|
|
||||||
|
|
||||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
|
||||||
|
|
||||||
controller->DataIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::FormatUnit(SASIDEV *controller)
|
void Disk::FormatUnit(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!Format(ctrl->cmd)) {
|
if (!Format(ctrl->cmd)) {
|
||||||
|
@ -393,93 +359,6 @@ void Disk::Verify16(SASIDEV *controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::Inquiry(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
int lun = controller->GetEffectiveLun();
|
|
||||||
const ScsiPrimaryCommands *device = ctrl->unit[lun];
|
|
||||||
|
|
||||||
// Find a valid unit
|
|
||||||
// TODO The code below is probably wrong. It results in the same INQUIRY data being
|
|
||||||
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
|
|
||||||
// In addition, it supports gaps in the LUN list, which is not correct.
|
|
||||||
if (!device) {
|
|
||||||
for (int valid_lun = 0; valid_lun < SASIDEV::UnitMax; valid_lun++) {
|
|
||||||
if (ctrl->unit[valid_lun]) {
|
|
||||||
device = ctrl->unit[valid_lun];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device) {
|
|
||||||
ctrl->length = Inquiry(ctrl->cmd, ctrl->buffer);
|
|
||||||
} else {
|
|
||||||
ctrl->length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctrl->length <= 0) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report if the device does not support the requested LUN
|
|
||||||
if (!ctrl->unit[lun]) {
|
|
||||||
LOGDEBUG("Reporting LUN %d for device ID %d as not supported", lun, ctrl->device->GetId());
|
|
||||||
|
|
||||||
ctrl->buffer[0] |= 0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->DataIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::ModeSelect6(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
|
||||||
|
|
||||||
ctrl->length = ModeSelectCheck6(ctrl->cmd);
|
|
||||||
if (ctrl->length <= 0) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->DataOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::ModeSelect10(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
|
||||||
|
|
||||||
ctrl->length = ModeSelectCheck10(ctrl->cmd);
|
|
||||||
if (ctrl->length <= 0) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->DataOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::ModeSense6(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
|
|
||||||
if (ctrl->length <= 0) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->DataIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::ModeSense10(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer);
|
|
||||||
if (ctrl->length <= 0) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->DataIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disk::StartStopUnit(SASIDEV *controller)
|
void Disk::StartStopUnit(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!StartStop(ctrl->cmd)) {
|
if (!StartStop(ctrl->cmd)) {
|
||||||
|
@ -559,122 +438,6 @@ bool Disk::Eject(bool force)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Disk::CheckReady()
|
|
||||||
{
|
|
||||||
// Not ready if reset
|
|
||||||
if (IsReset()) {
|
|
||||||
SetStatusCode(STATUS_DEVRESET);
|
|
||||||
SetReset(false);
|
|
||||||
LOGTRACE("%s Disk in reset", __PRETTY_FUNCTION__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not ready if it needs attention
|
|
||||||
if (IsAttn()) {
|
|
||||||
SetStatusCode(STATUS_ATTENTION);
|
|
||||||
SetAttn(false);
|
|
||||||
LOGTRACE("%s Disk in needs attention", __PRETTY_FUNCTION__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return status if not ready
|
|
||||||
if (!IsReady()) {
|
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
|
||||||
LOGTRACE("%s Disk not ready", __PRETTY_FUNCTION__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization with no error
|
|
||||||
LOGTRACE("%s Disk is ready", __PRETTY_FUNCTION__);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// REQUEST SENSE
|
|
||||||
// *SASI is a separate process
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int Disk::RequestSense(const DWORD *cdb, BYTE *buf)
|
|
||||||
{
|
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Return not ready only if there are no errors
|
|
||||||
if (GetStatusCode() == STATUS_NOERROR) {
|
|
||||||
if (!IsReady()) {
|
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size determination (according to allocation length)
|
|
||||||
int size = (int)cdb[4];
|
|
||||||
ASSERT((size >= 0) && (size < 0x100));
|
|
||||||
|
|
||||||
// For SCSI-1, transfer 4 bytes when the size is 0
|
|
||||||
// (Deleted this specification for SCSI-2)
|
|
||||||
if (size == 0) {
|
|
||||||
size = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the buffer
|
|
||||||
memset(buf, 0, size);
|
|
||||||
|
|
||||||
// Set 18 bytes including extended sense data
|
|
||||||
|
|
||||||
// Current error
|
|
||||||
buf[0] = 0x70;
|
|
||||||
|
|
||||||
buf[2] = (BYTE)(GetStatusCode() >> 16);
|
|
||||||
buf[7] = 10;
|
|
||||||
buf[12] = (BYTE)(GetStatusCode() >> 8);
|
|
||||||
buf[13] = (BYTE)GetStatusCode();
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::ModeSelectCheck(const DWORD *cdb, int length)
|
|
||||||
{
|
|
||||||
// Error if save parameters are set for other types than of SCHD or SCRM
|
|
||||||
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::ModeSelectCheck6(const DWORD *cdb)
|
|
||||||
{
|
|
||||||
// Receive the data specified by the parameter length
|
|
||||||
return ModeSelectCheck(cdb, cdb[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::ModeSelectCheck10(const DWORD *cdb)
|
|
||||||
{
|
|
||||||
// Receive the data specified by the parameter length
|
|
||||||
int length = cdb[7];
|
|
||||||
length <<= 8;
|
|
||||||
length |= cdb[8];
|
|
||||||
if (length > 0x800) {
|
|
||||||
length = 0x800;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModeSelectCheck(cdb, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Disk::ModeSelect(const DWORD* /*cdb*/, const BYTE *buf, int length)
|
|
||||||
{
|
|
||||||
ASSERT(buf);
|
|
||||||
ASSERT(length >= 0);
|
|
||||||
|
|
||||||
// cannot be set
|
|
||||||
SetStatusCode(STATUS_INVALIDPRM);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Get length, clear buffer
|
// Get length, clear buffer
|
||||||
|
@ -1426,38 +1189,6 @@ void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::ReportLuns(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
BYTE *buf = ctrl->buffer;
|
|
||||||
|
|
||||||
if (!CheckReady()) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
|
||||||
memset(buf, 0, allocation_length);
|
|
||||||
|
|
||||||
// Count number of available LUNs for the current device
|
|
||||||
int luns;
|
|
||||||
for (luns = 0; luns < controller->GetCtrl()->device->GetSupportedLuns(); luns++) {
|
|
||||||
if (!controller->GetCtrl()->unit[luns]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LUN list length, 8 bytes per LUN
|
|
||||||
// SCSI standard: The contents of the LUN LIST LENGTH field are not altered based on the allocation length
|
|
||||||
buf[0] = (luns * 8) >> 24;
|
|
||||||
buf[1] = (luns * 8) >> 16;
|
|
||||||
buf[2] = (luns * 8) >> 8;
|
|
||||||
buf[3] = luns * 8;
|
|
||||||
|
|
||||||
ctrl->length = allocation_length < 8 + luns * 8 ? allocation_length : 8 + luns * 8;
|
|
||||||
|
|
||||||
controller->DataIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// RESERVE(6)
|
// RESERVE(6)
|
||||||
|
|
|
@ -25,15 +25,14 @@
|
||||||
#include "file_access/file_access.h"
|
#include "file_access/file_access.h"
|
||||||
#include "file_support.h"
|
#include "file_support.h"
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
|
#include "interfaces/scsi_block_commands.h"
|
||||||
|
#include "interfaces/scsi_primary_commands.h"
|
||||||
|
#include "mode_page_device.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "../rascsi.h"
|
class Disk : public ModePageDevice, ScsiBlockCommands
|
||||||
#include "interfaces/scsi_block_commands.h"
|
|
||||||
#include "interfaces/scsi_primary_commands.h"
|
|
||||||
|
|
||||||
class Disk : public Device, ScsiPrimaryCommands, ScsiBlockCommands
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum access_mode { RW6, RW10, RW16 };
|
enum access_mode { RW6, RW10, RW16 };
|
||||||
|
@ -45,8 +44,6 @@ private:
|
||||||
// The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction
|
// The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction
|
||||||
map<uint64_t, Geometry> geometries;
|
map<uint64_t, Geometry> geometries;
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
|
uint32_t size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
|
||||||
// TODO blocks should be a 64 bit value in order to support higher capacities
|
// TODO blocks should be a 64 bit value in order to support higher capacities
|
||||||
|
@ -61,9 +58,9 @@ private:
|
||||||
|
|
||||||
_command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
_command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
} command_t;
|
} command_t;
|
||||||
std::map<SCSIDEV::scsi_command, command_t*> commands;
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
void AddCommand(SCSIDEV::scsi_command, const char*, void (Disk::*)(SASIDEV *));
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (Disk::*)(SASIDEV *));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Disk(std::string);
|
Disk(std::string);
|
||||||
|
@ -78,17 +75,9 @@ public:
|
||||||
void GetPath(Filepath& path) const;
|
void GetPath(Filepath& path) const;
|
||||||
bool Eject(bool) override;
|
bool Eject(bool) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
// Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm)
|
// Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm)
|
||||||
virtual void TestUnitReady(SASIDEV *) override;
|
|
||||||
void Inquiry(SASIDEV *) override;
|
|
||||||
void RequestSense(SASIDEV *) override;
|
|
||||||
void ModeSelect6(SASIDEV *) override;
|
|
||||||
void ModeSelect10(SASIDEV *) override;
|
|
||||||
void ModeSense6(SASIDEV *) override;
|
|
||||||
void ModeSense10(SASIDEV *) override;
|
|
||||||
void Rezero(SASIDEV *);
|
|
||||||
void FormatUnit(SASIDEV *) override;
|
|
||||||
void ReassignBlocks(SASIDEV *) override;
|
|
||||||
void StartStopUnit(SASIDEV *) override;
|
void StartStopUnit(SASIDEV *) override;
|
||||||
void SendDiagnostic(SASIDEV *) override;
|
void SendDiagnostic(SASIDEV *) override;
|
||||||
void PreventAllowMediumRemoval(SASIDEV *);
|
void PreventAllowMediumRemoval(SASIDEV *);
|
||||||
|
@ -108,16 +97,22 @@ public:
|
||||||
void Verify10(SASIDEV *) override;
|
void Verify10(SASIDEV *) override;
|
||||||
void Verify16(SASIDEV *) override;
|
void Verify16(SASIDEV *) override;
|
||||||
void Seek(SASIDEV *);
|
void Seek(SASIDEV *);
|
||||||
void Seek6(SASIDEV *);
|
|
||||||
void Seek10(SASIDEV *);
|
void Seek10(SASIDEV *);
|
||||||
void ReadCapacity10(SASIDEV *) override;
|
void ReadCapacity10(SASIDEV *) override;
|
||||||
void ReadCapacity16(SASIDEV *) override;
|
void ReadCapacity16(SASIDEV *) override;
|
||||||
void ReportLuns(SASIDEV *) override;
|
|
||||||
void Reserve6(SASIDEV *);
|
void Reserve6(SASIDEV *);
|
||||||
void Reserve10(SASIDEV *);
|
void Reserve10(SASIDEV *);
|
||||||
void Release6(SASIDEV *);
|
void Release6(SASIDEV *);
|
||||||
void Release10(SASIDEV *);
|
void Release10(SASIDEV *);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm)
|
||||||
|
void Rezero(SASIDEV *);
|
||||||
|
void FormatUnit(SASIDEV *) override;
|
||||||
|
void ReassignBlocks(SASIDEV *) override;
|
||||||
|
void Seek6(SASIDEV *);
|
||||||
|
|
||||||
// Command helpers
|
// Command helpers
|
||||||
virtual int Inquiry(const DWORD *cdb, BYTE *buf) = 0; // INQUIRY command
|
virtual int Inquiry(const DWORD *cdb, BYTE *buf) = 0; // INQUIRY command
|
||||||
virtual int WriteCheck(DWORD block); // WRITE check
|
virtual int WriteCheck(DWORD block); // WRITE check
|
||||||
|
@ -143,12 +138,10 @@ public:
|
||||||
void SetBlockCount(uint32_t);
|
void SetBlockCount(uint32_t);
|
||||||
bool CheckBlockAddress(SASIDEV *, access_mode);
|
bool CheckBlockAddress(SASIDEV *, access_mode);
|
||||||
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
|
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
|
||||||
bool CheckReady();
|
|
||||||
|
|
||||||
// TODO This method should not be called by SASIDEV
|
|
||||||
virtual bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
||||||
|
int ModeSense10(const DWORD *cdb, BYTE *buf);
|
||||||
virtual int AddErrorPage(bool change, BYTE *buf);
|
virtual int AddErrorPage(bool change, BYTE *buf);
|
||||||
virtual int AddFormatPage(bool change, BYTE *buf);
|
virtual int AddFormatPage(bool change, BYTE *buf);
|
||||||
virtual int AddDrivePage(bool change, BYTE *buf);
|
virtual int AddDrivePage(bool change, BYTE *buf);
|
||||||
|
@ -158,11 +151,11 @@ protected:
|
||||||
int AddCDROMPage(bool change, BYTE *buf);
|
int AddCDROMPage(bool change, BYTE *buf);
|
||||||
int AddCDDAPage(bool, BYTE *buf);
|
int AddCDDAPage(bool, BYTE *buf);
|
||||||
|
|
||||||
virtual int RequestSense(const DWORD *cdb, BYTE *buf);
|
|
||||||
|
|
||||||
// Internal disk data
|
// Internal disk data
|
||||||
disk_t disk;
|
disk_t disk;
|
||||||
|
|
||||||
|
set<Disk *> disks;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Read(SASIDEV *, uint64_t);
|
void Read(SASIDEV *, uint64_t);
|
||||||
void Write(SASIDEV *, uint64_t);
|
void Write(SASIDEV *, uint64_t);
|
||||||
|
@ -171,9 +164,4 @@ private:
|
||||||
void ReadWriteLong16(SASIDEV *);
|
void ReadWriteLong16(SASIDEV *);
|
||||||
void ReadCapacity16_ReadLong16(SASIDEV *);
|
void ReadCapacity16_ReadLong16(SASIDEV *);
|
||||||
bool Format(const DWORD *cdb);
|
bool Format(const DWORD *cdb);
|
||||||
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
|
||||||
int ModeSense10(const DWORD *cdb, BYTE *buf);
|
|
||||||
int ModeSelectCheck(const DWORD *cdb, int length);
|
|
||||||
int ModeSelectCheck6(const DWORD *cdb);
|
|
||||||
int ModeSelectCheck10(const DWORD *cdb);
|
|
||||||
};
|
};
|
||||||
|
|
134
src/raspberrypi/devices/host_services.cpp
Normal file
134
src/raspberrypi/devices/host_services.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
// Features of the host services device:
|
||||||
|
//
|
||||||
|
// 1. Vendor-specific mode page 0x20 returns the current date and time (realtime clock)
|
||||||
|
//
|
||||||
|
// typedef struct {
|
||||||
|
// // Major and minor version of this data structure
|
||||||
|
// uint8_t major_version;
|
||||||
|
// uint8_t minor_version;
|
||||||
|
// // Current date and time, with daylight savings time adjustment applied
|
||||||
|
// uint8_t year; // year - 1900
|
||||||
|
// uint8_t month; // 0-11
|
||||||
|
// uint8_t day; // 1-31
|
||||||
|
// uint8_t hour; // 0-23
|
||||||
|
// uint8_t minute; // 0-59
|
||||||
|
// uint8_t second; // 0-59
|
||||||
|
// } mode_page_datetime;
|
||||||
|
//
|
||||||
|
// 2. STOP UNIT shuts down RaSCSI or the Raspberry Pi
|
||||||
|
// a) !start && !load (STOP): Shut down RaSCSI
|
||||||
|
// b) !start && load (EJECT): Shut down the Raspberry Pi
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "host_services.h"
|
||||||
|
|
||||||
|
bool HostServices::Dispatch(SCSIDEV *controller)
|
||||||
|
{
|
||||||
|
unsigned int cmd = controller->GetCtrl()->cmd[0];
|
||||||
|
|
||||||
|
// Only certain commands are supported
|
||||||
|
// TODO Do not inherit from Disk, mode page handling should be moved to ModePageDevice
|
||||||
|
if (cmd == ScsiDefs::eCmdTestUnitReady || cmd == ScsiDefs::eCmdRequestSense
|
||||||
|
|| cmd == ScsiDefs::eCmdInquiry || cmd == ScsiDefs::eCmdReportLuns
|
||||||
|
|| cmd == ScsiDefs::eCmdModeSense6 || cmd == ScsiDefs::eCmdModeSense10
|
||||||
|
|| cmd == ScsiDefs::eCmdStartStop) {
|
||||||
|
LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, cmd);
|
||||||
|
|
||||||
|
return Disk::Dispatch(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostServices::TestUnitReady(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
// Always successful
|
||||||
|
controller->Status();
|
||||||
|
}
|
||||||
|
|
||||||
|
int HostServices::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
|
{
|
||||||
|
int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8);
|
||||||
|
if (allocation_length > 4) {
|
||||||
|
if (allocation_length > 44) {
|
||||||
|
allocation_length = 44;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic data
|
||||||
|
// buf[0] ... Processor Device
|
||||||
|
// buf[1] ... Not removable
|
||||||
|
// buf[2] ... SCSI-2 compliant command system
|
||||||
|
// buf[3] ... SCSI-2 compliant Inquiry response
|
||||||
|
// buf[4] ... Inquiry additional data
|
||||||
|
memset(buf, 0, allocation_length);
|
||||||
|
buf[0] = 0x03;
|
||||||
|
buf[2] = 0x01;
|
||||||
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
|
// Padded vendor, product, revision
|
||||||
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocation_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostServices::StartStopUnit(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
bool start = ctrl->cmd[4] & 0x01;
|
||||||
|
bool load = ctrl->cmd[4] & 0x02;
|
||||||
|
|
||||||
|
if (!start) {
|
||||||
|
// Delete all regular disk devices. This also flushes their caches.
|
||||||
|
for (auto disk : disks) {
|
||||||
|
if (disk && disk != this) {
|
||||||
|
delete disk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load) {
|
||||||
|
((SCSIDEV *)controller)->ShutDown(SCSIDEV::rascsi_shutdown_mode::PI);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((SCSIDEV *)controller)->ShutDown(SCSIDEV::rascsi_shutdown_mode::RASCSI);
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->Status();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
||||||
|
}
|
||||||
|
|
||||||
|
int HostServices::AddVendorPage(int page, bool, BYTE *buf)
|
||||||
|
{
|
||||||
|
if (page == 0x20) {
|
||||||
|
// Data structure version 1.0
|
||||||
|
buf[0] = 0x01;
|
||||||
|
buf[1] = 0x00;
|
||||||
|
|
||||||
|
std::time_t t = std::time(NULL);
|
||||||
|
std::tm tm = *std::localtime(&t);
|
||||||
|
buf[2] = tm.tm_year;
|
||||||
|
buf[3] = tm.tm_mon;
|
||||||
|
buf[4] = tm.tm_mday;
|
||||||
|
buf[5] = tm.tm_hour;
|
||||||
|
buf[6] = tm.tm_min;
|
||||||
|
// Ignore leap second for simplicity
|
||||||
|
buf[7] = tm.tm_sec < 60 ? tm.tm_sec : 59;
|
||||||
|
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
25
src/raspberrypi/devices/host_services.h
Normal file
25
src/raspberrypi/devices/host_services.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
|
class HostServices: public Disk
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HostServices() : Disk("SCHS") {};
|
||||||
|
~HostServices() {};
|
||||||
|
|
||||||
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
int Inquiry(const DWORD *, BYTE *) override;
|
||||||
|
void TestUnitReady(SASIDEV *) override;
|
||||||
|
void StartStopUnit(SASIDEV *) override;
|
||||||
|
int AddVendorPage(int, bool, BYTE *) override;
|
||||||
|
};
|
|
@ -11,19 +11,18 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "scsi_primary_commands.h"
|
||||||
|
|
||||||
class SASIDEV;
|
class SASIDEV;
|
||||||
|
|
||||||
class ScsiBlockCommands
|
class ScsiBlockCommands : virtual public ScsiPrimaryCommands
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ScsiBlockCommands() {};
|
ScsiBlockCommands() {}
|
||||||
virtual ~ScsiBlockCommands() {};
|
virtual ~ScsiBlockCommands() {}
|
||||||
|
|
||||||
// Mandatory commands
|
// Mandatory commands
|
||||||
virtual void TestUnitReady(SASIDEV *) = 0;
|
|
||||||
virtual void Inquiry(SASIDEV *) = 0;
|
|
||||||
virtual void ReportLuns(SASIDEV *) = 0;
|
|
||||||
virtual void FormatUnit(SASIDEV *) = 0;
|
virtual void FormatUnit(SASIDEV *) = 0;
|
||||||
virtual void ReadCapacity10(SASIDEV *) = 0;
|
virtual void ReadCapacity10(SASIDEV *) = 0;
|
||||||
virtual void ReadCapacity16(SASIDEV *) = 0;
|
virtual void ReadCapacity16(SASIDEV *) = 0;
|
||||||
|
@ -31,7 +30,6 @@ public:
|
||||||
virtual void Read16(SASIDEV *) = 0;
|
virtual void Read16(SASIDEV *) = 0;
|
||||||
virtual void Write10(SASIDEV *) = 0;
|
virtual void Write10(SASIDEV *) = 0;
|
||||||
virtual void Write16(SASIDEV *) = 0;
|
virtual void Write16(SASIDEV *) = 0;
|
||||||
virtual void RequestSense(SASIDEV *) = 0;
|
|
||||||
|
|
||||||
// Implemented optional commands
|
// Implemented optional commands
|
||||||
virtual void ReadLong10(SASIDEV *) = 0;
|
virtual void ReadLong10(SASIDEV *) = 0;
|
||||||
|
@ -40,10 +38,6 @@ public:
|
||||||
virtual void ReadLong16(SASIDEV *) = 0;
|
virtual void ReadLong16(SASIDEV *) = 0;
|
||||||
virtual void WriteLong16(SASIDEV *) = 0;
|
virtual void WriteLong16(SASIDEV *) = 0;
|
||||||
virtual void Verify16(SASIDEV *) = 0;
|
virtual void Verify16(SASIDEV *) = 0;
|
||||||
virtual void ModeSense6(SASIDEV *) = 0;
|
|
||||||
virtual void ModeSense10(SASIDEV *) = 0;
|
|
||||||
virtual void ModeSelect6(SASIDEV *) = 0;
|
|
||||||
virtual void ModeSelect10(SASIDEV *) = 0;
|
|
||||||
virtual void ReassignBlocks(SASIDEV *) = 0;
|
virtual void ReassignBlocks(SASIDEV *) = 0;
|
||||||
virtual void SendDiagnostic(SASIDEV *) = 0;
|
virtual void SendDiagnostic(SASIDEV *) = 0;
|
||||||
virtual void StartStopUnit(SASIDEV *) = 0;
|
virtual void StartStopUnit(SASIDEV *) = 0;
|
||||||
|
|
|
@ -11,14 +11,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "scsi_primary_commands.h"
|
||||||
|
|
||||||
class SASIDEV;
|
class SASIDEV;
|
||||||
|
|
||||||
class ScsiMmcCommands
|
class ScsiMmcCommands : virtual public ScsiPrimaryCommands
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ScsiMmcCommands() {};
|
ScsiMmcCommands() {}
|
||||||
virtual ~ScsiMmcCommands() {};
|
virtual ~ScsiMmcCommands() {}
|
||||||
|
|
||||||
virtual void ReadToc(SASIDEV *) = 0;
|
virtual void ReadToc(SASIDEV *) = 0;
|
||||||
virtual void GetEventStatusNotification(SASIDEV *) = 0;
|
virtual void GetEventStatusNotification(SASIDEV *) = 0;
|
||||||
|
|
|
@ -17,15 +17,15 @@ class ScsiPrimaryCommands
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ScsiPrimaryCommands() {};
|
ScsiPrimaryCommands() {}
|
||||||
virtual ~ScsiPrimaryCommands() {};
|
virtual ~ScsiPrimaryCommands() {}
|
||||||
|
|
||||||
// Mandatory commands
|
// Mandatory commands
|
||||||
virtual void TestUnitReady(SASIDEV *) = 0;
|
virtual void TestUnitReady(SASIDEV *) = 0;
|
||||||
virtual void Inquiry(SASIDEV *) = 0;
|
virtual void Inquiry(SASIDEV *) = 0;
|
||||||
virtual void ReportLuns(SASIDEV *) = 0;
|
virtual void ReportLuns(SASIDEV *) = 0;
|
||||||
|
|
||||||
// Implemented optional commands
|
// Optional commands
|
||||||
virtual void RequestSense(SASIDEV *) = 0;
|
virtual void RequestSense(SASIDEV *) = 0;
|
||||||
virtual void ModeSense6(SASIDEV *) = 0;
|
virtual void ModeSense6(SASIDEV *) = 0;
|
||||||
virtual void ModeSense10(SASIDEV *) = 0;
|
virtual void ModeSense10(SASIDEV *) = 0;
|
||||||
|
|
136
src/raspberrypi/devices/mode_page_device.cpp
Normal file
136
src/raspberrypi/devices/mode_page_device.cpp
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
// A basic device with mode page support, to be used for subclassing
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "controllers/scsidev_ctrl.h"
|
||||||
|
#include "mode_page_device.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
ModePageDevice::ModePageDevice(const string id) : PrimaryDevice(id)
|
||||||
|
{
|
||||||
|
AddCommand(ScsiDefs::eCmdModeSense6, "ModeSense6", &ModePageDevice::ModeSense6);
|
||||||
|
AddCommand(ScsiDefs::eCmdModeSense10, "ModeSense10", &ModePageDevice::ModeSense10);
|
||||||
|
AddCommand(ScsiDefs::eCmdModeSelect6, "ModeSelect6", &ModePageDevice::ModeSelect6);
|
||||||
|
AddCommand(ScsiDefs::eCmdModeSelect10, "ModeSelect10", &ModePageDevice::ModeSelect10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModePageDevice::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (ModePageDevice::*execute)(SASIDEV *))
|
||||||
|
{
|
||||||
|
commands[opcode] = new command_t(name, execute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModePageDevice::Dispatch(SCSIDEV *controller)
|
||||||
|
{
|
||||||
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
(this->*command->execute)(controller);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown command
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModePageDevice::ModeSense6(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
|
||||||
|
if (ctrl->length <= 0) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->DataIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModePageDevice::ModeSense10(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer);
|
||||||
|
if (ctrl->length <= 0) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->DataIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModePageDevice::ModeSelect(const DWORD* /*cdb*/, const BYTE *buf, int length)
|
||||||
|
{
|
||||||
|
ASSERT(buf);
|
||||||
|
ASSERT(length >= 0);
|
||||||
|
|
||||||
|
// cannot be set
|
||||||
|
SetStatusCode(STATUS_INVALIDPRM);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModePageDevice::ModeSelect6(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||||
|
|
||||||
|
ctrl->length = ModeSelectCheck6(ctrl->cmd);
|
||||||
|
if (ctrl->length <= 0) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->DataOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||||
|
|
||||||
|
ctrl->length = ModeSelectCheck10(ctrl->cmd);
|
||||||
|
if (ctrl->length <= 0) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->DataOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
||||||
|
{
|
||||||
|
// Error if save parameters are set for other types than of SCHD or SCRM
|
||||||
|
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
||||||
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModePageDevice::ModeSelectCheck6(const DWORD *cdb)
|
||||||
|
{
|
||||||
|
// Receive the data specified by the parameter length
|
||||||
|
return ModeSelectCheck(cdb, cdb[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModePageDevice::ModeSelectCheck10(const DWORD *cdb)
|
||||||
|
{
|
||||||
|
// Receive the data specified by the parameter length
|
||||||
|
int length = cdb[7];
|
||||||
|
length <<= 8;
|
||||||
|
length |= cdb[8];
|
||||||
|
if (length > 0x800) {
|
||||||
|
length = 0x800;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModeSelectCheck(cdb, length);
|
||||||
|
}
|
52
src/raspberrypi/devices/mode_page_device.h
Normal file
52
src/raspberrypi/devices/mode_page_device.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "primary_device.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class ModePageDevice: public PrimaryDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ModePageDevice(const string);
|
||||||
|
virtual ~ModePageDevice() {}
|
||||||
|
|
||||||
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
virtual int ModeSense6(const DWORD *, BYTE *) = 0;
|
||||||
|
virtual int ModeSense10(const DWORD *, BYTE *) = 0;
|
||||||
|
|
||||||
|
// TODO This method should not be called by SASIDEV
|
||||||
|
virtual bool ModeSelect(const DWORD *, const BYTE *, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef struct _command_t {
|
||||||
|
const char* name;
|
||||||
|
void (ModePageDevice::*execute)(SASIDEV *);
|
||||||
|
|
||||||
|
_command_t(const char* _name, void (ModePageDevice::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
|
} command_t;
|
||||||
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (ModePageDevice::*)(SASIDEV *));
|
||||||
|
|
||||||
|
void ModeSense6(SASIDEV *) override;
|
||||||
|
void ModeSense10(SASIDEV *) override;
|
||||||
|
void ModeSelect6(SASIDEV *) override;
|
||||||
|
void ModeSelect10(SASIDEV *) override;
|
||||||
|
|
||||||
|
int ModeSelectCheck(const DWORD *, int);
|
||||||
|
int ModeSelectCheck6(const DWORD *);
|
||||||
|
int ModeSelectCheck10(const DWORD *);
|
||||||
|
};
|
223
src/raspberrypi/devices/primary_device.cpp
Normal file
223
src/raspberrypi/devices/primary_device.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "controllers/scsidev_ctrl.h"
|
||||||
|
#include "primary_device.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
PrimaryDevice::PrimaryDevice(const string id) : ScsiPrimaryCommands(), Device(id)
|
||||||
|
{
|
||||||
|
ctrl = NULL;
|
||||||
|
|
||||||
|
// Mandatory SCSI primary commands
|
||||||
|
AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &PrimaryDevice::TestUnitReady);
|
||||||
|
AddCommand(ScsiDefs::eCmdInquiry, "Inquiry", &PrimaryDevice::Inquiry);
|
||||||
|
AddCommand(ScsiDefs::eCmdReportLuns, "ReportLuns", &PrimaryDevice::ReportLuns);
|
||||||
|
|
||||||
|
// Optional commands used by all RaSCSI devices
|
||||||
|
AddCommand(ScsiDefs::eCmdRequestSense, "RequestSense", &PrimaryDevice::RequestSense);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryDevice::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (PrimaryDevice::*execute)(SASIDEV *))
|
||||||
|
{
|
||||||
|
commands[opcode] = new command_t(name, execute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PrimaryDevice::Dispatch(SCSIDEV *controller)
|
||||||
|
{
|
||||||
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
(this->*command->execute)(controller);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown command
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryDevice::TestUnitReady(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
if (!CheckReady()) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->Status();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryDevice::Inquiry(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
int lun = controller->GetEffectiveLun();
|
||||||
|
const Device *device = ctrl->unit[lun];
|
||||||
|
|
||||||
|
// Find a valid unit
|
||||||
|
// TODO The code below is probably wrong. It results in the same INQUIRY data being
|
||||||
|
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
|
||||||
|
// In addition, it supports gaps in the LUN list, which is not correct.
|
||||||
|
if (!device) {
|
||||||
|
for (int valid_lun = 0; valid_lun < SASIDEV::UnitMax; valid_lun++) {
|
||||||
|
if (ctrl->unit[valid_lun]) {
|
||||||
|
device = ctrl->unit[valid_lun];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
ctrl->length = Inquiry(ctrl->cmd, ctrl->buffer);
|
||||||
|
} else {
|
||||||
|
ctrl->length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl->length <= 0) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report if the device does not support the requested LUN
|
||||||
|
if (!ctrl->unit[lun]) {
|
||||||
|
LOGDEBUG("Reporting LUN %d for device ID %d as not supported", lun, ctrl->device->GetId());
|
||||||
|
|
||||||
|
ctrl->buffer[0] |= 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->DataIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryDevice::ReportLuns(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
BYTE *buf = ctrl->buffer;
|
||||||
|
|
||||||
|
if (!CheckReady()) {
|
||||||
|
controller->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
||||||
|
memset(buf, 0, allocation_length);
|
||||||
|
|
||||||
|
// Count number of available LUNs for the current device
|
||||||
|
int luns;
|
||||||
|
for (luns = 0; luns < controller->GetCtrl()->device->GetSupportedLuns(); luns++) {
|
||||||
|
if (!controller->GetCtrl()->unit[luns]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LUN list length, 8 bytes per LUN
|
||||||
|
// SCSI standard: The contents of the LUN LIST LENGTH field are not altered based on the allocation length
|
||||||
|
buf[0] = (luns * 8) >> 24;
|
||||||
|
buf[1] = (luns * 8) >> 16;
|
||||||
|
buf[2] = (luns * 8) >> 8;
|
||||||
|
buf[3] = luns * 8;
|
||||||
|
|
||||||
|
ctrl->length = allocation_length < 8 + luns * 8 ? allocation_length : 8 + luns * 8;
|
||||||
|
|
||||||
|
controller->DataIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryDevice::RequestSense(SASIDEV *controller)
|
||||||
|
{
|
||||||
|
int lun = controller->GetEffectiveLun();
|
||||||
|
|
||||||
|
// Note: According to the SCSI specs the LUN handling for REQUEST SENSE non-existing LUNs do *not* result
|
||||||
|
// in CHECK CONDITION. Only the Sense Key and ASC are set in order to signal the non-existing LUN.
|
||||||
|
if (!ctrl->unit[lun]) {
|
||||||
|
// LUN 0 can be assumed to be present (required to call RequestSense() below)
|
||||||
|
lun = 0;
|
||||||
|
|
||||||
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
||||||
|
ctrl->status = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl->length = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(ctrl->cmd, ctrl->buffer);
|
||||||
|
ASSERT(ctrl->length > 0);
|
||||||
|
|
||||||
|
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
||||||
|
|
||||||
|
controller->DataIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PrimaryDevice::CheckReady()
|
||||||
|
{
|
||||||
|
// Not ready if reset
|
||||||
|
if (IsReset()) {
|
||||||
|
SetStatusCode(STATUS_DEVRESET);
|
||||||
|
SetReset(false);
|
||||||
|
LOGTRACE("%s Disk in reset", __PRETTY_FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not ready if it needs attention
|
||||||
|
if (IsAttn()) {
|
||||||
|
SetStatusCode(STATUS_ATTENTION);
|
||||||
|
SetAttn(false);
|
||||||
|
LOGTRACE("%s Disk in needs attention", __PRETTY_FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return status if not ready
|
||||||
|
if (!IsReady()) {
|
||||||
|
SetStatusCode(STATUS_NOTREADY);
|
||||||
|
LOGTRACE("%s Disk not ready", __PRETTY_FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization with no error
|
||||||
|
LOGTRACE("%s Disk is ready", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf)
|
||||||
|
{
|
||||||
|
ASSERT(cdb);
|
||||||
|
ASSERT(buf);
|
||||||
|
|
||||||
|
// Return not ready only if there are no errors
|
||||||
|
if (GetStatusCode() == STATUS_NOERROR) {
|
||||||
|
if (!IsReady()) {
|
||||||
|
SetStatusCode(STATUS_NOTREADY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size determination (according to allocation length)
|
||||||
|
int size = (int)cdb[4];
|
||||||
|
ASSERT((size >= 0) && (size < 0x100));
|
||||||
|
|
||||||
|
// For SCSI-1, transfer 4 bytes when the size is 0
|
||||||
|
// (Deleted this specification for SCSI-2)
|
||||||
|
if (size == 0) {
|
||||||
|
size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the buffer
|
||||||
|
memset(buf, 0, size);
|
||||||
|
|
||||||
|
// Set 18 bytes including extended sense data
|
||||||
|
|
||||||
|
// Current error
|
||||||
|
buf[0] = 0x70;
|
||||||
|
|
||||||
|
buf[2] = (BYTE)(GetStatusCode() >> 16);
|
||||||
|
buf[7] = 10;
|
||||||
|
buf[12] = (BYTE)(GetStatusCode() >> 8);
|
||||||
|
buf[13] = (BYTE)GetStatusCode();
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
56
src/raspberrypi/devices/primary_device.h
Normal file
56
src/raspberrypi/devices/primary_device.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Uwe Seimet
|
||||||
|
//
|
||||||
|
// A device implementing mandatory SCSI primary commands, to be used for subclassing
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "controllers/sasidev_ctrl.h"
|
||||||
|
#include "interfaces/scsi_primary_commands.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class PrimaryDevice: public Device, virtual public ScsiPrimaryCommands
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
PrimaryDevice(const string);
|
||||||
|
virtual ~PrimaryDevice() {}
|
||||||
|
|
||||||
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
void TestUnitReady(SASIDEV *);
|
||||||
|
void RequestSense(SASIDEV *);
|
||||||
|
|
||||||
|
bool CheckReady();
|
||||||
|
virtual int Inquiry(const DWORD *, BYTE *) = 0;
|
||||||
|
virtual int RequestSense(const DWORD *, BYTE *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef struct _command_t {
|
||||||
|
const char* name;
|
||||||
|
void (PrimaryDevice::*execute)(SASIDEV *);
|
||||||
|
|
||||||
|
_command_t(const char* _name, void (PrimaryDevice::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
|
} command_t;
|
||||||
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (PrimaryDevice::*)(SASIDEV *));
|
||||||
|
|
||||||
|
void Inquiry(SASIDEV *);
|
||||||
|
void ReportLuns(SASIDEV *);
|
||||||
|
};
|
|
@ -38,13 +38,13 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP")
|
||||||
m_tap = NULL;
|
m_tap = NULL;
|
||||||
m_bTapEnable = false;
|
m_bTapEnable = false;
|
||||||
|
|
||||||
AddCommand(SCSIDEV::eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady);
|
AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady);
|
||||||
AddCommand(SCSIDEV::eCmdRead6, "Read6", &SCSIDaynaPort::Read6);
|
AddCommand(ScsiDefs::eCmdRead6, "Read6", &SCSIDaynaPort::Read6);
|
||||||
AddCommand(SCSIDEV::eCmdWrite6, "Write6", &SCSIDaynaPort::Write6);
|
AddCommand(ScsiDefs::eCmdWrite6, "Write6", &SCSIDaynaPort::Write6);
|
||||||
AddCommand(SCSIDEV::eCmdRetrieveStats, "RetrieveStats", &SCSIDaynaPort::RetrieveStatistics);
|
AddCommand(ScsiDefs::eCmdRetrieveStats, "RetrieveStats", &SCSIDaynaPort::RetrieveStatistics);
|
||||||
AddCommand(SCSIDEV::eCmdSetIfaceMode, "SetIfaceMode", &SCSIDaynaPort::SetInterfaceMode);
|
AddCommand(ScsiDefs::eCmdSetIfaceMode, "SetIfaceMode", &SCSIDaynaPort::SetInterfaceMode);
|
||||||
AddCommand(SCSIDEV::eCmdSetMcastAddr, "SetMcastAddr", &SCSIDaynaPort::SetMcastAddr);
|
AddCommand(ScsiDefs::eCmdSetMcastAddr, "SetMcastAddr", &SCSIDaynaPort::SetMcastAddr);
|
||||||
AddCommand(SCSIDEV::eCmdEnableInterface, "EnableInterface", &SCSIDaynaPort::EnableInterface);
|
AddCommand(ScsiDefs::eCmdEnableInterface, "EnableInterface", &SCSIDaynaPort::EnableInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCSIDaynaPort::~SCSIDaynaPort()
|
SCSIDaynaPort::~SCSIDaynaPort()
|
||||||
|
@ -60,7 +60,7 @@ SCSIDaynaPort::~SCSIDaynaPort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIDaynaPort::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (SCSIDaynaPort::*execute)(SASIDEV *))
|
void SCSIDaynaPort::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSIDaynaPort::*execute)(SASIDEV *))
|
||||||
{
|
{
|
||||||
commands[opcode] = new command_t(name, execute);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,8 @@ bool SCSIDaynaPort::Dispatch(SCSIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl = controller->GetCtrl();
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
if (commands.count(static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
@ -162,8 +162,6 @@ int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGTRACE("response size is %d", allocation_length);
|
|
||||||
|
|
||||||
return allocation_length;
|
return allocation_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "ctapdriver.h"
|
#include "ctapdriver.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../rascsi.h"
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -50,11 +49,11 @@ private:
|
||||||
|
|
||||||
_command_t(const char* _name, void (SCSIDaynaPort::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
_command_t(const char* _name, void (SCSIDaynaPort::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
} command_t;
|
} command_t;
|
||||||
std::map<SCSIDEV::scsi_command, command_t*> commands;
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSIDaynaPort::*)(SASIDEV *));
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSIDaynaPort::*)(SASIDEV *));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SCSIDaynaPort();
|
SCSIDaynaPort();
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "scsi_host_bridge.h"
|
#include "scsi_host_bridge.h"
|
||||||
|
|
||||||
#include "../rascsi.h"
|
|
||||||
#include "ctapdriver.h"
|
#include "ctapdriver.h"
|
||||||
#include "cfilesystem.h"
|
#include "cfilesystem.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -39,9 +37,9 @@ SCSIBR::SCSIBR() : Disk("SCBR")
|
||||||
fs = new CFileSys();
|
fs = new CFileSys();
|
||||||
fs->Reset();
|
fs->Reset();
|
||||||
|
|
||||||
AddCommand(SCSIDEV::eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady);
|
AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady);
|
||||||
AddCommand(SCSIDEV::eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10);
|
AddCommand(ScsiDefs::eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10);
|
||||||
AddCommand(SCSIDEV::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10);
|
AddCommand(ScsiDefs::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCSIBR::~SCSIBR()
|
SCSIBR::~SCSIBR()
|
||||||
|
@ -98,7 +96,7 @@ bool SCSIBR::Init(const map<string, string>& params)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIBR::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (SCSIBR::*execute)(SASIDEV *))
|
void SCSIBR::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSIBR::*execute)(SASIDEV *))
|
||||||
{
|
{
|
||||||
commands[opcode] = new command_t(name, execute);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
@ -107,8 +105,8 @@ bool SCSIBR::Dispatch(SCSIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl = controller->GetCtrl();
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
if (commands.count(static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../rascsi.h"
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -40,11 +39,11 @@ private:
|
||||||
|
|
||||||
_command_t(const char* _name, void (SCSIBR::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
_command_t(const char* _name, void (SCSIBR::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
} command_t;
|
} command_t;
|
||||||
std::map<SCSIDEV::scsi_command, command_t*> commands;
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSIBR::*)(SASIDEV *));
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSIBR::*)(SASIDEV *));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SCSIBR();
|
SCSIBR();
|
||||||
|
|
|
@ -242,8 +242,8 @@ SCSICD::SCSICD() : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
|
||||||
dataindex = -1;
|
dataindex = -1;
|
||||||
audioindex = -1;
|
audioindex = -1;
|
||||||
|
|
||||||
AddCommand(SCSIDEV::eCmdReadToc, "ReadToc", &SCSICD::ReadToc);
|
AddCommand(ScsiDefs::eCmdReadToc, "ReadToc", &SCSICD::ReadToc);
|
||||||
AddCommand(SCSIDEV::eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification);
|
AddCommand(ScsiDefs::eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -261,7 +261,7 @@ SCSICD::~SCSICD()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSICD::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (SCSICD::*execute)(SASIDEV *))
|
void SCSICD::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSICD::*execute)(SASIDEV *))
|
||||||
{
|
{
|
||||||
commands[opcode] = new command_t(name, execute);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
@ -270,8 +270,8 @@ bool SCSICD::Dispatch(SCSIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl = controller->GetCtrl();
|
ctrl = controller->GetCtrl();
|
||||||
|
|
||||||
if (commands.count(static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
|
if (commands.count(static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
|
||||||
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
|
command_t *command = commands[static_cast<ScsiDefs::scsi_command>(ctrl->cmd[0])];
|
||||||
|
|
||||||
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);
|
||||||
|
|
||||||
|
|
|
@ -78,11 +78,11 @@ private:
|
||||||
|
|
||||||
_command_t(const char* _name, void (SCSICD::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
_command_t(const char* _name, void (SCSICD::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
|
||||||
} command_t;
|
} command_t;
|
||||||
std::map<SCSIDEV::scsi_command, command_t*> commands;
|
std::map<ScsiDefs::scsi_command, command_t*> commands;
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSICD::*)(SASIDEV *));
|
void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSICD::*)(SASIDEV *));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "../rascsi.h"
|
|
||||||
|
|
||||||
#define DEFAULT_PRODUCT "SCSI HD"
|
#define DEFAULT_PRODUCT "SCSI HD"
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ void SCSIHD::FinalizeSetup(const Filepath &path, off_t size)
|
||||||
{
|
{
|
||||||
// 2TB is the current maximum
|
// 2TB is the current maximum
|
||||||
if (size > 2LL * 1024 * 1024 * 1024 * 1024) {
|
if (size > 2LL * 1024 * 1024 * 1024 * 1024) {
|
||||||
throw io_exception("File size must not exceed 2 TB");
|
throw io_exception("File size must not exceed 2 TiB");
|
||||||
}
|
}
|
||||||
|
|
||||||
// For non-removable media drives set the default product name based on the drive capacity
|
// For non-removable media drives set the default product name based on the drive capacity
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
#include "scsimo.h"
|
#include "scsimo.h"
|
||||||
|
|
||||||
#include "../rascsi.h"
|
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../rascsi.h"
|
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "file_access/file_access.h"
|
#include "file_access/file_access.h"
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
#include "rascsi.h"
|
#include "rascsi.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "controllers/scsidev_ctrl.h"
|
|
||||||
#include "controllers/sasidev_ctrl.h"
|
#include "controllers/sasidev_ctrl.h"
|
||||||
#include "devices/device_factory.h"
|
#include "devices/device_factory.h"
|
||||||
#include "devices/device.h"
|
#include "devices/device.h"
|
||||||
|
@ -97,7 +96,7 @@ void Banner(int argc, char* argv[])
|
||||||
__TIME__);
|
__TIME__);
|
||||||
FPRT(stdout,"Powered by XM6 TypeG Technology / ");
|
FPRT(stdout,"Powered by XM6 TypeG Technology / ");
|
||||||
FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n");
|
FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n");
|
||||||
FPRT(stdout,"Copyright (C) 2020-2021 Contributors to the RaSCSI project\n");
|
FPRT(stdout,"Copyright (C) 2020-2022 Contributors to the RaSCSI project\n");
|
||||||
FPRT(stdout,"Connect type : %s\n", CONNECT_DESC);
|
FPRT(stdout,"Connect type : %s\n", CONNECT_DESC);
|
||||||
|
|
||||||
if ((argc > 1 && strcmp(argv[1], "-h") == 0) ||
|
if ((argc > 1 && strcmp(argv[1], "-h") == 0) ||
|
||||||
|
@ -108,7 +107,7 @@ void Banner(int argc, char* argv[])
|
||||||
FPRT(stdout," FILE is disk image file.\n\n");
|
FPRT(stdout," FILE is disk image file.\n\n");
|
||||||
FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]);
|
FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]);
|
||||||
FPRT(stdout," n is X68000 SASI HD number(0-15).\n");
|
FPRT(stdout," n is X68000 SASI HD number(0-15).\n");
|
||||||
FPRT(stdout," FILE is disk image file, \"daynaport\", or \"bridge\".\n\n");
|
FPRT(stdout," FILE is disk image file, \"daynaport\", \"bridge\" or \"services\".\n\n");
|
||||||
FPRT(stdout," Image type is detected based on file extension.\n");
|
FPRT(stdout," Image type is detected based on file extension.\n");
|
||||||
FPRT(stdout," hdf : SASI HD image (XM6 SASI HD image)\n");
|
FPRT(stdout," hdf : SASI HD image (XM6 SASI HD image)\n");
|
||||||
FPRT(stdout," hds : SCSI HD image (Non-removable generic SCSI HD image)\n");
|
FPRT(stdout," hds : SCSI HD image (Non-removable generic SCSI HD image)\n");
|
||||||
|
@ -695,6 +694,9 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<string, string> params = { pb_device.params().begin(), pb_device.params().end() };
|
std::map<string, string> params = { pb_device.params().begin(), pb_device.params().end() };
|
||||||
|
if (!device->SupportsFile()) {
|
||||||
|
params.erase("file");
|
||||||
|
}
|
||||||
if (!device->Init(params)) {
|
if (!device->Init(params)) {
|
||||||
delete device;
|
delete device;
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,3 @@
|
||||||
#if defined(__x86_64__) || defined(__X86__)
|
#if defined(__x86_64__) || defined(__X86__)
|
||||||
#undef USE_SEL_EVENT_ENABLE
|
#undef USE_SEL_EVENT_ENABLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Class Declarations
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
class Fileio;
|
|
||||||
// File I/O
|
|
||||||
class Disk;
|
|
||||||
// SASI/SCSI Disk
|
|
||||||
class Filepath;
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ enum PbDeviceType {
|
||||||
SCBR = 6;
|
SCBR = 6;
|
||||||
// DaynaPort network adapter
|
// DaynaPort network adapter
|
||||||
SCDP = 7;
|
SCDP = 7;
|
||||||
|
// Host services device
|
||||||
|
SCHS = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rascsi remote operations, returning PbResult
|
// rascsi remote operations, returning PbResult
|
||||||
|
|
|
@ -67,13 +67,13 @@ void RascsiResponse::GetDeviceTypeProperties(PbDeviceTypesInfo& device_types_inf
|
||||||
|
|
||||||
void RascsiResponse::GetAllDeviceTypeProperties(PbDeviceTypesInfo& device_types_info)
|
void RascsiResponse::GetAllDeviceTypeProperties(PbDeviceTypesInfo& device_types_info)
|
||||||
{
|
{
|
||||||
GetDeviceTypeProperties(device_types_info, SAHD);
|
int ordinal = 1;
|
||||||
GetDeviceTypeProperties(device_types_info, SCHD);
|
while (PbDeviceType_IsValid(ordinal)) {
|
||||||
GetDeviceTypeProperties(device_types_info, SCRM);
|
PbDeviceType type = UNDEFINED;
|
||||||
GetDeviceTypeProperties(device_types_info, SCMO);
|
PbDeviceType_Parse(PbDeviceType_Name(ordinal), &type);
|
||||||
GetDeviceTypeProperties(device_types_info, SCCD);
|
GetDeviceTypeProperties(device_types_info, type);
|
||||||
GetDeviceTypeProperties(device_types_info, SCBR);
|
ordinal++;
|
||||||
GetDeviceTypeProperties(device_types_info, SCDP);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RascsiResponse::GetDevice(const Device *device, PbDevice *pb_device)
|
void RascsiResponse::GetDevice(const Device *device, PbDevice *pb_device)
|
||||||
|
|
|
@ -87,6 +87,9 @@ PbDeviceType ParseType(const char *optarg)
|
||||||
case 'r':
|
case 'r':
|
||||||
return SCRM;
|
return SCRM;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
return SCHS;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include "gpiobus.h"
|
#include "gpiobus.h"
|
||||||
#include "rascsi.h"
|
|
||||||
#include "rascsi_version.h"
|
#include "rascsi_version.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -59,6 +59,10 @@ string ras_util::ListDevices(const list<PbDevice>& pb_devices)
|
||||||
filename = "DaynaPort SCSI/Link";
|
filename = "DaynaPort SCSI/Link";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCHS:
|
||||||
|
filename = "Host Services";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
filename = device.file().name();
|
filename = device.file().name();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "scsi.h"
|
#include "scsi.h"
|
||||||
#include "rascsi.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
|
@ -153,3 +153,57 @@ private:
|
||||||
|
|
||||||
static const char* phase_str_table[];
|
static const char* phase_str_table[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScsiDefs {
|
||||||
|
public:
|
||||||
|
enum scsi_command : int {
|
||||||
|
eCmdTestUnitReady = 0x00,
|
||||||
|
eCmdRezero = 0x01,
|
||||||
|
eCmdRequestSense = 0x03,
|
||||||
|
eCmdFormat = 0x04,
|
||||||
|
eCmdReassign = 0x07,
|
||||||
|
eCmdRead6 = 0x08,
|
||||||
|
// DaynaPort specific command
|
||||||
|
eCmdRetrieveStats = 0x09,
|
||||||
|
eCmdWrite6 = 0x0A,
|
||||||
|
eCmdSeek6 = 0x0B,
|
||||||
|
// DaynaPort specific command
|
||||||
|
eCmdSetIfaceMode = 0x0C,
|
||||||
|
// DaynaPort specific command
|
||||||
|
eCmdSetMcastAddr = 0x0D,
|
||||||
|
// DaynaPort specific command
|
||||||
|
eCmdEnableInterface = 0x0E,
|
||||||
|
eCmdInquiry = 0x12,
|
||||||
|
eCmdModeSelect6 = 0x15,
|
||||||
|
eCmdReserve6 = 0x16,
|
||||||
|
eCmdRelease6 = 0x17,
|
||||||
|
eCmdModeSense6 = 0x1A,
|
||||||
|
eCmdStartStop = 0x1B,
|
||||||
|
eCmdSendDiag = 0x1D,
|
||||||
|
eCmdRemoval = 0x1E,
|
||||||
|
// ICD specific command
|
||||||
|
eCmdIcd = 0x1F,
|
||||||
|
eCmdReadCapacity10 = 0x25,
|
||||||
|
eCmdRead10 = 0x28,
|
||||||
|
eCmdWrite10 = 0x2A,
|
||||||
|
eCmdSeek10 = 0x2B,
|
||||||
|
eCmdVerify10 = 0x2F,
|
||||||
|
eCmdSynchronizeCache10 = 0x35,
|
||||||
|
eCmdReadDefectData10 = 0x37,
|
||||||
|
eCmdReadLong10 = 0x3E,
|
||||||
|
eCmdWriteLong10 = 0x3F,
|
||||||
|
eCmdReadToc = 0x43,
|
||||||
|
eCmdGetEventStatusNotification = 0x4A,
|
||||||
|
eCmdModeSelect10 = 0x55,
|
||||||
|
eCmdReserve10 = 0x56,
|
||||||
|
eCmdRelease10 = 0x57,
|
||||||
|
eCmdModeSense10 = 0x5A,
|
||||||
|
eCmdRead16 = 0x88,
|
||||||
|
eCmdWrite16 = 0x8A,
|
||||||
|
eCmdVerify16 = 0x8F,
|
||||||
|
eCmdSynchronizeCache16 = 0x91,
|
||||||
|
eCmdReadCapacity16_ReadLong16 = 0x9E,
|
||||||
|
eCmdWriteLong16 = 0x9F,
|
||||||
|
eCmdReportLuns = 0xA0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include "rascsi.h"
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include "monitor/sm_reports.h"
|
#include "monitor/sm_reports.h"
|
||||||
#include "monitor/data_sample.h"
|
#include "monitor/data_sample.h"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user