mirror of https://github.com/akuker/RASCSI.git
Fixed missing media change handling (#690)
* Remember media change * Added comment * Added TODO * Updated SCSI level for host services to SPC-5 * Manpage update
This commit is contained in:
parent
5d92590877
commit
ba8ad2e7f5
|
@ -71,7 +71,7 @@ Set the vendor, product and revision for the device, to be returned with the INQ
|
||||||
The rascsi server port, default is 6868.
|
The rascsi server port, default is 6868.
|
||||||
.TP
|
.TP
|
||||||
.BR \-r\fI " " \fIRESERVED_IDS
|
.BR \-r\fI " " \fIRESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve.
|
Comma-separated list of IDs to reserve. Pass an empty list in order to not reserve anything.
|
||||||
.BR \-p\fI " " \fITYPE
|
.BR \-p\fI " " \fITYPE
|
||||||
The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP, SCLP, SCHS). 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, SCLP, 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
|
||||||
|
|
|
@ -91,35 +91,36 @@ OPTIONS
|
||||||
The rascsi server port, default is 6868.
|
The rascsi server port, default is 6868.
|
||||||
|
|
||||||
-r RESERVED_IDS
|
-r RESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve. -p TYPE The optional
|
Comma-separated list of IDs to reserve. Pass an empty list in
|
||||||
case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
|
order to not reserve anything. -p TYPE The optional case-insen‐
|
||||||
SCBR, SCDP, SCLP, SCHS). If no type is specified for devices
|
sitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP,
|
||||||
that support an image file, rascsi tries to derive the type from
|
SCLP, SCHS). If no type is specified for devices that support an
|
||||||
the file extension.
|
image file, rascsi tries to derive the type from the file exten‐
|
||||||
|
sion.
|
||||||
|
|
||||||
-v Display the rascsi version.
|
-v Display the rascsi version.
|
||||||
|
|
||||||
-z LOCALE
|
-z LOCALE
|
||||||
Overrides the default locale for client-faces error messages.
|
Overrides the default locale for client-faces error messages.
|
||||||
The client can override the locale.
|
The client can override the locale.
|
||||||
|
|
||||||
-IDn[:u] FILE
|
-IDn[:u] FILE
|
||||||
n is the SCSI ID number (0-7). u (0-31) is the optional LUN
|
n is the SCSI ID number (0-7). u (0-31) is the optional LUN
|
||||||
(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, SCLP,
|
For devices that do not support an image file (SCBR, SCDP, SCLP,
|
||||||
SCHS) the filename may have a special meaning or a dummy name
|
SCHS) the filename may have a special meaning or a dummy name
|
||||||
can be provided. For SCBR and SCDP it is an optioinal priori‐
|
can be provided. For SCBR and SCDP it is an optioinal priori‐
|
||||||
tized list of network interfaces, an optional IP address and
|
tized list of network interfaces, an optional IP address and
|
||||||
netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24".
|
netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24".
|
||||||
For SCLP it is the print command to be used and a reservation
|
For SCLP it is the print command to be used and a reservation
|
||||||
timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60".
|
timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60".
|
||||||
|
|
||||||
-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‐
|
||||||
lated as n/2, the effective SASI LUN is calculated is the re‐
|
lated as n/2, the effective SASI LUN is calculated is the re‐
|
||||||
mainder of n/2. Alternatively the n:u syntax can be used, where
|
mainder 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).
|
ns is the SASI ID (0-7) and u the LUN (0-1).
|
||||||
|
|
||||||
FILE is the name of the image file to use for the SASI device.
|
FILE is the name of the image file to use for the SASI device.
|
||||||
|
@ -136,7 +137,7 @@ EXAMPLES
|
||||||
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 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 daynaport
|
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp daynaport
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ Rename an image file in the default image folder.
|
||||||
The rascsi port to connect to, default is 6868.
|
The rascsi port to connect to, default is 6868.
|
||||||
.TP
|
.TP
|
||||||
.BR \-r\fI " " \fIRESERVED_IDS
|
.BR \-r\fI " " \fIRESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve.
|
Comma-separated list of IDs to reserve. Pass an empty list in order to not reserve anything.
|
||||||
.TP
|
.TP
|
||||||
.BR \-s\fI
|
.BR \-s\fI
|
||||||
Display server-side settings like available images or supported device types.
|
Display server-side settings like available images or supported device types.
|
||||||
|
|
|
@ -71,9 +71,10 @@ OPTIONS
|
||||||
The rascsi port to connect to, default is 6868.
|
The rascsi port to connect to, default is 6868.
|
||||||
|
|
||||||
-r RESERVED_IDS
|
-r RESERVED_IDS
|
||||||
Comma-separated list of IDs to reserve.
|
Comma-separated list of IDs to reserve. Pass an empty list in
|
||||||
|
order to not reserve anything.
|
||||||
|
|
||||||
-s Display server-side settings like available images or supported
|
-s Display server-side settings like available images or supported
|
||||||
device types.
|
device types.
|
||||||
|
|
||||||
-T Display all device types and their properties.
|
-T Display all device types and their properties.
|
||||||
|
@ -100,7 +101,7 @@ OPTIONS
|
||||||
d(etach): Detach disk
|
d(etach): Detach disk
|
||||||
i(nsert): Insert media (removable media devices only)
|
i(nsert): Insert media (removable media devices only)
|
||||||
e(ject): Eject media (removable media devices only)
|
e(ject): Eject media (removable media devices only)
|
||||||
p(rotect): Write protect the medium (not for CD-ROMs, which
|
p(rotect): Write protect the medium (not for CD-ROMs, which
|
||||||
are always read-only)
|
are always read-only)
|
||||||
u(nprotect): Remove write protection from the medium (not for
|
u(nprotect): Remove write protection from the medium (not for
|
||||||
CD-ROMs, which are always read-only)
|
CD-ROMs, which are always read-only)
|
||||||
|
@ -110,18 +111,18 @@ OPTIONS
|
||||||
|
|
||||||
-b BLOCK_SIZE
|
-b BLOCK_SIZE
|
||||||
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
|
The optional block size. For SCSI drives 512, 1024, 2048 or 4096
|
||||||
bytes, default size is 512 bytes. For SASI drives 256 or 1024
|
bytes, default size is 512 bytes. For SASI drives 256 or 1024
|
||||||
bytes, default is 256 bytes.
|
bytes, default is 256 bytes.
|
||||||
|
|
||||||
-f FILE|PARAM
|
-f FILE|PARAM
|
||||||
Device-specific: Either a path to a disk image file, or a param‐
|
Device-specific: Either a path to a disk image file, or a param‐
|
||||||
eter for a non-disk device. See the rascsi(1) man page for per‐
|
eter for a non-disk device. See the rascsi(1) man page for per‐
|
||||||
mitted file types.
|
mitted file types.
|
||||||
|
|
||||||
-t TYPE
|
-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
|
from the file extension of the specified image. See the
|
||||||
rascsi(1) man page for the available device types. For some
|
rascsi(1) man page for the available device types. For some
|
||||||
types there are shortcuts (only the first letter is required):
|
types there are shortcuts (only the first letter is required):
|
||||||
hd: SCSI hard disk drive
|
hd: SCSI hard disk drive
|
||||||
rm: SCSI removable media drive
|
rm: SCSI removable media drive
|
||||||
|
@ -133,16 +134,16 @@ OPTIONS
|
||||||
services: Host services device
|
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
|
||||||
with the INQUIRY data. A complete set of name components must be
|
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
|
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‐
|
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.
|
changed.
|
||||||
|
|
||||||
-u UNIT
|
-u UNIT
|
||||||
Unit number (0-31). This will default to 0. This option is only
|
Unit number (0-31). This will default to 0. This option is only
|
||||||
used when there are multiple SCSI devices on a shared SCSI con‐
|
used when there are multiple SCSI devices on a shared SCSI con‐
|
||||||
troller. (This is not common)
|
troller. (This is not common)
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
|
|
|
@ -31,6 +31,7 @@ Disk::Disk(const string& id) : ModePageDevice(id), ScsiBlockCommands()
|
||||||
disk.blocks = 0;
|
disk.blocks = 0;
|
||||||
disk.dcache = NULL;
|
disk.dcache = NULL;
|
||||||
disk.image_offset = 0;
|
disk.image_offset = 0;
|
||||||
|
disk.is_medium_changed = false;
|
||||||
|
|
||||||
dispatcher.AddCommand(eCmdRezero, "Rezero", &Disk::Rezero);
|
dispatcher.AddCommand(eCmdRezero, "Rezero", &Disk::Rezero);
|
||||||
dispatcher.AddCommand(eCmdFormat, "FormatUnit", &Disk::FormatUnit);
|
dispatcher.AddCommand(eCmdFormat, "FormatUnit", &Disk::FormatUnit);
|
||||||
|
@ -79,6 +80,16 @@ Disk::~Disk()
|
||||||
|
|
||||||
bool Disk::Dispatch(SCSIDEV *controller)
|
bool Disk::Dispatch(SCSIDEV *controller)
|
||||||
{
|
{
|
||||||
|
// Media changes must be reported on the next access, i.e. not only for TEST UNIT READY
|
||||||
|
if (disk.is_medium_changed) {
|
||||||
|
assert(IsRemovable());
|
||||||
|
|
||||||
|
disk.is_medium_changed = false;
|
||||||
|
|
||||||
|
controller->Error(ERROR_CODES::sense_key::UNIT_ATTENTION, ERROR_CODES::asc::NOT_READY_TO_READY_CHANGE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// The superclass handles the less specific commands
|
// The superclass handles the less specific commands
|
||||||
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
||||||
}
|
}
|
||||||
|
@ -395,6 +406,15 @@ void Disk::ReadDefectData10(SASIDEV *controller)
|
||||||
controller->DataIn();
|
controller->DataIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Disk::MediumChanged()
|
||||||
|
{
|
||||||
|
assert(IsRemovable());
|
||||||
|
|
||||||
|
if (IsRemovable()) {
|
||||||
|
disk.is_medium_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Disk::Eject(bool force)
|
bool Disk::Eject(bool force)
|
||||||
{
|
{
|
||||||
bool status = Device::Eject(force);
|
bool status = Device::Eject(force);
|
||||||
|
|
|
@ -51,6 +51,7 @@ private:
|
||||||
uint32_t blocks; // Total number of sectors
|
uint32_t blocks; // Total number of sectors
|
||||||
DiskCache *dcache; // Disk cache
|
DiskCache *dcache; // Disk cache
|
||||||
off_t image_offset; // Offset to actual data
|
off_t image_offset; // Offset to actual data
|
||||||
|
bool is_medium_changed;
|
||||||
} disk_t;
|
} disk_t;
|
||||||
|
|
||||||
Dispatcher<Disk, SASIDEV> dispatcher;
|
Dispatcher<Disk, SASIDEV> dispatcher;
|
||||||
|
@ -61,6 +62,7 @@ public:
|
||||||
|
|
||||||
virtual bool Dispatch(SCSIDEV *) override;
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
void MediumChanged();
|
||||||
void ReserveFile(const string&);
|
void ReserveFile(const string&);
|
||||||
|
|
||||||
// Media Operations
|
// Media Operations
|
||||||
|
|
|
@ -58,8 +58,8 @@ void HostServices::TestUnitReady(SCSIDEV *controller)
|
||||||
|
|
||||||
int HostServices::Inquiry(const DWORD *cdb, BYTE *buf)
|
int HostServices::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Processor device, not removable
|
// Processor device, SPC-5, not removable
|
||||||
return PrimaryDevice::Inquiry(3, false, cdb, buf);
|
return PrimaryDevice::Inquiry(3, 7, false, cdb, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostServices::StartStopUnit(SCSIDEV *controller)
|
void HostServices::StartStopUnit(SCSIDEV *controller)
|
||||||
|
|
|
@ -92,6 +92,7 @@ void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
||||||
int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
||||||
{
|
{
|
||||||
// Error if save parameters are set for other types than of SCHD or SCRM
|
// Error if save parameters are set for other types than of SCHD or SCRM
|
||||||
|
// TODO This assumption is not correct, and this code should be located elsewhere
|
||||||
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -149,7 +149,7 @@ bool PrimaryDevice::CheckReady()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PrimaryDevice::Inquiry(int type, bool is_removable, const DWORD *cdb, BYTE *buf)
|
int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8);
|
int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8);
|
||||||
if (allocation_length > 4) {
|
if (allocation_length > 4) {
|
||||||
|
@ -166,7 +166,7 @@ int PrimaryDevice::Inquiry(int type, bool is_removable, const DWORD *cdb, BYTE *
|
||||||
memset(buf, 0, allocation_length);
|
memset(buf, 0, allocation_length);
|
||||||
buf[0] = type;
|
buf[0] = type;
|
||||||
buf[1] = is_removable ? 0x80 : 0x00;
|
buf[1] = is_removable ? 0x80 : 0x00;
|
||||||
buf[2] = 0x02;
|
buf[2] = scsi_level;
|
||||||
buf[4] = 0x1F;
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int Inquiry(int, bool, const DWORD *, BYTE *);
|
int Inquiry(int, int, bool, const DWORD *, BYTE *);
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
|
|
|
@ -114,8 +114,8 @@ void SCSIDaynaPort::Open(const Filepath& path)
|
||||||
|
|
||||||
int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf)
|
int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Processor device, not removable
|
// Processor device, SCSI-2, not removable
|
||||||
return PrimaryDevice::Inquiry(3, false, cdb, buf);
|
return PrimaryDevice::Inquiry(3, 2, false, cdb, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -105,8 +105,8 @@ void SCSIPrinter::TestUnitReady(SCSIDEV *controller)
|
||||||
|
|
||||||
int SCSIPrinter::Inquiry(const DWORD *cdb, BYTE *buf)
|
int SCSIPrinter::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Printer device, not removable
|
// Printer device, SCSI-2, not removable
|
||||||
return PrimaryDevice::Inquiry(2, false, cdb, buf);
|
return PrimaryDevice::Inquiry(2, 2, false, cdb, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIPrinter::ReserveUnit(SCSIDEV *controller)
|
void SCSIPrinter::ReserveUnit(SCSIDEV *controller)
|
||||||
|
|
|
@ -822,6 +822,11 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
||||||
device->SetProtected(pb_device.protected_());
|
device->SetProtected(pb_device.protected_());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Disk *disk = dynamic_cast<Disk *>(device);
|
||||||
|
if (disk) {
|
||||||
|
disk->MediumChanged();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ public:
|
||||||
INVALID_FIELD_IN_CDB = 0x24,
|
INVALID_FIELD_IN_CDB = 0x24,
|
||||||
INVALID_LUN = 0x25,
|
INVALID_LUN = 0x25,
|
||||||
WRITE_PROTECTED = 0x27,
|
WRITE_PROTECTED = 0x27,
|
||||||
|
NOT_READY_TO_READY_CHANGE = 0x28,
|
||||||
MEDIUM_NOT_PRESENT = 0x3a
|
MEDIUM_NOT_PRESENT = 0x3a
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue