Made block size configurable (resolves issue #196)

This commit is contained in:
Uwe Seimet 2021-08-22 00:37:13 +02:00
parent 0bd12e93f5
commit db8c50ab00
12 changed files with 143 additions and 44 deletions

View File

@ -42,6 +42,9 @@ To quit RaSCSI, press Control + C. If it is running in the background, you can k
.SH OPTIONS
.TP
.BR \-b\fI " " \fIBLOCK_SIZE
The optional block size for SCSI hard disk drives, either 512, 1024, 2048 or 4096. The default size 512 bytes.
.TP
.BR \-f\fI " " \fIFOLDER
The default folder for image files. For files in this folder no absolute path needs to be specified. The initial default folder is '~/images'.
.TP

View File

@ -49,31 +49,35 @@ DESCRIPTION
you can kill it using an INT signal.
OPTIONS
-b BLOCK_SIZE
The optional block size for SCSI hard disk drives, either 512,
1024, 2048 or 4096. The default size 512 bytes.
-f FOLDER
The default folder for image files. For files in this folder no
absolute path needs to be specified. The initial default folder
The default folder for image files. For files in this folder no
absolute path needs to be specified. The initial default folder
is '~/images'.
-g LOG_LEVEL
The rascsi log level (trace, debug, info, warn, err, critical,
The rascsi log level (trace, debug, info, warn, err, critical,
off). The default log level is 'info'.
-h Show a help page.
-n VENDOR:PRODUCT:REVISION
Set the vendor, product and revision for the device, to be re
turned with the INQUIRY data. A complete set of name components
Set the vendor, product and revision for the device, to be re
turned with the INQUIRY data. A complete set of name components
must be provided. VENDOR may have up to 8, PRODUCT up to 16, RE
VISION up to 4 characters. Padding with blanks to the maxium
length is automatically applied. Once set the name of a device
VISION up to 4 characters. Padding with blanks to the maxium
length is automatically applied. Once set the name of a device
cannot be changed.
-p PORT
The rascsi server port, default is 6868.
-p TYPE
The optional case-insensitive device type (SAHD, SCHD, SCRM,
SCCD, SCMO, SCBR, SCDP). If no type is specified for devices
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.
@ -82,8 +86,8 @@ OPTIONS
-IDn FILE
n is the SCSI ID number (0-7)
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
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.
-HDn FILE
@ -91,7 +95,7 @@ OPTIONS
FILE is the name of the image file to use for the SASI device.
Note: SASI usage is rare, and is typically limited to early
Note: SASI usage is rare, and is typically limited to early
Sharp X68000 systems.
EXAMPLES
@ -103,7 +107,7 @@ EXAMPLES
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 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:
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME

View File

@ -59,6 +59,9 @@ Command is the operation being requested. options are:
.IP
eject, protect and unprotect are idempotent.
.TP
.BR \-b\fI " " \fIBLOCK_SIZE
The optional block size for SCSI hard disk drives, either 512, 1024, 2048 or 4096. The default size is 512 bytes.
.TP
.BR \-f\fI " " \fIFILE
Path to the disk image file. See the rascsi(1) man page for allowable file types.
.TP

View File

@ -52,32 +52,36 @@ OPTIONS
eject, protect and unprotect are idempotent.
-b BLOCK_SIZE
The optional block size for SCSI hard disk drives, either 512,
1024, 2048 or 4096. The default size is 512 bytes.
-f FILE
Path to the disk image file. See the rascsi(1) man page for al
Path to the disk image file. See the rascsi(1) man page for al
lowable file types.
-t TYPE
Specifies the device type. This type overrides the type derived
Specifies the device type. This type overrides the type derived
from the file extension of the specified image. See the
rascsi(1) man page for the available device types. Legacy drive
rascsi(1) man page for the available device types. Legacy drive
types are:
hd: Hard disk (SCSI or SASI)
mo: Magneto-Optical disk
cd: CD-ROM
bridge: Bridge device (This is only applicable to the Sharp
bridge: Bridge device (This is only applicable to the Sharp
X68000)
-u 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
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 au
tomatically applied. Once set the name of a device cannot be
tomatically applied. Once set the name of a device cannot be
changed.
-u UNIT
Unit number (0 or 1). This will default to 0. This option is
only used when there are multiple SCSI devices on a shared SCSI
Unit number (0 or 1). This will default to 0. This option is
only used when there are multiple SCSI devices on a shared SCSI
controller. (This is not common)
EXAMPLES

View File

@ -70,6 +70,9 @@ private:
bool lockable;
bool locked;
// The block size is configurable
bool block_size_configurable;
// Device ID and LUN
unsigned int id;
unsigned int lun;

View File

@ -702,6 +702,8 @@ void DiskCache::Update()
Disk::Disk(const std::string id) : BlockDevice(id)
{
// Work initialization
sector_size_configurable = false;
configured_sector_size = 0;
disk.size = 0;
disk.blocks = 0;
disk.dcache = NULL;
@ -1965,6 +1967,26 @@ void Disk::SetSectorSize(int size)
disk.size = size;
}
bool Disk::IsSectorSizeConfigurable() const
{
return sector_size_configurable;
}
void Disk::SetSectorSizeConfigurable(bool sector_size_configurable)
{
this->sector_size_configurable = sector_size_configurable;
}
int Disk::GetConfiguredSectorSize() const
{
return configured_sector_size;
}
void Disk::SetConfiguredSectorSize(int configured_sector_size)
{
this->configured_sector_size = configured_sector_size;
}
DWORD Disk::GetBlockCount() const
{
return disk.blocks;

View File

@ -36,8 +36,8 @@ public:
// Internal data definition
typedef struct {
int track; // Track Number
int size; // Sector Size(8 or 9)
int sectors; // Number of sectors(<=0x100)
int size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
int sectors; // Number of sectors(<0x100)
DWORD length; // Data buffer length
BYTE *buffer; // Data buffer
BOOL init; // Is it initilized?
@ -111,7 +111,7 @@ private:
cache_t cache[CacheMax]; // Cache management
DWORD serial; // Last serial number
Filepath sec_path; // Path
int sec_size; // Sector size (8 or 9 or 11)
int sec_size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
int sec_blocks; // Blocks per sector
BOOL cd_raw; // CD-ROM RAW mode
off_t imgoffset; // Offset to actual data
@ -124,10 +124,14 @@ private:
//===========================================================================
class Disk : public BlockDevice
{
private:
bool sector_size_configurable;
int configured_sector_size;
protected:
// Internal data structure
typedef struct {
int size; // Sector Size
int size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
DWORD blocks; // Total number of sectors
DiskCache *dcache; // Disk cache
off_t imgoffset; // Offset to actual data
@ -171,6 +175,10 @@ public:
int ReportLuns(const DWORD *cdb, BYTE *buf); // REPORT LUNS command
int GetSectorSize() const;
void SetSectorSize(int);
bool IsSectorSizeConfigurable() const;
void SetSectorSizeConfigurable(bool);
int GetConfiguredSectorSize() const;
void SetConfiguredSectorSize(int);
DWORD GetBlockCount() const;
void SetBlockCount(DWORD);
// TODO Currently not called

View File

@ -34,6 +34,7 @@ SCSIHD::SCSIHD(bool removable) : Disk(removable ? "SCRM" : "SCHD")
{
SetRemovable(removable);
SetProtectable(true);
SetSectorSizeConfigurable(true);
}
//---------------------------------------------------------------------------
@ -81,9 +82,9 @@ void SCSIHD::Open(const Filepath& path)
throw io_exception("File size must not exceed 2 TB");
}
// sector size 512 bytes and number of blocks
SetSectorSize(9);
SetBlockCount((DWORD)(size >> 9));
// sector size (default 512 bytes) and number of blocks
SetSectorSize(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 9);
SetBlockCount((DWORD)(size >> GetSectorSize()));
LOGINFO("Media capacity for image file '%s': %d blocks", path.GetPath(),GetBlockCount());

View File

@ -31,6 +31,8 @@
//---------------------------------------------------------------------------
SCSIHD_NEC::SCSIHD_NEC() : SCSIHD()
{
SetSectorSizeConfigurable(false);
SetVendor("NEC");
// Work initialization

View File

@ -590,7 +590,8 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
ostringstream s;
s << (dryRun ? "Validating: " : "Executing: ");
s << "cmd=" << PbOperation_Name(cmd) << ", id=" << id << ", unit=" << unit << ", type=" << PbDeviceType_Name(type)
<< ", filename='" << filename << "', device name='" << pbDevice.name() << "', params='" << params << "'";
<< ", filename='" << filename << "', device name='" << pbDevice.name()
<< "', block size=" << pbDevice.block_size() << ", params='" << params << "'";
LOGINFO("%s", s.str().c_str());
// Check the Controller Number
@ -648,6 +649,36 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm
device->SetProtected(pbDevice.protected_());
}
if (pbDevice.block_size()) {
Disk *disk = dynamic_cast<Disk *>(device);
if (disk && disk->IsSectorSizeConfigurable()) {
switch (pbDevice.block_size()) {
case 512:
disk->SetConfiguredSectorSize(9);
break;
case 1024:
disk->SetConfiguredSectorSize(10);
break;
case 2048:
disk->SetConfiguredSectorSize(11);
break;
case 4096:
disk->SetConfiguredSectorSize(12);
break;
default:
error << "Invalid block size " << pbDevice.block_size();
return ReturnStatus(fd, false, error);
}
}
else {
return ReturnStatus(fd, false, "Block size is not configurable for device type " + PbDeviceType_Name(type));
}
}
FileSupport *fileSupport = dynamic_cast<FileSupport *>(device);
// File check (type is HD, for removable media drives, CD and MO the medium (=file) may be inserted later)
@ -886,12 +917,13 @@ bool ParseArgument(int argc, char* argv[], int& port)
bool is_sasi = false;
int max_id = 7;
PbDeviceType type = UNDEFINED;
int block_size = 0;
string name;
string log_level;
opterr = 1;
int opt;
while ((opt = getopt(argc, argv, "-IiHhG:g:D:d:N:n:T:t:P:p:f:Vv")) != -1) {
while ((opt = getopt(argc, argv, "-IiHhG:g:D:d:B:b:N:n:T:t:P:p:f:Vv")) != -1) {
switch (tolower(opt)) {
case 'i':
is_sasi = false;
@ -905,6 +937,11 @@ bool ParseArgument(int argc, char* argv[], int& port)
id = -1;
continue;
case 'b': {
block_size = atoi(optarg);
continue;
}
case 'g':
log_level = optarg;
continue;
@ -976,11 +1013,14 @@ bool ParseArgument(int argc, char* argv[], int& port)
device->set_id(id);
device->set_unit(unit);
device->set_type(type);
device->set_block_size(block_size);
device->set_name(name);
device->set_file(optarg);
id = -1;
type = UNDEFINED;
block_size = 0;
name = "";
}
if (!log_level.empty() && !SetLogLevel(log_level)) {

View File

@ -61,10 +61,13 @@ message PbDeviceDefinition {
int32 id = 1;
int32 unit = 2;
PbDeviceType type = 3;
string file = 4;
// The optional SCSI hard disk drive block size in bytes per sector, must be 512, 1024, 2048 or 4096
int32 block_size = 4;
// The optional name of the image file
string file = 5;
// The device name, format is VENDOR:PRODUCT:REVISION
string name = 5;
bool protected = 6;
string name = 6;
bool protected = 7;
}
message PbDeviceDefinitions {
@ -80,22 +83,23 @@ message PbDevice {
string vendor = 5;
string product = 6;
string revision = 7;
int32 block_size = 8;
// Read-only media (e.g. CD-ROMs) are not protectable but read-only all the time
bool read_only = 8;
bool read_only = 9;
// Media can be write-protected
bool protectable = 9;
bool protectable = 10;
// Media is write-protected
bool protected = 10;
bool protected = 11;
// Media can be removed
bool removable = 11;
bool removable = 12;
// Media is removed
bool removed = 12;
bool removed = 13;
// Media can be locked
bool lockable = 13;
bool lockable = 14;
// Media is locked
bool locked = 14;
bool locked = 15;
// Device supports image file
bool supports_file = 15;
bool supports_file = 16;
}
message PbDevices {

View File

@ -270,11 +270,12 @@ int main(int argc, char* argv[])
if (argc < 2) {
cerr << "SCSI Target Emulator RaSCSI Controller" << endl;
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-n NAME] [-f FILE] [-d DEFAULT_IMAGE_FOLDER] [-g LOG_LEVEL] [-h HOST] [-p PORT] [-v]" << endl;
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE] [-d DEFAULT_IMAGE_FOLDER] [-g LOG_LEVEL] [-h HOST] [-p PORT] [-v]" << endl;
cerr << " where ID := {0|1|2|3|4|5|6|7}" << endl;
cerr << " UNIT := {0|1} default setting is 0." << endl;
cerr << " UNIT := {0|1}, default setting is 0." << endl;
cerr << " CMD := {attach|detach|insert|eject|protect|unprotect}" << endl;
cerr << " TYPE := {sahd|schd|scrm|sccd|scmo|scbr|scdp} or legacy types {hd|mo|cd|bridge}" << endl;
cerr << " BLOCK_SIZE := {512|1024|2048|4096) bytes per hard disk drive block" << endl;
cerr << " NAME := name of device to attach (VENDOR:PRODUCT:REVISION)" << endl;
cerr << " FILE := image file path" << endl;
cerr << " DEFAULT_IMAGE_FOLDER := default location for image files, default is '~/images'" << endl;
@ -302,7 +303,7 @@ int main(int argc, char* argv[])
opterr = 1;
int opt;
while ((opt = getopt(argc, argv, "i:u:c:t:f:d:h:n:p:u:g:lsv")) != -1) {
while ((opt = getopt(argc, argv, "b:i:u:c:t:f:d:h:n:p:u:g:lsv")) != -1) {
switch (opt) {
case 'i':
device->set_id(optarg[0] - '0');
@ -312,6 +313,10 @@ int main(int argc, char* argv[])
device->set_unit(optarg[0] - '0');
break;
case 'b':
device->set_block_size(atoi(optarg));
break;
case 'c':
command.set_cmd(ParseOperation(optarg));
break;