mirror of
https://github.com/akuker/RASCSI.git
synced 2025-04-08 21:41:39 +00:00
Made block size configurable (resolves issue #196)
This commit is contained in:
parent
0bd12e93f5
commit
db8c50ab00
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
//---------------------------------------------------------------------------
|
||||
SCSIHD_NEC::SCSIHD_NEC() : SCSIHD()
|
||||
{
|
||||
SetSectorSizeConfigurable(false);
|
||||
|
||||
SetVendor("NEC");
|
||||
|
||||
// Work initialization
|
||||
|
@ -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)) {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user