Category : HD Utilities
Archive   : SCSI-2.ZIP
Filename : CAM-R23.TXT

 
Output of file : CAM-R23.TXT contained in archive : SCSI-2.ZIP
Copies of this proposal may be purchased from: BSR X3.***
Global Engineering, 2805 McGaw St, Irvine, CA 92714 X3T9.2/90-186
800-854-7179 714-261-1455





working draft proposed American National
Standard for Information Systems -

SCSI-2 Common Access Method

Transport
and
SCSI Interface Module

Rev 2.3 February 25, 1991




Secretariat

Computer and Business Equipment Manufacturers Association (CBEMA)

Abstract: This standard defines the software interface between device drivers
and the Host Bus Adapters or other means by which SCSI peripherals are
attached to a host processor. The software interface defined provides a common
interface specification for systems manufacturers, system integrators,
controller manufacturers, and suppliers of intelligent peripherals.

This is an internal working document of X3T9.2, a Task Group of Accredited
Standards Committee X3. As such this is not a completed standard. The
contents are actively being modified by the X3T9.2 Task Group. This document
is made available for review and comment only.





POINTS OF CONTACT:

John B. Lohmeyer I. Dal Allan
Chairman X3T9.2 Vice-Chairman X3T9.2
NCR ENDL
3718 N Rock Rd 14426 Black Walnut Court
Wichita KS 67226 Saratoga CA 95070

316-636-8703 408-867-6630



An electronic copy of this document is available from the SCSI Bulletin Board
(316-636-8700).

This document has been prepared according to the style guide of the ISO
(International Organization of Standards).


If this document was printed in a 2-up form directly from the printer, NOTEs
had to be adjusted to fit into a half-page, which may have resulted in an
imperfect representation of the format within the NOTE. This is most likely to
occur if a series of NOTEs are mixed in without any line separation.






This revision contains recommended changes by Jerry Armstrong
and the DOS OSD working group. You will find that the DOS OSD
has been extensively revised.

John Gallant also submitted a list of change requests, most of
which are included. Please look them over carefully, and be
sure to advise Dal by fax at 408-867-2115 of any objections.

Foreword (This Foreword is not part of American National Standard X3.***-
199x.)

In this standard, the Transport (XPT) and SCSI Interface Module (SIM) for
the SCSI-2 Common Access Method is defined.

When the Small Computer System Interface (SCSI) was introduced, a large number
of systems integrators included support in their operating systems. However,
they were parochial in implementation and a diverse set of strategies to
support SCSI devices were implemented in software.

Some companies published their specifications and encouraged third-party
suppliers to add new peripherals. Others failed to add support for SCSI or
did not publish the specifications. An increasing demand developed for some
common method to attach SCSI peripherals to a number of operating systems
and a large range of computer systems. Much of this impetus stemmed from the
growth in the desktop computing environment.

In October 1988 a number of peripheral suppliers formed the Common Access
Method Committee to encourage an industry-wide effort to adopt a common
software interface to despatch input/output requests to SCSI peripherals.

The primary objective was to define a set of software constructs and tables
that would permit the manufacturers of host adapters to provide software or
microcode to interpret requests in a common manner.

Out of the proposals made by a large number of contributors, the CAM
Committee selected the best concepts and used them to develop the standard.

Some of the companies which contributed had designed their own methods to
support SCSI devices, and for the most part set aside individual business
considerations to foster the development and adoption of this standard.


Suggestions for improvement of this standard will be welcome. They should be
sent to the Computer and Business Equipment Manufacturers Association, 311
First Street N.W., Suite 500, Washington, DC 20001.

This standard was processed and approved for submittal to ANSI by the
Accredited Standards Committee on Information Procsessing Systems, X3.
Committee approval of this standard does not necessarily imply that all
committee members voted for its approval. At the time it approved this
standard, the X3 Committee had the following members:

X3 Committee list goes here:


Subcommittee X3T9 on I/O interfaces, which reviewed this standard, had the
following members:

X3T9 Committee list goes here:




Task Group X3T9.2 on Lower-Level Interfaces, which completed the development
of this standard, had the following members:

X3T9.2 Committee list goes here:



The initial development work on this standard was done by the CAM Committee,
an industry group formed for this purpose. The membership of the CAM
Committee consisted of the following organizations:

Adaptec Data Technology NCR
AMD Eastman Kodak Olivetti
Apple Emulex Quantum
AT&T Bell Labs Fujitsu uElectronics Scientific Micro Systems
Caliper Future Domain Seagate
Cambrian Systems Hewlett Packard Sony
Cipher Data IBM Storage Dimensions
Cirrus Logic Imprimis Sun Microsystems
Columbia Data Interactive Systems Syquest Technology
CompuAdd JVC Sytron
Conner Peripherals LMS OSD Trantor
Dell Computer Maxtor Western Digital
Digital Equipment Micropolis
DPT Miniscribe

TABLE OF CONTENTS

1. Scope 1
1.1 Description of Clauses 1

2. References 2
3. General Description 2
3.1 Environment 2
3.2 Peripheral Driver Functions 3
3.3 XPT Functions 4
3.4 SIM Functions 4

4. Definitions and Conventions 4
4.1 Definitions 4
4.2 Conventions 5

5. Background 6
5.1 Software 6
5.2 CAM (Common Access Method) 6
5.2.1 XPT (Transport) 6
5.2.2 SIM (SCSI Interface Module) 6
5.2.3 CCB (CAM Control Block) 7
5.2.4 OSD (Operating System Dependent) 7

5.3 Principles of Operation 7
5.4 Requirements 8

6. Transport 8
6.1 Accessing the XPT 8
6.2 Initialization 9
6.3 Callback on Completion 9
6.4 SCSI Request Queues 9
6.4.1 The Target/LUN and the Peripheral Driver 10
6.4.2 The SIM 10
6.4.3 SIM Queuing 10
6.4.3.1 SIM Queue Priority 10
6.4.3.2 Tag Recognition 10
6.4.3.3 Error conditions and Queues within the Subsystem 10

6.5 SIM Handling of SCSI Resets 11
6.6 Asynchronous Callback 12
6.7 Autosense 13
6.8 Loadable Modules 14

7. OSD (Operating System Dependent) Operation 15
7.1 UNIX Operating System 15
7.1.1 Initialization 15
7.1.2 Accessing the XPT 16
7.1.2.1 From the Peripheral Driver 16
7.1.2.2 From the SIM 16

7.1.3 Callback on Completion 17
7.1.4 Pointer Definition in the UNIX Environment 17
7.1.5 Request Mapping Information 17
7.1.6 XPT Interface 17
7.1.6.1 Functions for Peripheral Driver Support 17
7.1.6.2 Functions for SIM Module Support 18

7.1.7 SIM Interface 18

7.2 Novell Operating System 19
7.2.1 Initialization 19
7.2.2 De-Registration 20
7.2.3 Accessing the XPT 20
7.2.4 Hardware Registration 21
7.2.5 Miscellaneous 21

7.3 DOS (Disk Operating System) 21
7.3.1 Initialization 21
7.3.1.1 Multiple XPTs 22
7.3.1.2 Device Table Handling 22

7.3.2 Accessing the XPT 22
7.3.2.1 Testing for the presence of the XPT/SIM 22
7.3.2.2 Sending a CCB to the XPT 23

7.3.3 Callback on Completion 24
7.3.4 Asynchronous Callbacks 24
7.3.5 Pointer Definition 25

7.4 OS/2 (Operating System 2) 25

8. CAM Control Blocks 25
8.1 CCB Header 26
8.1.1 CAM Control Block Length 26
8.1.2 XPT Function Code 26
8.1.3 CAM Status 27
8.1.4 Path ID 27
8.1.5 CAM Flags 27

8.2 Function Codes 27
8.2.1 Get Device Type 27
8.2.2 Path Inquiry 28
8.2.3 Release SIM Queue 31
8.2.4 Set Async Callback 31
8.2.5 Set Device Type 32

8.3 SCSI Control Functions 33
8.3.1 Abort XPT Request 33
8.3.2 Reset SCSI Bus 34
8.3.3 Reset SCSI Device 34
8.3.4 Terminate I/O Process Request 35

9. Execute SCSI I/O 36
9.1 CAM Control Block to Request I/O 36
9.1.1 Address of this CCB 37
9.1.2 Callback on Completion 37
9.1.3 CAM Control Block Length 37
9.1.4 CAM Flags 37
9.1.4.1 Byte 1 Bits 38
9.1.4.2 Byte 2 Bits 39
9.1.4.3 Byte 3 Bits 39
9.1.4.4 Byte 4 Bits 40

9.1.5 CAM Status 40
9.1.6 CDB 42
9.1.7 CDB Length 42
9.1.8 Data Transfer Length 42
9.1.9 Function Code 43
9.1.10 LUN 43
9.1.11 Message Buffer Length (Target-only) 43
9.1.12 Message Buffer Pointer (Target-only) 43
9.1.13 Next CCB Pointer 43
9.1.14 Number of Scatter/Gather entries 43
9.1.15 Path ID 43
9.1.16 Peripheral Driver Pointer 43
9.1.17 Private Data 43
9.1.18 Request Mapping Information (OSD) 43
9.1.19 Residual Length 44
9.1.20 SCSI Status 44
9.1.21 Sense Info Buffer Length 44
9.1.22 Sense Info Buffer Pointer 44
9.1.23 SG List/Data Buffer Pointer 44
9.1.24 Tagged Queue Action 44
9.1.25 Target ID 44
9.1.26 Timeout Value 44
9.1.27 VU Flags 45

9.2 Command Linking 45
10. Target Mode (Optional) 45
10.1 Enable LUN 46
10.2 Phase Cognizant Mode 48
10.2.1 Target Operation of the HBA 48
10.2.2 Execute Target I/O 49

10.3 Processor Mode 50
10.3.1 CCB Acceptance 50
10.3.2 Target Operation of the HBA 50

11. HBA Engines 51
11.1 Engine Inquiry 51
11.2 Execute Engine Request (Optional) 52

FIGURES

FIGURE 3-1 CAM ENVIRONMENT MODEL 3

TABLES

TABLE 6-1 ASYNC CALLBACK OPCODE DATA REQUIREMENTS 13
TABLE 8-1 CAM CONTROL BLOCK HEADER 25
TABLE 8-2 SUPPORT OF SCSI MESSAGES 26
TABLE 8-3 XPT FUNCTION CODES 27
TABLE 8-4 GET DEVICE TYPE CCB 28
TABLE 8-5 PATH INQUIRY CCB - Part 1 of 2 29
TABLE 8-5 PATH INQUIRY CCB - Part 2 of 2 30
TABLE 8-6 RELEASE SIM QUEUE 31
TABLE 8-7 SET ASYNC CALLBACK CCB 32
TABLE 8-8 SET DEVICE TYPE CCB 33

TABLE 8-9 ABORT XPT REQUEST CCB 33
TABLE 8-10 RESET SCSI BUS CCB 34
TABLE 8-11 RESET SCSI DEVICE CCB 35
TABLE 8-12 TERMINATE I/O PROCESS REQUEST CCB 35
TABLE 9-1 SCSI I/O REQUEST CCB 36
TABLE 9-2 CAM FLAGS (OSD) 38
TABLE 9-3 SCATTER GATHER LIST 39
TABLE 9-4 CAM STATUS 41
TABLE 10-1 ENABLE LUN CCB 46
TABLE 10-2 TARGET CCB LIST 46

TABLE 11-1 ENGINE INQUIRY CCB 52
TABLE 11-1 EXECUTE ENGINE REQUEST CCB 53


Information Processing Systems --

Common Access Method --

SCSI and Generic I/O


1. Scope

This standard defines the CAM (Common Access Method) for SCSI (Small Computer
Systems Interface).

The purpose of this standard is to define a method whereby multiple
environments may adopt a common procedure for the support of SCSI devices.

The CAM provides a structured method for supporting peripherals with the
software (e.g. device driver) and hardware (e.g. host bus adapter) associated
with any computer.

SCSI has provided a diverse range of peripherals for attachment to a wide
range of computing equipment. Some system manufacturers have developed
approaches for SCSI attachment which are widely followed, increasing the
applications available for the attachment of SCSI peripherals. In markets
where no standard method of attachment exists, however, variations between
third party sellers has made it near-impossible for end users to rely on being
able to attach more than one SCSI peripheral to one host bus adapter.

In an effort to broaden the application base for SCSI peripherals an ad hoc
industry group of companies representing system integrators, controllers,
peripherals, and semiconductors decided to address the issues involved.

The CAM Committee was formed in October, 1988 and the first working document
of the XPT/SIM for SCSI I/O was introduced in October, 1989.

1.1 Description of Clauses

Clause 1 contains the Scope and Purpose.

Clause 2 contains Referenced and Related International Standards.

Clause 3 contains the General Description.

Clause 4 contains the Glossary.

Clause 5 describes the services provided by the XPT and SIM.

Clause 6 describes the facilities that use the Transport and SIM.

Clause 7 describes the ways that the Operating Systems support CAM and access
the XPT.

Clause 8 contains the description of non-I/O functions supported by the XPT
and SIM.

Clause 9 contains the description of I/O functions supported by the XPT and
SIM.

Clause 10 contains the description of Target Mode functions supported by the
XPT and SIM.

2. References

ISO DIS 10288 (ANSI X3.131-1990)
SCSI-2, Enhanced Small Computer Systems Interface


3. General Description

The application environment for CAM is any computer addressing a SCSI
peripheral through a protocol chip on a motherboard, an ATA interface, or a
Host Bus Adapter.

SCSI is a widely-used interface which provides common attachment for a variety
of peripherals. Unfortunately, there is no common way to provide access to
SCSI peripherals.

The purpose of the Common Access Method is to define a standard for the
support of Host Bus Adapters and the like by device driver software.

Software in the Operating System dispatches I/O (Input/Output) requests to
the SCSI peripherals in a number of different ways depending on the software
architecture. The OSD (Operating System Dependencies) are defined in Clause
6 for named software and hardware platforms.

3.1 Environment

A model of the CAM usage environment is illustrated in Figure 3-1, where there
may be multiple application and several device drivers attached to support the
peripherals on the system.

Requests for SCSI I/O are made through the CAM Transport (XPT) interface.
The XPT may execute them directly or pass them on to a lower level SIM for
execution.

The XPT (Transport) function is illustrated as a separate element. In many
applications, the XPT operations will be incorporated into a single module
which integrates both XPT and SIM functionality. The logical separation
between the two is maintained as there may be more than one SIM loaded.

A separate routing service may be provided by the operating system or the
routing function can be achieved through chaining when multiple SIMs are
loaded.

+-------------+ +-------------+ +-------------+
| Application | | Application | : : : : : | Application |
+-------------+ +-------------+ +-------------+
| | |
==========================================================================
Operating System
==========================================================================
| | | |
| | | +---------+
+---------+ +---------+ +---------+ |App Level|
| Disk | | Tape | | Any | |Pass-Thru|
| Driver | | Driver | | Driver | | Driver |
+---------+ +---------+ +---------+ +---------+
| | | |
+--------------+--------------+-------------------+
|
== XPT/SIM Interface (using CCBs) ========================================
|
+-----------------------------------------------+
| XPT |
+-----------------------------------------------+
| | |
| | |
| | |
| | |
| | |
+-------------+ +-------------+ +------------+
| | | | | |
| SIM |::::::| SIM | | ABIOS |
| | | | | |
+-------------+ +-------------+ +------------+
| | |
Vendor Vendor |
Specific Specific SCB
| | |
+---------+ +---------+ +---------+
| HBA | + | HBA | + | HBA |
+---------+ | +---------+ | +---------+
+---------+ +---------+
FIGURE 3-1 CAM ENVIRONMENT MODEL

3.2 Peripheral Driver Functions

Peripheral drivers provide the following functionality:

a) Interpretation of application or system level requests.
b) Mapping of application level requests to XPT/SIM Control Blocks.
c) Requesting of resources to initiate a CAM request.
- CAM Control Blocks and supporting blocks that may be needed.
- Buffer requirements.
d) Handling of exception conditions not managed transparently by SCSI e.g.
Check Condition status, unexpected Bus Free, Resets etc).
e) Logging of exception conditions for maintenance analysis programs.
f) Format utility or services required by format utilities.
g) Establish parameters for HBA operation.
h) Set up routing of SCSI requests to the correct Path/Bus, target and LUN.
i) Initialization and configuration functions of a target not handled by a
utility at installation and formatting time.
j) Establish a timeout value for a task and pass this value in the CCB.

3.3 XPT Functions

XPT services provide the following functionality to process CCBs:

a) Routing of the target CCB to the proper SIM.
b) OSD allocation of CCB resources e.g. Get_CCB, Free_CCB.
c) Maintenance of the SCSI Device Table. This consists of owning the table
and servicing requests to read and write the table.
d) Providing properly formatted control blocks and priming the fields needed
to accomplish a request.
e) Routing of asynchronous events back to peripheral driver.

3.4 SIM Functions

SIM services provide the following functionality to process CCBs:

a) Perform all interface functions to the SCSI HBA.
b) Manage or delegate, as required, all the SCSI HBA protocol steps.
c) Distinguish abnormal behavior and perform error recovery, as required.
d) Management of data transfer path hardware, including DMA circuitry and
address mapping, and establish DMA resource requests (if necessary).
e) Queueing of multiple operations for different LUNs as well as the same
LUN and assign tags for Tag Queueing (if supported).
f) Freeze and unfreeze the queue as necessary to accomplish queue recovery.
g) Assuring that the completed operation is posted back to the initiating
device driver.
h) Management of selection, disconnection, reconnection, and data pointers of
the SCSI HBA protocol.
i) Mechanisms to accept the selecting and sensing of the SCSI HBA functions
supported.
j) Implement a timer mechanism, using values provided by the peripheral
driver.

4. Definitions and Conventions

4.1 Definitions

For the purpose of this standard the following definitions apply:

4.1.1 Block: This defines an action to prevent access e.g. Busy.

4.1.2 CCB (CAM Control Block): The data structure provided by peripheral
drivers to the XPT to control execution of a function by the SIM.

4.1.3 CDB (Command Descriptor Block): A block of information containing the
SCSI opcode, parameters, and control bits for that operation.

4.1.4 DMA (Direct Memory Access): A means of data transfer between peripheral
and host memory without processor intervention.

4.1.5 Freeze: This defines a software action to quiesce activity e.g. freeze
the queue.

4.1.6 HBA (Host Bus Adapter): The hardware and microcode which provides the
interface between system memory and the SCSI bus.

4.1.7 Lock: This defines a hardware action e.g. data cartridge in a
removable media drive.

4.1.8 Nexus: A block of information containing the SCSI device, LUN, and
Queue Tag Number (if any, as used in command queuing).

4.1.9 Null: A value which indicates that the contents of a field have no
meanigng. This value is typically, though not necessarily, zero.

4.1.10 Optional: This term describes features which are not required by the
standard. However, if any feature defined by the standard is implemented, it
shall be done in the same way as defined by the standard. Describing a feature
as optional in the text is done to assist the reader. If there is a conflict
between text and tables on a feature described as optional, the table shall be
accepted as being correct.

4.1.11 Reserved: Where this term is used for bits, bytes, fields and code
values; the bits, bytes, fields and code values are set aside for future
standardization. The default value shall be zero. The originator is required
to define a Reserved field or bit as zero, but the receiver should not check
Reserved fields or bits for zero.

4.1.12 SCB (Subsystem Control Block): The term defined by IBM to refer to an
architecture to support SCSI Host Adapters.

4.1.13 SCSI (Small Computer Systems Interface): The I/O interface which this
standard is designed to support.

4.1.14 SIM (SCSI Interface Module): A module designed to accept the CAM
Control Blocks routed through the XPT in order to execute SCSI commands.

4.1.15 VU (Vendor Unique): This term is used to describe bits, bytes, fields,
code values and features which are not described in this standard, and may be
used in a way that varies between vendors.

4.1.16 XPT (Transport): A layer of software which peripheral drivers use to
originate the execution of CAM functions.

4.2 Conventions

Within the tables, there is a Direction bit which indicates In or Out. The
presumption is from the view of the peripheral driver i.e. information is Out
to the SIM from the peripheral driver and In to the peripheral driver from the
SIM.

Certain terms used herein are the proper names of signals. These are printed
in uppercase to avoid possible confusion with other uses of the same words;
e.g., ATTENTION. Any lower-case uses of these words have the normal American-
English meaning.

A number of conditions, commands, sequence parameters, events, English text,
states or similar terms are printed with the first letter of each word in
uppercase and the rest lower-case; e.g., In, Out, Request Status. Any lower-
case uses of these words have the normal American-English meaning.

The American convention of numbering is used i.e., the thousands and higher
multiples are separated by a comma and a period is used as the decimal point.
This is equivalent to the ISO convention of a space and comma.

American: 0.6 ISO: 0,6
1,000 1 000
1,323,462.9 1 323 462,9


5. Background

SCSI (Small Computer Systems Interface) is a peripheral interface designed to
permit a wide variety of devices to coexist. These peripherals are typically,
but not necessarily, attached to the host by a single SCSI HBA (Host Bus
Adapter).

5.1 Software

OS (Operating System) support for peripheral devices is normally achieved
through peripheral drivers or utility programs. No single driver or program
can reasonably support all possible SCSI peripherals, so separate drivers are
needed for each class of installed SCSI device. These drivers need to be able
to share the SCSI HBA hardware.

These drivers also have to work with a broad range of HBA hardware, from
highly intelligent coprocessors to the most primitive, including a SCSI chip
on a motherboard.

A standard SCSI programming interface layer is essential to insulate SCSI
peripheral drivers and utilities from the HBA hardware implementation, and to
allow multiple drivers to share a single SCSI hardware interface.

5.2 CAM (Common Access Method)

This standard describes the general definition of the CAM (Common Access
Method). CAM functionality has been separated into a few major elements.

5.2.1 XPT (Transport)

The XPT (Transport) defines a protocol for SCSI peripheral drivers and
programs to submit I/O requests to the HBA specific SIM module(s). Routing of
requests to the correct HBA and posting the results of a request back to the
driver are capabilities of the Transport.

5.2.2 SIM (SCSI Interface Module)

The SIM (SCSI Interface Module) manages HBA resources and provides a hardware-
independent interface for SCSI applications and drivers i.e. the SIM is
responsible to process and execute SCSI requests, and manage the interface to
the HBA hardware.

There are no requirements on how the SIM is implemented, in RAM (Random Access
Memory) or ROM (Read Only Memory), provided the XPT is properly supported. A
ROM-based SIM may need a transparent (to the user) software layer to match the
SIM-required services to the specific manner in which they are requested of
the OS.

5.2.3 CCB (CAM Control Block)

The CAM Control Block is a data structure passed from the peripheral driver to
the XPT. The contents of the data structure describe the action required and
provides the fields necessary for successful processing of a request.

5.2.4 OSD (Operating System Dependent)

The system environment in which the CAM is operating is a function of the
hardware platform and the Operating System being executed e.g. the byte
ordering is different between an Intel-based and a Motorola-based machine, and
the calling structure differs greatly between Operating Systems.

Although the fields of a CCB may have a common meaning, the contents will vary
by platform and OS. These dependencies cause differences in operation and
implementation, but do not prevent interoperation on the same platform of two
CAM modules implemented by different manufacturers.

The OSD issues are predominantly described in the XPT for each OS environment.

5.3 Principles of Operation

Ideally, a single XPT model would suffice for all OS environments for a single
HBA, but this is impractical in light of the wide architectural differences
between the various processor architectures.

Programming effort has been minimized by making the interfaces as similar as
possible across OS platforms, and customizing the SIM for each HBA to maximize
performance under each OS. HBAs vary widely in the capability and functions
they provide so there may be an internal (transparent) interface to isolate
hardware interface routines from routines which make use of OS resources.

In order to prevent each peripheral driver from having to scan the SCSI bus
for devices at initialization, the XPT determines all installed SCSI devices
and constructs an internal table. A XPT function is used by drivers and
programs to access this table.

Peripheral drivers need to be developed with documentation provided by the
operating system vendor in addition to that supplied by this standard.

Under Unix, the XPT and SIM would typically be compiled with the kernel at
System Generation time, so that entry points would be resolved during linkage-
editing.

Third party attachments may be supported without the need for a sysgen if
suitable routing facilities are provided by the system vendor.

Under Novell, the XPT is supplied by Novell, and the SIM is implemented
according to Novell documentation guidelines.

Under DOS, there is one logical XPT with one entry point, but it may consist
of a number of separate modules (perhaps supplied for each HBA in the system).

Routing is a mechanism to support concurrent SIM modules being co-resident so
that different HBAs can be mixed in the same system. This may be handled by
chaining the XPT entry points, defining additional character devices, or by a
specific routing entity.

Once the SIM is loaded, the peripheral drivers integrate each type of SCSI
device into the OS through XPT, independent of the installed HBA hardware.

Under OS/2 the equivalent to a XPT function is supplied by Microsoft, and the
SIM is implemented according to Microsoft LADDR documentation guidelines.

5.4 Requirements

System requirements addressed in defining the CAM include:

a) Device drivers and programs should be able to use any SCSI command, both
defined in SCSI-2 X3.131-1990 or Vendor Unique.
b) No assumptions on the size and format of transferred data.
c) Allowing all the capabilities of high end host adapters to be fully
utilized and accommodate HBAs which do most of the SCSI processing on
board (this precludes interfaces which expect to control SCSI phases).
d) Interpretation of sense data returned by SCSI devices shall be by the
calling driver or program.
e) Fully re-entrant code.
NOTE: This is an obvious requirement for multitasking environments such as
OS/2 or Unix but even in single tasking DOS applications,
multithreaded I/O is required to achieve maximum performance. SCSI
devices such as printers, communication ports and LAN interfaces are
often serviced in the background under DOS. If an HBA cannot support
multithreading, requests can be queued and serialized within the SIM
module transparently to the XPT.
f) Support of multiple HBAs.
g) If optional features are not supported in a minimum functionality XPT and
SIM, peripheral drivers shall be provided a means to determine what
features are available.
h) Providing an initialization service so that the process of identifying the
attached SCSI devices need not be repeated by each peripheral driver which
loads in the system.
i) Providing a mechanism to abort I/O threads (at request of peripheral
driver).
j) Ability to issue multiple I/O requests from one or more peripheral drivers
to a single Target/LUN.
k) Providing peripheral drivers with a mechanism for allocating a Sense data
area and for specifying the number of Sense bytes to be automatically
requested on a CHECK CONDITION.

6. Transport

6.1 Accessing the XPT

The OS peripheral drivers access the XPT through a software call to a single
entry point. The method for obtaining and using the entry point differs
between operating systems.

The XPT is not involved in the reverse process to advise the peripheral driver
of the completion of a request. The completion callback permits a direct
return from the SIM to the peripheral driver (the exact method employed in
callback is Operating System dependent).

The XPT is responsible to notify peripheral drivers of asynchronous events via
the Asynchronous Callback mechanism

6.2 Initialization

The XPT is responsible for determining the interface configuration at power up
initialization for the SIM drivers. Depending on the Operating System, the XPT
may perform a scan of the attached SCSI peripherals automatically. See also
the SCSI-2 X3.131-1990 Annex on Power Up Considerations.

The scan by the XPT/SIM would follow a pattern such as the following:

for all SCSI buses
for all target IDs (excluding the initiator)
find the device
if device exists
for all LUN's
use Inquiry command and save returned information
end for
end if
end for
end for

6.3 Callback on Completion

Callback on Completion refers to the XPT/SIM making a call to the routine
addressed by the Callback on Completion pointer in the CCB. The callback is
used by a peripheral driver in much the same manner as a hardware interrupt.

Callback routines have the same privileges and restrictions as hardware
interrupt service routines.

The Callback on Completion routine is called to indicate that the Requested
I/O is complete. The specific address of the CCB completed is passed to the
callback routine.

6.4 SCSI Request Queues

Queues are used in systems where there is a need to manage many outstanding
requests. There are various types of queues and each has different support
needs.

A SCSI request queue can occur in the following places:

o in the SIM
o in the Target/LUN
o in the peripheral driver

The SIM keeps a queue of all the CCB requests from the various peripheral
drivers that access a LUN.

A SCSI device may be able to keep a large queue using Tag Queues, or a simple
queue of one element.

A peripheral driver can also keep a queue e.g. a simple elevator sort, if the
LUN does not support tagged queuing.

6.4.1 The Target/LUN and the Peripheral Driver

The peripheral driver is responsible for maintaining the queue(s) internal to
the Target/LUN.

The SIM, acting on behalf of the peripheral driver, sends the appropriate
commands or messages to manage the Target/LUN queue(s).

When the Target/LUN has completed an operation, the peripheral driver is
advised by the SIM via a callback or by checking CAM status for completion.

The peripheral driver needs to be aware that there may be other peripheral
drivers and other systems working with the same Target/LUN.

6.4.2 The SIM

The SIM maintains a queue for each LUN which is logically shared by all
peripheral drivers. The queue may support tagged commands. Queue priority
shall be supported.

6.4.3 SIM Queuing

6.4.3.1 SIM Queue Priority

When SIM Queue Priority=1, the SIM places the CCB at the head of the queue for
the LUN, instead of at the end. One use of this CAM flag is during error
handling. If the queue is frozen and a CCB with SIM Queue Priority=1 is
received, the CCB shall be placed at the head of the queue and the queue
remains frozen. When the SIM queue is released, any CCBs with SIM Queue
Priority=1 are executed atomically, and in LIFO sequence.

To force step-by-step execution, the peripheral driver can set SIM Queue
Freeze=1, so that when the queue is released and a CCB with SIM Queue

Priority=1 is executed, the queue is re-frozen by the SIM at completion.

6.4.3.2 Tag Recognition

To support tagged queueing recognition the SIM maintains a reference between
the CCB pointers and the Queue Tags for a LUN. By this means, the SIM can
handle both the queue tag resource allocation and reconnection of the I_T_L_Q
nexus (see SCSI-2 X3.131-1990) for the CCB from a peripheral driver.

The peripheral driver is required to allow the SIM/XPT to handle the
assignment of the queue tag ID for the request. The SIM assigns unique TAG IDs
to the Target/LUN operation based on its internal reference table.

When a LUN that supports tagged queuing reconnects to the Initiator (SIM/HBA
pair), it will send the SIMPLE QUEUE TAG message with the queue tag value for
the I_T_L_Q nexus. Using the returned queue tag ID, the SIM restores what is
necessary to complete the SCSI transaction. The queue tag ID is freed by the
SIM at the completion of the SCSI request.

6.4.3.3 Error conditions and Queues within the Subsystem

The SIM shall place its internal queue for a LUN into the frozen state for any
status other than Request Completed Without Error and Request in Progress.
When a LUN's queue is in the frozen state, the SIM shall not dispatch any CCBs
to that LUN. Peripheral drivers can still send CCBs to the SIM for the LUN, or
any other LUN. Any new CCBs received by the SIM shall be placed at the end of
the queue, unless SIM Queue Priority=1 forces them to the head,

Following a Check Condition or Command Terminated status, the target's LUN
queue is also frozen, and all other tagged commands stay in the queue until
the allegiance condition is cleared. The allegiance condition is either
cleared by an incoming command or following the return of sense data for the
same initiator.

Since the SIM is the initiator, the SIM's internal queue shall go into a
frozen state so that the pending sense information in the LUN will not be
discarded. The SIM holds it's internal LUN queue in the frozen state until a
Release SIM Queue CCB is received.

Using the Callback on Completion pointer contained in the CCB the SIM returns
control of the CCB to the peripheral driver along with CAM Status indicating
the frozen queue condition and other information.

The peripheral driver acts upon the information returned via the CCB. In the
event that there is not a valid pointer in the callback field, the peripheral
driver that originated the CCB shall retain responsibility for the CCB by
watching the CAM Status field. The setting of the Autosense bit in the CAM
flags does not affect how the SIM handles freezing the SIM's internal queue
i.e. the Request Sense command issued by the SIM to recover status for
Autosense does not release the SIM queue.

If the peripheral driver has to perform recovery with the LUN, a CCB can be
placed at the head of the queue by setting SIM Queue Priority=1, and the SIM
queue released. If the peripheral driver has other pending CCBs in the queue
which it does not want to be sent to the LUN (depending on the cause of the
Check Condition), then it can use a CAM Flag to freeze the queue upon
completion of the CCB at the head of the queue. A SIM may reject a CCB with
SIM Queue Freeze=1 if the queue is not frozen at the time the CCB is received.

6.5 SIM Handling of SCSI Resets

The CAM shall not define support for the "Soft Reset" SCSI option, but
implementors may use the services of the SIM to provide vendor-specific
support.

Following a SCSI Bus Reset, the SIM shall:

a) Block Path IDs to the reset bus i.e. new CCBs are rejected with status of
CAM Busy.
b) Return all outstanding CCBs with status of SCSI Reset.
c) Unblock all Path IDs for the bus.
d) Call: xpt_async(opcode=reset,
path_id=bus that was reset,
target_id=-1,
lun=-1,
buffer_ptr=null,
data_cnt=0
e) Resume normal processing of CCBs.

6.6 Asynchronous Callback

In an event such as a SCSI Bus Reset or an Asynchronous Event Notification the
XPT has to be able to make a callback to the peripheral driver(s), even though
there may be no CCBs active for the peripheral driver(s).

Callback routines have the same privileges and restrictions as hardware
interrupt service routines.

During system startup and driver initialization, the peripheral driver should
register an Asynchronous Callback routine for all the SCSI devices with which
it is working. In order for a peripheral driver to receive asynchronous
callbacks, it shall issue a Set Asynchronous Callback CCB with the
Asynchronous Event fields set to 1 for those events the peripheral driver
wishes to be notified of through an asynchronous callback. The peripheral
driver is required to explicitly register for the path IDs, targets, and LUNs.
The use of a wildcard is not supported for the Set Asynchronous Callback CCB.

It is required that the Asynchronous Callback field be filled in with the
callback routine address if any of the Asynchronous Events Enabled bits are
set. The peripheral driver can de-register its Asynchronous Callback for a
particular SCSI device by issuing the Set Asynchronous Callback CCB with the
Events field cleared to zero and the Callback pointer containing the Callback
Routine address of the peripheral driver issuing the request. All XPTs must
provide the capability for any SIM to support asynchronous callback, but a
given SIM does not have to support each (or any) of the Asynchronous Events
Enabled bits.

Upon detection of a supported enabled event, the SIM shall do the following
once for each detected event:

a) Classify the event: determine the opcode which is the same as the encoded
bit number of the Asynchronous Events Enabled.
b) Format the associated data within an internal, to the SIM, local buffer,
e.g. the sense data received from an AEN.
NOTE: This is a multiple processor "lock" point.
c) Perform the XPT reverse routing required by the event. The SIM will call
the Async Callback entry point in the XPT:

long xpt_async(opcode, path_id, target_id, lun, buffer_ptr, data_cnt)

All of the arguments, other than the pointer, are long values of 32 bits. The
value of -1 in Path, Target and LUN can be used as a wild card. A null buffer
pointer value and a count of 0 are valid for opcodes that do not require any
data transfer.

NOTE: This call to the XPT is a multiple processor "lock" point.

Using the Path ID, Target, and LUN information from the xpt_async() call, the
XPT scans its internal tables looking for "matches" with what the peripheral
drivers had registered for using the Set Async Callback CCB (see 8.2.4). When
a match is found, either exactly or with a wild card of "-1," the XPT shall
copy the data for the opcode, if available, into the area reserved by the
peripheral driver and then call the peripheral driver's Async Callback
routine.

The arguments to the peripheral driver's Async Callback routine are the same
as the xpt_async() routine though:

- the buffer_ptr value shall be the peripheral driver's buffer
- the data_cnt shall either be what the XPT had to transfer from the SIM's
buffer or the limit of the peripheral driver's buffer.

Almost all of the information relating to the different opcodes can be
included in the Path ID, Target and LUN arguments. The only opcodes that
require an additional buffer area are AEN, Load SIM and Unload SIM. Table 6-1
lists the opcodes and the expected data requirements for the number of bytes
to be transferred.

TABLE 6-1 ASYNC CALLBACK OPCODE DATA REQUIREMENTS
+----------------------+---------+---------+--------+-------+----------+
| Event | Opcode | Path ID | Target | LUN | Data Cnt |
+----------------------+---------+---------+--------+-------+----------+
| Unsol. SCSI Bus Reset| 0x0001 | Valid | n/a | n/a | n/a |
| Unsol. Reselection | 0x0002 | Valid | Valid | Valid | n/a |
| reserved | 0x0004 | | | | |
| SCSI AEN | 0x0008 | Valid | Valid | Valid | Min. 22 |
| Sent BDR to Target | 0x0010 | Valid | Valid | n/a | n/a |
| SIM Module Loaded | 0x0020 | XPT ID | n/a | n/a | Min. 1 |
| SIM Module Unloaded | 0x0040 | XPT ID | n/a | n/a | Min. 1 |
| New Devices Found | 0x0080 | Valid | n/a | n/a | n/a |
+----------------------+---------+---------+--------+-------+----------+

The AEN data requirements are a minimum of 22 bytes of buffer space. This
space includes the 4 bytes required by the AEN Data Format and 18 bytes
defined by the Sense Data Format (see SCSI-2 X3.131-1990).

The Load SIM and Unload SIM data requirements are a minimum of 1 byte. This
byte contains the Path ID for the SIM. This Path ID is different that the
path_id argument. The argument contains the unique XPT ID of 0xFF. The XPT ID
is the ID used by the peripheral driver to register for async notification.

If there is valid data placed in the generic data buffer by the XPT/SIM, the
peripheral driver is required to save or discard that data before returning
control to the XPT/SIM.

6.7 Autosense

Autosense causes sense data to be retrieved automatically if a Check Condition
is reported in the SCSI Status field. On a Check Condition, a SCSI Request
Sense command is constructed and sent to the same target. The location and
amount of the Sense data is specified in the Sense Info Buffer Pointer and
Length fields respectively of the SCSI I/O Request CCB. If the length field is
0 or the buffer field is Null, the Request Sense command shall still be
issued, but with a data allocation length of 0 (this should only be done by
the peripheral driver when it is not interested in the sense information).

After completing the Request Sense sequence the CAM Status and SCSI Status
fields contain the status of the original command (which caused the Check
Condition).

The target can return fewer than the number of Sense bytes requested. This is
not reported as an error, and Sense Status shall be flagged as valid.

6.8 Loadable Modules

Some operating system environments provide the ability to load or unload
software drivers, thus peripheral drivers or SIM modules can be loaded
dynamically. In such systems, the XPT module (typically supplied by the OS
vendor) is either part of the system or must be loaded first.

The XPT, as part of a loadable OS, exports it's "label," which is to used as a
reference by the other loadable modules. The XPT manages the loading of SIMs
and provides the common access point for peripheral drivers to register a
loaded or unloaded SIM.

When a peripheral driver is loaded, it can go through it's initialization
process (see OSD initialization), call the XPT initalization point and then
query the XPT for the HBAs that are present in the system and targets that
have been identified as being on the SCSI channels.

When a SIM is loaded, the SIM and XPT have to work together to get the SIM
entered into the internal tables and have the SIM initialized.

The SIM shall call the XPT once for each supported bus in order to obtain the
Path ID for that bus.

long xpt_bus_register(CAM_SIM_ENTRY *)

The argument is the pointer for the data structure defining the entry points
for the SIM. The value returned is the assigned Path ID; a value of -1
indicates that registration was not successful.

The SIM shall call the XPT once to de-register the bus for a given Path ID:

long xpt_bus_deregister(path_id)

The argument is the Path ID for the bus being de-registered. A return value of
zero indicates the bus is no longer registered, any other value indicates the
call was unsuccessful.

When the XPT is called it will update it's internal tables and then call the
sim_init(path_id) function pointed to by the CAM_SIM_ENTRY structure. The

initialization for the loaded SIM is no different than for a SIM statically
included in the kernel at boot time. After the SIM has gone through the
initialization process the XPT shall scan the SCSI bus in order to update its
internal tables containing Inquiry information.

Peripheral drivers can request to be informed when a SIM is registered or de-
registered via the Async Callback feature (see 6.6 and 8.2.4).

The CAM_SIM_ENTRY table is used to define the entry points for the SIMs.

typedef struct
{
long (*sim_init)(); /* pointer to the SIM init routine */
long (*sim_action)(); /* pointer to the SIM CCB go routine */
} CAM_SIM_ENTRY;


7. OSD (Operating System Dependent) Operation

7.1 UNIX Operating System

The CAM subsystem is intended to provide a set of services for third-party
vendors.

There are several sets of modules for Unix:

- peripheral drivers that are device class specific
- a configuration_driver for initialization
- the XPT
- SIMs that are HBA-specific

Each member of these sets is treated as a UNIX driver and is linked into the
kernel. The XPT and configuration_driver (which is responsible for
initialization) are OS-vendor specific; other drivers may come from any
source.

At kernel configuration and link time the cam_conftbl[] is created and
contains entry points for the SIMs, which are used by the XPT.

The cam_conftbl[] is used by the XPT/configuration_driver to call routines and
pass CAM parameters between them e.g. the Path ID contained in the CCB created
by the peripheral driver is used to index into the cam_conftbl[]. The entry
point for the selected SIM, sim_action() is called with a pointer to the CCB
as an argument.

The cam_edt[] data structure is used and created during the initialization
process to contain the necessary information of all the targets found on all
the HBAs during the init sequence.

The CAM Flags used are as described in Table 9-2.

7.1.1 Initialization

The initialization of the XPT and SIMs is under the control of the
configuration_driver.

Due to the different Unix-based systems (BSD and System V), there is no common
initialization process that can control the order of calls to the peripheral
driver's and configuration_driver's init() routines. It is necessary to make
sure that the subsystem is initialized before any requests can be serviced
from the peripheral drivers. Due to this constraint when the peripheral
driver's initialization routines are called the driver shall call the
xpt_init() routine. If the subsystem is not yet initialized, the XPT shall
call the configuration_driver to formally initialize the subsystem. Once the
subsystem is set up, either from a previous xpt_init call or the
configuration_driver being called, all subsequent xpt_init calls shall simply
return.

When the configuration_driver is called for initialization, it uses the
cam_conftbl[] entry structures. The configuration_driver makes the init()
routine calls, to the XPT, and to each SIM in turn, allowing them to
initialize. The initialization routine for the SIM is called with its Path ID
as the argument. Interrupts shall be disabled or blocked by the
configuration_driver during the initialization process.

After the initialization process has been completed, the configuration_driver
obtains information about each SIM, HBA, and target device detected, and
maintains a table, the cam_edt[], of these devices. The information is
obtained by using CCBs through the CAM interface.

Once the CAM subsystem is initialized and the cam_edt[] set, the
peripheral drivers can use the subsystem. This allows them to determine what
devices are known and make appropriate memory allocations and resource
requests of the XPT.

The SCSI-2 Inquiry command shall be issued to all Target/LUNs on the attached
interfaces, and shall contain an allocation length of 36 bytes, which is
sufficient to transfer the device information and the product information. The
EVPD and Page code fields in the Inquiry command shall be set to 0. It is
assumed that the responding devices will return the Inquiry data, even though
the device may not be ready for other commands. A limited number of retries
will be done for devices that return Busy Status following the Inquiry
command. If the retry limit is reached, the status of the device in the XPT
will be set to "Not Found". The Inquiry command shall be the only command
issued by the XPT to the devices during initialization.

7.1.2 Accessing the XPT

7.1.2.1 From the Peripheral Driver

The XPT provides functions to obtain CAM system resources for the peripheral
driver. These functions are used to allocate and free CCB resources and to
allocate and free DMA resources.

There are two routines used in the handling the CCB resources. The two
routines are:

CCB *xpt_ccb_alloc() and
void xpt_ccb_free(CCB *):

- The xpt_ccb_alloc() routine returns a pointer to the allocated CCB. The
peripheral driver can now use this CCB for it's SCSI/XPT requests.
- The xpt_ccb_free() routine takes a pointer to the CCB that the
peripheral driver has finished with, and can now be returned to the CAM
subsystem CCB pool.
- The pointer to the CCB returned from the xpt_ccb_alloc() call shall be
large enough to contain any of the possible XPT/SIM function request CCBs.
- The CCB can only be used i.e. sent to the XPT, once. Once the CCB has
completed it shall be returned using the xpt_ccb_free() routine.

All returned status information is obtained at the callback point via the CAM
and SCSI status fields.

7.1.2.2 From the SIM

The SIMs obtain requests from the XPT as they are passed across from the
peripheral driver, via a routine included in the SIM's configuration
information. The field in the configuration table is declared as
"void (* sim_action)(CCB *)." The XPT does not modify CCBs or CDBs. The XPT
shall intercept those CCBs which must be redirected to the
configuration_driver (Get Device Type, and Set Device Type).

7.1.3 Callback on Completion

The Callback on Completion field in the CCB is a structure that is platform
specific, but always contains at least a callback function pointer, named
cbfcnp, and declared as "void (*cbfcnp)(CCB *)." The argument to cbfcnp shall
be the address to the CCB.

The Disable Callback on Completion feature is not supported.

7.1.4 Pointer Definition in the UNIX Environment

Pointers in the CAM environment are treated as any other pointer in a given
UNIX implementation. For the 80386 platforms, pointers are 32-bit virtual
addresses into a flat address space.

7.1.5 Request Mapping Information

This field is expected to contain a pointer to the buf structure that the SCSI
I/O CCB was created for. This copy of the buf structure pointer, bp, is used
by the SIM to get to the I/O mapping information needed to access the data
buffers allocated by the application program. A value of NULL is allowed if
there is no need for the SIM to map the data buffer addresses i.e. data count
is zero, the buffer is internal to the kernel, or the addresses are physical.

7.1.6 XPT Interface

The XPT interface provides functions that peripheral drivers and SIM modules
can access in order to transfer information and process user requests. The
following defines the entry points, and describes the required arguments and
return values.

7.1.6.1 Functions for Peripheral Driver Support

a) long xpt_init()

This routine is called by the peripheral driver to request that the XPT and
sub-layers be initialized. Once the sub-layers are initialized any subsequent
calls by other peripheral drivers shall quickly return.

There are no arguments and the return code is either Success or Failure.

b) CCB *xpt_ccb_alloc()

This routine is used whenever a peripheral driver needs a CCB (the common data
structure for processing SCSI requests). It returns a pointer to the allocated
CCB which the peripheral driver can now use as the CCB for it's SCSI/XPT
requests. The returned CCB shall be properly initialized for use as a SCSI I/O
Request CCB. The SIM Private Data area shall have been already set up to be
used by the XPT and SIM, and shall not be modified by the peripheral driver.
It is recommended that the CCB be returned to the XPT following its use, and
that CCBs not be re-used.

There are no arguments and the return value is a pointer to an initialized
CCB.

c) void xpt_ccb_free(CCB *)

This routine takes a pointer to the CCB that the peripheral driver has
finished with so it can be returned to the CAM subsystem CCB pool.

The argument is the pointer to the CCB to be freed, there is no return code.

d) long xpt_action(CCB *)

All CAM/SCSI CCB requests to the XPT/SIM are placed through this function
call. All returned CAM status information is obtained at the callback point
via the CAM and SCSI status fields.

The argument is a pointer to the CCB, and the return code is either Success or
Failure.

7.1.6.2 Functions for SIM Module Support

a) See 6.8 for loadable module support:

long xpt_bus_register(CAM_SIM_ENTRY *)

long xpt_bus_deregister(path_id)

b) long xpt_async(opcode, path_id, target_id, lun, buffer_ptr, data_cnt)

The SIM calls this routine to inform the XPT that an async event has occured
and that there may be peripheral drivers which need to be informed.

- The opcode, path_id, target_id, lun, and data_cnt arguments are long 32-bit
values.
- The path_id, target_id, and lun define a nexus for the Async Callback.
- The opcode contains the value for what has happened.
- The buffer_ptr and data_cnt are used to inform the XPT where and how much
data is associated with the opcode.

The return code is either Success or Failure.

7.1.7 SIM Interface

The SIM interface provides functions to the XPT, and should never be accessed
directly by the peripheral driver. Each vendor's SIM should provide a
publicly-defined entry structure such as CAM_SIM_ENTRY cse_vendorname.

The following defines the entry points, and describes the required arguments
and return values.

a) long sim_init(pathid)

This routine is called by the XPT to request that the SIM be initialized.
There are no arguments and the return code is either Success or Failure.

b) long sim_action(CCB *)

All CCB requests to the SIM are placed through this function call. All
returned CAM status information is obtained at the callback point via the CAM
and SCSI status fields.

The argument is a pointer to the CCB, and the return code is either Success or
Failure.


7.2 Novell Operating System

Novell NetWare 386 drivers are called NLMs (NetWare Loadable Modules). These
modules are registered and linked dynamically with NetWare 386: they are
registered after the server is running and may be unloaded at any time.

The NetWare 386 CAM subsystem consists of 3 sets of NLMs:

- peripheral drivers (NLMs) that are device class specific
- the XPT router and SIM maintenance NLM
- SIM NLMs that are HBA-specific

The peripheral drivers and SIMs communicate with the XPT through labels
exported by the XPT when it is registered.

The CAM Flags used are as described in Table 9-2.

7.2.1 Initialization

As the Novell dynamic linker will not allow an NLM to register if it makes
references to a label it cannot resolve, the order in which the NLMs register
is important. The XPT module exports four entry points when it is registered,
and both peripheral drivers and SIM modules make references to them. The XPT
shall be registered first, after which either peripheral drivers or SIMs may
be registered.

+--------------+
| Peripheral |
| Driver | references labels exported by XPT
+--------------+
|
v
+--------------+
| XPT | xpt_action ();
| | xpt_async ();
| (first) | xpt_bus_register ();
+--------------+ xpt_bus_deregister ();
^
|
+--------------+
| SIM | SIM - references label exported by XPT
+--------------+

For an overview of SIM registration with the XPT see 6.8. For an overview of
peripheral driver registration with the XPT see 6.6 and 8.2.4.

When NetWare 386 loads a SIM, it shall call the initialization routine
specified in the Novell linker definition file. At this point the SIM can
perform its initialization functions.

As part of initialization the SIM shall call the xpt_bus_register function
once for each HBA it will support, to register the address of its entry point
with the XPT and to get a path ID for each HBA from the XPT. The XPT then adds
this SIM to its internal tables so it can route requests to the new SIM. The
XPT also notifies all peripheral drivers that registered an asynchronous
callback routine with the XPT (with the SIM Module Registered bit set), that a
new path ID exists. Upon receiving this message the peripheral drivers can
check for new devices on this path.

When NetWare 386 loads a peripheral driver, the initialization routine
specified in the linker definition file shall be called. At this time,the
driver needs to determine which, if any, SIMs are registered.

The peripheral driver sends a Path Inquiry CCB to each path to determine if a
SIM is registered. If a valid response is returned the peripheral driver
checks for devices that it will support on that path. If the peripheral driver
supports any devices on this path, it shall register an asynchronous callback
routine and specify the SIM registration in the opcode field so that if the
SIM is de-regitered, the peripheral driver shall be notified. In addition, a
peripheral driver should also register for SIM registration to alert the
driver of the need to locate devices on a newly added SIM module.


7.2.2 De-Registration

When a SIM de-registers, it shall call the xpt_bus_deregister() function once
for each path the SIM supports. The XPT then calls every peripheral driver
that has registered an asynchronous callback routine with the SIM Module De-
Registered bit set on this path. Peripheral drivers then notify NetWare 386
that the drives on this path are in an inactive state. The XPT will then
remove the path from its internal tables and block further peripheral driver
requests on this path.

If a peripheral driver de-registers, it needs to notify the XPT module so that
the dependency tables can be updated. This is done by registering an
asynchronous callback routine with the opcode set to zero. The XPT will then
remove this driver from its callback tables.

The XPT can only be unloaded after all peripheral drivers and SIM modules have
been de-registered. NetWare 386 will not allow an NLM to unload if it has
exported labels that other NLMs are using. As all SIM and peripheral drivers
refer to labels exported by the XPT, NetWare 386 will not allow the XPT to
unload until all the SIMs and peripheral drivers have been unloaded, at which
point there is nothing left for the XPT to support and it can be safely de-
registered.

7.2.3 Accessing the XPT

NetWare 386 allows an NLM to export functions which NLMs registered at a later
time can reference. An NLM calls an exported function in the same way it calls
any other function. The C language calling convention is assumed. In order for
communication between the peripheral drivers, XPT, and SIM modules to work
correctly the names of the XPT entry points have to be constant.

The entry points in the XPT module are:
- xpt_action () accepts CAM blocks from the peripheral driver and routes them
to the correct SIM
- xpt_async () is used by the SIM module to notify the XPT when an
asynchronous event occurs.
- xpt_bus_register () is used to register the SIM with the XPT and obtain a
Path ID.
- xpt_bus_deregister () is used to unload the SIM associated with the Path
ID.

7.2.4 Hardware Registration

The SIM module needs to do the actual registration of the host adapter with
NetWare. Since only one SIM may support a given host adapter this prevents any
hardware options from being registered twice. The SIM does not register any
devices with NetWare, only the hardware options used by the card e.g.
interrupt line, base address, DMA etc.

Interrupts generated by the host adapter will be handled by the SIM module, so
the SIM must also register its interrupt service routine with NetWare.

A peripheral driver registers a logical card with NetWare 386 for each path_id
it supports. This logical card uses no hardware resources, but does have entry
points IO and IOCTL requests from NetWare. The peripheral driver also reports
the devices that it will support to NetWare.

The XPT does not register any hardware or devices with NetWare 386. It loads
as a driver, but does not register any IOPOLL or IOCTL entry points.

7.2.5 Miscellaneous

It is the responsibility of the peripheral driver to allocate memory for its
CCB blocks. Normally the peripheral driver needs to keep one CCB structure for
each device it will support, so the memory can be allocated in the
DiskStructure provided by NetWare 386 when a device is added to the system.

Since fast disk channels are essential for a NetWare 386 server, peripheral
drivers should never poll the CAM status field to wait for completion. The
driver should send the CCB to the XPT module and then either do more work, or
exit immediately. The SIM module will call the function whose address is in
the callback field of the CCB block when the request is finished. The callback
function runs at interrupt level, so it cannot call any NetWare 386 routines
that are "blocking" or the file server will abend. See the Novell Disk Driver
manual for details on blocking and non-blocking levels.

7.3 DOS (Disk Operating System)

Under DOS, a software interrupt is used to access any of the XPT or SIM
functions, which are combined into a single module.

The routing functions of the XPT are performed by the DOS concept of
"interrupt vector chaining." During execution, an XPT/SIM module determines
if a particular CCB is one that it should handle. If not, it routes the CCB
to the previous "owner" of the interrupt vector.

The CAM flags used by the DOS XPT/SIM are described in Table 9-2.

7.3.1 Initialization

During initialization, the XPT/SIM modules should be loaded as character
device drivers.

As character device drivers are required by DOS to have unique names, the 8-
character device name should be "$$CAMxxx", where xxx is the ASCII decimal
numeric value of the lowest path ID supported by this XPT/SIM module.

The programming examples in this clause are used to assist the reader's
understanding. Implementations do not need to use the same code, but they
are required to accomplish the same goals.

7.3.1.1 Multiple XPTs

The pseudocode for the XPT initialization sequence is as follows:

Get INT 4Fh interrupt vector;
Save this address for chaining;
IF there is a CAM XPT already installed (see 7.3.2.1)
Perform PATH INQUIRY (Path ID=0FFh) to get Highest Path ID;
First Path ID = Highest Path ID + 1;
ELSE
First Path ID = 0;
END IF;
Count number of Path IDs needed;
IF no HBAs to support (Count = 0)
Exit initialization without installing driver;
END IF;
Set INT 4Fh interrupt vector to point to CAM entry point;
Save Highest Path ID used (First Path ID + Count - 1);
Set character device name to "$$CAMxxx",
where xxx=First Path ID;
Perform all necessary HBA initialization;
FOR each SCSI Bus supported:
FOR each SCSI ID (excluding initiator)
IF device exists
FOR each LUN
Perform INQUIRY to get PDT for table;
END FOR;
END IF;
END FOR;
END FOR;

7.3.1.2 Device Table Handling

The XPT/SIM is only required to keep the peripheral device type of the
devices connected to the supported SCSI bus(es).

7.3.2 Accessing the XPT

There are various mechanisms used to access XPT or SIM functions from
peripheral drivers or application programs.

7.3.2.1 Testing for the presence of the XPT/SIM

Peripheral drivers and applications can check for the presence of an XPT/SIM
module by performing a "check install" function such as:

On entry:
AX = 8200h
CX = 8765h
DX = CBA9h

On return:
AH = 0 (if successful)
CX = 9ABCh
DX = 5678h
ES:DI = address of character string "SCSI_CAM"
All other registers unaffected.

The following routine checks for the presence of an XPT/SIM module. It
returns a value of 1 if a module is found and a value of 0 if not found.

CHK_FOR_CAM PROC NEAR
MOV CX,8765H ; load l.s.w. of signature
MOV DX,0CBA9H ; load m.s.w. of signature
MOV AX,8200H ; load "check install" code
INT 4FH ; perform "check install"
CMP AH,0 ; function supported?
JNE NOT_THERE ; if not, no xpt/sim
CMP DX,5678H ; check m.s.w. of signature
JNE NOT_THERE ; if invalid, no xpt/sim
CMP CX,9ABCH ; check l.s.w. of signature
JNE NOT_THERE ; if invalid, no xpt/sim
CLD ; set direction flag
MOV CX,8 ; load string length
MOV SI,OFFSET SCSI_CAM ; get string address
REPE CMPSB ; compare strings
JNE NOT_THERE ; if strings differ, no xpt/sim
MOV AX,1 ; load "found" status
RET ; return to caller
NOT_THERE: MOV AX,0 ; load "not found" status
RET ; return to caller
CHK_FOR_CAM ENDP
SCSI_CAM DB 'SCSI_CAM' ; string to find

7.3.2.2 Sending a CCB to the XPT

Once it is determined that an XPT/SIM module is present, the peripheral
driver or application can access the XPT/SIM functions by sending a CCB to
the XPT/SIM:

On entry:
ES:BX = address of the CCB
AX = 8100h

On return:
AH = 0 if successful
= 1 if invalid CCB address (segment=offset=0)
All other registers unaffected.

NOTE: The SIM may complete and return control to the location pointed to by
the Callback on Completion field in the CCB before the software interrupt
returns.

The following routine sends a CCB to the XPT/SIM module. It returns a value of
0 if successful and 1 if not.

SEND_CCB PROC NEAR
MOV AX,8100H ; load "send ccb" function
MOV ES,SEGMENT CCB ; load segment of ccb
MOV BX,OFFSET CCB ; load offset of ccb
INT 4FH ; call xpt/sim module
SHR AX,8 ; put return code in al
RET ; return to caller
SEND_CCB ENDP

7.3.3 Callback on Completion

When an I/O operation has completed, a XPT/SIM module shall make a FAR call to
the routine which had its address passed in the Callback on Completion field
of the CCB. The first 4 bytes of this field are used to indicate the routine's
address in the Intel Segment:Offset format. When the callback is made,
hardware interrupts shall be disabled and ES:BX shall point to the completed
CCB.

7.3.4 Asynchronous Callbacks

There are some differences in the DOS XPT/SIM implementation of Asynchronous
Callbacks as compared with the description in 6.6.

The DOS XPT/SIM does not support the SIM Module Loaded and SIM Module Unloaded
opcodes reported by the XPT/SIM module when the Asynchronous Callback Routine
is called.

The Set Async Callback CCB is held by the XPT/SIM until it is "de-registered."
This is accomplished by sending another Set Async Callback CCB to the XPT/SIM
with all of the Asynchronous Event Enables reset and the address of the
original Set Async Callback CCB in the Peripheral Driver Buffer Pointer field.
At that point the original CCB shall be dequeued and both CCBs shall be
returned to the peripheral driver or application.

NOTE: There is an implication here that a peripheral driver or application
which wishes to be notified when the specified asynchronous event occurs, has
to register separately with each path ID.

The Peripheral Driver Buffer Pointer and Size of Allocated Peripheral Buffer
fields in the Set Async Callback CCB are considered as Private Data by the
XPT/SIM, to be used for CCB queuing.

When an Asynchronous event occurs that is enabled by the bits in the
Asynchronous Event Enables field of the Set Async Callback CCB, the virtual
address specified by the Asynchronous Callback Pointer field shall be called
with the following registers:

On entry:
AH = opcode as specified in Table 6-1.
AL = path ID that generated the callback.
DH = target ID that caused event (if applicable).
DL = LUN that caused event (if applicable).
CX = data byte count (if applicable).
ES:BX = address of data buffer (if applicable).

On return:
All registers shall be preserved.

It is the responsibility of the peripheral driver or application to copy any
or all required data out of the data buffer into a local buffer before
returning from the Asynchronous Callback routine.

7.3.5 Pointer Definition

All pointers shall be passed to the XPT/SIM as segment:offset type virtual
addresses.


7.4 OS/2 (Operating System 2)

Microsoft has documented LADDR as a generic I/O interface which supports many
device interfaces, not only SCSI. The control blocks and their method of
operation are defined in OS/2 Technical Reference Manuals which are available
from Microsoft.

The OS/2 equivalent to the SIM is a BID (Bus Interface Driver).

The OS/2 equivalent to the CCB is an SRB (SCSI Request Block).

The CCB and the SRB share many common fields. The fields in the CCB are
designated as OSD if they vary between OS/2 and other operating systems.

For further information on how peripheral drivers use the CCB/SRB and other
SIM/BID capabilities of OS/2, it is necessary to use information available
from Microsoft.

The CAM Flags used are as described by LADDR documentation.

8. CAM Control Blocks

The CCBs used by drivers and applications to request functions of the XPT and
SIM have a common header, as shown in Table 8-1.

TABLE 8-1 CAM CONTROL BLOCK HEADER
+----+---+
|Size|Dir|
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
+----+------------------------------------------+

The sequence of the fields in the data structures will be consistent between
vendors, but not necessarily the binary contents. The size and definition of
the fields in the data structures can vary beween operating systems and
hardware platforms, but the vendors are expected to provide compiler
definitions which can be used by third-party attachments.

Several fields in the CCB are pointers, and their meaning is dependent on the
OS which is being supported. In general, these pointers are interpreted as
either virtual or physical addresses.

Additional bytes beyond the CCB Header are dependent on the Function Code.

Most SCSI messages are handled transparently by the SIM, but in some cases,
the peripheral driver has been given the ability to force the SIM to issue a
message. Table 8-2 summarizes the message support.

TABLE 8-2 SUPPORT OF SCSI MESSAGES
+-----------------------------+----------------------------------------+
| Abort | Discretely supported by function codes |
| Abort Tag | Discretely supported by function codes |
| Bus Device Reset | Discretely supported by function codes |
| Clear Queue | Not Supported |
| Command Complete | Transparently supported by SIM |
| Disconnect | Transparently supported by SIM * |
| Identify | Transparently supported by SIM |
| Ignore Wide Residue | Transparently supported by SIM |
| Initiate Recovery | Not Supported |
| Initiator Detected Error | Transparently supported by SIM |
| Linked Command Complete | Transparently supported by SIM |
| Message Parity Error | Transparently supported by SIM |
| Message Reject | Transparently supported by SIM |
| Modify Data Pointer | Transparently supported by SIM |
| No Operation | Transparently supported by SIM |
| Queue Tag Messages | |
| Head of Queue Tag | Discretely supported by function codes |
| Ordered Queue Tag | Discretely supported by function codes |
| Simple Queue Tag | Discretely supported by function codes |
| Release Recovery | Not Supported |
| Restore Pointers | Transparently supported by SIM |
| Save Data Pointers | Transparently supported by SIM |
| Synch Data Transfer Request | Transparently supported by SIM * |
| Terminate I/O Process | Discretely supported by function codes |
| Wide Data Transfer Request | Transparently supported by SIM |
+-----------------------------+----------------------------------------+
| * Issuing this message influenced by peripheral driver via CAM flags |
+----------------------------------------------------------------------+

8.1 CCB Header

The Function Codes used to identify the XPT service being requested are listed
in Table 8-3.

8.1.1 CAM Control Block Length

See 9.1.1.

8.1.2 XPT Function Code

TABLE 8-3 XPT FUNCTION CODES
+-----+
| Code|
+-----+-------------------------------+
|00-0F| Common Functions |
| 00h | NOP |
| 01h | Execute SCSI I/O (see 9.x) |
| 02h | Get Device Type |
| 03h | Path Inquiry |
| 04h | Release SIM Queue |
| 05h | Set Async Callback |
| 06h | Set Device Type |
|07-0F| reserved |
|10-1F| SCSI Control Functions |
| 10h | Abort SCSI command |
| 11h | Reset SCSI Bus |
| 12h | Reset SCSI Device |
| 13h | Terminate I/O Process |
|14-1F| reserved |
| 20h | Engine Inquiry (see 11.x)|
| 21h | Execute Engine Request |
|22-2F| reserved |
|30-3F| Target Mode (see 10.x)|
| 30h | Enable LUN |
| 31h | Execute Target I/O |
|32-3F| reserved |
|40-7F| reserved |
|80-FF| Vendor Unique |
+-----+-------------------------------+

If a Function Code which is not supported is issued to the XPT, the XPT shall
complete the request and post CAM Status of Invalid Request.

8.1.3 CAM Status

See 9.1.3.

8.1.4 Path ID

See 9.1.4.

8.1.5 CAM Flags

The CAM Flags qualify the Function to be executed, and vary by Function Code.
See 9.1.5.

8.2 Function Codes

8.2.1 Get Device Type

This function is executed at driver initialization in order to identify the
targets they are intended to support e.g. A CD ROM driver can scan each
Target/LUN address on each installed HBA to look for the CD ROM device type.

TABLE 8-4 GET DEVICE TYPE CCB
+----+---+
|Size|Dir| Get Device Type
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | Inquiry Data Pointer |
| 1 | I | Peripheral Device Type of Target/LUN |
+----+---+--------------------------------------+

The information on attached SCSI devices is gathered at power on by the XPT
(to eliminate the need for each driver to duplicate the effort of scanning the
SCSI bus for devices).

The Peripheral Device Type is a 1-byte representation of Byte 0 of SCSI
Inquiry Data i.e. bits 7-5=000.

If the Inquiry Data Pointer contains a value other than Null, it is a pointer
to a buffer in the peripheral driver's data space large enough to hold the 36
bytes of Inquiry data associated with the Target/LUN. The data shall be
copied from the internal tables of the XPT to the peripheral driver's buffer.

This function shall return non-zero CAM Status.
- CAM Status of Request Completed Without Error indicates that the specified
device is installed and the Peripheral Device Type field is valid.
- CAM Status of SCSI Device Not Installed indicates that the Peripheral
Device Type field is not valid.
- CAM Status of Invalid Path ID indicates that the Path ID is invalid.

Drivers are always able to use SCSI I/O requests to check for devices which
may not have been found at power up.

8.2.2 Path Inquiry

This function is used to get information on the installed HBA hardware,
including number of HBAs installed. To obtain further information on any other
HBAs attached, this function can be issued for each HBA.

If the Path ID field of the CCB has a value of FFh on a PATH INQUIRY request,
then the only field that shall be valid upon return to the caller is the
Highest Path ID Assigned field. In addition, this field shall not be valid if
the Path ID field in the CCB contains a value other than FFh.

TABLE 8-5 PATH INQUIRY CCB - Part 1 of 2
+----+---+
|Size|Dir| Path Inquiry
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| | I | Features Supported |
| 1 | | Version Number |
| | | 00-07h Prior to Rev 1.7 |
| | | 08h Implementation Version 1.7 |
| | | 09-FFh Rev No e.g. 23h = 2.3 |
| 1 | | SCSI Capabilities |
| | | 7 Modify Data Pointers |
| | | 6 Wide Bus 32 |
| | | 5 Wide Bus 16 |
| | | 4 Synchronous Transfers |
| | | 3 Linked Commands |
| | | 2 reserved |
| | | 1 Tagged Queueing |
| | | 0 Soft Reset |
| 1 | | Target Mode Support |
| | | 7 Processor Mode |
| | | 6 Phase Cognizant Mode |
| | | 5-0 reserved |
| 1 | | Miscellaneous |
| | | 7 0=Scanned Low to High |
| | | 1=Scanned High to Low |
| | | 6 0=Removables included in scan |
| | | 1=Removables not included |
| | | 5 1=Inquiry data not kept by XPT |
| | | 4-0 reserved |
+----+---+--------------------------------------+

TABLE 8-5 PATH INQUIRY CCB - Part 2 of 2
+----+---+--------------------------------------+
| | | HBA capabilities |
| 2 | I | Engine count |
| 14 | I | Vendor Unique |
| 4 | I | Size of Private Data Area |
| 4 | I | Asynchronous Event capabilities |
| | | 31-24 Vendor Unique |
| | | 23- 8 reserved |
| | | 7 New Devices found during rescan|
| | | 6 SIM module De-Registered |
| | | 5 SIM module Registered |
| | | 4 Sent Bus Device Reset to Target|
| | | 3 SCSI AEN |
| | | 2 reserved |
| | | 1 Unsolicited Reselection |
| | | 0 Unsolicited SCSI Bus Reset |
| 1 | I | Highest Path ID Assigned |
| 1 | I | SCSI Device ID (of Initiator) |
| 1 | | reserved |
| 1 | | reserved |
| 16 | I | Vendor ID of SIM-supplier |
| 16 | I | Vendor ID of HBA-supplier |
| 4 | O | OSD Usage |
+----+---+--------------------------------------+

In some Operating System environments it may be possible to dynamically load
and unload SIMs, so Path IDs may not be consecutive from 0 to the Highest Path
ID Assigned.

The Path ID value of FFh is assigned as the address of the XPT.

The SCSI Capabilities field is a duplicate of the Byte 7 field in Inquiry Data
Format.

The OSD Usage Pointer field is provided for OS-specific or platform-specific
functions to be executed by the SIM. The contents of this field are vendor-
specific and are not defined by this standard.

In some environments, the Private Data value returned may be zero because the
OSD has central allocation of private data requirements, or it is a fixed size
as defined by the OSD vendor.

See the vendor specification for the definition of Vendor Unique HBA
capabilities peculiar to a particular HBA implementation.

The Asynchronous Event capabilities indicate what reasons cause the SIM to
generate an asynchronous event.

This function shall return non-zero CAM Status.
- CAM Status of Request Completed Without Error indicates that the other
returned fields are valid.
- CAM Status of Invalid Path ID indicates that the specified Path ID is not
installed.

8.2.3 Release SIM Queue

This function is provided so that the peripheral driver can release a frozen
SIM queue for the selected LUN (see 6.4.3.3).

TABLE 8-6 RELEASE SIM QUEUE
+----+---+
|Size|Dir| Release SIM Queue
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
+----+---+--------------------------------------+

This function shall return CAM status of Request Completed Without Error.

8.2.4 Set Async Callback

This function is provided so that a peripheral driver can register a callback
routine for the selected Bus/Target/LUN nexus.

TABLE 8-7 SET ASYNC CALLBACK CCB
+----+---+
|Size|Dir| Set Async Callback
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | Asynchronous Event Enables |
| | | 31-24 Vendor Unique |
| | | 23- 8 reserved |
| | | 7 New Devices found during rescan|
| | | 6 SIM module De-Registered |
| | | 5 SIM module Registered |
| | | 4 Sent Bus Device Reset to Target|
| | | 3 SCSI AEN |
| | | 2 reserved |
| | | 1 Unsolicited Reselection |
| | | 0 Unsolicited SCSI Bus Reset |
| 4 | O | Asynchronous Callback Pointer |
| 4 | O | Peripheral Driver Buffer Pointer |
| 1 | O | Size of Allocated Peripheral Buffer |
+----+---+--------------------------------------+

This function shall return:

- CAM Status of Request Completed Without Error indicates that the
registration of the callback routine was accepted.
- CAM Status of Request Completed with Error indicates that the registration
was rejected (possibly due to invalid parameter settings).

8.2.5 Set Device Type

This function requires the XPT to add the Target ID, LUN and peripheral type
to the table of attached peripherals built during CAM initialization.

TABLE 8-8 SET DEVICE TYPE CCB
+----+---+
|Size|Dir| Set Device Type
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 1 | O | Peripheral Device Type of Target/LUN |
+----+---+--------------------------------------+

The SIM does not check the validity of the information supplied by the
peripheral driver. This function shall return non-zero CAM Status.

NOTE: Blind insertion of device type information may corrupt the table, and
results would be unpredictable.

- CAM Status of Request Completed Without Error indicates that the specified
information was inserted into the table of SCSI devices.
- CAM Status of Request Completed with Error indicates a problem e.g. not
enough room in the table to add the device information.

8.3 SCSI Control Functions

8.3.1 Abort XPT Request

This function requests that an XPT request be aborted by identifying the CCB
associated with the request. It should be issued on any I/O request that has
not completed that the driver wishes to abort. Success of the Abort function
is never assured. This request does not necessarily result in an Abort message
being issued over SCSI.

TABLE 8-9 ABORT XPT REQUEST CCB
+----+---+
|Size|Dir| Abort XPT Request
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | CCB to be Aborted Pointer |
+----+---+--------------------------------------+

This function shall return CAM Status of Request Completed Without Error or
Unable to Abort Request.

The actual failure or success of the Abort operation is indicated by the CAM
Status eventually returned in the CCB specified.

8.3.2 Reset SCSI Bus

This function is used to reset the specified SCSI bus. This function should
not be used in normal operation. This request shall always result in the SCSI
RST signal being asserted (see 6.4.3.3 and 6.5).

TABLE 8-10 RESET SCSI BUS CCB
+----+---+
|Size|Dir| Reset SCSI Bus
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
+----+---+--------------------------------------+

This function shall return CAM Status of Request Completed Without Error.

The actual failure or success of the Reset SCSI Bus is indicated by the
Asynchronous Callback information.

8.3.3 Reset SCSI Device

This function is used to reset the specified SCSI target. This function should
not be used in normal operation, but if I/O to a particular device hangs up
for some reason, drivers can abort the I/O and Reset the device before trying
again. This request shall always result in a Bus Device Reset message being
issued over SCSI (see 6.4.3.3 and 6.5).

TABLE 8-11 RESET SCSI DEVICE CCB
+----+---+
|Size|Dir| Reset SCSI Device
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
+----+---+--------------------------------------+

This function shall return CAM Status of Request Completed Without Error.

The actual failure or success of the Reset SCSI Device is indicated by the
Asynchronous Callback information.

8.3.4 Terminate I/O Process Request

This function requests that an XPT I/O request be terminated by identifying
the CCB associated with the request. It should be issued on any I/O request
that has not completed that the driver wishes to terminate. Success of the
Terminate I/O Process is never assured. This request does not necessarily
result in a Terminate I/O Process message being issued over SCSI.

TABLE 8-12 TERMINATE I/O PROCESS REQUEST CCB
+----+---+
|Size|Dir| Terminate I/O Process Request
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | CCB to be Aborted Pointer |
+----+---+--------------------------------------+

This function shall return CAM Status of Request Completed Without Error.

The actual failure or success of the Terminate I/O Process operation is
indicated by the CAM Status eventually returned in the CCB specified.

9. Execute SCSI I/O

The most commonly executed request of the SIM is an I/O command, as defined in
the CCB with a Function Code of Execute SCSI I/O.

9.1 CAM Control Block to Request I/O

Peripheral drivers should make all of their SCSI I/O requests using this
function, which is designed to take advantage of all features of SCSI which
can be provided by virtually any HBA/SIM combination. The CCB is as defined in
Table 9-1.

This function will typically return with CAM Status of zero indicating that
the request was queued successfully. Function completion can be determined by
polling for non-zero status or through use of the Callback on Completion
field.

TABLE 9-1 SCSI I/O REQUEST CCB
+----+---+
|Size|Dir| SCSI I/O Request
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | Peripheral Driver Pointer |
| 4 | O | Next CCB Pointer |
| 4 | O | Request Mapping Information (OSD) |
| 4 | O | Callback on Completion |
| 4 | O | SG List/Data Buffer Pointer |
| 4 | O | Data Transfer Length |
| 4 | O | Sense Info Buffer Pointer |
| 1 | O | Sense Info Buffer Length |
| 1 | O | CDB Length |
| 2 | O | Number of Scatter/Gather entries |
| 4 | | reserved (OSD) |
| 1 | I | SCSI Status |
| 3 | | reserved (OSD) |
| 4 | I | Residual Length |
| 12 | O | CDB |
| | | - - - - - OSD - - - - - |
| 4 | O | Timeout Value |
| 4 | O | Message Buffer Pointer (Target-only)|
| 2 | O | Message Buffer Length (Target-only)|
| 2 | O | VU Flags |
| 1 | O | Tag Queue Action |
| 3 | | reserved |
| n | O | Private Data |
+----+---+--------------------------------------+

9.1.1 Address of this CCB

Pointer containing the Physical address of this CCB.

9.1.2 Callback on Completion

This is an OSD field which contains the method by which the SIM is to return
to the caller. In some applications it is a pointer, but in others the
location of the Callback on Completion routine may be a fixed location and the
CCB would contain an argument. See the OSD-specific considerations in
Clause 6. The address of the Completed CCB shall be passed on the stack to
inform the peripheral driver which CCB has completed.

9.1.3 CAM Control Block Length

This field contains the length in bytes of the CCB, including this field and
the Address of this CCB in the total.

9.1.4 CAM Flags

This field contains bit settings as described in Table 9-2 to indicate special
handling of the requested function.

TABLE 9-2 CAM FLAGS (OSD)
+----+----+
|Size|Bits| CAM Flags (OSD)
+----+----+----------------------------------+
| 1 | 7-6| Direction |
| | | 00= reserved |
| | | 01=In |
| | | 10=Out |
| | | 11=No Data Transfer |
| | 5 | 1=Disable Autosense |
| | 4 | 1=Scatter/Gather |
| | 3 | 1=Disable Callback on Comp |
| | 2 | 1=Linked CDB |
| | 1 | 1=Tagged Queue Action Enable |
| | 0 | 1=CDB is a Pointer |
| 1 | 7 | 1=Disable Disconnect |
| |* 6 | 1=Initiate Synchronous Transfers |
| |* 5 | 1=Disable Synchronous Transfers |
| | 4 | SIM Queue Priority |
| | | 1=Head insertion |
| | | 0=Normal (tail insertion) |
| | 3 | SIM Queue Freeze |
| | 2 | Engine Synchronize |
| | 1-0| reserved |
| 1 | 7 | SG List/Data 0=Host 1=Engine |
| | 6 | CDB Pointer 0=VA 1=PA |
| | 5 | SG List/Data 0=VA 1=PA |
| | 4 | Sense Buffer 0=VA 1=PA |
| | 3 | Message Buffer 0=VA 1=PA |
| | 2 | Next CCB 0=VA 1=PA |
| | 1 | Callback on Comp 0=VA 1=PA |
| | 0 | reserved |
| 1 | | Target Mode-Specific CAM Flags |
| | 7 | Data Buffer Valid |
| | 6 | Status Buffer Valid |
| | 5 | Message Buffer Valid |
| | 4 | reserved |
| | 3 | 1=Phase-Cognizant Mode |
| | 2 | 1=Target CCB Available |
| | 1 | 1=Disable AutoDisconnect |
| | 0 | 1=Disable AutoSave/Restore |
+----+----+----------------------------------+
* These bits are mutually exclusive

9.1.4.1 Byte 1 Bits

7-6 Direction - These encoded bits identify the direction of data movement
during the data transfer phase, though when used in conjunction with
Engine processing, they have a little diffferent meaning (see 11).
- a setting of 01 indicates a Read operation (data transfer from target to
initiator).
- a setting of 10 indicates a Write operation (data transfer from
initiator to target).
- a setting of 11 indicates there is to be no data transfer.
5 Disable Autosense - When set to 1 this bit disables autosense.
4 Scatter/Gather - when set to 1 this bit indicates that data is not to be
transferred to/from a single location in memory but to/from several. In
this case the Data Buffer Pointer refers to a list of addresses and length
in bytes at each address to which the data is to be transferred. The
format of the SG List is defined in Table 9-3.

TABLE 9-3 SCATTER GATHER LIST
+----+
|Size|
+----+-----------------+
| 4 | Data Address 1 |
| 4 | Data Length 1 |
| 4 | Data Address 2 |
| 4 | Data Length 2 |
| | : |
| 4 | Data Address n |
| 4 | Data Length n |
+----+-----------------+

3 Disable Callback on Completion - When set to 1 the peripheral driver does
not want the SIM to callback automatically when the request is completed.
This implies that the caller will be polling for a non-zero CAM Status
(which indicates successful completion or termination of the request).
2 Linked CDB - When set to 1 this CDB is a linked command. If this bit is
set, then the Control field in the CDB shall have bit 0=1. If not, the
results are unpredictable. See 9.2.
1 Tag Queue Actions are to be enabled.
0 If the CDB is identified as a Pointer, the first four bytes of the CDB
field contain a pointer to the location of the CDB.

9.1.4.2 Byte 2 Bits

7 When Disable Disconnect=1 the Disconnect capability of SCSI is disabled.
The default of 0 sets bit 6=1 in the SCSI Identify MSG (which indicates
that the initiator has the ability to disconnect and reconnect.
6 When Initiate Synchronous Transfers=1 the SIM shall negotiate Synchronous
transfers, and wherever possible execute synchronous transfers.
5 When Disable Synchronous Transfers=1 the SIM shall negotiate Asynchronous
transfers (if previously negotiated Synchronous). If unable to negotiate
Synchronous or negotiation has not yet been attempted, the SIM shall not
initiate negotiation.
4 When SIM Queue Priority=1 the SIM shall place this CCB at the head of the
Target/LUN internal queue to be the next operation sent to the Target/LUN
by the SIM.
3 When SIM Queue Freeze=1 the SIM shall place its internal Target/LUN queue
into the frozen state. Upon callback, the CAM Status for this CCB shall
have the SIM Queue Freeze flag set. This bit should only be set for SIM
error recovery and should be used in conjuntion with the SIM Queue
Priority bit and the Release SIM Queue command.
2 The Engine Synchronize=1 is used in conjunction with the In or Out setting
to flush any residual bits before terminating engine processing (see 11).

9.1.4.3 Byte 3 Bits

The Pointer fields are set up to have one characteristic. If a bit is set to 1
it means the pointer contains a Physical Address. If set to 0 it means the
pointer contains a Virtual Address. If the SIM needs an address in a different
form to that provided, it should be converted by the SIM (using OSD
facilities) and stored in Private Data.

9.1.4.4 Byte 4 Bits

The Target Mode Only Flags are only active on Enable LUN or Execute Target I/O
commands.
7-5 The Buffer Valid bits identify which buffers have contents. In the event
that more than one bit is set, they shall be transferred in the sequence
of Data Buffer, Status, Message Buffer.
3 Phase-Cognizant Mode - if target operations are supported, when set to 1,
the SIM shall operate in Phase-Cognizant Mode, otherwise it shall operate
in Processor Mode.
2 Target CCB Available - when set to 1 this bit indicates that the XPT/SIM
can use this CCB to process this request. A value of 0 indicates that this
CCB is not available to the XPT/SIM.
1 AutoDisconnect - when set to 1 this bit disables AutoDisconnect. The
default of 0 causes the XPT/SIM to automatically disconnect, if the
Identify message indicates DiscPriv is set.
0 AutoSave - when set to 1 this bit disables AutoSave. The default of 0
causes the XPT/SIM to automatically to send a Save Data Pointer message on
an AutoDisconnect.

9.1.5 CAM Status

This field is returned by the SIM after the function is completed. A zero
status indicates that the request is still in progress or queued. CAM Status
is defined in Table 9-4.

If Autosense information is available, the code returned shall be incremented
by 80h e.g. 04h indicates an error occurred, and 84h indicates that an error
occurred and Autosense information is available for analysis.

TABLE 9-4 CAM STATUS
+------+--------------------------------------+
| 00h | Request in progress |
| 01h | Request completed without error |
| 02h | Request aborted by host |
| 03h | Unable to Abort Request |
| 04h | Request completed with error |
| 05h | CAM Busy |
| 06h | Invalid Request |
| 07h | Invalid Path ID |
| 08h | SCSI device not installed |
| 09h | Unable to Terminate I/O Process |
| 0Ah | Target Selection Timeout |
| 0Bh | Command Timeout |
| 0Ch | reserved |
| 0Dh | Message Reject received |
| 0Eh | SCSI Bus Reset Sent/Received |
| 0Fh | Uncorrectable Parity Error Detected |
| 10h | Autosense Request Sense Cmd Failed |
| 11h | No HBA detected |
| 12h | Data OverRun/UnderRun |
| 13h | Unexpected Bus Free |
| 14h | Target bus phase sequence failure |
| 15h | CCB Length Inadequate |
| 16h | Cannot Provide Requested Capability |
| 17h | Bus Device Reset Sent |
| 18h | Terminate I/O Process |
|19-37h| reserved |
| | Target Mode Only Status |
| 38h | Invalid LUN |
| 39h | Invalid Target ID |
| 3Ah | Function not Implemented |
| 3Bh | Nexus not Established |
| 3Ch | Invalid Initiator ID |
| 3Dh | SCSI CDB Received |
| 3Eh | LUN Already Enabled |
| 3Fh | SCSI bus Busy |
+------+--------------------------------------+
| +40H | to indicate that SIM Queue is frozen |
| +80h | to indicate that Autosense is valid |
+------+--------------------------------------+

- 00h Request in progress: the request is still in process.
- 01h Request completed without error: the request has completed and no error
condition was encountered.
- 02h Request aborted by host: the request was aborted by the peripheral
driver.
- 03h Unable to Abort Request: the SIM was unable to abort the request as
instructed by the peripheral driver.
- 04h Request completed with error: the request has completed and an error
condition was encountered.
- 05h CAM Busy: CAM unable to accept request at this time.
- 06h Invalid Request: the request has been rejected because it is invalid.
- 07h Invalid Path ID indicates that the Path ID is invalid.
- 08h SCSI device not installed: Peripheral Device Type field is not valid.
- 09h Unable to Terminate I/O Process: the SIM was unable to terminate the
request as instructed by the peripheral driver.
- 0Ah Target Selection Timeout: The target failed to respond to selection.
- 0Bh Command Timeout: the specified command did not complete within the
timer value specified in the CCB.
- 0Dh Message Reject received: The SIM received a Message Reject MSG.
- 0Eh SCSI Bus Reset Sent/Received: The SCSI operation was terminated at some
point because the SCSI bus was reset.
- 0Fh Uncorrectable Parity Error Detected: An uncorrectable SCSI bus parity
error was detected. When this occurs, the SIM sends the ABORT message
to the target.
- 10h Autosense Request Sense Command Failed: The SIM attempted to obtain
sense data and failed.
- 11h No HBA detected: HBA no longer responding to SIM (assumed to be a
hardware problem).
- 12h Data OverRun: target transferred more data bytes than peripheral driver
indicated in the CCB.
- 13h Unexpected Bus Free: an unexpected Bus Free condition occurred.
- 14h Target Bus Phase Sequence Failure: the target failed to operate in a
proper manner according to X3.131-1990 e.g. it went to the Message Out
phase after the initiator asserted ATN.
- 15h CCB Length Inadequate: More private data area is required in the CCB.
- 16h Cannot Provide Requested Capability: Resources are not available to
provide the capability requested (in the CAM Flags).
- 17h Bus Device Reset Sent: this CCB was terminated because a Bus Device
Reset was sent to the target.
- 18h Terminate I/O Process: this CCB was terminated because a Terminate I/O
Process was sent to the target.
- 38h Invalid LUN indicates that the LUN specified is outside the supported
range of the SCSI bus.
- 39h Invalid Target ID indicates that the Target ID does not match that used
by the HBA specified by the Path ID field.
- 3Ah Function Not Implemented indicates that Target Mode is not supported.
- 3Bh Nexus not Established: There is currently no connection established
between the specified Target ID and Target LUN and any initiator.
- 3Ch Invalid Initiator ID: The initiator ID specified is outside the valid
range that is supported.
NOTE: This status can also be returned if the target tries to reselect an
initiator other than the one to which it was previously connected.
- 3Dh SCSI CDB Received: Indicates that the target has been selected and that
the SCSI CDB is present in the CCB.
- 3Eh LUN Already Enabled: The LUN identified in Enable LUN was previously
enabled.
- 3Fh SCSI bus Busy: The SIM failed to win arbitration for the SCSI Bus
during several different bus free phases.

9.1.6 CDB

This field either contains the SCSI CDB (Command Descriptor Block), or a
pointer to the CDB, to be dispatched.

9.1.7 CDB Length

This field contains the length in bytes of the CDB.

9.1.8 Data Transfer Length

This field contains the length in bytes of the data to be transferred.

9.1.9 Function Code

See 8.1.2.

9.1.10 LUN

This field identifies the SCSI LUN to which this CCB is being directed.

9.1.11 Message Buffer Length (Target-only)

This field contains the length in bytes of the field which is to be used to
hold Message information in the event that the Peripheral Drivers needs to
issue any MSGs. This field is exclusive to Target Mode operation.

9.1.12 Message Buffer Pointer (Target-only)

This field contains a pointer to buffer containing Messages. This pointer is
only valid for use in Target Mode.

9.1.13 Next CCB Pointer

This field contains a pointer to the next command block in a chain of command
blocks. A value of 0 indicates the last command block on the chain. This field
is used for the linking of commands.

9.1.14 Number of Scatter/Gather entries

This field contains the number of entries in the SG List.

9.1.15 Path ID

The Path ID specifies the SCSI port on the installed HBA to which the request
is addressed. Path IDs are assigned by the XPT, begin with zero, and need not
be consecutive. The Path ID of FFh is assigned for the XPT. An HBA may have
more than one SCSI port. A SIM may support more than one HBA.

9.1.16 Peripheral Driver Pointer

This field contains a pointer which is for the exclusive use of the Peripheral
Driver, which use is not defined by this standard.

9.1.17 Private Data

This field is used to contain whatever fields the CAM Module needs to execute
the request. As such it constitutes a scratchpad of working space needed by
the SIM and/or the XPT. The size of this area is an OSD as it may differ
between SIMs and XPTs by environment or by vendor implementation. The device
driver is responsible to query the XPT and ensure that enough Private Data
area is available to the SIM and/or XPT.

9.1.18 Request Mapping Information (OSD)

This field is a pointer to an OSD dependent data structure which is associated
with the original I/O request.

9.1.19 Residual Length

This field contains the difference in twos complement form of the number of
data bytes transferred by the HBA compared with the number of bytes requested
by the CCB.

9.1.20 SCSI Status

This field contains the status byte returned by the SCSI target after the
command is completed.

9.1.21 Sense Info Buffer Length

This field contains the length in bytes of the field which is to be used to
hold Sense data in the event that a Request Sense is issued.

9.1.22 Sense Info Buffer Pointer

This field contains a pointer to the data buffer for Request Sense data. This
pointer will only be used if a Check Condition occurs while performing the
specified command.

9.1.23 SG List/Data Buffer Pointer

This field contains a pointer to either the data buffer to which data is to be
transferred, or to the SG List which contains the list of scatter/gather
addresses to be used for the transfer.

9.1.24 Tagged Queue Action

SCSI provides the capability of tagging commands to force execution in a
specific sequence, or of letting the target optimize the sequence of execution
to improve performance. This function provides a similar capability. For a
description of the tagged command queueing philosophy see SCSI-2 X3.131-1990.

When the Queue Action Enable bit in the CAM Flags is set, the CDB issued by
the SIM shall be associated with the Queue Action specified as:

20h = Simple Tag Request
21h = Head of Queue Tag Request
22h = Ordered Queue Tag Request

9.1.25 Target ID

This field identifies the SCSI target which is to be selected for execution of
the CCB request.

9.1.26 Timeout Value

This field contains the maximum period in seconds that a request can remain
outstanding. If this value is exceeded then the CAM Status shall report the
timeout condition. A value of 00h in the CCB means the peripheral driver
accepts the SIM default timeout. A value of F...Fh in the CCB specifies an
infinite period.

9.1.27 VU Flags

The uses for this field are defined in the vendor specification.

9.2 Command Linking

The SIM supports SCSI's ability to link commands in order to guarantee the
sequential execution of several requests. This function requires that both the
HBA and the involved target(s) support the SCSI Link capability.

To utilize linking, a chain of CCBs is built with the Next CCB Pointer being
used to link the CCBs together. The CAM Flag Link bit shall be set in all CCBs
but the last in the chain. When a SCSI target returns the Linked Command
Complete message, the next CCB is processed, and its associated CDB is
dispatched.

Any Check Condition returned by the target on a linked command shall break the
chain.

10. Target Mode (Optional)

If a Target Mode function is specified by a CCB and this functionality is not
provided by a particular SIM implementation, then a CAM Status of Function Not
Implemented shall be returned in the CCB.

The Target Mode functionality causes the HBA associated with the specified
SCSI link to be set up so that it may be selected as a target i.e. when an HBA
is operating in Target mode, it is responding to other HBAs on the same SCSI
cable.

There are two different modes of target operation, either or both of which may
be supported by the XPT/SIM as defined by the Target Mode Support flags in the
Path Inquiry CCB.

- Processor mode
- Phase-Cognizant mode

Processor mode permits an application to register itself as a LUN and provide
a set of one or more CCBs that the XPT/SIM can use for receiving and sending
data. In this mode, when the adapter is selected and the XPT/SIM receives an
Identify message for a LUN that has registered as a Processor LUN, the XPT/SIM
will accept any processor device commands (Inquiry, Request Sense, Send,
Receive) and, using one of the available CCB's, process the SCSI command
through completion.

Upon disconnection, the SIM calls back on completion to let the application
know that the CCB has been processed. From the time that the application
registers itself until the time a command has completed, there is no callabck
to the application.

In summary, Processor applications get called back only after the SCSI command
has been completely processed, and leaves all phase handling and SCSI command
processing nuances to the XPT/SIM and the previously registered CCB's.

Phase-Cognizant mode permits an application tighter control over what takes
place when a SCSI command is received by the SIM. When a Phase-Cognizant
application registers itself and a command is received, the XPT/SIM does an
immediate Callback on Completion after placing the SCSI command in an
available CCB. The Phase-Cognizant application is responsible to set up data,
message, status fields and CAM-Flags in the CCB and re-issue the CCB with an
Execute Target I/O function code so that the XPT/SIM knows which phases it
should execute. The "callback-reissue CCB" cycle may happen multiple times
before a command completes execution.

In summary, Phase Cognizant applications get a callback immediately after the
SCSI command block is received and is expected to instruct the XPT/SIM as to
which phases to go through to perform the command.

10.1 Enable LUN

The specified Target ID shall match that returned by the HBA Inquiry Function
for the HBA. The specified LUN is the one enabled for selection, and if the
HBA is to respond as an additional LUN, another Enable LUN is required.

In addition to providing a hook into the application, this function is
intended to provide an area that the XPT/SIM can use as working space when the
HBA is selected.

TABLE 10-1 ENABLE LUN CCB
+----+---+
|Size|Dir| Enable LUN CCB
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 2 | O | Group 6 Vendor Unique CDB Length |
| 2 | O | Group 7 Vendor Unique CDB Length |
| 4 | O | Pointer to Target CCB List |
| 2 | O | Number of Target CCBs |
+----+---+--------------------------------------+

If the Number of Target CCBs is zero, then Target Mode is disabled, otherwise
the Pointer to Target CCB List refers to a list of addresses of CCBs to which
the data is to be transferred (see Table 10-2).

TABLE 10-2 TARGET CCB LIST
+----+
|Size| Target CCB List
+----+-----------------+
| 4 | CCB Address 1 |
| 4 | CCB Address 2 |
| | : |
| 4 | CCB Address n |
+----+-----------------+

The XPT/SIM shall place the pointer to the CCB, or the pointer to the list of
CCBs, in a list until the specified Target ID and LUN is selected on the SCSI
link specified by the Path ID field. While the request is being held, the CAM
Status field of the Target CCB, shall be set to Request in Progress. The
application is required to poll on the CAM status field of the Target CCB or
provide a Completion Callback routine through the Target CCB.

The XPT/SIM shall keep an indication of whether a single CCB or list of CCBs
was provided on the Enable LUN service.

The XPT/SIM shall set the following in each Target CCB when they are first
provided:

- CAM Status to Request In Progress
- CAM Flags shall be the same as those in the Enable LUN CCB
- CAM Flags shall set the Target CCB Available as needed

Within the Target CCB provided, the following information shall be present and
valid,

- CAM Flag information including AutoDisconnect and AutoSave.
- CDB field is valid for the Command Blocks that may be received. That is
either CDBs are embedded in the CCB, or a pointer to a CDB area is provided
in the CDB field.
- The Group 6 and 7 Vendor Unique CDB Length fields contain the number of
bytes a target application expects to receive for it's vendor unique
command set. The previous item shall go hand-in-hand with this requirement.
The Group 6 and 7 Vendor Unique CDB Length fields shall be retained for
each LUN enabled.

If the target application supports Vendor Unique Command Blocks, then the CDB
field of the CCB shall reflect the nature and size of those Vendor Unique
Command Blocks. Ample space shall be provided to contain the CDBs that may be
received. If a CDB greater than the size of the CDB field is desired, then the
CDB field shall contain a pointer to a CDB.

To disable the selection of a specific LUN, the application performs an Enable
LUN with a zero value for the Number of Target CCBs.

If a LUN is disabled, after having been enabled, then the Inquiry data and the
Vendor Unique CDB Length data shall be cleared.

The XPT/SIM shall prevent a nexus being established between an initiator and a
specified LUN that has been disabled. If there is a pre-existing nexus, then
Invalid Request shall be returned.

This function shall return non-zero CAM Status.

- CAM Status of Request Completed Without Error indicates that the Enable LUN
was completed successfully.
- CAM Status of Invalid Request indicates that there is currently a nexus
established with an initiator that shall be terminated, first.
- CAM Status of Invalid Path ID indicates that the Path ID is invalid.
- CAM Status of Invalid Target ID indicates that the Target ID does not match
that used by the HBA specified by the Path ID field.
- CAM Status of Invalid LUN indicates that the LUN specified is outside the
supported range of the SCSI bus.
- CAM Status of Function Not Implemented indicates that Target Mode is not
supported by this implementation of CAM.

10.2 Phase Cognizant Mode

10.2.1 Target Operation of the HBA

When the HBA is selected, the XPT/SIM automatically sets the HBA to the
Message Out phase to receive the Identify, Synchronous Data, and other
messages that may be sent by the Initiator. The XPT/SIM response to these
messages shall be as defined in X3.131-1990.

The LUN shall be extracted from the Identify Message and the appropriate CCB
shall be extracted from the list of CCBs being held by the XPT/SIM.

If the LUNTAR bit (or any of the reserved bits) of the Identify Message is set
to 1, then the XPT/SIM shall send a MESSAGE REJECT message back to the
initiator.

If no CCBs are being held by the XPT/SIM for a Target ID, then the XPT/SIM
shall not respond to the selection of that Target ID.

If CCBs are being held by the XPT/SIM, and the LUN indicated by the Identify
Message does not have a CCB provided by an application, then the XPT/SIM shall
provide the following support:

a) If an Inquiry command is sent to this LUN, then the XPT/SIM shall respond
with Inquiry Data that indicates "Logical Unit Not Supported."
b) If any other command (except Request Sense) is sent to this LUN, then the
XPT/SIM shall respond with a Check Condition.
c) If a Request Sense command is sent to this LUN after a Check Condition
status is sent, then the XPT/SIM shall respond with sense data that
indicates "Logical Unit Not Supported".

The XPT/SIM shall scan the CAM Flags in the CCB(s) provided with Enable LUN.
If none of them have the Target CCB Available bit set, the XPT/SIM shall
request the SCSI CDB and post BSY status. The XPT/SIM shall not modify the
SCSI CDB(s) in the CCB(s).

After processing the CDB from a Target CCB, the target application shall set
CCB Available in the CAM Flags, which allows the application to pass the same
CCB back to the XPT/SIM upon Callback on Completion (this prevents the
possibility that the XPT/SIM could use the CCB on selection). The setting of
the Target Available bit could be done at the Callback on Completion after the
Exectute Target I/O which trasnmits SCSI Status.

If a target application sets Target Available upon recognizing that a CDB has
been received and uses a different CCB to perform the data transfer, there is
a lower likelihood of a BSY response to the initiator when a CCB is not
available.

The Disable Disconnect bit in the CAM Flags field shall be updated to indicate
the state of the DiscPriv bit in the Identify message that was received from
the initiator. If the DiscPriv bit was set in the Identify Message, then the
Disable Disconnect bit shall be cleared, and vice-versa. NOTE: The default
state of the Disable Disconnect bit in the CAM Flags is cleared, implying that
disconnect is enabled.

The Target ID field shall be set to the ID of the initiator that performed the
selection. This field can then be used by subsequent functions, such as
reselect, to determine the Initiator's ID.

Once the initial Message Out Phase is complete, the XPT/SIM automatically sets
the HBA to the Command Out Phase to request the SCSI CDB. After receiving the
SCSI CDB bytes, the XPT/SIM shall set the CAM status field to CAM Status of
SCSI CDB received, and clear the CCB Available bit in the CAM Flags.

Upon completion of the data phase, the XPT/SIM shall send the appropriate SCSI
status and Command Complete and then disconnect from the bus. The XPT/SIM
shall then post the required CAM Status in the CCB, or Callback on Completion.

If the Group Code of the Operation Code of the Command Block is Vendor Unique
the XPT/SIM shall ensure that only the indicated number of command bytes are
received. If the required number of bytes are exceeded or not transferred,
then the XPT/SIM shall return a status of Check Condition, the Sense Key in
the Sense Buffer shall be set to Illegal Request, and the Additional Sense Key
and Qualifier shall be set to Command Phase Error.

If the DiscPriv bit in the Identify message was set, which results in the
Disable Disconnect bit of the CAM Flags being cleared, and the Disable
AutoDisconnect bit of the CAM Flags field is cleared, the XPT/SIM shall
automatically disconnect upon receipt of the command block. The subsequent
invocation of the Execute Target I/O function shall perform an automatic
reselect when it is invoked.

If a BUS DEVICE RESET message is received at any time, the XPT/SIM shall set
the CAM Status field to SCSI Bus Reset Sent/Received for any CCB being held
(through Enable LUN), or that is active in the XPT/SIM.

If a SCSI Bus Reset occurs the asynchronous callback and bus reset mechanism
defined for initiator mode shall be followed.

The SIM shall reject any CCB which has a Timeout Value of other than infinity.

10.2.2 Execute Target I/O

If the Data Valid bit is set, the XPT/SIM shall enter the data phase indicated
by the direction bit in the CAM Flags field (ie. DATA IN or DATA OUT). It
shall send/receive data to/from the buffer(s) indicated in the CCBs Scatter
Gather List or Data Pointer.

If the Status Valid bit is set, the XPT shall send the status byte specified
in the SCSI Status field to the current initiator and then send the Command
Complete Message.

If the Message Valid bit is set, the XPT shall enter the Message phase and
transfer the contents of the Message buffer.

The XPT/SIM shall receive and respond to any messages resulting from ATN being
asserted by the initiator, in addition to any messages it sends to the
initiator.

The XPT/SIM shall be able to execute all the phases indicated by the Buffer
Valid bits of the CAM Flags, within a single invocation of the Execute Target
I/O i.e. if more than one bit is set, the order of execution of the phases
shall be data, status, and message.

If the Data Buffer Valid and Status Buffer Valid bits of the CAM Flags are
both set for an invocation of Execute Target I/O, the AutoDisconnect and
AutoSave features shall be disabled.

If the Disable AutoDisconnect bit of the CAM Flags is cleared, and the Disable
Disconnect of the CAM Flags bit is cleared, then the XPT/SIM shall disconnect
on the completion of the data transfer.

If the Disable AutoSave bit of the CAM Flags is cleared, then the
XPT/SIM shall send a Save Data Pointers message to the initiator prior to
disconnect.

The XPT/SIM shall perform an automatic reselect if the XPT/SIM had

disconnected after the receipt of the CDB, or had disconnected upon completion
of a previous Execute Target I/O (within the same I/O process).

Upon the last Execute Target I/O, the target application should consider
setting the Disable AutoSave bit, which shall disable the sending of the Save
Data Pointers.

This function typically returns with CAM Status of zero indicating that the
request was executed successfully. Function completion can be determined by
polling for non-zero status or through use of the Callback on Completion
field.

10.3 Processor Mode

10.3.1 CCB Acceptance

In Processor mode, the Target CCB List shall contain at least one pre-built
CCB that the SIM can use when it responds to selection. The Target CCBs that
are supported by the SIM include CDBs for the following commands:

- Inquiry
- Receive
- Request Sense
- Send

The SIM shall verify that the CCBs in the Target CCB List contain supported
commands, valid data buffers etc.

Any invalid CCB in the list shall be rejected and the LUN shall not be
enabled.

10.3.2 Target Operation of the HBA

When the target HBA is selected, it shall automatically request the CDB.

The SIM shall search the Target CCB List to find a matching CDB. If a matching
CDB is found, it shall verify that Target CCB Available=1, and use the
contents of the data buffers to process the command received. The SIM shall
clear Target CCB Available, and if the peripheral driver wants the CCB to be
re-used it is responsible to set Target CCB Available=1,

Upon completion of the CDB received, the SIM shall report CAM Status in the
CCB and call back the peripheral driver.

If the Target CCB List has no CCBs with Target CCB Available=1, but matches
were found, the SIM shall send Busy Status to the Initiator.

If the Target CCB List contained no matching CCBs, then the SIM shall return
Check Condition to the Initiator. Upon receipt of a Request Sense command, the
SIM shall return a Sense code of "Invalid CDB" to the Initiator.

If an Inquiry CDB is received but there is no Inquiry CDB in one of the CCBs
in the Target CCB List then the SIM shall return Inquiry Data of "LUN Not
Supported" to the Initiator. NOTE: A CCB to respond to an Inquiry CDB should
be provided in every Target CCB List.

If an Inquiry CDB is and there is an Inquiry CDB in one of the CCBs in the
Target CCB List then the SIM shall return the Inquiry information provided by
the data buffer pointer. The SIM does not clear Target CCB Available or call
back as it is a placeholder of consistent information.


11. HBA Engines

An engine is a hardware device implemented in an HBA to perform time-intensive
functions not available on target devices. Generally, these engines are
required to process data prior to building a CDB and submitting to the device.
There may be more than one engine in a HBA.

One use of engines is to compress data. In this mode, a device driver first
submits data to the engine. Once the engine has completed processing the data,
an Execute SCSI CCB can be built for the SCSI transfer.

The engine model allows for the addressing of buffer memory located on the
HBA. The buffer addressing appears to the host as contiguous space. Using this
model, it is possible to submit multiple requests until the engine buffer is
full. Once the full condition is met, an Execute SCSI CCB can be built.

When the full condition occurs (as defined by the Destination Data Length
equalling the Destination Data Maximum Length), the amount of unprocessed
source data is reported in the Source Residual Length. The residual data may
then be re-submitted at a later time.

11.1 Engine Inquiry

This function is used to learn information on the engines installed in the HBA
hardware. This function is issued for each engine.

TABLE 11-1 ENGINE INQUIRY CCB
+----+---+
|Size|Dir| Engine Inquiry
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 2 | O | Engine Number |
| 1 | I | Engine Type |
| | | 0=Buffer Memory |
| | | 1=Lossless Compression |
| | | 2=Lossy Compression |
| | | 3=Encryption |
| | | 4-FF reserved |
| 1 | I | Engine Algoritm ID |
| | | 0=Vendor Unique |
| | | 1=LZ1 Variation 1 (STAC) |
| | | 2=LZ2 Variation 1 (HP DCZL) |
| | | 3=LZ2 Variation 2 (Infochip) |
| | | 4-FF reserved |
| 4 | I | Engine Memory Size |
+----+---+--------------------------------------+

The Engine Type reports the generic function the addressed engine number is
capable of supporting.

The Engine Algorithm ID reports the specific capability the addressed engine
supports.

The amount of buffer memory provided for an engine is reported in the Engine
Memory Size.

This function shall return non-zero CAM Status.
- CAM Status of Request Completed Without Error indicates that the other
returned fields are valid.
- CAM Status of Invalid Request indicates that the specified Engine Number is
not installed.

11.2 Execute Engine Request (Optional)

To accomodate buffering associated with the engine, the CAM Flag SG List/Data
set to 1=Engine is used to specify that the normal Data Buffer Pointer is
actually a physical address in the buffer space of the engine.

There are four modes associated with engine processing established by CAM
Flags:

- A Direction setting of Out is used to Encrypt or Compress the data
- A Direction setting of Out is used to Decrypt or Decompress the data
- Synchronize is used in conjunction with In or Out to flush any residual
bits prior to terminating engine processing.

Certain types of engines change the size of data as part of their operation
e.g. the purpose of compression engines is to reduce the size of data prior to
transmission over SCSI. As such, the Execute Engine Request CCB allows the
engine to report the size of the resultant data.

TABLE 11-1 EXECUTE ENGINE REQUEST CCB
+----+---+
|Size|Dir| Execute Engine Request
+----+---+--------------------------------------+
| | | - - - - - OSD - - - - - |
| 4 | O | Address of this CCB |
| 2 | O | CAM Control Block Length |
| 1 | O | Function Code |
| 1 | I | CAM Status |
| 1 | | reserved |
| | | - - - - Common - - - - - |
| 1 | O | Path ID |
| 1 | O | Target ID |
| 1 | O | LUN |
| 4 | O | CAM Flags (OSD) |
| 4 | O | Peripheral Driver Pointer |
| 4 | O | reserved (OSD) |
| 4 | O | Request Mapping Information (OSD) |
| 4 | O | Callback on Completion |
| 4 | O | SG List/Data Buffer Pointer |
| 4 | O | Data Transfer Length |
| 4 | O | Engine Buffer Data Pointer |
| 1 | | reserved (OSD) |
| 1 | | reserved (OSD) |
| 2 | O | Number of Scatter/Gather entries |
| 4 | O | Destination Data Maximum Length |
| 4 | I | Destination Data Length |
| 4 | I | Source Residual Length |
| 12 | | reserved (OSD) |
| | | - - - - - OSD - - - - - |
| 4 | O | Timeout Value |
| 4 | | reserved |
| 2 | O | Engine Number |
| 2 | O | VU Flags |
| 1 | | reserved |
| 3 | | reserved |
| n | O | Private Data |
+----+---+--------------------------------------+

This function will typically return with CAM status of zero indicating that
the request was queued successfully. Function completion can be determined by
polling for non-zero status or through use of the Callback on Completion
field.

ANNEX

Annex A. Physical/Logical Translation in 80x86 Environment

A.1 OSD Formatting of Disk Drives

The DOS physical address to/from logical block address conversion algorithms
to map SCSI disks into int 13h Head-Cylinder-Sector format vary widely between
suppliers of software to support third party disks.

The following "C" routines have been adopted by CAM as representing the most
efficient utlization of capacity. The following code is ANSI "C" that can be
compiled using the Microsoft C compiler, version 5.1.

a) SETSIZE converts a Read Capacity value to int 13h Head-Cylinder-Sector
requirements. It minimizes the value for number of heads and maximizes the
number of cylinders. This will support rather large disks before the
number of heads will not fit in 4 bits (or 6 bits). This algorithm also
minimizes the number of sectors that will be unused at the end of the disk
while allowing for very large disks to be accomodated. This algorithm does
not use physical geometry.

b) LTOP does logical to physical conversion

c) PTOL does physical to logical conversion

d) MAIN is a test routine for a, b and c.

A.1.1 SETSIZE

*/
typedef unsigned int UINT;
typedef unsigned long ULNG;
/*
* Convert from logical block count to Cylinder, Sector and Head (int 13)
*/

int setsize(ULNG capacity,UINT *cyls,UINT *hds,UINT *secs)

{
UINT rv = 0;
ULNG heads, sectors, cylinders, temp;

cylinders = 1024L; /* Set number of cylinders to max value */
sectors = 62L; /* Max out number of sectors per track */

temp = cylinders * sectors; /* Compute divisor for heads */
heads = capacity / temp; /* Compute value for number of heads */
if (capacity % temp) { /* If no remainder, done! */
heads++; /* Else, increment number of heads */
temp = cylinders * heads; /* Compute divisor for sectors */
sectors = capacity / temp; /* Compute value for sectors per track */
if (capacity % temp) { /* If no remainder, done! */
sectors++; /* Else, increment number of sectors */
temp = heads * sectors; /* Compute divisor for cylinders */
cylinders = capacity / temp; /* Compute number of cylinders */
}
}
if (cylinders == 0) rv=1; /* Give error if 0 cylinders */

*cyls = (UINT) cylinders; /* Stuff return values */
*secs = (UINT) sectors;
*hds = (UINT) heads;
return(rv);
}

A.1.2 LTOP

/*
* logical to physical conversion
*/

void ltop(ULNG block,UINT hd_count,UINT sec_count,UINT *cyl,UINT *hd,UINT
*sec)

{
UINT spc;
spc = hd_count * sec_count;
*cyl = block / spc;
*hd = (block % spc) / sec_count;
*sec = (block % spc) % sec_count;
}

A.1.3 PTOL

/*
* Physical to logical conversion
*/

ULNG ptol(UINT cyl,UINT hd,UINT sec,UINT cyl_count,UINT hd_count,UINT
sec_count)

{
ULNG cylsize;
cylsize = sec_count * hd_count;
return((cyl * cylsize) + (hd * sec_count) + sec);
}

A.2 Backwards Compatibility

The selection of a new algorithm for CAM solves the problem of future
compatibility, but it does not solve the problem of the installed base. The
following technique will permit a supplier to update the installed base to
CAM-compliant operation but not require users to reforamt their drives.

A.2.1 ROM-based

The one sector that is independent of the algorithm is sector 00. Under DOS
and many other Operating Systems this sector is used for the boot sector and
contains the Partition Table for a fixed disk.

If the Partition Table is structured according to MS DOS and IBM DOS
standards, partitions end on cylinder boundaries e.g.

Offset from start of Partition Table entry

00h Boot Indicator 80h
01h Beginning or start head 01h
02h beginning or start sector 01h
03h Beginning or start cylinder 00h
04h System indicator 04h
05h Ending head 07h
06h Ending sector 91h
07h Ending cylinder 7Ch
08h Starting sector (relative to beginning of disk)
0Ch Number of sectors in partition

The ending head 07h indicates a device with 8 heads (0 to 7). The ending
sector 91h contains 2 bits of high cylinder so it has to be masked to obtain
ending sector = 11h (17 decimal).

To verify these values calculate:

Logical Ending sector (from Beginning Head, Cylinder, and Sector)

and compare it to:

(Starting Sector + Number of Sectors in Partition)

This leaves Number of Cylinders as the one unresolved parameter. This is
obtained by:

Read Capacity divided by (Heads * Sectors).

All of this can be done by the BIOS in ROM or RAM. To be capable of booting
from any drive or cartridge regardless of the algorithm used to partition and
format the media, the BIOS would need to respond to int 13 function 8 with the
head, sector, and cylinder values obtained from this information. In addition,
the BIOS would need to use those values in its calculation from physical to
logical sectors.

Example of Pseudocode:

For each Drive
Read Boot Sector (LBA 0)
Validate The Signature at end of Sector (55AA)
Find Partion with largest Logical Start Cyl

If No Partitions found
Use Defaults
Exit

SECS = Ending Sector (from partition table)
Heads = Ending Head+1 (from partition table)

Logical_End = End_cyl * (End_head+1 * End_sector) +
(End_head * End_sector) + End_sector

Compare Logical_End to Starting_sec + Number_sec
If not equal
Use Defaults
Exit

Cyls = Capacity / (End_head+1 * End_sector)

A.2.2 RAM-based

Under DOS it is possible to modify the code of the boot sector to accomplish
bootability. Access to other partitions is dependent on the device driver to
do a translation.

This method is a patch just prior to jumping to code loaded in memory at
segment 00 offset 7C00h.

PUSH AX ; Save registers used in patch
PUSH DX
MOV AH,08 ; set function code = 8 get drive parameters
INT 13 ; do INT 13 call
INC DH ; inc head number to convert from zero based
MOV [7C1A],DH ; fix value of heads in BPB table
AND CL,3F ; Mask off non-sector information
MOV [7C18],CL ; fix value of sectors in BPB table
POP DX
POP AX ; Restore registers used in patch
JMP 7C00 ; jump to partition boot loader

01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 80 01
01C0 01 00 06 07 91 7C 11 00-00 00 57 52 01 00 00 00
01D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA

+------------+-------------------------+---------+---------+---------+
| 7C00 | 7C03 | 7C0B | 7C0D | 7C0E |
+------------+-------------------------+---------+---------+---------+
| | Name | Bytes/ |Sectors/ |Reserved |
| jump nop | I B M 4 . 0 | Sector | Cluster | Sectors |
+------------+-------------------------+---------+---------+---------+
| EB 3C 90 | 49 42 4D 20 20-34 2E 30 | 00 02 | 04 | 01 00 |
+------------+-------------------------+---------+---------+---------+

+---------+---------+---------+---------+---------+---------+---------+
| 7C10 | 7C11 | 7C13 | 7C15 | 7C16 | 7C18 | 7C1A |
+---------+---------+---------+---------+---------+---------+---------+
| # | # DIR | # Log'l | Media | # FAT | # | # |
| FATs | entries | Sectors | Descrip | Sectors | Sectors | Heads |
| 02 | 00 02 | 00 00 | F8 | 55 00 | 11 00 | 08 00 |
+---------+---------+---------+---------+---------+---------+---------+

Annex B: Target Application Examples

[ Mike Roche to prepare an update which is consistent with Section 10.]

The following are examples of how a Target Application can operate the Target
Mode capabilities defined in Section 9.

B.1 Initialization Sequence with Single Target CCB provided

- fill Target CCB with required info
targetCCB.callbackPointer = callback routine address
- fill Enable CCB with the required information
enableCCB.functionCode = function code for enable lun
enableCCB.targetid = the id of the target
enableCCB.targetLun = the lun to enable
enableCCB.group6VULength = vendor unique length for Group 6 (IF required)
enableCCB.group7VULength = vendor unique length for Group 7 (IF required)
enableCCB.targetCCBListLength = 0
enableCb.targetCCBPointer = &targetCCB
- Enable LUN (&enableCCB)
- EXIT

B.2 Initialization Sequence with Multiple Target CCBs provided

- fill Target CCB #1 with required info
target1CCB.callbackPointer = callback routine address #1
- fill Target CCB #2 with required info
target2CCB.callbackPointer = callback routine address #2
target2CCB.camStatus = request completed by target application
- fill Target CCB #n with required info
targetnCCB.callbackPointer = callback routine address #n
targetnCCB.camStatus = request completed by target application
- targetCCBList [0] = pointer to target1CCB
- targetCCBList [1] = pointer to target2CCB
- targetCCBList [n] = pointer to targetnCCB

NOTE: where targetCCBList is an array of pointers

- fill enable CCB with the required information
enableCCB.functionCode = function code for enable lun
enableCCB.targetid = the id of the target
enableCCB.targetLun = the lun to enable
enableCCB.group6VULength = vendor unique length for Group 6 (IF required)
enableCCB.group7VULength = vendor unique length for Group 7 (IF required)
enableCCB.targetCCBListLength = 4 * number of target CCBs
enableCb.targetCCBPointer = &targetCCBList
- Enable LUN (&enableCCB)
- EXIT

B.3 Application Sequence with single Execute Target I/O

- IF targetCCB.camStatus != SCSI CDB Received THEN EXIT, OR
callback from XPT/SIM
- process SCSI CDB field in targetCCB
- fill targetCCB with required information
targetCCB.functionCode = function code for execute target io
targetCCB.camFlags = data phase and status phase
targetCCB.dataBufferPointerLength = length of data
targetCCB.dataBufferPointer = pointer to data buffer
targetCCB.SCSIStatus = whatever status is appropriate
- Execute Target IO (&targetCCB)
/* return target CCB to pool */
- targetCCB.camStatus = request in progress
- EXIT

B.4 Application Sequence with multiple Execute Target I/O

- IF targetCCB.camStatus != SCSI CDB Received THEN EXIT, OR
callback from XPT/SIM
- process SCSI CDB field in targetCCB
- loop until all data transferred
fill targetCCB with required information
targetCCB.functionCode = function code for execute target io
targetCCB.camFlags = data phase
targetCCB.dataBufferPointerLength = length of data
targetCCB.dataBufferPointer = pointer to data buffer

IF (last data block)
targetCCB.camFlags = data phase AND status phase
targetCCB.SCSIStatus = whatever status is appropriate

Execute Target IO (&targetCCB)
- end loop
/* return target CCB to pool */
- targetCCB.camStatus = request in progress
- EXIT

Annex C: Unix OSD Data Structures

/* ---------------------------------------------------------------------- */

/* cam.h Version 1.05 Nov. 07, 1990 */

/* This file contains the definitions and data structures for the CAM
Subsystem interface. The contents of this file should match the
data structures and constants that were specified in the CAM document,
CAM/89-003 Rev 2.2.

*/

/* ---------------------------------------------------------------------- */

/* Defines for the XPT function codes, Table 8-2 in the CAM spec. */

/* Common function commands, 0x00 - 0x0F */
#define XPT_NOOP 0x00 /* Execute Nothing */
#define XPT_SCSI_IO 0x01 /* Execute the requested SCSI IO */
#define XPT_GDEV_TYPE 0x02 /* Get the device type information */
#define XPT_PATH_INQ 0x03 /* Path Inquiry */
#define XPT_REL_SIMQ 0x04 /* Release the SIM queue that is frozen */
#define XPT_SASYNC_CB 0x05 /* Set Async callback parameters */
#define XPT_SDEV_TYPE 0x06 /* Set the device type information */

/* XPT SCSI control functions, 0x10 - 0x1F */
#define XPT_ABORT 0x10 /* Abort the selected CCB */
#define XPT_RESET_BUS 0x11 /* Reset the SCSI bus */
#define XPT_RESET_DEV 0x12 /* Reset the SCSI devies, BDR */
#define XPT_TERM_IO 0x13 /* Terminate the I/O process */

/* Target mode commands, 0x30 - 0x3F */
#define XPT_EN_LUN 0x30 /* Enable LUN, Target mode support */
#define XPT_TARGET_IO 0x31 /* Execute the target IO request */

#define XPT_FUNC 0x7F /* TEMPLATE */
#define XPT_VUNIQUE 0x80 /* All the rest are vendor unique commands */

/* ---------------------------------------------------------------------- */

/* General allocation length defines for the CCB structures. */

#define IOCDBLEN 12 /* Space for the CDB bytes/pointer */
#define VUHBA 16 /* Vendor Unique HBA length */
#define SIM_ID 16 /* ASCII string len for SIM ID */
#define HBA_ID 16 /* ASCII string len for HBA ID */
#define SIM_PRIV 50 /* Length of SIM private data area */

/* Structure definitions for the CAM control blocks, CCB's for the
subsystem. */

/* Common CCB header definition. */
typedef struct ccb_header
{
struct ccb_header *my_addr; /* The address of this CCB */
u_short cam_ccb_len; /* Length of the entire CCB */
u_char cam_func_code; /* XPT function code */
u_char cam_status; /* Returned CAM subsystem status */
u_char cam_path_id; /* Path ID for the request */
u_char cam_target_id; /* Target device ID */
u_char cam_target_lun; /* Target LUN number */
u_long cam_flags; /* Flags for operation of the subsystem */
} CCB_HEADER;

/* Common SCSI functions. */

/* Union definition for the CDB space in the SCSI I/O request CCB */
typedef struct
{
u_char *cam_cdb_ptr; /* Pointer to the CDB bytes to send */
u_char cam_cdb_bytes[ IOCDBLEN ]; /* Area for the CDB to send */
} CDB_UN;

/* Get device type CCB */
typedef struct
{

CCB_HEADER cam_ch; /* Header information fields */
u_char cam_pd_type; /* Periph device type from the TLUN */
char *cam_inq_data; /* Ptr to the inquiry data space */
} CCB_GETDEV;

/* Path inquiry CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
u_long cam_feature_flags; /* Supported features flags field */
u_char cam_version_num; /* Version number for the SIM/HBA */
u_char cam_hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
u_char cam_target_sprt; /* Flags for target mode support */
u_char cam_hba_misc; /* Misc HBA feature flags */
u_char cam_vuhba_flags[ VUHBA ]; /* Vendor unique capabilities */
u_long cam_sim_priv; /* Size of SIM private data area */
u_long cam_async_flags; /* Event cap. for Async Callback */
u_char cam_hpath_id; /* Highest path ID in the subsystem */
u_char cam_initiator_id; /* ID of the HBA on the SCSI bus */
char cam_sim_vid[ SIM_ID ]; /* Vendor ID of the SIM */
char cam_hba_vid[ HBA_ID ]; /* Vendor ID of the HBA */
u_char *cam_osd_usage; /* Ptr for the OSD specific area */
} CCB_PATHINQ;

/* Release SIM Queue CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
} CCB_RELSIM;

/* SCSI I/O Request CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
u_char *cam_pdrv_ptr; /* Ptr used by the Peripheral driver */
CCB_HEADER *cam_next_ccb; /* Ptr to the next CCB for action */
void (*cam_cbfcnp)(); /* Callback on completion function */
u_char *cam_data_ptr; /* Pointer to the data buf/SG list */
u_long cam_dxfer_len; /* Data xfer length */
u_char *cam_sense_ptr; /* Pointer to the sense data buffer */
u_short cam_sense_len; /* Num of bytes in the Autosense buf */
u_char cam_cdb_len; /* Number of bytes for the CDB */
u_short cam_sglist_cnt; /* Num of scatter gather list entries */
u_char cam_scsi_status; /* Returned scsi device status */
long cam_resid; /* Transfer residual length: 2's comp */
CDB_UN cam_cdb_io; /* Union for CDB bytes/pointer */
u_long cam_timeout; /* Timeout value */
u_char *cam_msg_ptr; /* Pointer to the message buffer */
u_short cam_msgb_len; /* Num of bytes in the message buf */
u_short cam_vu_flags; /* Vendor unique flags */
u_char cam_tag_action; /* What to do for tag queuing */
u_char cam_sim_priv[ SIM_PRIV ]; /* SIM private data area */
} CCB_SCSIIO;

/* Set Async Callback CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
u_long cam_async_flags; /* Event enables for Callback resp */
void (*cam_async_func)(); /* Async Callback function address */
u_char *pdrv_buf; /* Buffer set aside by the Per. drv */
u_char pdrv_buf_len; /* The size of the buffer */
} CCB_SETASYNC;

/* Set device type CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
u_char cam_dev_type; /* Val for the dev type field in EDT */
} CCB_SETDEV;

/* SCSI Control Functions. */

/* Abort XPT Request CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
CCB_HEADER *cam_abort_ch; /* Pointer to the CCB to abort */
} CCB_ABORT;

/* Reset SCSI Bus CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
} CCB_RESETBUS;

/* Reset SCSI Device CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
} CCB_RESETDEV;

/* Terminate I/O Process Request CCB */
typedef struct
{
CCB_HEADER cam_ch; /* Header information fields */
CCB_HEADER *cam_termio_ch; /* Pointer to the CCB to terminate */
} CCB_TERMIO;

/* Target mode structures. */

typedef struct
{
CCB_HEADER cam_ch;
u_short cam_grp6_len; /* Group 6 VU CDB length */
u_short cam_grp7_len; /* Group 7 VU CDB length */
u_short cam_ccb_listcnt; /* Count of Target CCBs in the list */
u_char *cam_ccb_listptr; /* Pointer to the target CCB list */
} CCB_EN_LUN;

/* -------------------------------------------------------------------- */

/* Defines for the CAM status field in the CCB header. */

#define CAM_REQ_INPROG 0x00 /* CCB request is in progress */
#define CAM_REQ_CMP 0x01 /* CCB request completed w/out error */
#define CAM_REQ_ABORTED 0x02 /* CCB request aborted by the host */
#define CAM_UA_ABORT 0x03 /* Unable to Abort CCB request */
#define CAM_REQ_CMP_ERR 0x04 /* CCB request completed with an err */
#define CAM_BUSY 0x05 /* CAM subsystem is busy */
#define CAM_REQ_INVALID 0x06 /* CCB request is invalid */
#define CAM_PATH_INVALID 0x07 /* Path ID supplied is invalid */
#define CAM_DEV_NOT_THERE 0x08 /* SCSI device not installed/there */
#define CAM_UA_TERMIO 0x09 /* Unabel to Terminate I/O CCB req */
#define CAM_SEL_TIMEOUT 0x0A /* Target selection timeout */
#define CAM_CMD_TIMEOUT 0x0B /* Command timeout */
#define CAM_MSG_REJECT_REC 0x0D /* Message reject received */
#define CAM_SCSI_BUS_RESET 0x0E /* SCSI bus reset sent/received */
#define CAM_UNCOR_PARITY 0x0F /* Uncorrectable parity error occured */
#define CAM_AUTOSENSE_FAIL 0x10 /* Autosense: Request sense cmd fail */
#define CAM_NO_HBA 0x11 /* No HBA detected Error */
#define CAM_DATA_RUN_ERR 0x12 /* Data overrun/underrun error */
#define CAM_UNEXP_BUSFREE 0x13 /* Unexpected BUS free */
#define CAM_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
#define CAM_CCB_LEN_ERR 0x15 /* CCB length supplied is inadaquate */
#define CAM_PROVIDE_FAIL 0x16 /* Unable to provide requ. capability */
#define CAM_BDR_SENT 0x17 /* A SCSI BDR msg was sent to target */
#define CAM_REQ_TERMIO 0x18 /* CCB request terminated by the host */

#define CAM_LUN_INVALID 0x38 /* LUN supplied is invalid */
#define CAM_TID_INVALID 0x39 /* Target ID supplied is invalid */
#define CAM_FUNC_NOTAVAIL 0x3A /* The requ. func is not available */
#define CAM_NO_NEXUS 0x3B /* Nexus is not established */
#define CAM_IID_INVALID 0x3C /* The initiator ID is invalid */
#define CAM_CDB_RECVD 0x3E /* The SCSI CDB has been received */
#define CAM_SCSI_BUSY 0x3F /* SCSI bus busy */

#define CAM_SIM_QFRZN 0x40 /* The SIM queue is frozen w/this err */
#define CAM_AUTOSNS_VALID 0x80 /* Autosense data valid for targit */

/* -------------------------------------------------------------------- */

/* Defines for the CAM flags field in the CCB header. */

#define CAM_DIR_RESV 0x00000000 /* Data direction (00: reserved) */
#define CAM_DIR_IN 0x00000040 /* Data direction (01: DATA IN) */
#define CAM_DIR_OUT 0x00000080 /* Data direction (10: DATA OUT) */
#define CAM_DIR_NONE 0x000000C0 /* Data directino (11: no data) */
#define CAM_DIS_AUTOSENSE 0x00000020 /* Disable auto sence feature */
#define CAM_SCATTER_VALID 0x00000010 /* Scatter/gather list is valie */
#define CAM_DIS_CALLBACK 0x00000008 /* Disable callback feature */
#define CAM_CDB_LINKED 0x00000004 /* The CCB contains a linked CDB */
#define CAM_QUEUE_ENABLE 0x00000002 /* SIM queue actions are enabled */
#define CAM_CDB_POINTER 0x00000001 /* The CDB field contains a pointer */

#define CAM_DIS_DISCONNECT 0x00008000 /* Disable disconnect */
#define CAM_INITIATE_SYNC 0x00004000 /* Attempt Sync data xfer, and SDTR */
#define CAM_DIS_SYNC 0x00002000 /* Disable sync, go to async */
#define CAM_SIM_QHEAD 0x00001000 /* Place CCB at the head of SIM Q */
#define CAM_SIM_QFREEZE 0x00000800 /* Return the SIM Q to frozen state */

#define CAM_CDB_PHYS 0x00400000 /* CDB pointer is physical */
#define CAM_DATA_PHYS 0x00200000 /* SG/Buffer data ptrs are physical */
#define CAM_SNS_BUF_PHYS 0x00100000 /* Autosense data ptr is physical */
#define CAM_MSG_BUF_PHYS 0x00080000 /* Message buffer ptr is physical */
#define CAM_NXT_CCB_PHYS 0x00040000 /* Next CCB pointer is physical */
#define CAM_CALLBCK_PHYS 0x00020000 /* Callback func ptr is physical */

#define CAM_DATAB_VALID 0x80000000 /* Data buffer valid */
#define CAM_STATUS_VALID 0x40000000 /* Status buffer valid */
#define CAM_MSGB_VALID 0x20000000 /* Message buffer valid */
#define CAM_TGT_PHASE_MODE 0x08000000 /* The SIM will run in phase mode */
#define CAM_TGT_CCB_AVAIL 0x04000000 /* Target CCB available */
#define CAM_DIS_AUTODISC 0x02000000 /* Disable autodisconnect */
#define CAM_DIS_AUTOSRP 0x01000000 /* Disable autosave/restore ptrs */

/* ---------------------------------------------------------------------- */

/* Defines for the SIM/HBA queue actions. These value are used in the
SCSI I/O CCB, for the queue action field. [These values should match the
defines from some other include file for the SCSI message phases. We may
not need these definitions here. ] */

#define CAM_SIMPLE_QTAG 0x20 /* Tag for a simple queue */
#define CAM_HEAD_QTAG 0x21 /* Tag for head of queue */
#define CAM_ORDERED_QTAG 0x22 /* Tag for ordered queue */

/* ---------------------------------------------------------------------- */

/* Defines for the timeout field in the SCSI I/O CCB. At this time a value
of 0xF-F indicates a infinite timeout. A value of 0x0-0 indicates that the
SIM's default timeout can take effect. */

#define CAM_TIME_DEFAULT 0x00000000 /* Use SIM default value */
#define CAM_TIME_INFINITY 0xFFFFFFFF /* Infinite timout for I/O */

/* ---------------------------------------------------------------------- */

/* Defines for the Path Inquiry CCB fields. */

#define CAM_VERSION 0x22 /* Binary value for the current ver */

#define PI_MDP_ABLE 0x80 /* Supports MDP message */
#define PI_WIDE_32 0x40 /* Supports 32 bit wide SCSI */
#define PI_WIDE_16 0x20 /* Supports 16 bit wide SCSI */
#define PI_SDTR_ABLE 0x10 /* Supports SDTR message */
#define PI_LINKED_CDB 0x08 /* Supports linked CDBs */
#define PI_TAG_ABLE 0x02 /* Supports tag queue message */
#define PI_SOFT_RST 0x01 /* Supports soft reset */

#define PIT_PROCESSOR 0x80 /* Target mode processor mode */
#define PIT_PHASE 0x40 /* Target mode phase cog. mode */

#define PIM_SCANHILO 0x80 /* Bus scans from ID 7 to ID 0 */
#define PIM_NOREMOVE 0x40 /* Removable dev not included in scan */

/* -------------------------------------------------------------------- */

/* Defines for Asynchronous Callback CCB fields. */

#define AC_FOUND_DEVICES 0x80 /* During a rescan new devies found */
#define AC_SIM_DEREGISTER 0x40 /* A loaded SIM has de-registered */
#define AC_SIM_REGISTER 0x20 /* A loaded SIM has registered */
#define AC_SENT_BDR 0x10 /* A BDR message was sent to target */
#define AC_SCSI_AEN 0x08 /* A SCSI AEN has been received */
#define AC_UNSOL_RESEL 0x02 /* A unsolicited reselection occured */
#define AC_BUS_RESET 0x01 /* A SCSI bus RESET occured */

/* ---------------------------------------------------------------------- */

/* Typedef for a scatter/gather list element. */

typedef struct
{
u_long cam_sg_address; /* Scatter/Gather address */
u_long cam_sg_count; /* Scatter/Gather count */
} SG_ELEM;

/* ---------------------------------------------------------------------- */

/* Unix OSD defines and data structures. */

#define INQLEN 36 /* Inquiry string length to store. */

/* General Union for Kernal Space allocation. Contains all the possible CCB
structures. This union should never be used for manipulating CCB's its only
use is for the allocation and deallocation of raw CCB space. */

typedef union
{
CCB_SCSIIO csio; /* Please keep this first, for debug/print
*/
CCB_GETDEV cgd;
CCB_PATHINQ cpi;
CCB_RELSIM crs;
CCB_SETASYNC csa;
CCB_SETDEV csd;
CCB_ABORT cab;
CCB_RESETBUS crb;
CCB_RESETDEV crd;
CCB_TERMIO ctio;
} CCB_SIZE_UNION;

/* The typedef for the Async callback information. This structure is used to
store the supplied info from the Set Async Callback CCB, in the EDT table. */

typedef struct
{
u_short cam_event_enable; /* Event enables for Callback resp */
void (*cam_async_func)(); /* Async Callback function address */
u_long cam_async_blen; /* Length of "information" buffer */
u_char *cam_async_ptr; /* Address for the "information */
} ASYNC_INFO;

/* The CAM_SIM_ENTRY definition is used to define the entry points for
the SIMs contained in the SCSI CAM subsystem. Each SIM file will
contain a declaration for it's entry. The address for this entry will
be stored in the cam_conftbl[] array along will all the other SIM
entries. */

typedef struct
{
void (*sim_init)(); /* Pointer to the SIM init routine */
void (*sim_action)(); /* Pointer to the SIM CCB go routine */
} CAM_SIM_ENTRY;

/* The CAM EDT table, this structure contains the device information for
all the devices, SCSI ID and LUN, for all the SCSI busses in the system. */

typedef struct
{
long cam_tlun_found; /* Flag for the existence of the target/LUN */
ASYNC_INFO cam_ainfo; /* Async callback info for this B/T/L */
u_long cam_owner_tag; /* Tag for the peripheral driver's ownership */
char cam_inq_data[ INQLEN ];/* storage for the inquiry data */
} CAM_EDT_ENTRY;

/* ---------------------------------------------------------------------- */


Annex D: Operating System Vendor Documentation

D.1 Documentation

The following lists those operating system vendors which have agreed to supply
information to third party vendors on the support of SCSI devices. This is not
a complete list of all vendors that support CAM.


[ This is a partial list and as it is the addresses of the CAM members
it is unlikely to be the right address to contact for information
and documentation. Would those listed please advise correct addresses
and department and advise the phone number and fax number? Also, any
that I should have included, please add yourselves to the list by
sending Dal a fax at 408-867-2115. ]


AT&T BELL LABS MICROSOFT
1100 E Warrenville Rd POB 97017
Naperville Redmond
IL 60566 WA 98073


INTERACTIVE SYSTEMS NOVELL
2401 Colorado Ave 122 E 1700 S
Santa Monica Provo
CA 90404 UT 84606


DIGITAL EQUIPMENT SUN MICROSYSTEMS
110 Spit Brook Rd 2550 Garcia Ave Bdg 15
ZKO3-3/T79 Mountain View
Nashua CA 94043
NH 03062


IBM
MS 5226
PO Box 1328
Boca Raton
FL 33429

D.2 DOS Background

During the development of XPT/SIM by the CAM Committee, several approaches to
support SCSI under DOS were implemented by vendors. Some were proprietary and
required licensing agreements while others were parochial. Of the latter, some
provided documentation upon request in order to encourage their adoption.

Subsequent to the XPT/SIM being defined across multiple operating systems, IBM
made information available on the attachment of SCSI devices using the 4Bh/80h
interrupt, which assumes that there is an SCB (Subsystem Control Block) data
structure. SCBs are unlike CCBs.

The IBM introduction created a de facto implementation, and IBM has provided a
software license at no charge to those companies which write peripheral
drivers to support SCBs. The SCBs and their method of operation are defined in
Technical Reference Manuals which are available from IBM.

The CAM approach is oriented towards using the CCB data structure to provide a
common approach across multiple operating systems. Although it may have been
possible to use SCBs to provide this capability, full technical information
was not provided early enough in the development cycle.



  3 Responses to “Category : HD Utilities
Archive   : SCSI-2.ZIP
Filename : CAM-R23.TXT

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/