The SCSI Switcher system
An increasing number of devices are using SCSI command protocols over
non-SCSI connections. Examples include ATAPI (SCSI-over-ATA), Iomega Zip
drives (SCSI-over-Parallel) and USB Mass Storage devices (SCSI-over-USB).
Hitherto, the standard RISC OS SCSI programming interface has been provided
by a "SCSIdriver" module appropriate for whichever SCSI interface was
fitted to a machine. This system does not allow for more than one type of
SCSI interface card to be fitted to a machine, and precludes easy integration
of SCSI-like devices.
The SCSI Switcher system rectifies the situation by acting as the "SCSIdriver"
module, and dispatching the SCSI SWIs to multiple hardware drivers. SCSI
hardware drivers interfacing to the SCSI Switcher can be simpler than a full
SCSIdriver module, as the Switcher itself handles many of the higher-level
calls and details like device reservation.
Example compilable source code for the SCSISoftWD33C93 driver for the Acorn SCSI card
is available here. This includes a compiled (but untested) version of the enclosed source code.
From the application programmers point of view, there should be little visible
difference between a system using the SCSI Switcher and a system with a standalone
SCSIdriver module. One point to note is that SCSI_Version may not accurately report
the capabilities of every device - for example some devices may support
background operations, others may not.
SCSIdriver 2 has some new SWIs and service calls, detailed below.
| In: | | R1 = &20100
| | Out: | | All registers preserved to pass on
|
Issued as SCSIdriver initialises. The SWIs will not yet be available at this
point - use a callback to call them if you need to.
| In: | | R1 = &20101
| | Out: | | All registers preserved to pass on
|
Issued before SCSIdriver dies. The SCSI system is still alive at this point,
but a hardware driver may have shut down if it received this service call
before you.
| In: | | R0 = | | device ID
| | | R1 = | | &20103
| | | R2 = | | device ID mask
|
Issued when a new device or bus is registered with SCSIdriver. A hardware
driver may issue this itself to indicate that a device has been attached to an
ID already registered with SCSIdriver.
The mask indicates whether a bus, a device or a unit (potentially multiple)
has been attached; someone wanting to rescan the bus should scan all devices
with IDs such that <device ID> AND R2 = R0.
| Example: | | Bus 0, device 1 attached: R0 = &01 (0:1.0), R2 = &1F (3:7.0)
| | | Bus 3, device 4, unit 5 attached: R0 = &BC (3:4.5), R2 = &FF (3:7.7)
| | | Bus 2 attached: R0 = &10 (2:0.0), R2 = &18 (2:0.0)
|
| In: | | R0 = | | device ID
| | | R1 = | | &20103
| | | R2 = | | device ID mask
|
Issued when a new device or bus is deregistered with SCSIdriver. A hardware
driver may issue this itself to indicate that a device has been detached
without deregistering from SCSIdriver. See Service_SCSIAttached for details
of the ID mask.
| In: | | R0 | | Bit 0:- 0 => device, 1 => bus
| | | | | Bits 8-15:- highest device number (if bus)
| | | | | Bits 16-23:- default host ID (if bus) - 255 signifies no host ID
| | | | | other bits reserved
| | | R1 -> | | handler code
| | | R2 = | | handler R12 value
| | | R3 = | | handler R8 value
| | Exit: | | R0 = | | device / bus ID (bus ID has LUN/Device fields 0)
|
This call registers a hardware driver with the SCSI Switcher. The handler
routine will be called to request various actions (see section below).
| In: | | R0 = device / bus ID
| | | R1 -> handler code
| | | R2 = handler R12 value
| | | R3 = handler R8 value
| | Exit: | | -
|
This call deregisters a hardware driver with the SCSI Switcher. Only the
bus part of the ID is significant for bus drivers.
The rest of this document covers the information required to write a SCSI
hardware driver that interfaces to the SCSI Switcher
Each registration from a hardware driver may provide either a bus, or a
single device. A standard SCSI interface card would typically provide a bus, a
USB mass storage driver would typically provide multiple individual devices.
Depending on the type of registration, the handler routines are called slightly
differently. This is detailed in the relevant calls.
If a command completes, the status byte (eg &00 for GOOD, &02 for CHECK
CONDITION) is returned in R0. Higher-level functions like sending automatic
REQUEST SENSE commands (or not), or retrying after Unit Attention (if
enabled) is handled by the dispatcher. The driver should just return the
top-level response.
All driver entries use standard device IDs:
| Bits | | 0-2 | | Device ID |
| | 3-4 | | Bus ID |
| | 5-7 | | LUN |
The LUN is passed down to the driver to treat as it wishes (eg to be inserted
into the CDB, placed into an IDENTIFY message, or used in some other
encapsulation scheme). It is not interpreted by the switcher.
Device reservation (the SCSI R8 access lock) is handled by the dispatcher.
All driver entries can return a standard SCSI error by returning with V set
and R0 < 256 - this will be translated into the appropriate standard RISC OS
SCSI error with number &201nn and the corresponding message. Any other error
can be returned with V set and R0 >= 256 being a pointer to an error block.
| In: | | R0..R7 | | depend on entry number
| | | R8 = | | handle
| | | R11 = | | reason codes
| | | R12 = | | workspace pointer
|
Any unrecognised or unimplemented reason codes must return with V set and
R0 = 1 (corresponding to the standard SCSI error "Unknown SCSI SWI number").
All entry points may corrupt R10-R12. All other registers must be preserved
except where specified by a particular reason code.
| In: | | R11 = | | 0
| | Out: | | R1 | | bit 5: supports scatter lists
| | | | | bit 1: supports background operations
| | | | | all other bits reserved (must be 0)
|
If a device supports background operations, all operation requests given
to it will be background ones (foreground SCSI_Op SWIs will be translated
into background ones by the switcher).
Similarly, if a device supports scatter lists, then all operation requests
given to it will use scatter lists.
Sets a new host ID and causes a full reset of the SCSI bus by driving the
SCSI bus RESET line. All commands in progress should be silently cancelled.
Corresponds to SCSI_Initialise 0. The host ID is the device ID part only -
the LUN and Card fields are zero.
This call is only issued to bus drivers.
| In: | | R0 = | | Bits 0..7 | | Device ID |
| | | | Bit 20 | | Inhibit Identify message (Parallel SCSI-specific) |
| | | | Bit 21 | | Inhibit Disconnection (Parallel SCSI-specific) |
| | | | Bits 24-25 | | 00 => no data transfer, 01 => read, 10=>write, 11=>reserved |
| | | | Bit 26 | | Scatter Bit, if set, R3 is a pointer to a scatter list. |
| | | | Bit 27 | | If clear, poll escape during transfer and abort if escape pressed |
| | | | Bit 29 | | Clear (=> foreground operation) |
| | | | | | Other bits should be ignored |
| | R1 = | | Length of SCSI control block |
| | R2 -> | | Ptr to SCSI control block | | | |
| | R3 -> | | RAM ptr for start of transfer or pointer to scatter list of address length pairs if Bit 26 of R0 is set. |
| | R4 = | | Length of transfer (in bytes). |
| | R5 = | | Timeout in centiseconds or 0 for no timeout |
| | R11 = | | 4 | | | |
| Out: | | R0 = | | status byte or error value (depending on V) |
| | R4 = | | Number of bytes not transferred |
This call is only issued for drivers that do not support background operations.
The length will be 0 if and only if "no data transfer" is flagged.
The scatter list must not be updated. The driver should accept FileCore-style
wrapping (ie if an address entry is between &FFFF0000 and &FFFFFFFF, and the
length field is 0, then that should be treated as an instruction to push the
scatter list pointer backwards by an offset of up to 64K).
Flag bits 20 and 21 correspond to the settings of SCSI_Control 6, and are
specific to Parallel (standard) SCSI.
| In: | | R0 = | | Bits 0..7 | | Device ID |
| | | | Bit 20 | | Inhibit Identify message (Parallel SCSI-specific) |
| | | | Bit 21 | | Inhibit Disconnection (Parallel SCSI-specific) |
| | | | Bits 24..25 | | 00 => no data transfer, 01 => read, 10=>write, 11=>reserved |
| | | | Bit 26 | | Scatter Bit, if set, R3 is a pointer to a scatter list. |
| | | | Bit 29 | | Set (=> background operation) |
| | R1 = | | Length of SCSI control block |
| | R2 -> | | Ptr to SCSI control block (guaranteed valid until command completes) |
| | R3 -> | | RAM ptr for start of transfer or pointer to scatter list of address length |
| | | | pairs if Bit 26 of R0 is set. |
| | R4 = | | Length of transfer (in bytes). |
| | R5 = | | Command handle to pass in R5 for background call back |
| | R6 -> | | Address to call back when transfer is complete. |
| | R7 = | | Workspace pointer to pass in R12 for background call back. |
| | R11 = | | 5 |
| Out: | | | | If completed immediately |
| | R0 = | | status byte or error value (depending on V) |
| | R4 = | | amount not transferred |
| | | | else |
| | R0 = | | -1 |
| | R1 = | | driver handle for operation |
| |
|
The length will be 0 if and only if "no data transfer" is flagged.
Completion/errors can be signalled either immediately, or by returning with
R0=-1, then calling the callback routine at a later date.
If an immediate error is returned, this will be passed straight back to the
user, unless the error is &2010D ("Queue full"). This will be taken as an
indication that the driver is unable to accept the command at this time (eg
if a driver that can only can only handle 1 command at a time is issued a 2nd
command while a previous command is still active). The command will be
reoffered the next time a command for this driver completes. Queue full must
not be returned if no commands are currently running for the driver.
The scatter list must not be updated. The driver should accept FileCore-style
wrapping (ie if an address entry is between &FFFF0000 and &FFFFFFFF, and the
length field is 0, then that should be treated as an instruction to push the
scatter list pointer backwards by an offset of up to 64K).
Flag bits 20 and 21 correspond to the settings of SCSI_Control 6, and are
specific to Parallel (standard) SCSI.
The callback must operate as follows:
The call is made in privileged mode with IRQs disabled.
If the operation completed, V is clear & R0 is set to the SCSI status byte.
If an error occurred, V is set and R0 is an error number or pointer.
R4 should be set to the data not transferred.
R5 and R12 must be set to the values passed in.
All registers will be preserved.
| In: | | R0 = | | flags: Bit 11 = Timeout
| | | | | Bit 12 = Escape
| | | | | Bit 13 = Abort operation
| | | R1 = | | device ID
| | | R2 = | | driver handle for operation
| | | R11 = | | 6
|
This call is a request to cancel a pending background operation. If the
driver is able to cancel the operation, the callback routine (as passed in
the background operation request) should be called with an appropriate error,
eg R0=&0B ("Timeout"); R0 -> {17,"Escape"}; R0=&12 ("Operation aborted").
| In: | | R0 -> | | 28-byte buffer [0..7] = Vendor, [8..23] = Product, [24..27] = Revision
| | | R1 = | | device ID
| | | R11 = | | 7
|
The buffer should be filled in with ASCII data describing the host adapter
for the bus, to be used by SCSI_Initialise 3 (and hence *Devices). The data
corresponds to bytes 8-35 of a SCSI INQUIRY reply.
 |
| © 2006 IYONIX Ltd |
32-bit RISC OS |
|