-
Notifications
You must be signed in to change notification settings - Fork 0
SCSI Driver
JNode's SCSI driver subsystem for disk and CD-ROM devices with command descriptor blocks and sense data handling.
The SCSI driver subsystem in JNode provides block device drivers for SCSI-based storage. The architecture is layered: a SCSI bus layer (org.jnode.driver.bus.scsi) containing core device classes and protocol utilities, a command layer with command descriptor block (CDB) implementations organized by command set (SPC for primary commands, MMC for multimedia), and a block driver layer (org.jnode.driver.block.scsi) that maps SCSI devices to block device APIs for use by the filesystem layer.
The subsystem bridges hardware SCSI devices (accessed via host controller bus drivers) to the block device layer, making disks and CD-ROMs accessible to filesystems through FSBlockDeviceAPI. The SCSI bus is abstract — concrete implementations like USB mass storage wrap SCSI-over-USB protocols.
| Class/File | Purpose |
|---|---|
SCSIDevice.java |
Abstract base for all SCSI devices, extends Device, declares executeCommand and getDescriptor
|
SCSIDeviceAPI.java |
Device API interface exposing executeCommand(CDB, ...) and getDescriptor() to upper layers |
CDB.java |
Abstract base class for all command descriptor blocks; extends SCSIBuffer, stores opcode |
SCSIBuffer.java |
Big-endian byte buffer for all SCSI data structures; provides getUInt8/16/32, getASCII, setInt8/16/32
|
SCSIConstants.java |
Timeout constants: GROUP_NOTIMEOUT (500ms), GROUP1_TIMEOUT (10s), GROUP2_TIMEOUT (5s) |
SCSIException.java |
Exception thrown by executeCommand on SCSI errors |
InquiryData.java |
Wrapper for INQUIRY response; exposes getPeripheralDeviceType, getVendorIdentification, getProductIdentification
|
SenseData.java |
Wrapper for sense data; exposes getSenseKey(), getASC(), getASCQ()
|
SenseKey.java |
Enum for SCSI sense keys (NO_SENSE, RECOVERED_ERROR, NOT_READY, etc.) |
SCSICDROMDriver.java |
Block driver for CD/DVD; implements FSBlockDeviceAPI and RemovableDeviceAPI; 2048-byte alignment |
CDROMDeviceToDriverMapper.java |
Maps SCSI devices with peripheral device type 0x05 to SCSICDROMDriver; match level MATCH_DEVCLASS
|
| Class | Opcode | Purpose |
|---|---|---|
CDBInquiry |
0x12 | Retrieve device identification and capabilities |
CDBRequestSense |
0x03 | Request sense data after check condition |
CDBReportLuns |
0xA0 | Report configured logical units |
CDBTestUnitReady |
0x00 | Check if device is ready |
| Class | Opcode | Purpose |
|---|---|---|
CDBRead10 |
0x28 | Read data from optical media |
CDBReadCapacity |
0x25 | Retrieve medium capacity |
CDBReadTOC |
0x43 | Read table of contents |
CDBMediaRemoval |
0x1E | Lock/unlock removable media |
CDBStartStopUnit |
0x1B | Start/stop/load/eject medium |
CDBGetConfiguration |
0x46 | Get current device configuration |
MMCUtils.java |
— | Static utility methods for MMC operations (readCapacity, readData, setMediaRemoval, startStopUnit) |
CapacityData.java |
— | Wrapper for READ CAPACITY response; exposes getLogicalBlockAddress(), getBlockLength()
|
SCSIDevice extends Device and sits below the driver framework. It is subclassed by hardware-specific bus drivers (e.g., USB mass storage wraps SCSI commands over USB). The device exposes SCSIDeviceAPI to the driver layer:
public abstract class SCSIDevice extends Device {
public abstract InquiryData getDescriptor();
public abstract int executeCommand(CDB cdb, byte[] data, int dataOffset, long timeout)
throws SCSIException, TimeoutException, InterruptedException;
public final SenseData requestSense() { ... }
}The SCSIDeviceAPIImpl inner class wraps a SCSIDevice and implements SCSIDeviceAPI, registering it on the device during startDevice() in drivers like SCSICDROMDriver.
- A driver (e.g.,
SCSICDROMDriver.read()) creates aCDBsubclass (e.g.,CDBRead10) with parameters encoded into the byte buffer. - The driver calls
SCSIDevice.executeCommand(cdb, data, offset, timeout). - The host controller implementation (e.g., USB) translates the CDB to the transport protocol, sends it, and receives data/status.
- On check condition, the driver calls
requestSense()to retrieveSenseDataand determine the error. -
SCSIExceptionwraps the error for the block layer.
CDB extends SCSIBuffer and assigns the opcode at byte 0:
public abstract class CDB extends SCSIBuffer {
public CDB(int cdbLength, int opcode) {
super(cdbLength);
setInt8(0, opcode);
}
public abstract int getDataTransfertCount();
}CDBs are grouped: Group 0 (6-byte CDB) for basic commands, Group 1 (10-byte CDB) for block devices. MMCUtils uses Group 1 timeouts for all CDB operations.
SCSICDROMDriver extends Driver and implements FSBlockDeviceAPI and RemovableDeviceAPI. On startDevice() it registers three APIs on the underlying SCSIDevice: SCSIDeviceAPI, RemovableDeviceAPI, and FSBlockDeviceAPI backed by FSBlockAlignmentSupport with 2048-byte alignment (standard CD-ROM sector size).
Read operations (read(long devOffset, ByteBuffer destBuf)) compute the LBA from devOffset / blockLength, construct a CDBRead10, call MMCUtils.readData(), and refresh the ByteBuffer. Write throws IOException("Readonly device").
The driver handles media changes via a changed flag. On getLength(), getSectorSize(), or read(), processChanged() re-reads the capacity if the flag is set.
CDROMDeviceToDriverMapper implements DeviceToDriverMapper with match level MATCH_DEVCLASS. It checks device instanceof SCSIDevice and getDescriptor().getPeripheralDeviceType() == 0x05 (CD/DVD device per SPC). Returns a new SCSICDROMDriver instance on match.
SCSIBuffer extends BigEndian to handle multi-byte values as MSB-first (big-endian), matching SCSI protocol requirements. Subclasses (InquiryData, CapacityData, SenseData) use typed getter/setter methods rather than raw offsets.
InquiryData masks peripheral device type with & 0x1F per SPC section 4.4.4. Vendor/product/revision fields are read as 8/16/4-byte ASCII strings with trailing space trimming.
SenseData extracts response code, sense key (masked to 4 bits), ASC, and ASCQ from the fixed-format sense buffer per SPC section 4.5.
-
No write support on CD-ROM:
SCSICDROMDriver.write()throws"Readonly device". This is correct for read-only optical media but must not be assumed for all SCSI devices. -
Media change detection: The driver uses a
changedboolean flag to trigger capacity re-reads. Applications relying on media change notifications should checkRemovableDeviceAPIstate or implement polling. -
SCSIDiskDriver not present: The issue mentions
SCSIDiskDriver.javabut it does not exist in the current codebase. SCSI disk support may be unimplemented or handled via other mechanisms (e.g., SCSI-over-USB in USBStorageSCSIDriver). -
Host controller abstraction:
SCSIDevice.executeCommand()is abstract — actual command transport depends on the host controller implementation (USB mass storage, hardware SCSI adapter). Drivers must handle transport-specific errors. -
Request sense on every error: The
requestSense()helper simplifies error diagnosis but adds an extra command on error paths. Some transports may not support it. - Peripheral device type checks: Device type 0x05 is CD/DVD per SPC. Other values (0x00=disk, 0x01=tape, 0x07=optical) require different block drivers.
- Block-Device-Layer — block I/O APIs that SCSI drivers implement
- Driver-Framework — device manager and driver lifecycle
- Filesystem-Layer — filesystem drivers consuming SCSI block devices
- IDEDisk-Driver — comparison with the IDE/ATA driver
- Bus-Drivers — bus enumeration that discovers SCSI devices
- Partition-Tables — partition discovery on SCSI disks
- ISO9660 — CD-ROM filesystem consuming SCSI CD/DVD devices