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.6 January 14, 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. Preliminary draft proposed American National Standard This is an internal working document of X3T9, a Technical Committee of Accredited Standards Committee X3. As such, this is not a completed standard, but is considered to be technically complete by the X3T9.n Task Group. The contents of this document may be modified as a result of comments received during the review process. 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 is the version of CAM XPT/SIM that was forwarded in August 1991 from X3T9.2 to X3T9 for further processing as an American National Standard. X3T9 has authorized a letter ballot on forwarding this document to X3 for a public review period. 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 and Conformance 2 2.1 References 2 2.2 Conformance 2 3. General Description 2 3.1 Environment 3 3.2 Peripheral Driver Functions 4 3.3 XPT Functions 5 3.4 SIM Functions 5 4. Definitions and Conventions 5 4.1 Definitions 5 4.2 Conventions 6 5. Background 7 5.1 Software 7 5.2 CAM (Common Access Method) 7 5.2.1 XPT (Transport) 7 5.2.2 SIM (SCSI Interface Module) 7 5.2.3 CCB (CAM Control Block) 8 5.2.4 OSD (Operating System Dependent) 8 5.3 Principles of Operation 8 5.4 Requirements 9 6. Transport 9 6.1 Accessing the XPT 9 6.2 Initialization 10 6.3 CCB Completion 10 6.3.1 Completion of Immediate CCB 10 6.3.2 Completion of Queued CCB 10 6.4 SCSI Request Queues 10 6.4.1 The Target/LUN and the Peripheral Driver 11 6.4.2 The SIM 11 6.4.3 SIM Queuing 11 6.4.3.1 SIM Queue Priority 11 6.4.3.2 Tag Recognition 11 6.4.3.3 Error conditions and Queues within the Subsystem 12 6.5 SIM Handling of SCSI Resets 12 6.6 Asynchronous Callback 13 6.7 Autosense 15 6.8 Loadable Modules 15 7. OSD (Operating System Dependent) Operation 16 7.1 UNIX Operating System 16 7.1.1 Initialization 17 7.1.2 Accessing the XPT 17 7.1.2.1 From the Peripheral Driver 17 7.1.2.2 From the SIM 18 7.1.3 Callback on Completion 18 7.1.4 Pointer Definition in the UNIX Environment 18 7.1.5 Request Mapping Information 18 7.1.6 XPT Interface 19 7.1.6.1 Functions for Peripheral Driver Support 19 7.1.6.2 Functions for SIM Module Support 19 7.1.7 SIM Interface 20 7.2 Novell Operating System 20 7.2.1 Initialization 20 7.2.2 SIM and peripheral driver unloading 21 7.2.3 Accessing the XPT 22 7.2.4 Hardware Registration 22 7.2.5 Miscellaneous 22 7.3 DOS (Disk Operating System) 23 7.3.1 Initialization 23 7.3.1.1 Multiple XPTs 23 7.3.1.2 Device Table Handling 24 7.3.2 Accessing the XPT 24 7.3.2.1 Testing for the presence of the XPT/SIM 24 7.3.2.2 Sending a CCB to the XPT 25 7.3.3 Callback on Completion 26 7.3.4 Asynchronous Callbacks 26 7.3.5 Pointer Definition 26 8. CAM Control Blocks 27 8.1 CCB Header 28 8.1.1 Address of this CCB 28 8.1.2 CAM Control Block Length 28 8.1.3 XPT Function Code 28 8.1.4 CAM Status 29 8.1.5 Path ID 29 8.1.6 CAM Flags 29 8.2 Function Codes 29 8.2.1 Get Device Type 29 8.2.2 Path Inquiry 30 8.2.3 Release SIM Queue 33 8.2.4 Set Async Callback 33 8.2.5 Set Device Type 34 8.3 SCSI Control Functions 35 8.3.1 Abort SCSI Command 35 8.3.2 Reset SCSI Bus 36 8.3.3 Reset SCSI Device 36 8.3.4 Terminate I/O Process Request 37 9. Execute SCSI I/O 37 9.1 CAM Control Block to Request I/O 37 9.1.1 Callback on Completion 38 9.1.2 CAM Control Block Length 38 9.1.3 CAM Flags 38 9.1.3.1 Byte 1 Bits 39 9.1.3.2 Byte 2 Bits 40 9.1.3.3 Byte 3 Bits 41 9.1.3.4 Byte 4 Bits 41 9.1.4 CAM Status 41 9.1.5 CDB 43 9.1.6 CDB Length 43 9.1.7 Data Transfer Length 43 9.1.8 Function Code 44 9.1.9 LUN 44 9.1.10 Message Buffer Length (Target-only) 44 9.1.11 Message Buffer Pointer (Target-only) 44 9.1.12 Next CCB Pointer 44 9.1.13 Number of Scatter/Gather entries 44 9.1.14 Path ID 44 9.1.15 Peripheral Driver Pointer 44 9.1.16 Private Data 44 9.1.17 Request Mapping Information (OSD) 44 9.1.18 Residual Length 45 9.1.19 SCSI Status 45 9.1.20 Sense Info Buffer Length 45 9.1.21 Sense Info Buffer Pointer 45 9.1.22 SG List/Data Buffer Pointer 45 9.1.23 Tagged Queue Action 45 9.1.24 Target ID 45 9.1.25 Timeout Value 45 9.1.26 VU Flags 46 9.2 Command Linking 46 10. Target Mode (Optional) 46 10.1 Enable LUN 47 10.2 Phase Cognizant Mode 49 10.2.1 Target Operation of the HBA 49 10.2.2 Execute Target I/O 50 10.3 Processor Mode 51 10.3.1 CCB Acceptance 51 10.3.2 Target Operation of the HBA 51 11. HBA Engines 52 11.1 Engine Inquiry 52 11.2 Execute Engine Request (Optional) 53 FIGURES FIGURE 3-1 CAM ENVIRONMENT MODEL 4 TABLES TABLE 6-1 ASYNC CALLBACK OPCODE DATA REQUIREMENTS 14 TABLE 8-1 CAM CONTROL BLOCK HEADER 27 TABLE 8-2 SUPPORT OF SCSI MESSAGES 28 TABLE 8-3 XPT FUNCTION CODES 29 TABLE 8-4 GET DEVICE TYPE CCB 30 TABLE 8-5 PATH INQUIRY CCB - Part 1 of 2 31 TABLE 8-5 PATH INQUIRY CCB - Part 2 of 2 32 TABLE 8-6 RELEASE SIM QUEUE 33 TABLE 8-7 SET ASYNC CALLBACK CCB 34 TABLE 8-8 SET DEVICE TYPE CCB 35 TABLE 8-9 ABORT SCSI COMMAND CCB 35 TABLE 8-10 RESET SCSI BUS CCB 36 TABLE 8-11 RESET SCSI DEVICE CCB 36 TABLE 8-12 TERMINATE I/O PROCESS REQUEST CCB 37 TABLE 9-1 SCSI I/O REQUEST CCB 38 TABLE 9-2 CAM FLAGS (OSD) 39 TABLE 9-3 SCATTER GATHER LIST 40 TABLE 9-4 CAM STATUS 42 TABLE 10-1 ENABLE LUN CCB 47 TABLE 10-2 TARGET CCB LIST 47 TABLE 11-1 ENGINE INQUIRY CCB 53 TABLE 11-2 EXECUTE ENGINE REQUEST CCB 54 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 and Conformance 2.1 References ISO DIS 10288 (ANSI X3.131-1991) SCSI-2, Enhanced Small Computer Systems Interface 2.2 Conformance An implementation claiming conformance to the XPT for a specified operating system and language environment shall: - provide all the XPT functions and services specified in this standard. - correctly interoperate with any conforming SIM for the specified environment. - provide the necessary interface specifications that a conforming SIM will be required to interface with the XPT. An implementation claiming conformance to the SIM for a specified operating system and language environment shall: - provide all the SIM functions and services specified in this standard. - correctly interoperate with any conforming XPT for the specified environment. - provide the necessary interface specifications that a conforming XPT will be required to interface with SIMs. A conforming implementation shall execute all function codes as required by this standard, and in response to these codes shall only return specified status and return codes. A conforming implementation may provide additional capabilities via Vendor Unique function codes. Claims of conformance to this standard shall state: - whether conformance is claimed with the XPT or the SIM or both. - which operating systems and environments are supported. - whether the optional capabilities of target mode or executing engines are supported. 3. General Description The application environment for CAM is any computer addressing a SCSI peripheral through a protocol chip on a motherboard 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. The XPT function may be provided by the operating system, or 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. An immediate CCB provides valid completion status when the call to xpt_action () returns e.g. Path Inquiry. A queued CCB provides valid completion status when the Completion Callback routine is called. 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 SCSI (Small Computer Systems Interface): The I/O interface which this standard is designed to support. 4.1.13 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.14 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.15 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. There are places in the standard where programming language is used to define or express a concept in order to assist the reader. These are not copyrighted program steps, and implementors are encouraged to use the code wherever it suits the application. 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 loaded as a loadable device driver. SIMs are also implemented as loadable device drivers. 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 task is handled by the XPT logical entity. The XPT is implemented differently under each operating system, but the logical functionality is the same for all operating systems. Once one or more of the SIMs are loaded, the peripheral drivers integrate each type of SCSI device into the OS through XPT, independent of the installed HBA hardware. 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-1991 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 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 responsible for routing a CCB to the SIM indicated by the Path ID field. 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. 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 CCB Completion 6.3.1 Completion of Immediate CCB All CCBs except the Execute SCSI CCB and Execute Engine Request are completed when the CCB function returns. 6.3.2 Completion of Queued CCB Callback on Completion refers to the XPT/SIM making a call to the routine addressed by the Callback on Completion pointer in an Execute SCSI 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 individually, 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-1991) 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, unless the SIM Queue Freeze Disable bit has been set in the CCB. If the SIM Queue Freeze Disable bit is set, the queue is not frozen and CCB execution continues from the SIM queue. In the event that a SIM encounters an error condition which cannot be associated with a CCB, the SIM shall not freeze the queue. NOTE: The SIM should attempt to continue operation. 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/SIM 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. The peripheral driver is required to return from the callback. 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 change its Asynchronous Callback for a particular SCSI device by issuing the Set Asynchronous Callback CCB with the Events field set to the replacement value and the Callback pointer containing the original registered value. 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 original registered value, A peripheral driver changes its Callback Pointer by de-registering and then following the registration procedure. The XPT shall pass all Asynchonous Event Notification requests to the SIM in addition to performing XPT table maintenance related to the Asynchonous Event Notification request. This allows the SIM to perform its own Asynchronous Callbacks to peripheral drivers, foregoing the available (and required) XPT services. The callback interface to the peripheral driver is the same whether the Asynchronous Callback is from the XPT or directly from the SIM. 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) Alternatively, the SIM shall call the peripheral driver directly. 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, LUN and event opcode information available directly to the SIM or to the XPT from the xpt_async() call, the XPT or SIM scans its internal tables looking for "matches" with the registered Asynchronous Callback peripheral drivers (see 8.2.4). When a match is found, either exactly or with a wild card of "-1," the XPT or SIM 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. void (*cam_async_func) (opcode,path_id,target_id,lun,buffer_ptr,data_cnt) The buffer_ptr value shall be the peripheral driver's buffer. The data_cnt value shall be what the XPT has to transfer from the SIM's buffer up to 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, Path ID Registered and Path ID De- Registered. 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 | | Path ID Registered | 0x0020 | XPT ID | n/a | n/a | Min. 1 | | Path ID De-Registered | 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-1991). The Path ID Registered and Path ID De-Registered data requirements are a minimum of 1 byte. This byte contains the Path ID to access SCSI. This Path ID is different from the path_id argument. The path_id argument contains the unique XPT ID of 0xFF. The XPT ID is the ID used by the peripheral driver to register for async notification. The New Devices Found opcode shall be returned whenever the XPT/SIM issues an Inquiry which detects that a device is attached which was not previously found e.g. a printer powered on after system initialization was completed. NOTE: Some devices provide minimal information at power-on and cannot provide complete Inquiry information until after some delay. An XPT/SIM may scan the bus after initialization to update its tables with the complete Inquiry information. If there is valid data placed in the peripheral driver's 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 status is reported in the SCSI Status field. 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 (Path IDs) 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 have the SIM- supported HBAs registered to addressable Path IDs. 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 Path ID (SCSI bus) 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. The Success of a function is reported in a CAM Status of Request Completed without error. The Failure of a function is reported in any other CAM Status except Command in progress. 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, 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. 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. - The xpt_ccb_alloc() routine shall return a null if memory resources are not immediately available. 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 "long (* 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 should not be used. Peripheral drivers should not poll the CAM Status field. 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 Intel 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 CAM Status 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. 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 CAM Status. 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 CAM Status 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) void 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. 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 CAM Status 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 CAM Status 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 loaded after the operating system is initialized 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 loaded. 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 load if it makes references to a label it cannot resolve, the order in which the NLMs load is important. The XPT module exports four entry points when it is loaded, and both peripheral drivers and SIM modules make references to them. The XPT shall be loaded first, after which either peripheral drivers or SIMs may be loaded. +--------------+ | 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 SCSI 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 SIM and peripheral driver unloading Before a SIM unloads, 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 further peripheral driver requests on this path shall return CAM Status of Invalid Path ID. Before a peripheral driver unloads, 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 unloaded. 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 unloaded. 7.2.3 Accessing the XPT NetWare 386 allows an NLM to export functions which NLMs loaded 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 by the SIM to register a SCSI bus with the XPT and obtain a Path ID for the SCSI bus. - xpt_bus_deregister () is used to de-register the passed Path ID and associated SCSI bus. 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 for 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 data structure 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. 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 e.g. 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 e.g. On entry: ES:BX = address of the CCB AX = 8100h On return: AH = 0 if successful = any other value if an error occurred 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, all 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. 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| +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 shall be consistent between vendors i.e. the binary offset shall be the same for every field. The binary contents of fields may vary according to the memory addressing protocol of the processor which is operating. The 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 Address of this CCB Pointer containing the Physical address of this CCB. 8.1.2 CAM Control Block Length See 9.1.3 8.1.3 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 | | 07h | Scan SCSI Bus | |08-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.4 CAM Status See 9.1.4 8.1.5 Connect ID The Connect ID consists of 4 separate fields, of which the first is reserved. - Path ID: See 9.1.14. - Target ID: See 9.1.24 - LUN: See 9.1.9 8.1.6 CAM Flags The CAM Flags qualify the Function to be executed, and vary by Function Code. See 9.1.3. 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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/SIM (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/SIM 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, the Highest Path ID Assigned 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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. 31h = 3.1 | | 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. If the Path ID is FFh (that of the XPT), then only the highest Path ID Assigned field is valid on CCB completion. If no Path IDs exist, i.e. no SCSI buses are registered, then the Highest Path ID assigned shall be FFh, the ID 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 Scan SCSI Bus This function is executed to get information on the installed devices on the identified path. The Target and LUN fields are ignored. The XPT/SIM shall scan each Target/LUN address on the SCSI bus and update it's tables with the Inquiry information provided by each Target/LUN that responds. TABLE 8-4 GET DEVICE TYPE CCB +----+---+ |Size|Dir| Get Device Type +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 1 | O | Path ID | | 1 | O | Target ID | | 1 | O | LUN | | 4 | O | CAM Flags (OSD) | +----+---+--------------------------------------+ The information on attached SCSI devices is gathered at power on by the XPT/SIM. This function is provided to force an update of the table contents and it is not recommended that it be used often as execution can take a long time. Any new devices detected during the scan shall generate Asynchronous Callbacks to peripheral drivers registered for New Devices Found. This function shall return non-zero CAM Status. - CAM Status of Request Completed Without Error indicates that the devices have been scanned and the table updated. - 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.5 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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.6 Set Device Type This function requires the XPT/SIM 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 XPT/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 SCSI Command This function requests that a SCSI command 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 SCSI COMMAND CCB +----+---+ |Size|Dir| Abort SCSI Command +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 Abort operation shall always succeed. 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 a SCSI 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 | | 1 | I | Autosense Residual Length | | 2 | | reserved (OSD) | | 4 | I | Residual Length | | 12 | O | CDB | | 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 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.2 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.3 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 | SIM Queue Freeze Disable | | | 1 | Engine Synchronize | | | 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 # These bits are mutually exclusive 9.1.3.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.3.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. If the SIM is in the midst of an extended I/O operation it may attempt to disconnect from the current Target/LUN in order to service this CCB. 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 conjunction with the SIM Queue Priority bit and the Release SIM Queue command. 2 When SIM Queue Freeze Disable=1 the SIM Queue Freeze mechanism shall be disabled i.e. the SIM Queue shall not be frozen for the Target/LUN addressed in this CCB in the event of a non-complete CAM status. NOTE: This capability relieves the peripheral driver from having to unlock the SIM Queue, thus simplifying peripheral drivers. 1 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.3.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.3.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.4 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. Prior to reporting this status the SIM is responsible for ensuring the command is no longer active in the target. - 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-1991 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 message 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.5 CDB This field either contains the SCSI CDB (Command Descriptor Block), or a pointer to the CDB, to be dispatched. 9.1.6 CDB Length This field contains the length in bytes of the CDB. 9.1.7 Data Transfer Length This field contains the length in bytes of the data to be transferred. 9.1.8 Function Code See 8.1.2. 9.1.9 LUN This field identifies the SCSI LUN to which this CCB is being directed. 9.1.10 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.11 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.12 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.13 Number of Scatter/Gather entries This field contains the number of entries in the SG List. 9.1.14 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.15 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.16 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.17 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.18 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.19 SCSI Status This field contains the status byte returned by the SCSI target after the command is completed. 9.1.20 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.21 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.22 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.23 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-1991. 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.24 Target ID This field identifies the SCSI target which is to be selected for execution of the CCB request. 9.1.25 Timeout Value This field contains the maximum period in seconds that an issued SCSI command 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.26 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 +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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-1991. 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 gather information about the data processing engines installed in the HBA hardware. TABLE 11-1 ENGINE INQUIRY CCB +----+---+ |Size|Dir| Engine Inquiry +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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 Algorithm 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 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 In 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. The Execute Engine Request CCB activates the engine to perform the requested function. Some functions change the data size e.g. a compression engine reduces the size of data prior to transmission over SCSI. TABLE 11-2 EXECUTE ENGINE REQUEST CCB +----+---+ |Size|Dir| Execute Engine Request +----+---+--------------------------------------+ | 4 | O | Address of this CCB | | 2 | O | CAM Control Block Length | | 1 | O | Function Code | | 1 | I | CAM Status | | | | Connect ID | | 1 | | reserved | | 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) | | 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 In Progress 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 (Informative) 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 techniques are an example of how a supplier can update the installed base to CAM-compliant operation but not require users to reformat their drives. These techniques are suitable for support of more than one device, as long as the number of sectors per track is the same on all devices. 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 (Informative) The following are examples of how a Target Application can operate the Target Mode capabilities defined in Section 10. B.1 Phase-Cognizant Examples B.1.1 Initialization Sequence with Single Target CCB Provided - fill Target CCB #1 with required info targetCCB1.callbackPointer = callback routine address #1 - targetCCBList [0] = pointer to target1CCB 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 = 1 enableCb.targetCCBPointer = &targetCCBList - Enable LUN (&enableCCB) - EXIT B.1.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 = n, where n is the number of target CCBs enableCb.targetCCBPointer = &targetCCBList - Enable LUN (&enableCCB) - EXIT B.1.3 Application Sequence with Single Execute Target I/O - loop until target1CCB.camFlags TargetCCB Available bit is reset, OR callback routine called from XPT/SIM - process Scsi CDB field in target1CCB - fill target1CCB with required information target1CCB.functionCode = function code for execute target io target1CCB.camFlags = data phase and status phase target1CCB.dataBufferPointerLength = length of data target1CCB.dataBufferPointer = pointer to data buffer target1CCB.scsiStatus = whatever status is appropriate - Execute Target I/O (&targetCCB) /* return target CCB to pool */ - set target1CCB.camFlags TargetCCB Available bit B.1.4 Application Sequence with Multiple Execute Target I/O - loop until targetxCCB.camFlags TargetCCB Available bit is reset, OR callback routine called from XPT/SIM (where x is one of the targetCCBs provided in targetCCBList) - process Scsi CDB field in targetxCCB - loop until all data transferred fill targetxCCB with required information targetxCCB.functionCode = function code for execute target io targetxCCB.camFlags = data phase targetxCCB.dataBufferPointerLength = length of data targetxCCB.dataBufferPointer = pointer to data buffer IF (last data block) targetxCCB.camFlags = data phase AND status phase targetxCCB.scsiStatus = whatever status is appropriate Execute Target I/O (&targetxCCB) - end loop /* return target CCB to pool */ - set target1CCB.camFlags TargetCCB Available bit B.2 Processor Mode Examples B.2.1 Initialization Sequence with Single Target CCB Provided - fill Target CCB #1 with required info target1CCB.callbackPointer = callback routine address #1 target1CCB.dataBufferPointerLength = length of data target1CCB.dataBufferPointer = pointer to data buffer target1CCB.camFlags = data phase - fill Target CCB #2 with required info target2CCB.callbackPointer = NULL target2CCB.dataBufferPointerLength = length of inquiry data target2CCB.dataBufferPointer = pointer to inquiry data buffer, which contains the necessary inquiry information target2CCB.camFlags = data phase - targetCCBList [0] = pointer to target1CCB - targetCCBList [1] = pointer to target2CCB 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 = 2 enableCb.targetCCBPointer = &targetCCBList - Enable LUN (&enableCCB) - EXIT B.2.2 Initialization Sequence with Multiple Target CCBs Provided - fill Target CCB #1 with required info target1CCB.callbackPointer = callback routine address #1 target1CCB.dataBufferPointerLength = length of data target1CCB.dataBufferPointer = pointer to data buffer targetxCCB.camFlags = data phase - fill Target CCB #2 with required info target2CCB.callbackPointer = callback routine address #2 target2CCB.dataBufferPointerLength = length of data target2CCB.dataBufferPointer = pointer to data buffer target2CCB.camFlags = data phase - fill Target CCB #n with required info targetnCCB.callbackPointer = NULL targetnCCB.functionCode = function code for execute target io targetnCCB.dataBufferPointerLength = length of inquiry data targetnCCB.dataBufferPointer = pointer to inquiry data buffer, which contains the necessary inquiry information targetnCCB.camFlags = data phase - 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 = n, where n is the number of target CCBs enableCb.targetCCBPointer = &targetCCBList - Enable LUN (&enableCCB) - EXIT B.2.3 Application Sequence - loop until targetxCCB.camFlags TargetCCB Available bit is reset, OR callback routine called from XPT/SIM - any processing of targetxCCB necessary (i.e. failure, check conditions, CAM status, etc.) /* return target CCB to pool */ - set targetxCCB.camFlags TargetCCB Available bit Annex C: Unix OSD Data Structures (Informative) /* This file contains the definitions and data structures for the CAM Subsystem interface. The contents of this file should match what data structures and constants that are specified in the CAM document, X3T9.2/90-186 Rev 2.3. */ /* ---------------------------------------------------------------------- */ /* 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 device, BDR */ #define XPT_TERM_IO 0x13 /* Terminate the I/O process */ /* HBA engine commands, 0x20 - 0x2F */ #define XPT_ENG_INQ 0x20 /* HBA engine inquiry */ #define XPT_ENG_EXEC 0x21 /* HBA execute engine request */ /* 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 14 /* 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_hrsvd0; /* Reserved field, for alignment */ 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 union { 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 */ char *cam_inq_data; /* Ptr to the inquiry data space */ u_char cam_pd_type; /* Periph device type from the TLUN */ } 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_short cam_hba_eng_cnt; /* HBA engine count */ 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 */ u_char cam_prsvd0; /* Reserved field, for alignment */ u_char cam_prsvd1; /* Reserved field, for alignment */ 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 */ u_char *cam_req_map; /* Ptr for mapping info on the Req. */ 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_char 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_long cam_osd_rsvd0; /* OSD Reserved field, for alignment */ u_char cam_scsi_status; /* Returned scsi device status */ u_char cam_osd_rsvd1[3]; /* OSD Reserved field, for alignment */ 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_iorsvd0[3]; /* Reserved field, for alignment */ 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; /* Header information fields */ u_short cam_grp6_len; /* Group 6 VU CDB length */ u_short cam_grp7_len; /* Group 7 VU CDB length */ u_char *cam_ccb_listptr; /* Pointer to the target CCB list */ u_short cam_ccb_listcnt; /* Count of Target CCBs in the list */ } CCB_EN_LUN; /* HBA engine structures. */ typedef struct { CCB_HEADER cam_ch; /* Header information fields */ u_short cam_eng_num; /* The number for this inquiry */ u_char cam_eng_type; /* Returned engine type */ u_char cam_eng_algo; /* Returned algorithm type */ u_long cam_eng_memory; /* Returned engine memory size */ } CCB_ENG_INQ; typedef struct /* NOTE: must match SCSIIO size */ { CCB_HEADER cam_ch; /* Header information fields */ u_char *cam_pdrv_ptr; /* Ptr used by the Peripheral driver */ u_long cam_engrsvd0; /* Reserved field, for alignment */ u_char *cam_req_map; /* Ptr for mapping info on the Req. */ 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_engdata_ptr; /* Pointer to the engine buffer data */ u_char cam_engrsvd1; /* Reserved field, for alignment */ u_char cam_engrsvd2; /* Reserved field, for alignment */ u_short cam_sglist_cnt; /* Num of scatter gather list entries */ u_long cam_dmax_len; /* Destination data maximum length */ u_long cam_dest_len; /* Destination data length */ long cam_src_resid; /* Source residual length: 2's comp */ u_char cam_engrsvd3[12]; /* Reserved field, for alignment */ u_long cam_timeout; /* Timeout value */ u_long cam_engrsvd4; /* Reserved field, for alignment */ u_short cam_eng_num; /* Engine number for this request */ u_short cam_vu_flags; /* Vendor unique flags */ u_char cam_engrsvd5; /* Reserved field, for alignment */ u_char cam_engrsvd6[3]; /* Reserved field, for alignment */ u_char cam_sim_priv[ SIM_PRIV ]; /* SIM private data area */ } CCB_ENG_EXEC; /* 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 { long (*sim_init)(); /* Pointer to the SIM init routine */ long (*sim_action)(); /* Pointer to the SIM CCB go routine */ } CAM_SIM_ENTRY; /* ---------------------------------------------------------------------- */ /* 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 /* Unable 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 err occurred */ #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 inadequate */ #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 target */ #define CAM_STATUS_MASK 0x3F /* Mask bits for just the status # */ /* ---------------------------------------------------------------------- */ /* 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 direction (11: no data) */ #define CAM_DIS_AUTOSENSE 0x00000020 /* Disable autosense feature */ #define CAM_SCATTER_VALID 0x00000010 /* Scatter/gather list is valid */ #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_ENG_SYNC 0x00000400 /* Flush resid bytes before cmplt */ #define CAM_ENG_SGLIST 0x00800000 /* The SG list is for the HBA engine */ #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 timeout for I/O */ /* ---------------------------------------------------------------------- */ /* Defines for the Path Inquiry CCB fields. */ #define CAM_VERSION 0x23 /* 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 */ #define PIM_NOINQUIRY 0x20 /* Inquiry data not kept by XPT */ /* ---------------------------------------------------------------------- */ /* Defines for Asynchronous Callback CCB fields. */ #define AC_FOUND_DEVICES 0x80 /* During a rescan new device 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 occurred */ #define AC_BUS_RESET 0x01 /* A SCSI bus RESET occurred */ /* ---------------------------------------------------------------------- */ /* 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; /* ---------------------------------------------------------------------- */ /* Defines for the HBA engine inquiry CCB fields. */ #define EIT_BUFFER 0x00 /* Engine type: Buffer memory */ #define EIT_LOSSLESS 0x01 /* Engine type: Lossless compression */ #define EIT_LOSSLY 0x02 /* Engine type: Lossly compression */ #define EIT_ENCRYPT 0x03 /* Engine type: Encryption */ #define EAD_VUNIQUE 0x00 /* Eng algorithm ID: vendor unique */ #define EAD_LZ1V1 0x00 /* Eng algorithm ID: LZ1 var. 1*/ #define EAD_LZ2V1 0x00 /* Eng algorithm ID: LZ2 var. 1*/ #define EAD_LZ2V2 0x00 /* Eng algorithm ID: LZ2 var. 2*/ /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* Unix OSD defines and data structures. */ #define INQLEN 36 /* Inquiry string length to store. */ #define CAM_SUCCESS 0 /* For signaling general success */ #define CAM_FAILURE 1 /* For signaling general failure */ #define CAM_FALSE 0 /* General purpose flag value */ #define CAM_TRUE 1 /* General purpose flag value */ #define XPT_CCB_INVALID -1 /* for signaling a bad CCB to free */ /* General Union for Kernel 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_EN_LUN cel; CCB_ENG_INQ cei; CCB_ENG_EXEC cee; } 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 in a linked list structure. */ typedef struct async_info { struct async_info *cam_async_next; /* pointer to the next structure */ u_long 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 EDT table contains the device information for all the devices, SCSI ID and LUN, for all the SCSI busses in the system. The table contains a CAM_EDT_ENTRY structure for each device on the bus. */ typedef struct { long cam_tlun_found; /* Flag for the existence of the target/LUN */ ASYNC_INFO *cam_ainfo; /* Async callback list 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; /* ---------------------------------------------------------------------- */