WORKING                                                    X3T9.2
DRAFT                                                        792D


                                                       Revision 6
                                                        10-MAR-94









Information technology -
SCSI-2 Common access method
transport and SCSI interface module


This is a draft proposed American National Standard of Accredited
Standards Committee X3.  As such this is not a completed standard.  The
X3T9 Technical Committee may modify this document as a result of
comments received during public review and its approval as a standard. 
Use of the information contained here in is at your own risk.


Permission is granted to members of X3, its technical committees, and
their associated task groups to reproduce this document for the purposes
of X3 standardization activities without further permission, provided this
notice is included.  All other rights are reserved.  Any commercial or for-
profit use is strictly prohibited.







ASC X3T9.2 CAM Technical Editor:    WillIiam D. Dallas
                                    Digital Equipment Corporation
                                    110 Spit Brook Road
                                    Nashua N.H. 03060
                                    USA

                                    Telephone: 603-881-2508
                                    Facsimile: 603-881-2257
                                    Email:
                                    dallas@wasted.enet.dec.com



                                                 Reference number
                                              ISO/IEC **** : 199x
                                               ANSI X3.221 - 199x
                                   Printed April, 19, 1994 5:01pm


Contents
                                                                        Page

Contents. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii

Annexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi

Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .vii

Tables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii

Foreword. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix

Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  x

1 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1

2 References. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1

3  Definitions and conventions. . . . . . . . . . . . . . . . . . . . . .  1
   3.1  Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . .  1
   3.2  Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . .  2

4 Conformance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3

5  General description. . . . . . . . . . . . . . . . . . . . . . . . . .  3
   5.1  Environment . . . . . . . . . . . . . . . . . . . . . . . . . . .  3
   5.2 Peripheral driver functions. . . . . . . . . . . . . . . . . . . .  4
   5.3  XPT functions . . . . . . . . . . . . . . . . . . . . . . . . . .  5
   5.4  SIM functions . . . . . . . . . . . . . . . . . . . . . . . . . .  5

6 Background. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
   6.1  Software  . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
   6.2  CAM (Common Access Method). . . . . . . . . . . . . . . . . . . .  6
   6.2.1  OSD (Operating System Dependencies) . . . . . . . . . . . . . .  6
   6.3 Architectural Considerations . . . . . . . . . . . . . . . . . . .  6

7 Principles of Operation . . . . . . . . . . . . . . . . . . . . . . . .  8
   7.1  Accessing the XPT . . . . . . . . . . . . . . . . . . . . . . . .  8
   7.2  Initialization. . . . . . . . . . . . . . . . . . . . . . . . . .  8
   7.3  CCB completion. . . . . . . . . . . . . . . . . . . . . . . . . .  8
   7.3.1  Completion of immediate CCB . . . . . . . . . . . . . . . . . .  8
   7.3.2  Completion of queued CCB. . . . . . . . . . . . . . . . . . . .  9
   7.4  SCSI request queues . . . . . . . . . . . . . . . . . . . . . . .  9
   7.4.1 The Logical Unit and the peripheral driver . . . . . . . . . . .  9
   7.4.2  SIM queuing . . . . . . . . . . . . . . . . . . . . . . . . . .  9
   7.4.2.1 SIM queue priority . . . . . . . . . . . . . . . . . . . . . .  9
   7.4.2.2  Tag recognition . . . . . . . . . . . . . . . . . . . . . . . 10
   7.4.2.3  Error conditions and queues within the subsystem. . . . . . . 10
   7.5  SIM handling of SCSI resets . . . . . . . . . . . . . . . . . . . 11
   7.6  Asynchronous callback . . . . . . . . . . . . . . . . . . . . . . 11
   7.7  Autosense . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
   7.8  Loadable modules. . . . . . . . . . . . . . . . . . . . . . . . . 14

8  OSD (operating system dependent) operation . . . . . . . . . . . . . . 15
   8.1  UNIVOS operating system . . . . . . . . . . . . . . . . . . . . . 15
   8.1.1  Initialization  . . . . . . . . . . . . . . . . . . . . . . . . 15
   8.1.2  Accessing the XPT . . . . . . . . . . . . . . . . . . . . . . . 16
   8.1.2.1  From the peripheral driver  . . . . . . . . . . . . . . . . . 16
   8.1.2.2  From the SIM  . . . . . . . . . . . . . . . . . . . . . . . . 16
   8.1.3  Callback on completion  . . . . . . . . . . . . . . . . . . . . 16
   8.1.4  Pointer definition in the UNIVOS environment  . . . . . . . . . 17
   8.1.5  Request mapping information . . . . . . . . . . . . . . . . . . 17
   8.1.6  XPT interface . . . . . . . . . . . . . . . . . . . . . . . . . 17
   8.1.6.1  Functions for peripheral driver support . . . . . . . . . . . 17
   8.1.6.2  Functions for SIM module support. . . . . . . . . . . . . . . 18
   8.1.7  SIM interface . . . . . . . . . . . . . . . . . . . . . . . . . 18
   8.2  LANOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
   8.2.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . 19
   8.2.2 SIM and peripheral driver unloading. . . . . . . . . . . . . . . 19
   8.2.3 Accessing the XPT. . . . . . . . . . . . . . . . . . . . . . . . 20
   8.2.4 Hardware registration. . . . . . . . . . . . . . . . . . . . . . 20
   8.2.5 Miscellaneous. . . . . . . . . . . . . . . . . . . . . . . . . . 20
   8.3  DOS (disk operating system) . . . . . . . . . . . . . . . . . . . 21
   8.3.1  Initialization  . . . . . . . . . . . . . . . . . . . . . . . . 21
   8.3.1.1  Multiple XPTs . . . . . . . . . . . . . . . . . . . . . . . . 21
   8.3.1.2  Device table handling . . . . . . . . . . . . . . . . . . . . 22
   8.3.2  Accessing the XPT . . . . . . . . . . . . . . . . . . . . . . . 22
   8.3.2.1  Testing for the presence of the XPT/SIM . . . . . . . . . . . 22
   8.3.2.2  Sending a CCB to the XPT  . . . . . . . . . . . . . . . . . . 23
   8.3.3  Callback on completion  . . . . . . . . . . . . . . . . . . . . 23
   8.3.4  Asynchronous callbacks  . . . . . . . . . . . . . . . . . . . . 23
   8.3.5  Pointer definition  . . . . . . . . . . . . . . . . . . . . . . 24

9  CAM control blocks . . . . . . . . . . . . . . . . . . . . . . . . . . 24
   9.1  CCB header. . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
   9.1.1  Address of this CCB . . . . . . . . . . . . . . . . . . . . . . 25
   9.1.2  CAM control block length. . . . . . . . . . . . . . . . . . . . 25
   9.1.3  XPT function code . . . . . . . . . . . . . . . . . . . . . . . 25
   9.1.4  CAM status  . . . . . . . . . . . . . . . . . . . . . . . . . . 26
   9.1.5  Connect ID  . . . . . . . . . . . . . . . . . . . . . . . . . . 26
   9.1.6  CAM flags . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
   9.2  Function codes. . . . . . . . . . . . . . . . . . . . . . . . . . 27
   9.2.1 NOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
   9.2.2  Get device type . . . . . . . . . . . . . . . . . . . . . . . . 27
   9.2.3  Path inquiry  . . . . . . . . . . . . . . . . . . . . . . . . . 28
   9.2.4  Release SIM queue . . . . . . . . . . . . . . . . . . . . . . . 30
   9.2.5  Scan SCSI bus . . . . . . . . . . . . . . . . . . . . . . . . . 30
   9.2.6  Set async callback  . . . . . . . . . . . . . . . . . . . . . . 31
   9.2.7  Set device type . . . . . . . . . . . . . . . . . . . . . . . . 31
   9.3  SCSI control functions. . . . . . . . . . . . . . . . . . . . . . 32
   9.3.1  Abort SCSI command. . . . . . . . . . . . . . . . . . . . . . . 32
   9.3.2  Reset SCSI bus  . . . . . . . . . . . . . . . . . . . . . . . . 33
   9.3.3  Reset SCSI device . . . . . . . . . . . . . . . . . . . . . . . 33
   9.3.4  Terminate I/O process request . . . . . . . . . . . . . . . . . 34

10  Execute SCSI I/O. . . . . . . . . . . . . . . . . . . . . . . . . . . 35
   10.1  CAM control block to request I/O . . . . . . . . . . . . . . . . 35
   10.1.1  Callback on completion . . . . . . . . . . . . . . . . . . . . 35
   10.1.2  CAM control block length . . . . . . . . . . . . . . . . . . . 36
   10.1.3  CAM flags. . . . . . . . . . . . . . . . . . . . . . . . . . . 36
   10.1.3.1  Byte 1 bits. . . . . . . . . . . . . . . . . . . . . . . . . 37
   10.1.3.2  Byte 2 bits. . . . . . . . . . . . . . . . . . . . . . . . . 37
   10.1.3.3  Byte 3 bits. . . . . . . . . . . . . . . . . . . . . . . . . 38
   10.1.3.4  Byte 4 bits for phase cognizant mode . . . . . . . . . . . . 38
   10.1.3.5 Byte 4 bits for host target mode. . . . . . . . . . . . . . . 38
   10.1.4  CAM status . . . . . . . . . . . . . . . . . . . . . . . . . . 39
   10.1.5  CDB  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
   10.1.6  CDB length . . . . . . . . . . . . . . . . . . . . . . . . . . 41
   10.1.7  Data transfer length . . . . . . . . . . . . . . . . . . . . . 42
   10.1.8  Function code. . . . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.9 Initiator ID. . . . . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.10  LUN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.11  Message buffer length (target-only) . . . . . . . . . . . . . 42
   10.1.12  Message buffer pointer (target-only). . . . . . . . . . . . . 42
   10.1.13  Next CCB pointer. . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.14  Number of scatter/gather entries. . . . . . . . . . . . . . . 42
   10.1.15  Path ID . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.16  Peripheral driver pointer . . . . . . . . . . . . . . . . . . 42
   10.1.17  Private data. . . . . . . . . . . . . . . . . . . . . . . . . 42
   10.1.18  Request mapping information . . . . . . . . . . . . . . . . . 43
   10.1.19  Residual length . . . . . . . . . . . . . . . . . . . . . . . 43
   10.1.20  SCSI status . . . . . . . . . . . . . . . . . . . . . . . . . 43
   10.1.21  Sense info buffer length. . . . . . . . . . . . . . . . . . . 43
   10.1.22  Sense info buffer pointer . . . . . . . . . . . . . . . . . . 43
   10.1.23  SG list/data buffer pointer . . . . . . . . . . . . . . . . . 43
   10.1.24 Tag ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
   10.1.25  Tagged queue action . . . . . . . . . . . . . . . . . . . . . 43
   10.1.26  Target ID . . . . . . . . . . . . . . . . . . . . . . . . . . 43
   10.1.27  Timeout value . . . . . . . . . . . . . . . . . . . . . . . . 44
   10.1.28  VU field. . . . . . . . . . . . . . . . . . . . . . . . . . . 44
   10.1.29  VU flags. . . . . . . . . . . . . . . . . . . . . . . . . . . 44
   10.2  Command linking. . . . . . . . . . . . . . . . . . . . . . . . . 44

11  Target mode (optional). . . . . . . . . . . . . . . . . . . . . . . . 44
   11.1 Phase Cognizant Mode. . . . . . . . . . . . . . . . . . . . . . . 45
   11.2 Enable LUN for Phase Cognizant Mode . . . . . . . . . . . . . . . 45
   11.2.1 Target Operation of the HBA for Phase Cognizant Mode. . . . . . 47
   11.2.2  Execute Target I/O for Phase Cognizant Mode. . . . . . . . . . 49
   11.2.3 EXECUTE TARGET I/O CCB. . . . . . . . . . . . . . . . . . . . . 49
   11.3 Host Target Mode. . . . . . . . . . . . . . . . . . . . . . . . . 50
   11.3.1 Host Target Mode Functionality Not Specified. . . . . . . . . . 50
   11.3.2 Host Target Mode Messages . . . . . . . . . . . . . . . . . . . 50
   11.3.3 Use of the IMMEDIATE NOTIFY CCB . . . . . . . . . . . . . . . . 51
   11.3.3.1 The events/messages that use the Immediate Notify mechanism . 53
   11.3.3.1.1 Sense Data preservation where no nexus has been established. 53
   11.3.3.1.2 Mandatory Messages. . . . . . . . . . . . . . . . . . . . . 54
   11.3.3.1.2.1 ABORT message . . . . . . . . . . . . . . . . . . . . . . 54
   11.3.3.1.3 Optional messages . . . . . . . . . . . . . . . . . . . . . 55
   11.3.3.1.3.1 Optional messages that are not supported. . . . . . . . . 55
   11.3.3.1.3.2 ABORT TAG message . . . . . . . . . . . . . . . . . . . . 55
   11.3.3.1.3.3 CLEAR QUEUE message . . . . . . . . . . . . . . . . . . . 56
   11.3.3.1.3.4  Head of Queue, Ordered Queue and Simple Queue messages . 57
   11.3.3.1.3.5 Terminate I/O Process message . . . . . . . . . . . . . . 57
   11.3.3.1.4 Resource Unavailable to SIM/HBA . . . . . . . . . . . . . . 58
   11.3.4 IMMEDIATE NOTIFY CCB. . . . . . . . . . . . . . . . . . . . . . 58
   11.3.5 NOTIFY ACKNOWLEDGE CCB. . . . . . . . . . . . . . . . . . . . . 59
   11.3.6 Enable Target Mode LUN For Host Target Mode . . . . . . . . . . 60
   11.3.7 ENABLE LUN CCB For Host Target Mode . . . . . . . . . . . . . . 63
   11.3.8 ACCEPT TARGET I/O and CONTINUE TARGET I/O CCB Operation . . . . 64
   11.3.8.1 SIM/HBA ACCEPT TARGET I/O CCB Acceptance. . . . . . . . . . . 64
   11.3.8.2 SIM/HBA CDB Reception . . . . . . . . . . . . . . . . . . . . 65
   11.3.8.3 Host Peripheral Driver CDB Completion Callback. . . . . . . . 66
   11.3.8.4 SIM/HBA CONTINUE TARGET I/O CCB Acceptance. . . . . . . . . . 66
   11.3.8.5 Host Target Mode Peripheral Driver CONTINUE TARGET I/O
      Callback. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
   11.3.8.6 Command Reception Errors and Data Phase Errors Handling.. . . 67
   11.3.8.7 ACCEPT and CONTINUE TARGET I/O CCB TIMEOUTS . . . . . . . . . 69
   11.3.9 ACCEPT TARGET I/O CCB . . . . . . . . . . . . . . . . . . . . . 70
   11.3.10 CONTINUE TARGET I/O CCB. . . . . . . . . . . . . . . . . . . . 72
   11.3.11 Disable of a Host Target Mode LUN. . . . . . . . . . . . . . . 73
   11.3.12 Exception Conditions . . . . . . . . . . . . . . . . . . . . . 73
   11.3.12.1 BUS RESET. . . . . . . . . . . . . . . . . . . . . . . . . . 74
   11.3.12.2 BUS DEVICE RESET message . . . . . . . . . . . . . . . . . . 74
   11.3.13 CDB Reception on a Non Enabled LUN . . . . . . . . . . . . . . 75
   11.3.14 Retrieving unused ACCEPT TARGET I/O CCBs from the SIM. . . . . 76

12  HBA engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
   12.1  Engine inquiry . . . . . . . . . . . . . . . . . . . . . . . . . 76
   12.2  Execute engine request (optional). . . . . . . . . . . . . . . . 77




Annexes

                                                                        Page

ANNEX A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Physical/logical translation in 80x86 environment . . . . . . . . . . . . 79

Annex B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Target application examples . . . . . . . . . . . . . . . . . . . . . . . 83

Annex C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
UNIVOS OSD data structures. . . . . . . . . . . . . . . . . . . . . . . . 85





Figures

                                                                        Page
Figure 1 - CAM environment model  . . . . . . . . . . . . . . . . . . . .  4




Tables

Table 1 - ASYNC callback opcode data requirements . . . . . . . . . . . . 13
Table 2 - Cam control block header. . . . . . . . . . . . . . . . . . . . 24
Table 3 - Support of SCSI messages. . . . . . . . . . . . . . . . . . . . 25
Table 4 - XPT function codes. . . . . . . . . . . . . . . . . . . . . . . 26
Table 5 - NOP CCB . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Table 6 - Get device type CCB . . . . . . . . . . . . . . . . . . . . . . 27
Table 7 - Path inquiry CCB - Part 1 of 2. . . . . . . . . . . . . . . . . 28
Table 7 - Path inquiry CCB - Part 2 of 2. . . . . . . . . . . . . . . . . 29
Table 8 - Release SIM queue . . . . . . . . . . . . . . . . . . . . . . . 30
Table 9 - Scan SCSI bus . . . . . . . . . . . . . . . . . . . . . . . . . 30
Table 10 - Set async callback CCB . . . . . . . . . . . . . . . . . . . . 31
Table 11 - Set device type CCB. . . . . . . . . . . . . . . . . . . . . . 32
Table 12 - Abort SCSI command CCB . . . . . . . . . . . . . . . . . . . . 32
Table 13 - Reset SCSI bus CCB . . . . . . . . . . . . . . . . . . . . . . 33
Table 14 - Reset SCSI device CCB. . . . . . . . . . . . . . . . . . . . . 34
Table 15 - Terminate I/O process request CCB. . . . . . . . . . . . . . . 34
Table 16 - SCSI I/O request CCB . . . . . . . . . . . . . . . . . . . . . 35
Table 17- CAM flags . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Table 17a Target Mode Specific CAM Flags. . . . . . . . . . . . . . . . . 36
Table 18 - Scatter gather list. . . . . . . . . . . . . . . . . . . . . . 37
Table 19 - CAM status . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Table 20 - ENABLE LUN CCB for Phase Cognizant Mode. . . . . . . . . . . . 46
Table 21 - TARGET CCB LIST. . . . . . . . . . . . . . . . . . . . . . . . 46
Table 22 - EXECUTE TARGET I/O CCB . . . . . . . . . . . . . . . . . . . . 50
Table 23 - IMMEDIATE NOTIFY CCB . . . . . . . . . . . . . . . . . . . . . 59
Table 24 - NOTIFY ACKNOWLEDGE CCB . . . . . . . . . . . . . . . . . . . . 60
Table 25 - ENABLE LUN CCB For Host Target Mode. . . . . . . . . . . . . . 63
Table 26 - ACCEPT TARGET I/O CCB. . . . . . . . . . . . . . . . . . . . . 70
Table 27 - CONTINUE TARGET I/O CCB. . . . . . . . . . . . . . . . . . . . 72
Table 28 - Engine inquiry CCB . . . . . . . . . . . . . . . . . . . . . . 77
Table 29 - Execute engine request CCB . . . . . . . . . . . . . . . . . . 78




Foreword





Introduction

SCSI provides 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 have made it nearly impossible for end users 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.  That effort has evolved
into this Internation Standard.




Information processing systems -- SCSI-2 common
access method transport and SCSI interface module

1 Scope

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

The purpose of this International 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. 

2 References

    ISO Normative 10288 informative technology
    SCSI-2, Small Computer Systems Interface-2 (X3.133-1993)

3  Definitions and conventions

3.1  Definitions

For the purposes of this International Standard the following
definitions apply

3.1.1          block. 
This defines an action to prevent access, (e.g., busy).

3.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.   

3.1.3          Immediate CCB. 
Provides valid completion status when the call to xpt_action ()
returns (e.g., path inquiry).

3.1.4          Queued CCB. 
Provides valid completion status when the completion callback routine
is called.

3.1.5          CDB (command descriptor block). 
A data structure containing the SCSI opcode, parameters and control
bits for that operation. 

3.1.6          DMA (direct memory access). 
A means of data transfer between peripheral and host memory without
processor intervention. 

3.1.7          freeze. 
This defines a software action to quiesce activity (e.g., freeze) the
queue.

3.1.8          HBA (host bus adapter). 
The hardware and microcode which provides the interface between system
memory and the SCSI bus. 

3.1.9      null. 
A value which indicates that the contents of a field have no meaning.
This value is typically, though not necessarily, zero.

3.1.10     optional. 
This term describes features which are not required by the
International Standard. However, if any feature defined by the
International Standard is implemented, it shall be done in the same
way as defined by the International 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. 

3.1.11     OSD (Operateing System Dependent). 
This term describes a capability. method of operation, or feature
depends on the specific operating system on which CAM is implemented.

3.1.12     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. 

3.1.13     SCSI (small computer systems interface). 
The I/O interface which this International Standard is designed to
support. See Clause 2 for further information.

3.1.14     SIM (SCSI interface module). 
A module designed to accept the CAM control blocks routed through the
XPT in order to execute SCSI commands and perform other functions.

3.1.15     VU (vendor unique). 
This term is used to describe bits, bytes, fields, code values and
features which are not described in this International Standard, and
may be used in a way that varies between vendors. 

3.1.16     XPT (transport). 
A layer of software which peripheral drivers use to originate the
execution of CAM functions. 

3.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. 

There are places in the International 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. 

4 Conformance

An implementation claiming conformance to the transport layer (XPT)
for a specified operating system and language environment shall:

    -   provide all the mandatory XPT functions and services specified
        in this International Standard;
    -   correctly interoperate with any conforming SCSI Interface Module
        (SIM) for the specified environment;
    -   provide the necessary interface specifications that a conforming
        SIM will  require 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
        International Standard;
    -   correctly interoperate with any conforming XPT for the specified
        environment;
    -   provide the necessary interface specifications that a conforming
        XPT will require to interface with SIMs. 

A conforming implementation shall execute all function codes as
required by this International 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 International 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 HBA engines
        are supported. 

5  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, operating system software has
no common way to provide access to SCSI peripherals. 

The purpose of the CAM is to define a standard for the support of Host
Bus Adapters (HBA) and the like by device driver software. 

Software in the operating system dispatches I/O requests to the SCSI
peripherals in a number of different ways depending on the software
architecture. The operating system dependencies (OSD) are defined in
clause 8 for certain named software and hardware platforms. 

5.1  Environment

A model of the CAM usage environment is illustrated in figure 1.
Multiple applications are shown accessing a variety of SCSI devices.
Several device drivers, both peripheral drivers amd SIM, are present
to support the peripherals on the system.

The choice of XPT and SIM packaging is an operating system dependency.
Clause 8 defines this dependency for certain named software and
hardware platforms.

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

The XPT function is illustrated as a separate element. In some
operating systems, 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 because there may be
more than one SIM loaded. The XPT function may be provided by the
operating system, or can be achieved through associating multiple
separately loaded XPTs 


    +-------------+       +-------------+             +-------------+  
    | 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 1 - CAM environment model 


5.2 Peripheral driver functions

Peripheral drivers provide the following functionality:

    a)     Interpreting 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:
        1)     CAM control blocks and supporting blocks that may be
               needed,
        2)     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)     Establishing 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)     Establishing a timeout value for a task and pass this value in
           the CCB.


5.3  XPT functions

XPT services provide the following functionality to process CCBs: 

    a)     Routing of the CCB to the proper SIM;
    b)     OSD management 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;

5.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 appropriate) all the SCSI HBA protocol
           steps;
    c)     Distinguish abnormal behavior and perform error recovery, as
           required;
    d)     Manage of data transfer path hardware, including DMA circuitry
           and address mapping, and establish DMA resource requests (if
           necessary);
    e)     Queuing of multiple operations for different LUNs as well as
           the same LUN and assign tags for tag queuing (if supported);
    f)     Freeze and unfreeze the queue as necessary to accomplish queue
           recovery;
    g)     Post the completed operation to the initiating device driver;
    h)     Manage  selection, disconnection, reconnection, and data
           pointers of the SCSI HBA protocol;
++  i)     Provide 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;

++ This item will be removed from the list in draft 7 unless a
justification for its presence is delivered to the editor or working
group.

6 Background

SCSI 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. 

6.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. 

6.2  CAM (Common Access Method)

This International Standard describes the general definition of the
CAM (Common Access Method).  CAM functionality has been separated into
a few major elements.
    -   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
        responsibility of the transport. 

    -   SIM (SCSI Interface Module) 
        The SIM (SCSI interface module) manages HBA resources and
        provides a hardware-independent interface for SCSI applications
        and drivers. 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. 

    -   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. 
 
6.2.1  OSD (Operating System Dependencies)

The system environment in which the CAM is operating is a function of
the hardware platform and the operating system being executed. The
byte ordering is different between an Intel-based and a Motorola-based
machine for example,  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. 

Some OSD issues are discussed in Clause 8.


6.3 Architectural Considerations

Ideally, a single XPT structure would suffice for all OS environments,
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
International Standard. 

Under a UNIVOS (Universal Operating System), the XPT and SIMs 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. One
example of a universal operating system is Unix (a trademark of AT&T)
and as described in this International Standard, software developed
for a UNIVOS could be compatible within a Unix system.

Under a LANOS (Local Area Networking System), the XPT can be loaded as
a loadable device driver. SIMs are also implemented as loadable device
drivers. One example of a local area network operating system is
Netware 386 (a Trademark of Novell) and as described in this
International Standard, software developed for a LANOS could be
compatible within a Netware 386 system.

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

    
    

XPT routing is a mechanism to support concurrent multiple co-resident
SIMs so that different HBAs can be present 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 SIMs are loaded, the peripheral drivers integrate
each type of SCSI device into the OS through the XPT, independent of
the installed HBA hardware.

This is a list of requirements that CAM is designed to meet:
    a)     The ability  to use any SCSI command (including vendor
           unique);
    b)     No restrictions on the size or format of transferred data; 
    c)     Allowing all the capabilities of high end host adapters to be
           fully utilized and accommodating 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 by the
           calling driver or program; 
    e)     Fully re-entrant code; 

    NOTE:  This is an obvious requirement for multi-tasking environments such
           as UNIVOS but even in single tasking DOS applications, multi-
           threaded 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 multi-threading, requests can be queued and serialized
           within the SIM module transparently to the XPT.

    f)     Support of multiple HBAs; 
    g)     Peripheral drivers may determine which optional features are
           available; 
    h)     Definiton of a single XPT-based SCSI Bus scanning algorithm
           (so that each peripheral driver need not use bus bandwidth to
           perform this function; 
    i)     Providing a mechanism to abort I/O requests (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. 

7 Principles of Operation 

7.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 of advising the
peripheral driver of the completion of a queued 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). Completion notification for immediate requests is
accomplished by the normal function call retrun mechanism. 

The XPT is responsible for notifying peripheral drivers of
asynchronous events via the asynchronous callback mechanism.

7.2  Initialization

The XPT is responsible for determining the SCSI Bus configuration at
initialization for each SIM. 

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

7.3  CCB completion

CCB completion is either immediate or queued.

7.3.1  Completion of immediate CCB

All CCBs are complete when the xpt_action() call returns except:
    -   Execute SCSI I/O
    -   Execute Target I/O
    -   Accept Target I/O
    -   Continue Target I/O
    -   Immediate Notify
    -   Execute Engine Request

7.3.2  Completion of queued CCB

A peripheral driver is notified of the completion of a queued CCB
using a callback routine. The SIM/XPT calls the peripheral driver's
callback routine when execution of the queued CCB completes. The
queued CCB includes a pointer to the peripheral driver's callback
routine (in the Callback on completion field).

The peripheral driver callback routine is used much like a hardware
interrupt handler. The callback routine has the same privileges and
restrictions as an interrupt handler.

The address of the specific CCB that completed is passed to  the
peripheral driver's callback routine.  


7.4  SCSI request queues

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

A SCSI request can be queued in any of the following places:

    a)     in the SIM 
    b)     in the target/LUN
    c)     in the peripheral driver

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

A SCSI Logical Unit may keep a  queue using tag queues, or a simple
queue of one element. 

A peripheral driver may also keep a queue (e.g., to perform a simple
elevator sort).
 
7.4.1 The Logical Unit and the peripheral driver 

Based on the needs outside the scope of CAM, the peripheral driver may
maintain a list of unfinished queued CCBs. The SIM, acting on behalf
of the peripheral driver, sends the appropriate commands or messages
to manage the queues in the Logical Unit. When the Logical Unit
completes an operation, the peripheral driver is advised by the SIM
via a callback (or by checking CAM status for completion). 

The peripheral driver should be coded as if there are other peripheral
drivers and other systems working with the same Logical Unit.

7.4.2  SIM queuing

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

7.4.2.1 SIM queue priority

When a CCB has a SIM queue priority=1, the SIM places the CCB ahead of
all CCBs that have a SIM queue priority=0 for the Logical Unit and at
the end (tail) of all other CCBs having a SIM queue priority=1. 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 of CCBs that have SIM priority=0 and
the queue remains frozen. When the SIM queue is released, any CCBs
with SIM queue priority=1 are executed individually first (in FIFO
sequence), followed by CCBs with a SIM priority=0 (in FIFO sequence).
See Clause 7.4.2.3 on how to release the SIM queue

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.

7.4.2.2  Tag recognition

To support tagged queuing recognition the SIM maintains a reference
between the CCB pointers and the queue tags for a Logical Unit. 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 for further
information on I_T_L_Q nexus) 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 for the Logical Unit operation based on its internal reference
table. 

When a Logical Unit 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. 

7.4.2.3  Error conditions and queues within the subsystem

The SIM shall place its internal queue for a Logical Unit 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.

The SIM shall maintain a count of the number of CCBs returned with the
indication of SIM queue frozen. The SIM shall decrement the SIM queue
frozen count for each CCB received with a Release SIM queue function
code. The SIM shall not be release its internal queue until the SIM
queue frozen count is zero.  The SIM shall not allow the SIM queue
frozen to have a negative value. The SIM shall not consider it an
error when a CCB is received with a Release SIM queue function code
that would decrement the SIM queue frozen count pass zero (negative). 

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 Logical Unit's queue is in the frozen state, a positive value
in the SIM queue frozen count, the SIM shall not dispatch any CCBs to
that Logical Unit. Peripheral drivers can still send CCBs to the SIM
for the Logical Unit, or any other Logical Unit. 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 of all CCBs with a SIM queue
priority=0 and at the end (tail) of all other CCBs having a SIM queue
priority=1.  in a FIFO order.

Following a check condition or command terminated status, the Logical
Unit's 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 Logical
Unit will not be discarded. The SIM holds it's internal Logical Unit
queue in the frozen state until Release SIM queue CCB(s) are received
that decrement the SIM queue frozen count to zero.

    Note:  The SIM queue frozen count can be greater then one for a number of
           conditions. An example of two of these conditions are SCSI BUS RESET,
           and a target operating in tagged queue mode.
 
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 Logical
Unit, 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 Logical Unit (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. 

  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.

7.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 each Logical Unit. 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, an updated
Peripheral Driver Buffer Pointer, an updated Size of Allocated
Peripheral Buffer, 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 asynchronous event notification requests to the
SIM in addition to performing XPT table maintenance related to the
asynchronous 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 fields 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 fields 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 9.2.6).
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 1 lists the opcodes and the expected data
requirements for the number of bytes to be transferred. 

                      Table 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. 

7.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.

7.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
initialization 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 7.6 and 9.2.6). 

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; 

8  OSD (operating system dependent) operation

8.1  UNIVOS operating system 

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

There are several sets of modules for UNIVOS:

    -   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 UNIVOS 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 17.

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. 

8.1.1  Initialization 

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

Due to the different UNIVOS-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 Logical Units 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.

8.1.2  Accessing the XPT 

8.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. 

8.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). 

8.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. 

8.1.4  Pointer definition in the UNIVOS environment 

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

8.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.

8.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. 

8.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. 

8.1.6.2  Functions for SIM module support

    a)     See 7.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
occurred 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 Logical Unit 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. 

8.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. 

8.2  LANOS

LANOS drivers are called NLMs (LANOS loadable modules). These modules
are registered and linked dynamically with LANOS: they are loaded
after the operating system is initialized and may be unloaded at any
time. 

The LANOS 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 17.

8.2.1 Initialization 

As the LANOS 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 7.8. For an
overview of peripheral driver registration with the XPT see 7.6 and
9.2.6.

When LANOS loads a SIM, it shall call the initialization routine
specified in the LANOS 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 LANOS 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-registered,
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. 


8.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 LANOS 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. LANOS 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, LANOS 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. 

8.2.3 Accessing the XPT

LANOS 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. 

8.2.4 Hardware registration

The SIM module needs to do the actual registration of the host adapter
with LANOS. 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 LANOS, 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 LANOS. 

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

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

8.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 LANOS when a device is
added to the system. 

Since fast disk channels are essential for a LANOS 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 LANOS routines that are "blocking" or the file
server will abend. 

8.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 17. 

8.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. 

8.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 8.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; 

8.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). 

8.3.2  Accessing the XPT 

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

8.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

8.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    

8.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. 

8.3.4  Asynchronous callbacks 

There are some differences in the DOS XPT/SIM implementation of
asynchronous callbacks as compared with the description in 7.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 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. 

8.3.5  Pointer definition 

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

@  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 2. 

                             Table 2 - 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                            |
+===============================================+


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 between
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 3 summarizes the message support.

                             Table 3 - 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 |
+======================================================================+


9.1  CCB header

The function codes used to identify the XPT service being requested
are listed in table 4.

9.1.1  Address of this CCB

Pointer containing the physical address of this CCB. 

9.1.2  CAM control block length

See 10.1.2

9.1.3  XPT function code


                                Table 4 - 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          |
| 32h |   Accept Target I/O           |
| 33h |   Continue Target I/O         |
| 34h |   Immediate Notify            |
| 35h |   Notify Acknowledge          |
|36-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.


9.1.4  CAM status 

See 10.1.4. 

9.1.5  Connect ID 

The connect ID consists of 4 separate fields, of which the first is
reserved. 

    -   Path ID:          see 10.1.15.
    -   Target ID:        see 10.1.26.
    -   LUN:          see 10.1.10.

9.1.6  CAM flags

The CAM flags qualify the function to be executed, and vary by
function code. See 10.1.3.

9.2  Function codes

9.2.1 NOP

A peripheral driver can execute this function at any time. The xpt
shall call sim_action passing this CCB if the PATH ID is valid. The
SIM shall return immediately.  
                                      Table 5 - NOP CCB
+====-===-======================================+
|Size|Dir|  NOP 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                            |
+===============================================+

This function shall return a CAM Status other than Request in
Progress.
    -   CAM Status of Request Completed Without Error.
    -   CAM Status of Invalid Path ID indicates that the specified Path
        ID is not installed.

9.2.2  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 Logical Unit address on each installed HBA to
look for the CD ROM device type). 

                                Table 6 - 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                            |
|  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 Logical Unit. 
The data shall be copied from the internal tables of the XPT/SIM to
the peripheral driver's buffer.

This function shall return a CAM Status other than Request in Progress.
    -   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. 

9.2.3  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 7 - 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                            |
|    | 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 queuing                 |
|    |   |     0 soft reset                     |
+===============================================+

                                      
                                      
                                      
                          Table 7 - Path inquiry CCB - Part 2 of 2
+====-===-======================================+
|Size|Dir| Path Inquiry                         |
|----+---+--------------------------------------|
|  1 | I |  Target mode support                 |
|    |   |     7 host target mode               |
|    |   |     6 phase cognizant mode           |
|    |   |     5 target mode disconnects        |
|    |   |     4 terminate I/O process          |
|    |   |     3 group 6 commands               |
|    |   |     2 group 7 commands               |
|    |   | 1 - 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                     |
|    |   | 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.

    NOTE:  For CCB's other than PATH INQUIRY CCB with a Path ID of the XPT
           the CCB shall be returned with a CAM Status of Invalid Path ID.

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
International 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.

    NOTE:  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 a CAM status other than Request in
Progress. 
    -   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. 

9.2.4  Release SIM queue 

This function is provided so that the peripheral driver can release a
frozen SIM queue for the selected Logical Unit. 

                                 Table 8 - 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                            |
+===============================================+


This function shall return a CAM Status other than Request in
Progress.
    -   CAM Status of Request Completed Without Error.
    -   CAM Status of Invalid Path ID indicates that the Path ID is
        invalid.

9.2.5  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 Logical Unit address on the SCSI bus and
update it's tables with the inquiry information provided by each
Logical Unit that responds. 

                                   Table 9 - Scan SCSI bus
+====-===-======================================+
|Size|Dir| Scan 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                            |
+===============================================+


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. 

9.2.6  Set async callback 

This function is provided so that a peripheral driver can register a
callback routine for the selected Logical Unit .

                              Table 10 - 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                           |
|    |   |      Reserved                        |
|  1 | O |    Path ID                           |
|  1 | O |    Target ID                         |
|  1 | O |    LUN                               |
|  4 | O | CAM flags                            |
|  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 a CAM Status other than Request in
Progress.  A CAM status of request completed without error indicates
that the  registration of the callback routine was accepted.  A CAM
status of request completed with error indicates that the registration
was rejected (possibly due to invalid parameter settings).

9.2.7  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 11 - 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                            |
|  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 a CAM Status other than
Request in Progress.

    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.

9.3  SCSI control functions

9.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 12 - 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                            |
|  4 | O | CCB to be aborted pointer            |
+===============================================+


This function shall return CAM status of request completed without
error. 

The abort operation shall always succeed. 

9.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 7.4.3.3 and 7.5).

                                Table 13 - 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                            |
+===============================================+

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.

9.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
7.4.3.3 and 7.5).


                              Table 14 - 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                            |
+===============================================+

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.

9.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 15 - 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                            |
|  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. 

10  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.

10.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 16.

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

                               Table 16 - 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                            |
|  4 | O | Peripheral driver pointer            |
|  4 | O | Next CCB pointer                     |
|  4 | O | Request mapping information          |
|  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 |   | VU field                             |
|  1 | I | SCSI status                          |
|  1 | I | Autosense residual length            |
|  2 |   |   Reserved                           |
|  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                     |
|  1 | O | Tag ID                  (target only)|
|  1 | O | Initiator ID            (target only)|
|  1 |   |   Reserved                           |
|  n | O | Private data                         |
+===============================================+


10.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.

10.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. 

10.1.3  CAM flags

This field contains bit settings as described in table 16 to indicate
special handling of the requested function. 

                                     Table 17- CAM flags
+====-====-==================================+
|Size|Bits|   CAM flags                      |
|----+----+----------------------------------|
|  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 | SG list pointers 0=VA   1=PA     |
|  1 |    | Target mode-specific CAM flags   |
|    |    |     See Table 17a                |
|--------------------------------------------|
|  * These bits may be mutually exclusive    |
|  # These bits are mutually exclusive       |
+============================================+

                          Table 17a Target Mode Specific CAM Flags
+====-====-==================-============================+
|Size|Bit | Host Target      |  Phase Cognizant           |
|----+----+------------------+----------------------------|
| 1  |  7 | Send Status      |  Data Buffer Valid         |
| 1  |  6 | Disconnects      |  Status Buffer Valid       |
|    |    | Mandatory        |                            |
| 1  |  5 | Terminate I/O    |  Message Buffer Valid      |
| 1  |  4 | Reserved         |         Reserved           |
| 1  |  3 | 0 = Host Target  | 1 =Phase-Cognizant Mode    |
| 1  |  2 | Reserved         | 1=Target CCB Available     |
| 1  |  1 | Reserved         | 1=Disable AutoDisconnect   |
| 1  |  0 | Reserved         | 1=Disable AutoSave/Restore |
+=========================================================+

 
10.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
           different 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 17.

                               Table 18 - 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
           (non Request in Progress 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. 

10.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 for
        the best  transfer parameters it is capable of with the target,
        and wherever possible execute the negotiated transfer parameters
        (synchronous, fast, wide transfers). 

    5   When disable synchronous transfers=1 the SIM shall negotiate for
        the least transfer parameters (asynchronous, narrow tranfers) if
        the SIM previously negotiated synchronous. If unable to negotiate
        synchronous (best transfer parameters) 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
        tail of the Logical Unit's (FIFO order) priority internal queue
        and to be ahead of all CCB operations with normal priority sent
        to the Logical Unit by the SIM. If the SIM is in the midst of an
        extended I/O operation it may attempt to disconnect from the
        current Logical Unit in order to service this CCB.

    3   When SIM queue freeze=1 the SIM shall place its internal Logical
        Unit 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).

10.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. See
section 11.2 for a description of bit 7.

10.1.3.4  Byte 4 bits for phase cognizant mode

The target mode only flags are only active on enable LUN or execute
target I/O commands. See Clause 11.2 for complete details.

    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 Host Target 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.

10.1.3.5 Byte 4 bits for host target mode

The target mode only flags are only active on enable LUN , accept
target I/O and continue target I/O commands. See Clause 11.3 for
complete details.

    7      send status - when set to a 1 this bit directs the SIM/HBA
           that it shall go to status phase after data phase (if there is
           a data phase for this CCB) and send the SCSI status byte
           contained within this CCB. 

    6      disconnects mandatory - when set to a 1 this bit directs the
           SIM/HBA that it shall disconnect from the SCSI bus for each
           CCB processed for the enabled LUN.

    5      terminate I/O - when set to a 1 this bit informs the SIM/HBA
           the the Host Target Mode peripheral driver is supporting the
           TERMINATE I/O process SCSI message.

    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 Host Target Mode. 

10.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 19. 

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 19 - 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                |
|  19h | Unrecoverable host bus adaptor error |
|  1Ah | SCSI bus reset denied                |
|19-33h|   Reserved                           |
|      |              Target mode only status |
|  34h | Resource unavailable                 |
|  35h | Unacknowledged event by host         |
|  36h | Message Received                     |
|  37h | Invalid CDB                          |
|  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.
    -   19h Unrecoverable Host Bus Adaptor error: this CCB was terminated
        because of a hardware error detected by the HBA. The error does
        not indicate a SCSI bus problem but an error within the HBA or
        host.
    -   1Ah SCSI bus reset denied: this CCB was not accepted by the
        SIM/HBA due to a bus hung condition. This CAM status is a result
        of an inteligent HBA detecting a hung SCSI bus and requesting
        permission from the controlling SIM software to perform a SCSI
        bus reset. The permission to perfrom a SCSI bus reset was denied
        by the SIM.
    -   34h Resource unavailable: indicates that the SIM/HBA has run out
        of resources for processing connections (Host Target Mode only).
    -   35 Unacknowledged event: indicates that the Host Target Mode
        peripheral driver has not acknowledged   
    -   38h Invalid LUN: indicates that the Logical Unit 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 with
        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.

10.1.5  CDB 

This field either contains the SCSI CDB (command descriptor block), or
a pointer to the CDB, to be dispatched.

10.1.6  CDB length

This field contains the length in bytes of the CDB. 

10.1.7  Data transfer length

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

10.1.8  Function code

See 9.1.3.

10.1.9 Initiator ID

This field indicates which SCSI initiator this CCB is in response to.
This field is only valid for target mode operation.

10.1.10  LUN

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

10.1.11  Message buffer length (target-only)

This field contains the length in bytes of the field which is to be
used to hold message information in the event that the peripheral
drivers needs to issue any MSGs. This field is exclusive to target
mode operation. 

10.1.12  Message buffer pointer (target-only)

This field contains a pointer to buffer containing messages. This
pointer is only valid for use in target mode. 

10.1.13  Next CCB pointer

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

10.1.14  Number of scatter/gather entries

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

10.1.15  Path ID

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

10.1.16  Peripheral driver pointer

This field contains a pointer which is for the exclusive use of the
peripheral driver, which use is not defined by this International
Standard. 

10.1.17  Private data

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

10.1.18  Request mapping information

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

10.1.19  Residual length

This field contains the difference in twos complement form of the
number of data bytes transferred by the HBA compared with the number
of bytes requested by the CCB. This is calculated by the total number
of bytes requested to be transferred by the CCB minus the actual
number of bytes transferred by the HBA.

10.1.20  SCSI status

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

10.1.21  Sense info buffer length

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

10.1.22  Sense info buffer pointer

This field contains a pointer to the data buffer for request sense
data. This pointer will only be used if a check condition occurs while
performing the specified command.

10.1.23  SG list/data buffer pointer

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

10.1.24 Tag ID

This field indicates the SCSI TAG QUEUE ID that this CCB is in
response to if tagged queue operation. This field is valid only for
Host Target Mode operation.

10.1.25  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 queuing 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      

10.1.26  Target ID

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

10.1.27  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.

The timeout value is on a per CCB basis, and is measured from
successful selection to command completion.

10.1.28  VU field

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


10.1.29  VU flags

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


10.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. 

11  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 SIM/HBA as defined by the Target Mode
Support flags in the Path Inquiry CCB.

 - Phase-Cognizant Mode
 - Host Target Mode

Host Target Mode permits a peripheral driver to register itself as a
LUN and provide a set of one or more ACCEPT TARGET I/O CCBs that the
SIM/HBA can use for Target Mode command processing. In this mode, when
the adapter is selected and the XPT/SIM receives an Identify message
for a LUN that has registered as a Host Target LUN, the SIM/HBA may
accept any target mode command, based on conditions specified in this
document.  Using one of the available ACCEPT TARGET I/O CCBs, the
SIM/HBA shall pass the received Host Target mode command to the
Peripheral Driver CDB Received Completion function.  The peripheral
driver shall interpret the command and based on its internal knowledge
shall decide how to respond. Response shall be in the form of one or
more CONTINUE TARGET I/O CCBs to the SIM/HBA.  The SIM/HBA shall
callback as specified by the peripheral driver for each completed
CONTINUE TARGET I/O CCB.

Some SCSI bus message processing and event notification is handled
both in the SIM/HBA and the Host Target Mode peripheral driver. An
example of this is the Abort message.  Other messages are handled
transparently by the SIM/HBA. An example of this is the synchronous
data transfer request message. For optional messages that  require
notification from the  SIM/HBA, the peripheral driver decides which
optional messages it shall  support. If the Host Target Mode
peripheral driver has indicated that the message is not to be
supported, the SIM/HBA shall reject the message. On receipt of a
supported target message that is not handled transparently, the
SIM/HBA shall immediately notify the Host Target Mode peripheral
driver using the mechanisms provided by the IMMEDIATE NOTIFY CCB. The
IMMEDIATE NOTIFY CCB ownership shall always be with the SIM/HBA until
the LUN is no longer enabled.

In summary, Host Target Mode peripheral drivers can be called back
multiple times for a command received by the SIM/HBA, once for each
command required and an additional number depending on the command 
and how the Host Target Mode peripheral driver has been implemented. 
The Host Target Mode model allows for a peripheral driver to mimic any
SCSI device type.  The model allows all phase handling and SCSI
command processing nuances to be performed by the SIM/HBA but allows
the peripheral driver enough functionality for emulated device
control.

Phase-Cognizant mode permits an application tighter control over what
takes place when an 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 for setting up data, message, status fields
and CAM-Flags in the CCB. It then reissues 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.
While Phase Cognizant mode allows an application tighter control in
some areas of SCSI bus control, some target mode capability can not be
implemented, i.e. tagged command queing.

11.1 Phase Cognizant Mode

11.2 Enable LUN for Phase Cognizant Mode

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. 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.

The following lists the fields of the ENABLE LUN CCB. No entry under
the "Dir" heading indicates that this field is not being used for the
ENABLE LUN function.

                     Table 20 - ENABLE LUN CCB for Phase Cognizant Mode
+====-===-=====================================+
 |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                           | 
 |  2 | O | Group 6 Vendor Unique CDB Lengths   | 
 |  2 | O | Group 7 Vendor Unique CDB Lengths   | 
 |  4 |   | Pointer to Immediate Notify CCB List| 
 |  4 |   | Number of Immediate Notify CCBs     | 
 |  4 | O | Pointer to Target CCB list          | 
 |  2 | O | Number of Target CCBs               | 
 |  n |   | Sim private                         | 
 +==============================================+ 

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 21).

                                 Table 21 - 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 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 LUN is enabled for Phase
Cognizant mode operation, the CAM Status field of each Target CCB
shall be set to Request in Progress. The application is required to
poll 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 be set the Target CCB Available as needed 

Within the Target CCB provided, the following information shall be
present and valid.
    -   CAM Flags 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.
    -   Timeout Value field shall be set to the the infinity value.
     
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. Sufficient 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. See Clause
11.2.1 for additional information regarding Inquiry data.

The XPT/SIM shall prevent a nexus being established between an
initiator and a specified LUN that has been disabled. 

The Enable LUN 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 LUN Already Enabled 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 Phase
        Cognizant Target mode is not supported by this implementation of
        CAM. 


11.2.1 Target Operation of the HBA for Phase Cognizant Mode

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 SCSI-2.

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 BUSY 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 Execute Target I/O which
transmits 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 BUSY 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 Initiator 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 CDB is Vendor Unique,
the XPT/SIM shall transfer the number of CDB bytes specified in the
ENABLE LUN CCB for this LUN. The Group Code in the incoming CDB
(either 6 or 7) shall select the Vendor Unique CDB size from the
ENABLE LUN CCB. If the selected CDB size (specified in the ENABLE LUN
CCB) is zero, the XPT/SIM shall transfer only the CDB Operation Code.
If the required number of bytes not transferred or the specified size
for this Group Code is zero, 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.

11.2.2  Execute Target I/O for Phase Cognizant Mode

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.

11.2.3 EXECUTE TARGET I/O CCB

The following lists the fields of the EXECUTE TARGET I/O CCB. No entry
under the "Dir" heading indicates that this field is not being used
for the EXECUTE TARGET I/O function.


                              Table 22 - EXECUTE TARGET I/O CCB
+====-===-===========================================+
|Size|Dir|   EXECUTE TARGET I/O CCB                  |
|----+---+-------------------------------------------|
|  4 | O | Address of this CCB                       |
|  2 | O | CAM Control Block Length                  |
|  1 | O | Function Code     (EXECUTE TARGET I/O)    |
|  1 | I | CAM Status                                |
|    |   | Connect ID                                |
|  1 |   |     Reserved                              |
|  1 | O |     Path ID       (Bus no. of SIM/HBA)    |
|  1 | O |     Target ID     (Target ID of SIM/HBA ) |
|  1 | O |     LUN                                   |
|  4 |I/O| CAM Flags                                 |
|  4 | O | Peripheral Driver Pointer                 |
|  4 |   | Next CCB Pointer                          |
|  4 | O | Request Mapping Information (If needed)   |
|  4 | O | Callback on Completion                    |
|  4 | O | SG List/Data Buffer Pointer               |
|  4 | O | Data Transfer Length                      |
|  4 |   | Sense Info Buffer Pointer                 |
|  4 |   | Sense Info Buffer Length                  |
|  1 | O | CDB Length                                |
|  2 | O | Number of Scatter/Gather Entries          |
|  4 |   | VU Field                                  |
|  1 |I/O| SCSI Status                               |
|  2 |   | Autosense Residual Length                 |
|  2 |   | Reserved OSD                              |
|  4 | I | Residual Length                           |
|  12|I/O| CDB                                       |
|  4 |   | Timeout Value                             |
|  4 | O | Message Buffer Pointer                    |
|  4 | O | Message Buffer Length                     |
|  2 | O | VU Flags                                  |
|  1 |   | Tag Queue Action                          |
|  1 |   | Tag ID                                    |
|  1 | I | Initiator ID                              |
|  1 |   | Reserved                                  |
|  n |   | Private Data                              |
+====================================================+

11.3 Host Target Mode

11.3.1 Host Target Mode Functionality Not Specified
 
This standard does not address the following SCSI functionality for
Host Target Mode operation:
    A)     LUNTAR
    B)     Linked Commands
    C)     Extended Contingent Allegiance
    D)     Soft Reset


11.3.2 Host Target Mode Messages

The SCSI messages outlined below are in two main categories for Host
Target Mode. The  categories  are transparent message handling and
notification message handling.  These 2 main categories can further be
divided into mandatory messages and optional messages.  Transparent
message handling shall mean that the SIM/HBA shall handle the message
and that there is no notification of the message to a peripheral
driver. Notification message handling shall mean that the SIM/HBA
shall receive the message and notify the Host Target Mode peripheral
driver. For notification message handling the SIM/HBA shall maintain
certain state information about the message, but how that is
accomplished is left to the discretion of the SIM/HBA implementer.

    A)     Mandatory Transparent Message Handling 

        1)     Command Complete
        2)     Identify
        3)     Initiator Detected Error
        4)     Message Parity Error
        5)     Message Reject
        6)     No Operation

    B)     Optional Transparent Message Handling at the discretion of
           SIM/HBA.

        1)     Disconnect 
        2)     Ignore Wide Residue 
        3)     Modify Data Pointer 
        4)     Restore Pointers 
        5)     Save Data Pointers 
        6)     Synchronous Data Transfer Request 
        7)     Wide Data Transfer Request

    C)     Mandatory Message Handling that requires notification to the
           Host Target Mode peripheral driver.

        1)     Abort Message
               Host Target Mode peripheral driver shall be notified by the
               Immediate Notify CCB mechanism.

        2)     Bus Device Reset Message
               Host Target Mode peripheral driver shall be notified by the 
               Asynchronous Event mechanism.

    D)     Optional Message Handling that requires notification to the
           Host Target Mode peripheral driver. 

        1)     Abort Tag.  
        2)     Clear Queue  
        3)     Head of Queue Tag  (Note 1)
        4)     Ordered Queue Tag  (Note 1)
        5)     Simple Queue Tag  (Note 1)
        6)     Terminate I/O Process. 

        Note 1 - The handling of these messages are described in Clause 11.3.8

Note:   See Clause 11.3.3 (Use of the IMMEDIATE NOTIFY CCB), Clause 11.3.4
        (Enable Target Mode LUN for Host Target Mode), and Clause 11.3.8 (ACCEPT
        TARGET I/O and CONTINUE TARGET I/O CCB Operation) for clarification.


11.3.3 Use of the IMMEDIATE NOTIFY CCB

The IMMEDIATE NOTIFY CCB is for Host Target Mode use only. It is used
to notify the Host Target Mode peripheral driver of events detected by
the SIM/HBA.  The IMMEDIATE NOTIFY CCBs, once passed to the SIM/HBA by
the ENABLE LUN CCB, shall be maintained by the SIM/HBA for its
exclusive use. Ownership of  IMMEDIATE NOTIFY CCB(s) shall not be
returned to the Host Target Mode peripheral driver until the
successful completion of an DISABLE TARGET MODE LUN.  The IMMEDIATE
NOTIFY CCB contents shall be valid to the Host Target Mode peripheral
driver only at the point where the SIM/HBA does the callback for
notification of an event. The Host Target Mode peripheral driver
should at that point read its contents to determine event and sense
data.  Upon callback return, the contents of IMMEDIATE NOTIFY CCB
shall no longer be considered valid.

The Immediate Notify mechanism from the SIM/HBA has a corresponding
Notify Acknowledgement mechanism. The IMMEDIATE NOTIFY CCB shall
contain a unique sequence identifier for a Host Target Mode LUN. For
each event/message delivered to the Host Target Mode peripheral driver
by the callback mechanism, the Host Target Mode peripheral driver
shall do the following:

    A)     Any processing needed to comply with this specification and
           the SCSI-2 specification.

    B)     Issue a NOTIFY ACKNOWLEDGE CCB with the Sequence Identifier
           field set to the value from Sequence Identifier field of the
           IMMEDIATE NOTIFY CCB for the event/message being processed.

There shall be a one to one correspondence between the Immediate
Notify and the Notify Acknowledgement from the Host Target Mode
peripheral driver.  For each Immediate Notify for a LUN there shall be
a Notify Acknowledgement.

Sequence identifiers shall be unique for each Host Target Mode LUN.
There shall not be two identical sequence identifiers in use at the
same time for a Host Target Mode LUN. A sequence identifier is "in
use" from the time the peripheral driver callback is invoked until the
receipt of the Notify Acknowledgement from the peripheral driver.
Sequence Identifiers shall be non zero value(s).

If an event/message is detected by the SIM/HBA that requires a
notification back to the Host Target Mode peripheral driver and there
are no IMMEDIATE NOTIFY CCBs available, the SIM/HBA shall do the
following:

    A)     Record all information about the event/message  as specified
           later in this section, and preserve ordering                         of the
           event/message, in FIFO fashion. 

    B)     When an IMMEDIATE NOTIFY CCB becomes available for use the
           SIM/HBA shall notify the Host Target Mode peripheral driver
           using the mechanisms specified later in this section.

The ordering of Host Target Mode peripheral notification and when the
SIM/HBA release of the SCSI bus to a Bus Free state is not specified.
The change to Bus Free phase and the peripheral driver callback in
clause 11.3.3.1 may occur in either order, but both steps are
required.  In all other cases, the order in which  clause 11.3.3.1
lists operations is the order in which those operations shall be
performed.

The order in which the SIM/HBA places the Extended message arguments
into the IMMEDIATE NOTIFY CCB Message Arguments field for an Extended
message is specificed. After the Extended message code is received all
Extended message bytes recieved for the Extended message shall be
placed into the IMMEDIATE NOTIFY CCB Message Arguments field in
ascending order in the order that they were received. The first
Extended message argument byte received after the Extended message
code shall be placed into the Message Arguments array[0] field. The
next Extended message argument byte received shall be placed into the
Message Arguments array[1] field.

For the SCSI ABORT and CLEAR QUEUE messages, the order in which the
CCBs are returned to the Host Target Mode peripheral driver and the
IMMEDIATE NOTIFY CCB callback is done to the driver is specified. The
order shall be as follows:

    A)     All CONTINUE TARGET I/O CCBs

    B)     IMMEDIATE NOTIFY CCB callback to the Host Target Mode
           peripheral driver

11.3.3.1 The events/messages that use the Immediate Notify mechanism

11.3.3.1.1 Sense Data preservation where no nexus has been
established.
 
There are certain events that require or optionally provide for sense
data preservation by the target/LUN. These events are specified in the
SCSI-2 specification. If one of these events is detected by the
SIM/HBA, the SIM/HBA shall respond as follows:

    A)     Set the pathid of an IMMEDIATE NOTIFY CCB to the bus number of
           this bus, target id of the SIM/HBA, and LUN id from the
           IDENTIFY message. 

    B)     The SIM/HBA shall form correct sense data for the event and
           place the sense data in the sense buffer provided in the
           IMMEDIATE NOTIFY CCB. It shall not be considered an error if
           the sense buffer  bytes are NULL, indicating NOSENSE. However
           the Host Target Mode peripheral driver is not required to
           preserve NOSENSE data.

    C)     The SIM/HBA shall set the CAM Status to Nexus Not Established
           in the IMMEDIATE NOTIFY CCB indicating that a nexus was not
           yet established. 

    D)     The SIM/HBA shall indicate in the CAM Status field of the
           IMMEDIATE NOTIFY CCB that Autosense is valid. Autosense valid
           indicates to the Host Target Mode peripheral driver that the
           sense buffer data is valid and can be copied. The Host Target
           Mode peripheral shall save the copied sense data for use if
           the next received command is request sense.

    E)     The SIM/HBA shall form an unique sequence identifier and place
           it in the IMMEDIATE NOTIFY CCBs sequence identifier field.

    F)     The SIM/HBA shall transition the SCSI Bus to BUS FREE. The
           SIM/HBA shall callback the Host Target Mode peripheral driver
           using the callback notify field in the available IMMEDIATE
           NOTIFY CCB. The exact order of these two operations is not
           specified.

    G)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY until all
           events are acknowledged events by the Host Target  Mode
           peripheral driver.

    H)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Unacknowledged Event by Host

        2)     A return status of Unacknowledged Event by Host.

Acknowledgment of this event by the Host Target Mode peripheral driver
shall be accomplished by the SIM/HBA receiving an NOTIFY AKNOWLEDGE
CCB for this LUN with the sequence identifier field equal to the
sequence identifier of the IMMEDIATE NOTIFY CCB for this event.

The Host Target Mode peripheral driver shall be responsible for
preserving Contingent Allegiance conditions.


11.3.3.1.2 Mandatory Messages

Mandatory messages that are handled jointly between the SIM/HBA and
the corresponding Host Target Mode peripheral driver.

Note:   The ABORT message is the only mandatory message that is handled with the
        IMMEDIATE NOTIFY CCB. BUS DEVICE RESET messages are handled by the
        Asynchronous Event mechanism.

11.3.3.1.2.1 ABORT message

When the mandatory ABORT message is received for an enabled Host
Target Mode LUN by the SIM/HBA, the SIM/HBA  shall:

    A)     Accept the message. 

    B)     Set the Path ID of an IMMEDIATE NOTIFY CCB to the bus number
           of this bus. Set the Target ID of the SIM/HBA, and LUN ID from
           the IDENTIFY message. Set the Initiator ID field of the
           IMMEDIATE NOTIFY CCB to the ID of the Initiator that selected
           this SIM/HBA.

    C)     Set the IMMEDIATE NOTIFY CCB CAM Status to Message
           Received.

    D)     Form an unique sequence identifier and place it in the
           IMMEDIATE NOTIFY CCBs Sequence Identifier field.

    E)     Set the IMMEDIATE NOTIFY CCB Message Code field to the ABORT
           Message code.

    F)     All CONTINUE TARGET I/O CCBs for this I_T_L nexus shall have
           the CAM status set to Request Aborted by Host and shall be
           returned to the Host Target Mode peripheral driver by the
           CONTINUE TARGET I/O CCB callback mechanism.

    G)     The SIM/HBA shall transition the SCSI Bus to BUS FREE. The
           SIM/HBA shall callback the Host Target Mode peripheral driver
           using the callback notify field in the available IMMEDIATE
           NOTIFY CCB. The exact order of these two operations is not
           specified.

    H)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY until all
           events are acknowledged events by the Host Target Mode
           peripheral driver.

    I)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Request Aborted by Host

        2)     A return status of Request Aborted by Host.

Acknowledgment of this event by the Host Target Mode peripheral driver
shall be accomplished by the SIM/HBA receiving an NOTIFY ACKNOWLEDGE
CCB for this I_T_L nexus with the sequence identifier field equal to
the sequence identifier of the IMMEDIATE NOTIFY CCB for this event.
 

11.3.3.1.3 Optional messages

This clause describes optional messages that are handled by the
SIM/HBA with or without notification to the corresponding Host Target
Mode peripheral  driver.


11.3.3.1.3.1 Optional messages that are not supported
 
For all messages in this category which are not supported:

    A)     If the SIM/HBA can not provide support or the Host Target Mode
           peripheral driver has indicated through the ENABLE TARGET LUN
           CCB that a message is not supported, the SIM/HBA shall reject
           the message and shall continue normal bus processing.

    B)     No processing shall be required of the Host Target Mode
           peripheral driver.


11.3.3.1.3.2 ABORT TAG message

The ABORT TAG message shall be supported if Tagged Queue Operation is
active for this LUN. When the supported ABORT TAG message is received
for an enabled Host Target Mode LUN by the SIM/HBA, the SIM/HBA 
shall:

    A)     Accept the message.

    B)     Set the Path ID of an IMMEDIATE NOTIFY CCB to the bus number
           of this bus. Set the Target ID of the SIM/HBA, and LUN ID from
           the IDENTIFY message. Set the Initiator ID field of the
           IMMEDIATE NOTIFY CCB to the ID of the initiator that selected
           this SIM/HBA.

    C)     Set the IMMEDIATE NOTIFY CCB CAM Status to Message Received.

    D)     Set the IMMEDIATE NOTIFY CCB Message Code field to the ABORT
           TAG Message code. Place the Additional Arguments to the
           message (Queue Tag) in the Message arguments array of the
           IMMEDIATE NOTIFY CCB.

    E)     The SIM/HBA shall form an unique sequence identifier and place
           it in the IMMEDIATE NOTIFY CCBs sequence identifier field.

    F)     The SIM/HBA shall search the list of CONTINUE TARGET I/O
           CCB(s) for this I_T_L nexus looking for a match between the
           TAG ID field of the CCB and the Queue Tag of the I_T_L_Q
           nexus. If a match is found, that CONTINUE TARGET I/O CCBs CAM
           status shall be set to Request Aborted by Host and shall be
           returned to the Host Target Mode peripheral driver by the
           CONTINUE TARGET I/O CCB callback mechanism.

    G)     The SIM/HBA shall transition the SCSI Bus to BUS FREE. The
           SIM/HBA shall callback the Host Target Mode peripheral driver
           using the callback notify field in the available IMMEDIATE
           NOTIFY CCB. The exact order of these two operations is not
           specified.

    H)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY  until all
           events are acknowledged events by the Host Target Mode
           peripheral driver.

    I)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Unacknowledged Event by Host

        2)     A return status of Unacknowledged Event by Host.

Acknowledgment of this event by the Host Target Mode peripheral driver
shall be accomplished by the SIM/HBA receiving a NOTIFY ACKNOWLEDGE
CCB for this I_T_L nexus with the sequence identifier field equal to
the sequence identifier of the IMMEDIATE NOTIFY CCB for this event.

11.3.3.1.3.3 CLEAR QUEUE message
 
The CLEAR QUEUE message shall be supported if Tagged Queue Operation
is active for this LUN. When the supported CLEAR QUEUE message is
received for an enabled Host Target Mode LUN by the SIM/HBA, the
SIM/HBA  shall:

    A)     Accept the message.

    B)     Set the Path ID of an IMMEDIATE NOTIFY CCB to the bus
           number of this bus. Set the Target ID of the SIM/HBA, and
           LUN ID from the IDENTIFY message. Set the Initiator ID
           field of the IMMEDIATE NOTIFY CCB to the ID of the
           initiator that selected this SIM/HBA.

    C)     Set the IMMEDIATE NOTIFY CCB CAM Status to Message Received.

    D)     Set the IMMEDIATE NOTIFY CCB Message Code field to the  CLEAR
           QUEUE Message code.

    E)     The SIM/HBA shall form an unique sequence identifier and place
           it in the IMMEDIATE NOTIFY CCBs sequence identifier field.

    F)     All CONTINUE TARGET I/O CCBs for this I_T_L nexus, shall have
           the CAM status set to Request Aborted by Host and shall be
           returned to the Host Target Mode peripheral driver by the
           CONTINUE TARGET I/O CCB callback mechanism. Refer to the SCSI-
           2 specification clause 5.6.4 for any further clarification.

    G)     The SIM/HBA shall transition the SCSI Bus to BUS FREE. The
           SIM/HBA shall callback the Host Target Mode peripheral driver
           using the callback notify field in the available IMMEDIATE
           NOTIFY CCB. The exact order of these two operations is not
           specified.

    H)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY until all
           events are acknowledged events by the Host Target  Mode
           peripheral driver.

    I)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Unacknowledged Event by Host.

        2)     A return status of Unacknowledged Event by Host.

Acknowledgment of this event by the Host Target Mode peripheral driver
shall be accomplished by the SIM/HBA receiving a NOTIFY ACKNOWLEDGE
CCB for this LUN with the sequence identifier field equal to the
sequence identifier of the IMMEDIATE NOTIFY CCB for this event.

11.3.3.1.3.4  Head of Queue, Ordered Queue and Simple Queue messages

The handling of these messages is described in detail in Clause
11.3.8.


11.3.3.1.3.5 Terminate I/O Process message
 
When the supported TERMINATE I/O PROCESS message is received for an
enabled Host Target Mode LUN by the SIM/HBA, the SIM/HBA  shall:
    
    A)     If there is no current I/O process, the SIM/HBA shall reject
           the message, and no further processing is required.

    B)     If there is a current I/O process, accept the message.

    C)     If disconnects are mandatory the SIM/HBA shall disconnect from
           the bus. If disconnects are allowed the SIM/HBA should
           disconnect from the bus.

    D)     Set the Path ID of an IMMEDIATE NOTIFY CCB to the bus number
           of this bus. Set the Target ID of the SIM/HBA, and LUN ID from
           the IDENTIFY message. Set the Initiator ID field of the
           IMMEDIATE NOTIFY CCB to the ID of the initiator that selected
           this SIM/HBA.

    E)     The SIM/HBA shall form an unique sequence identifier and place
           it in the IMMEDIATE NOTIFY CCBs Sequence Identifier field.

    F)     Set the IMMEDIATE NOTIFY CCB CAM Status to Message Received.

    G)     Set the IMMEDIATE NOTIFY CCB Message Code field to the
           TERMINATE I/O PROCESS Message code.

    H)     The CONTINUE TARGET I/O CCB that is currently active for this
           I_T_L nexus shall have the CAM status set to  Terminate I/O
           Process, The Residual Length field shall be set to valid 
           number of bytes not transferred for this CCB. The CCB shall be
           returned to the Host Target Mode peripheral driver by the
           CONTINUE TARGET I/O CCB callback mechanism.

    I)     Call back the peripheral driver by the mechanism provided by
           the IMMEDIATE NOTIFY CCB.

    J)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY until all
           events are acknowledged events by the Host Target Mode
           peripheral driver.

    K)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Unacknowledged Event by Host

        2)     A return status of Unacknowledged Event by Host.

The Host Target Mode Peripheral driver shall:

    A)     If the Host Target Mode peripheral driver has other CONTINUE
           TARGET I/O CCBs associated with this terminated I/O process,
           the Host Target Mode peripheral driver shall issue an ABORT
           CCB for each one.

    B)     Acknowledgment of this event by the Host Target Mode
           peripheral driver shall be accomplished by the SIM/HBA
           receiving an NOTIFY ACKNOWLEDGE CCB for this I_T_L nexus with
           the sequence identifier field equal to the Sequence Identifier
           of the IMMEDIATE NOTIFY CCB for this event.

    C)     It shall be the responsibility of the Host Target Mode
           peripheral driver to respond with a CHECK CONDITION command
           status and sense data (if next command is a request sense).
           The Host Target Mode peripheral driver shall be responsible
           for preserving Contingent Allegiance conditions.

11.3.3.1.4 Resource Unavailable to SIM/HBA

If the SIM/HBA receives a CDB on the SCSI bus for an enabled LUN in
Host Target Mode that does not have any ACCEPT TARGET I/O CCBs
available for use, it shall do the following:

    A)     Set the Path ID of an IMMEDIATE NOTIFY CCB to the bus number
           of this bus. Set the Target ID of the SIM/HBA, and LUN ID from
           the IDENTIFY message. Set the Initiator ID field of the
           IMMEDIATE NOTIFY CCB to the ID of the initiator that selected
           this SIM/HBA.

    B)     Set the IMMEDIATE NOTIFY CCB CAM Status to Unavailable
           Resource.

    C)     The SIM/HBA shall form an unique sequence identifier and place
           it in the IMMEDIATE NOTIFY CCBs sequence identifier field.

    D)     The SIM/HBA shall transition the SCSI Bus to status phase and
           return BUSY SCSI status to the initiator. The SIM/HBA shall
           callback the Host Target Mode peripheral driver using the
           callback notify field in the available IMMEDIATE NOTIFY CCB.
           These operations shall be performed in the order shown here.

    E)     For all connections the SIM/HBA for this LUN shall
           transparently respond with a SCSI Status of BUSY until all
           events are acknowledged events by the Host Target  Mode
           peripheral driver.

    F)     All ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs received by
           the SIM/HBA for this LUN until all events are acknowledged by
           the Host Target Mode Peripheral driver shall be rejected with:

        1)     A CAM status field set to Unacknowledged Event by Host

        2)     A return status of Unacknowledged Event by Host.

Acknowledgment of this event by the Host Target Mode peripheral driver
shall be accomplished by the SIM/HBA receiving a NOTIFY ACKNOWLEDGE
CCB for this LUN with the sequence identifier field equal to the
sequence identifier of the IMMEDIATE NOTIFY CCB for this event.


11.3.4 IMMEDIATE NOTIFY CCB

The following lists the fields of the IMMEDIATE NOTIFY CCB.  No entry
under the "Dir" heading indicates that this  field is not being used
for the IMMEDIATE NOTIFY CCB.                                        
                     

                               Table 23 - IMMEDIATE NOTIFY CCB
+====-====-==================================================+
|Size|Dir | IMMEDIATE NOTIFY CCB                             |
|----+----+--------------------------------------------------|
|  4 | O  | Address of this CCB                              |
|  2 | O  | CAM Control Block Length                         |
|  1 | O  | Function Code     (IMMEDIATE NOTIFY )            |
|  1 | I  | CAM Status                                       |
|    |    | Connect ID                                       |
|  1 |    |     Reserved                                     |
|  1 | O  |     Path ID       (Bus no. of SIM/HBA  )         |
|  1 | I  |     Target ID     (Target ID of SIM/HBA)         |
|  1 | O  |     LUN                                          |
|  4 | O  | CAM Flags                                        |
|  4 | O  | Pointer to the sense buffer                      |
|  1 | O  | Length of the sense buffer                       |
|  4 | I  | Callback on notification                         |
|  1 | I  | Initiator ID      (ID of Initiator that selected |
|    |    |                    SIM/HBA )                     |
|  2 | I  | Sequence Identifier                              |
|  1 | I  | Message Code                                     |
|  7 | I  | Message Arguments                                |
+============================================================+

Fields Described:

The following are the only possible CAM status values for the
IMMEDIATE NOTIFY CCB passed to the SIM/HBA from the Host Target Mode
peripheral driver:
    -   Invalid Path ID - Indicates the Path ID is not known.
    -   Invalid Target ID - Indicates the Target ID is not that of the
        target device.
    -   Invalid LUN ID - Indicates the Target LUN is not in the valid
        range for LUNs.

The following are the only possible CAM status values for the
IMMEDIATE NOTIFY CCB passed from the SIM/HBA to the Host Target Mode
peripheral driver:
    -   Nexus Not Established
    -   Message Received 
    -   Unavailable Resource

The Pointer to Sense Buffer field shall contain a pointer to a buffer
having minimum of 18 bytes. 

The Sense Buffer Length field shall be the length of the sense buffer.
The length shall be at least 18.

Initiator ID field is the SCSI BUS ID of the Initiator that selected
the SIM/HBA.

The Message Code field is used to store the SCSI message code for
received messages.

The Message Arguments field is used to store SCSI message  arguments
received. 

11.3.5 NOTIFY ACKNOWLEDGE CCB

The following lists the fields of the NOTIFY ACKNOWLEDGE CCB. No entry
under the "Dir" heading indicates that this field is not being used
for the NOTIFY ACKNOWLEDGE CCB.

                              Table 24 - NOTIFY ACKNOWLEDGE CCB
+====-====-========================================+
|Size|Dir | NOTIFY ACKNOWLEDGE CCB                 |
|----+----+----------------------------------------|
|  4 | O  | Address of this CCB                    |
|  2 | O  | CAM Control Block Length               |
|  1 | O  | Function Code     (NOTIFY ACKNOWLEDGE) |
|  1 | I  | CAM Status                             |
|    |    | Connect ID                             |
|  1 |    |     Reserved                           |
|  1 | O  |     Path ID    (Bus no. of SIM/HBA )   |
|  1 | O  |     Target ID  (Target ID of SIM/HBA ) |
|  1 | O  |     LUN                                |
|  4 | O  | CAM Flags                              |
|  2 | O  | Sequence Identifier                    |
|  1 | O  | Event                                  |
|    | O  | 7 Reset Cleared                        |
|    |    | 6 - 0 Reserved                         |
|  1 |    | Reserved                               |
+==================================================+

Fields Described:

The following are the only possible CAM status values for the NOTIFY
ACKNOWLEDGE CCB passed to the SIM/HBA from the Host Target Mode
peripheral driver:
    -   Request Complete without error
    -   Invalid Path ID - Indicates the Path ID is not known.
    -   Invalid Target ID - Indicates the Target ID is not that of the
        target device.
    -   Invalid LUN ID - Indicates the Target LUN is not in the valid
        range for LUNs.

The following are the only possible CAM status values for the  NOTIFY
ACKNOWLEDGE CCB passed from the SIM/HBA to the Host Target Mode
peripheral driver:
    -   Invalid Request -  Unknown Sequence Identifier

The Sequence Identifier field is the sequence event identifier which
is being acknowledged.

The Event field is used for acknowledgement of events whose
notifications is delivered buy the Asynchronous Event mechanism  (Bus
Reset and Bus Device Reset message).  



11.3.6 Enable Target Mode LUN For Host Target Mode

It is recommended that the SIM/HBA reserve LUN 0 for Asynchronous
Event Notification. While it is not a requirement, it is a suggestion
due to the increased complexity required to handle both Host Target
Mode and AENs. If the SIM/HBA reserves LUN 0 for AENs then it shall
return the CAM Status of LUN Already Enabled for all ENABLE LUN CCBs
for LUN 0.

When a peripheral driver wishes to enable a LUN for Host Target Mode
it shall perform the following tasks:

    A)     Issue a PATH INQUIRY to the SIM/HBA to determine what features
           and options it supports.

    B)     If the Host Target Mode peripheral driver requires
           disconnecting from the SCSI bus after receiving a CDB,
           supports optional immediate notify message processing or the
           peripheral driver wishes to support tagged commands, it shall
           use the information returned from the PATH INQUIRY CCB to
           determine whether the SIM/HBA supports these capabilities.  It
           is recommended that the Host Target Mode peripheral driver
           return for the INQUIRY command data that reflects the features
           of the SIM/HBA. These features include Wide Bus 32, Wide Bus
           16, and Synchronous Data Transfers and are obtained from the
           PATH INQUIRY CCB.  If the SIM/HBA supports Tag Queuing and the
           Host Target Mode peripheral driver wishes to support the
           feature, it shall be reflected in INQUIRY data.

    C)     The Host Target Mode peripheral driver shall issue the SET
           ASYNCH CALLBACK CCB for each LUN that it will support to
           register for bus reset and bus device reset.

    Implementation Note:     The peripheral driver should prepare, if necessary,
                             to handle the Contingent Allegiance condition on a
                             per initiator basis.  Therefore the peripheral driver
                             may need to do some initial setup for this.

    D)     The Host Target Mode peripheral driver shall issue the ENABLE
           LUN CCB to the SIM to register for Host Target Mode with the
           SIM/HBA.  The ENABLE LUN CCB shall be setup as follows:

        1)     If the peripheral driver requires disconnects and the
               SIM/HBA supports disconnects (as determined by the
               Disconnects Supported field in the PATH INQUIRY CCB ), the
               Disconnect Mandatory bit in the target mode specific CAM
               flags field in the ENABLE LUN CCB shall be set.

        2)     If the peripheral driver supports tagged commands, and if
               the SIM/HBA supports Tagged Queuing, the Tag Queue Enable
               bit shall be set in the CAM flags field of the ENABLE LUN
               CCB.

        3)     A peripheral driver shall clear the Host Target Mode flag
               indicating this is a Host Target Mode ENABLE LUN CCB. The
               peripheral driver shall set in the Target Mode bits of the
               CAM flags all other optional settings it wishes to support.

        Editors note:        The Send Status Bit is for CONTINUE I/O CCBs
                             only. The ENABLE LUN CCB shall specify either
                             Host Target Mode or Phase Cognizant Mode operation.

        4)     The Immediate Notify CCB list pointer field shall point to
               a list of CCBs (of at least one) available to the SIM/HBA
               to use for Host Target Mode event/message notification.  It
               is recommended that there should at least one CCB for each
               and every initiator that this peripheral expects to have a
               connection with.  These CCBs are pre-allocated  CCBs from
               the XPT layer which are empty (NULL) except for the
               following:

           a)     The Address of this CCB and CAM Control Block Length,
                  shall contain the proper information as defined
                  previously in this specification.

           b)     The completion callback function shall be set to the
                  Immediate Notify callback function. This is the function
                  in the peripheral driver to be called when a event is
                  detected by the SIM/HBA. These events are described in
                  Clause 11.3.3.

           c)     The function code shall be set to IMMEDIATE NOTIFY. 

           d)     The pointer to the sense buffer, and the length of the
                  sense buffer shall be set. The sense buffer length shall
                  be a minimum of 18 bytes.

           Note:  See clause 11.3.11 (Disable of Host Target Mode LUN) for the
                  mechanism on how to retrieve ownership of the IMMEDIATE NOTIFY
                  CCBs.

        5)     The ACCEPT TARGET I/O CCB list pointer field shall point to
               a list of CCBs (of at least one) available to the SIM to
               use for Host Target Mode operation.  These CCBs are
               pre-allocated CCBs from the XPT layer which are empty
               (NULL) except for the following:

           a)     The Address of this CCB and CAM Control Block Length.
                  These fields shall contain the proper information as
                  defined previously in this specification.

           b)     The completion callback function shall be set to the CDB
                  received callback function. This is the function in the
                  peripheral driver to be called when a CDB is received
                  error free from an initiator by the SIM.

           c)     The function code shall be set to ACCEPT TARGET I/O. 

           d)     If the CDB Pointer bit is set in the flags field of the
                  ACCEPT TARGET I/O CCB, the cdb pointer and cdb length
                  field shall be set.

           e)     The pointer to the sense buffer, and the length of the
                  sense buffer shall be set.. The sense buffer length
                  shall be a minimum of 18 bytes.

           Note:  For error conditions detected by the SIM/HBA,  the sense
                  buffers in both the ACCEPT TARGET I/O and CONTINUE TARGET I/O
                  CCBs are used to report proper sense data back to the Host
                  Target Mode peripheral driver. i.e. Memory/RAM failures that
                  the peripheral driver has no knowledge of unless reported by
                  the SIM/HBA.

        6)     If Group 6 and/or 7 commands are to be supported by the
               Host Target Mode peripheral driver, then the Group 6 and/or
               7 Vendor Unique CDB Length fields shall contain the number
               of bytes for these CDB group codes. If Group 6 and/or 7
               commands are not supported by the Host Target Mode
               peripheral driver, then the Group 6 and/or 7 Vendor Unique
               CDB Length fields shall be equal to zero. If the Host
               Target Mode peripheral driver supports Group 6 and/or 7
               commands, then the Host Target Mode peripheral driver shall
               ensure that all ACCEPT TARGET I/O CCBs passed to the
               SIM/HBA contain sufficient storage for the received CDB. If
               a vendor unique command CDB is greater than the CDB field
               for the ACCEPT TARGET I/O is desired, then the CDB field
               shall contain a pointer to a buffer of sufficient length.

    E)     The Host Target Mode peripheral driver shall verify that the
           ENABLE LUN succeeded by checking that the CAM status in the
           ENABLE LUN CCB is set to Request Completed Without Error.

    F)     The Host Target Mode peripheral driver may add to the list of
           ACCEPT TARGET I/O CCBs by issuing an ACCEPT TARGET I/O CCB to
           the SIM/HBA anytime after the LUN has been enabled.

    G)     The Host Target Mode peripheral driver may add to the list of
           IMMEDIATE NOTIFY CCBs by issuing an IMMEDIATE NOTIFY CCB to
           the SIM/HBA anytime after the LUN has been enabled.

    Note:  Once an IMMEDIATE NOTIFY CCB is given to an enabled Host Target Mode
           SIM/HBA, ownership of the CCB remains with the SIM/HBA until the LUN
           is disabled.

When the SIM/HBA receives Host Target Mode ENABLE LUN CCB with a non
zero number of Target CCBs from the Host Target Mode peripheral
driver, it shall do the following:

    A)     If the LUN is already enabled, the ENABLE LUN CCB shall be
           returned with a CAM status of LUN Already Enabled.

    B)     If the path id, target id or target LUN specified in the
           ENABLE LUN CCB are invalid then the ENABLE LUN shall be failed
           with the proper CAM status. (see Table 10-6).

    C)     The SIM/HBA shall check that the ENABLE LUN CCB Immediate
           Notify CCB pointer field is non NULL and for each IMMEDIATE
           NOTIFY in the list, the Immediate Notify CCB notify callback
           field is set. The SIM/HBA shall check that the pointer to the
           sense buffer is non NULL and length of the sense buffer is a
           minimum of 18 bytes for each IMMEDIATE NOTIFY CCB. If either
           the ENABLE LUN CCB or the IMMEDIATE NOTIFY CCB is found to be
           in error, then the ENABLE LUN CCB shall fail with Request
           Completed With Error.

    D)     The SIM/HBA shall check that the ENABLE LUN CCB Target CCB
           pointer field is non NULL and for each ACCEPT TARGET I/O CCB
           in the list, the ACCEPT TARGET I/O CCB Callback on Completion
           field is set. The SIM/HBA shall check that the pointer to the
           sense buffer is non NULL and length of the sense buffer is a
           minimum of 18 bytes for each ACCEPT TARGET I/O CCB. If either
           the ENABLE LUN CCB or an ACCEPT TARGET I/O CCB is found to be
           in error, then the ENABLE LUN CCB shall fail with Request
           Completed With Error.

    E)     The SIM/HBA shall check the Host Target Mode options in the
           target mode specific CAM flags field of the ENABLE LUN CCB. If
           specific target mode options are set in this field and the SIM
           does not support these options, the ENABLE LUN CCB shall be
           returned with a CAM status of Invalid Request.

    F)     The SIM/HBA shall check whether the Tagged Queue Enable bit is
           set in the CAM flags field of the ENABLE LUN CCB.  If the
           Tagged Queue Enable bit is set but the SIM does not support
           tagged commands, the ENABLE LUN CCB shall be returned with a
           CAM status of Invalid Request.

    G)     If preceding checks complete without error, the CAM status of
           the ENABLE LUN CCB shall be set to Request Completed and the
           CCB returned.


11.3.7 ENABLE LUN CCB For Host Target Mode

The following lists the fields of the ENABLE LUN CCB. No entry under
the "Dir" heading indicates that this field is not being used for the
ENABLE LUN CCB.

                       Table 25 - ENABLE LUN CCB For Host Target Mode
+====-===-============================================+
|Size|Dir| ENABLE LUN CCB                             |
|----+---+--------------------------------------------|
|  4 | O | Address of this CCB                        |
|  2 | O | CAM Control Block Length                   |
|  1 | O | Function Code               (ENABLE LUN)   |
|  1 | I | CAM Status                                 |
|    |   | Connect ID                                 |
|  1 |   |     Reserved                               |
|  1 | O |     Path ID       (Bus no. of SIM/HBA)     |
|  1 | O |     Target ID     (Target ID of SIM/HBA)   |
|  1 | O |     LUN                                    |
|  4 | O | CAM Flags                                  |
|  2 | O | Group 6 Vendor Unique CDB Lengths          |
|  2 | O | Group 7 Vendor Unique CDB Lengths          |
|  4 | O | Pointer to Immediate Notify CCB List       |
|  4 | O | Number of Immediate Notify CCBs            |
|  4 | O | Pointer to Target CCB list                 |
|  2 | O | Number of Target CCBs                      |
|  n |   | SIM private                                |
+=====================================================+


Fields Described:

The following are the only possible CAM status return values for the
ENABLE LUN CCB:
    -   Request Completed without Error - Completed without error.
    -   Request Completed with Error - Invalid field(s) within the CCBs.
    -   LUN Already Enabled - The specified target mode LUN is already
        enabled.
    -   Invalid Path ID - Indicates the Path ID is not known.
    -   Invalid Target ID - Indicates the Target ID is not that of the
        peripheral device.
    -   Invalid LUN ID - Indicates the Target LUN is not in the valid
        range for LUNs.
    -   Invalid Request 
        For ENABLE LUN CCB with a list count greater than zero, this
        value can indicate one of the following:

        A)     The SIM does not support target mode.

        B)     The peripheral driver requires disconnects but the SIM does
               not support disconnects.

        C)     The peripheral driver requested the ability to run tagged
               but the SIM does not support this feature.

        D)     A field within an ACCEPT TARGET I/O or IMMEDIATE NOTIFY CCB
               is invalid.
        
    -   Invalid Request 
        For ENABLE LUN CCB with a list count of zero (DISABLE LUN) see
        section 11.3.11. 

The following are the only possible CAM Flags bits which are valid for
the ENABLE LUN CCB:
    -   Tagged Queue Action Enable - Indicates to the SIM/HBA that the
        peripheral driver requires tagged queued operation.
    -   Disconnects Mandatory - Indicates to the SIM/HBA that any
        Identify message received shall have the DiscPriv bit set. Clause
        11.3.8.2 describes the SIM/HBA response if the DiscPriv bit is
        not set when Disconnect Mandatory CAM Flag indicates that it is
        required.

The Pointer to Target CCB List field shall contain a pointer to a list
of ACCEPT TARGET I/O CCBs for the Enable LUN request.  For the Disable
LUN request, this field shall be NULL.

The Number of Target CCBs shall be set to the number of CCBs pointed
to by the Pointer to Target CCB List field for the Enable LUN request. 
For the Disable LUN request this field shall be zero.

The Pointer to Immediate Notify CCB List field shall contain a pointer
to a list of IMMEDIATE NOTIFY CCBs for the Enable LUN request.  For
the Disable LUN request, this field shall be NULL.

The Number of Immediate Notify CCBs shall be set to the number of CCBs
pointed to by the Pointer to Immediate Notify CCB List field for the
Enable LUN request.  For the Disable LUN request this field shall be
zero.


11.3.8 ACCEPT TARGET I/O and CONTINUE TARGET I/O CCB Operation

11.3.8.1 SIM/HBA ACCEPT TARGET I/O CCB Acceptance

When the SIM/HBA receives an ACCEPT TARGET I/O CCB from a Host Target
Mode peripheral driver, it shall do the following:

    A)     Check whether there are outstanding unacknowledged events for
           this I_T_L nexus, if there are any the SIM/HBA shall  set the
           CAM status and the xpt_action() return status to
           Unacknowledged Event by Host and return.

    B)     Check that the path id, target id, and target LUN specified in
           the ACCEPT TARGET I/O CCB is that of an enabled LUN.  If the
           LUN is not enabled, the CCB CAM status and xpt_action() return
           status shall be Path Invalid.

    C)     Check that the CDB completion function is set in the ACCEPT
           TARGET I/O CCB. If it is not set, the CCB CAM status and
           xpt_action() return status shall be Request Completed With
           Error.

    D)     Check that the pointer to the sense buffer is set, and that
           the sense buffer length is a minimum of 18 bytes.  If not
           correct, the CCB CAM status and xpt_action() return status
           shall be Request Completed With Error.

    E)     Otherwise the xpt_action() return status shall be Request in
           Progress.

11.3.8.2 SIM/HBA CDB Reception

When the SIM/HBA receives a CDB on the SCSI bus for an enabled LUN in
Host Target Mode, it shall do the following:

    A)     If the disconnect privilege bit is not set in the IDENTIFY
           message and the Disconnect Mandatory bit was set in the target
           mode specific CAM flags field of the ENABLE LUN CCB, then the
           SIM shall go to BUS FREE.  
        Note:  Refer to Clause 11.3.3 (Use of the IMMEDIATE NOTIFY CCB) for
               reference in handling this condition. Additional information can
               be found in the SCSI-2 specification Clause 5.1.1 BUS FREE.

    B)     Otherwise, the SIM shall remove a CCB from the SIM's list of
           available ACCEPT TARGET I/O CCBs which were sent down with the
           ENABLE LUN  or ACCEPT TARGET I/O commands. If there are no
           CCBs available, then the SIM shall go to status phase and
           return BUSY SCSI status to the initiator. The SIM/HBA shall
           notify the Host Target Mode peripheral driver of this event by
           the Immediate Notify mechanism described in Clause 11.3.3.

    C)     The ACCEPT TARGET I/O CCB shall be filled in with the
           following information:
        1)     The target ID of this SIM/HBA.
        2)     Bus ID of the SIM/HBA. 
        3)     LUN ID. 
        4)     The CDB data received from the initiator. 
        5)     The SCSI Bus ID of the initiator that selected this SIM/HBA
               in the Initiator ID field.

    D)     The CAM status shall be set to CDB Received.

    E)     If this is a tagged request then the SIM/HBA shall do the
           following: 

        1)     The SIM/HBA shall check whether the Host Target Mode
               peripheral driver has enabled tagged queuing with the
               ENABLE LUN command for this LUN.  If the peripheral driver
               does not support tagged commands then the SIM/HBA shall
               reject the QUEUE TAG message and continue as specified in
               SCSI-2 Clause 5.6.14 (Message Reject).

        2)     If the Host Target Mode peripheral driver does support
               tagged  commands, the following shall occur:

           a)     The QUEUE TAG message (HEAD OF QUEUE TAG, ORDERED QUEUE
                  TAG, or SIMPLE QUEUE TAG) shall be  placed in the Tag
                  Queue Action field of  the ACCEPT TARGET I/O CCB.

           b)     The queue tag value shall be placed in the  tag id field
                  of the ACCEPT TARGET I/O CCB. 

    F)     If the peripheral driver requires disconnects, the SIM shall
           disconnect from the bus. If disconnects are not required but
           are allowed (IDENTIFY) the SIM/HBA should  disconnect from the
           bus. 

    G)     Call the peripheral driver CDB completion callback function
           provided in the ACCEPT TARGET I/O CCB Callback on Completion
           field.

    Note:  The SIM/HBA shall handle  SDTR and WDTR messages transparently.


11.3.8.3 Host Peripheral Driver CDB Completion Callback

When the peripheral driver's CDB completion callback function is
called,  it shall do the following:

    A)     Determine how it will respond to the SCSI command specified in
           the CDB. The peripheral driver may use the same CCB (although
           this is not a requirement) for the CONTINUE TARGET I/O
           function, filling in the connect id, initiator id, function
           code, the data pointer (if needed), data count (if needed),
           data direction (if any), the callback completion function, and
           the queue tag id if running tagged. If a data transfer is
           required then the Direction bits shall be set in the CAM flags
           field of the CONTINUE TARGET I/O CCB. If disconnects are
           enabled, the peripheral driver may require a SAVE DATA
           POINTERS message and DISCONNECT message after  transferring
           some of the data. If the request is to be completed then the
           SEND_STATUS bit shall be set in the CAM flags field of the
           CONTINUE TARGET I/O CCB and the SCSI status field shall
           contain the SCSI status to be returned to the initiator.

    B)     If a CHECK CONDITION SCSI status is to be returned to the
           initiator, then the Host Target Mode peripheral driver shall
           setup and maintain the CONTINGENT ALLEGIANCE condition as
           specified in SCSI-2.

     Note:     Peripheral driver sense data shall always represent the current
               status of the peripheral driver.

    C)     The peripheral driver shall then call the XPT/SIM via 
           xpt_action() passing the CONTINUE TARGET I/O CCB.

    D)     On return from the xpt_action() call, the peripheral driver
           shall check that the return value from xpt_action() is Request
           in Progress. If a status other than Request in Progress is
           returned, then the command could not be completed to the
           initiator (possibly due to a bus reset or the receipt of a
           message). It is the responsibility of the peripheral driver to
           handle the condition correctly.

Note:   Refer to Clause 13.3.3 (Use of the IMMEDIATE NOTIFY CCB) for additional
        information. 

11.3.8.4 SIM/HBA CONTINUE TARGET I/O CCB Acceptance

When the SIM/HBA receives a CONTINUE TARGET I/O CCB it shall do the
following:

    A)     If the SIM/HBA is recovering from a bus reset or bus device
           reset, or an Immediate Notify Condition the CAM status and the
           xpt_action() return status shall be set appropriately.

    B)     Check whether there are outstanding unacknowledged events for
           this I_T_L nexus, if there are any the SIM/HBA shall  set the
           CAM status and the xpt_action() return status to
           Unacknowledged Event by Host and return. 

    C)     Otherwise, the SIM shall set the CAM status and xpt_action()
           return value to Request in Progress.

    D)     If disconnects are not enabled, the SIM shall perform the
           necessary phase transitions. If disconnects are enabled,  the
           SIM/HBA shall reselect the initiator, when possible, to
           perform the necessary phase transitions and reestablish the
           I_T_L or I_T_L_Q nexus. 

        1)     If the Direction Bits are set specifying DATA In ( data to
               initiator) or DATA Out (data from the initiator )in the CAM
               flags field of the CONTINUE TARGET I/O CCB, then data shall
               be transferred.

        2)     If the SEND_STATUS bit is set in the CAM Flags field of the
               CONTINUE TARGET I/O CCB, the SIM shall go to status phase
               and complete the request.

        3)     If disconnects are enabled and the SEND_STATUS bit is not
               set in the CAM flags field of the CONTINUE TARGET I/O CCB,
               the SIM shall disconnect.

        4)     After all data specified in the CCB has been sent and/or
               SCSI status has been sent, the peripheral driver's callback
               completion function in the CONTINUE TARGET I/O CCB shall be
               called with a CAM status of Request Completed Without
               Error.

11.3.8.5 Host Target Mode Peripheral Driver CONTINUE TARGET I/O
Callback

The peripheral driver's CONTINUE TARGET I/O callback completion
function shall:

    A)     If the CAM status is not Request Complete Without Error, then
           an error has occurred. The Host Target Mode  peripheral driver
           shall be responsible for forming sense data, if applicable and
           for maintaining it.  The sense data conditions are defined in
           the SCSI-2 specification. The Host Target Mode peripheral
           driver also shall be responsible for maintaining the
           CONTINGENT ALLEGIANCE condition associated with the sense
           data.

    B)     If the request completed and the peripheral driver has more
           data and/or status to send to the initiator then a CONTINUE
           TARGET I/O CCB shall be sent to the SIM with the proper fields
           set.

    C)     If status has been sent to the initiator then the peripheral
           driver may reissue the same CCB by calling the XPT/SIM passing
           the same CCB. The CCB shall have all fields properly set for
           the ACCEPT TARGET I/O CCB as specified in this document. The
           SIM/HBA  can now reuse this CCB to accept a new connection for
           the CDB received.

    D)     If status has not been sent, then the Host Target Mode
           peripheral driver can reissue the CCB as a CONTINUE TARGET I/O
           CCB after it has been set up.

11.3.8.6 Command Reception Errors and Data Phase Errors Handling.

If the command Group code is not supported (Groups 3,4,6 or 7) or
there were errors in the incoming CDB that could not be handled
transparently, the SIM/HBA shall do the following:

Note:   Additional information can be found in the SCSI-2 specification Clause
        5.1.1 BUS FREE.

    A)     Set the proper Connect ID in the ACCEPT TARGET I/O CCB, and
           the Target ID of the initiator that selected this SIM/HBA in
           the Initiator ID field.

    B)     If the condition was an error in incoming the CDB, the SIM/HBA
           shall form correct SCSI sense data and place it in the ACCEPT
           TARGET I/O CCB sense buffer.  The SIM/HBA shall also indicate
           that sense data is valid by setting the Autosense flag in CAM
           Status and set the SCSI Status field to CHECK CONDITION.

    C)     For a Tagged Queue I/O process: 

        Note:  If the SIM/HBA or the Host Target Mode peripheral driver has
               indicated that Queue Tags are not supported, the QUEUE TAG message
               shall have been rejected. 

        1)     The QUEUE TAG message (HEAD OF QUEUE TAG, ORDERED QUEUE
               TAG, or SIMPLE QUEUE TAG) is  placed in the Tag Queue
               Action field of the ACCEPT TARGET I/O CCB.

        2)     The QUEUE TAG value shall be placed in the Tag ID
               field of the ACCEPT TARGET I/O CCB. 

        3)     The Tagged Queue Action Enable bit shall be set in the CAM
               flags field of the ACCEPT TARGET I/O CCB.

    D)     Due to the variety of SIM/HBA functionality and bus
           conditions, the SIM/HBA shall release the SCSI BUS in one of
           the following ways:

        1)     If the peripheral driver required disconnects, the SIM
               shall disconnect from the bus. If disconnects are not
               required but are allowed  (IDENTIFY), the SIM/HBA should
               disconnect from the bus. 

               If the SIM/HBA disconnects from the bus, then the CAM
               status in the ACCEPT TARGET I/O CCB shall be set to Invalid
               CDB. 

        2)     Cause an unexpected bus free.  See Clause 5.1.1 in the
               SCSI-2 specification.

           If the SIM/HBA causes an unexpected BUS FREE condition, then
           the CAM status in the ACCEPT TARGET I/O CCB shall be set to
           Unexpected Bus Free.

           Note:  The Unexpected Bus Free Cam status ends the I/O process and
                  the Host Target Mode peripheral driver should not try to
                  terminate it.

    E)     Call back the peripheral driver using the callback field
           within the ACCEPT TARGET I/O CCB.

It is the responsibility of the Host Target peripheral driver to
preserve Contingent Allegiance. If the CAM status is not Unexpected
Bus Free, it shall also complete the bus transaction by sending a
CONTINUE TARGET I/O CCB to properly terminate this connection.

If the SIM/HBA detects data/bus phase error that cannot be handled
transparently or other unrecoverable errors, (except  timeouts) while
processing a CONTINUE TARGET I/O CCB, the SIM/HBA shall:

    A)     Set the proper Connect ID in the CONTINUE TARGET I/O CCB, and
           the Target ID of the initiator that selected this SIM/HBA in
           the Initiator ID field.

    B)     The SIM/HBA shall form correct SCSI sense data and place it in
           the CONTINUE TARGET I/O CCB sense buffer. The SIM/HBA shall
           also indicate that sense data is valid by setting the
           Autosense flag in CAM Status and set the SCSI Status field to
           CHECK CONDITION.

    C)     For a Tagged Queue I/O process: 

        1)     The queue tag value shall be placed in the Tag ID field of
               the CONTINUE TARGET I/O CCB.

        2)     The Tagged Queue Action Enable bit shall be set in the CAM
               flags field of the CONTINUE TARGET I/O CCB.

    D)     Due to the variety of SIM/HBA functionality and bus
           conditions, the SIM/HBA shall release the SCSI BUS in one of
           the following ways:

        1)     If the peripheral driver required disconnects, the SIM
               shall disconnect from the bus. If disconnects are not
               required but are allowed (IDENTIFY), the SIM/HBA should
               disconnect from the bus. If the SIM/HBA disconnects from
               the bus, then the CAM status in the CONTINUE TARGET I/O CCB
               shall be set to one of the following: 

           a)     Target Bus phase sequence failure 

           b)     Uncorrectable Parity error detected

        2)     Cause an unexpected bus free. See Clause 5.1.1 in the SCSI-
               2 specification.

           If the SIM/HBA causes an unexpected BUS FREE condition, then
           the CAM status in the CONTINUE TARGET I/O CCB shall be set to
           Unexpected Bus Free.

           Note:  The Unexpected Bus Free Cam status ends the I/O process and
                  the Host Target Mode peripheral driver should not try to
                  terminate it.

    E)     Call back the peripheral driver using the callback field
           within the CONTINUE TARGET I/O CCB.

    It is the responsibility of the Host Target peripheral driver to
    preserve Contingent Allegiance. If the CAM status is not Unexpected
    Bus Free, it shall also complete the bus transaction by sending a
    CONTINUE TARGET I/O CCB to properly terminate this connection.

11.3.8.7 ACCEPT and CONTINUE TARGET I/O CCB TIMEOUTS

The timeout periods specified in the CCBs shall be measured in seconds
and handled in the following manner:

    A)     ACCEPT TARGET I/O TIMEOUTS

        1)     The timeout period shall be from SIM/HBA selection to the
               next bus free or the receipt of a CONTINUE TARGET I/O CCB
               that causes a phase transition. The timeout period then
               shall change to that of the CONTINUE TARGET I/O CCB that
               caused the phase transition or command complete.

        Note:  For this example Disconnects are mandatory.
               -   When the SIM/HBA is selected  by an initiator, the timeout
                  period starts. 
               -  The IDENTIFY message is received and SIM/HBA drives the bus to
                  command phase. 
               -  The command is received and SIM/HBA disconnects. 
               -  When the SIM/HBA disconnects from the bus (bus free) the
                  timeout period ends,  but no action is taken. 
               -  If the timer expired before the disconnect then this ACCEPT
                  TARGET I/O CCB shall represent a timeout condition.

               For this example Disconnects are not allowed. 
               -  When the SIM/HBA is selected by an initiator, the timeout
                  period starts. 
               -  The IDENTIFY message is received and SIM/HBA drives the bus to
                  command phase. 
               -  The command is received but SIM/HBA is not allowed to
                  disconnect. 
               -  The SIM/HBA  calls back the Host Target Mode peripheral
                  driver. 
               -  The Host Target Mode peripheral driver responds with a
                  CONTINUE TARGET I/O CCB that causes a transition to data
                  phase. 
               -  The ACCEPT TARGET I/O timeout period ends and a new period
                  begins as specified by the CONTINUE TARGET I/O CCB.
        End Note:

        2)     If the timeout period expires for the ACCEPT TARGET I/O
               CCB, the SIM/HBA shall set the CAM status to Command
               Timeout.

        3)     The proper Connect ID shall be set in the ACCEPT TARGET I/O
               CCB. The SCSI  BUS ID of the initiator that selected this
               SIM/HBA shall be set in the Initiator ID field.

        4)     The SIM/HBA shall cause an unexpected bus free. See Clause 
               5.1.1 in the SCSI-2 specification.

        5)     Call back the peripheral driver using the callback field
               within the ACCEPT TARGET I/O CCB.

    B)     CONTINUE TARGET I/O TIMEOUTS

        1)     The time period shall be measured from SIM/HBA reselection
               of the initiator to the next bus free or the receipt of a
               CONTINUE TARGET I/O CCB which causes a phase transition. 
               The timeout period then shall change to that of the
               CONTINUE TARGET I/O CCB which caused the phase transition
               or command complete.

        2)     If the timeout period expires for the CONTINUE TARGET I/O
               CCB, the SIM/HBA shall set the CAM status to Command
               Timeout.

        3)     The proper Connect ID shall be set in the CONTINUE TARGET
               I/O CCB. The SCSI BUS ID of the initiator that selected
               this SIM/HBA shall be set in the Initiator ID field.

        4)     If a data transfer has been specified for this CCB, the
               Residual Length shall be set to the number of bytes not
               transferred.
         
        5)     The SIM/HBA shall cause an unexpected bus free.  See Clause
               5.1.1 in the SCSI-2 specification.

        6)     Call back the peripheral driver using the callback field
               within the CONTINUE TARGET I/O CCB.

    The Host Target Mode  peripheral driver shall be responsible for
    forming and maintaining sense data for all timeouts. The Host
    Target Mode peripheral driver shall maintain the CONTINGENT
    ALLEGIANCE condition associated with any sense data.


11.3.9 ACCEPT TARGET I/O CCB

The following lists the fields of the ACCEPT TARGET I/O CCB. No entry
under the "Dir" heading indicates that this field is not being used
for the ACCEPT TARGET I/O function.

                              Table 26 - ACCEPT TARGET I/O CCB
+====-===-===========================================+
|Size|Dir| ACCEPT TARGET I/O CCB                     |
|----+---+-------------------------------------------|
|  4 | O | Address of this CCB                       |
|  2 | O | CAM Control Block Length                  |
|  1 | O | Function Code     (ACCEPT TARGET I/O)     |
|  1 | I | CAM Status                                |
|    |   | Connect ID                                |
|  1 |   |     Reserved                              |
|  1 | O |     Path ID       (Bus no. of SIM/HBA)    |
|  1 | O |     Target ID     (Target ID of SIM/HBA ) |
|  1 | O |     LUN                                   |
|  4 |I/O| CAM Flags                                 |
|  4 | O | Peripheral Driver Pointer                 |
|  4 |   | Next CCB Pointer                          |
|  4 | O | Request Mapping Information (If needed)   |
|  4 | O | Callback on Completion                    |
|  4 |   | SG List/Data Buffer Pointer               |
|  4 |   | Data Transfer Length                      |
|  4 | O | Sense Info Buffer Pointer                 |
|  4 | O | Sense Info Buffer Length                  |
|  1 |I/O| CDB Length                                |
|  2 |   | Number of Scatter/Gather Entries          |
|  4 |   | VU Field                                  |
|  1 | I | SCSI Status                               |
|  2 |   | Autosense Residual Length                 |
|  2 |   | Reserved OSD                              |
|  4 |   | Residual Length                           |
|  12|I/O| CDB                                       |
|  4 | O | Timeout Value                             |
|  4 |   | Message Buffer Pointer                    |
|  4 |   | Message Buffer Length                     |
|  2 |   | VU Flags                                  |
|  1 | I | Tag Queue Action                          |
|  1 | I | Tag ID                                    |
|  1 | I | Initiator ID                              |
|  1 |   | Reserved                                  |
|  n |   | Private Data                              |
+====================================================+

Fields Described:

The following lists the possible CAM status values of the ACCEPT
TARGET I/O CCB:
    -   Request Completed with Error 
    -   CDB Received - Indicates that the CCB contains a CDB received
        from an initiator.
    -   Invalid CDB - Target Mode CDB error
    -   Request Aborted by Host 
    -   Bus Reset - This SIM is recovering from a bus reset.
    -   Bus Device Reset - This SIM is recovering from a BUS DEVICE RESET
        message.
    -   Command Timeout - Time period specified expired 
    -   Path Invalid 
    -   Unexpected Bus Free
    -   Unacknowledged Event by Host - An event has not been acknowledged
        by the Host Target Mode peripheral driver.

The only valid bits for the CAM flags field are the following:
    -   CDB is a Pointer - Indicates the CDB contained in the ACCEPT
        TARGET I/O CCB is a pointer. The CDB Length field shall indicate
        the size of the CDB buffer.
    -   CDB Physical - Indicates whether the pointer address is virtual
        or physical. 
    -    Sense Buffer - Indicates whether the pointer address is virtual
        or physical. 
    -   Callback on Comp. 


11.3.10 CONTINUE TARGET I/O CCB

The following lists the fields of the CONTINUE TARGET I/O CCB. No
entry under the "Dir" heading indicates that this field is not being
used for the CONTINUE TARGET I/O function.
                                         
                             Table 27 - CONTINUE TARGET I/O CCB
+====-===-===========================================+
|Size|Dir| CONTINUE TARGET I/O CCB                   |
|----+---+-------------------------------------------|
|  4 | O | Address of this CCB                       |
|  2 | O | CAM Control Block Length                  |
|  1 | O | Function Code    (CONTINUE TARGET I/O)    |
|  1 | I | CAM Status                                |
|    |   | Connect ID                                |
|  1 |   |     Reserved                              |
|  1 | O |     Path ID       (Bus no. of SIM/HBA)    |
|  1 | O |     Target ID     (Target ID of SIM/HBA)  |
|  1 | O |     LUN                                   |
|  4 |I/O| CAM Flags                                 |
|  4 | O | Peripheral Driver Pointer                 |
|  4 |   | Next CCB Pointer                          |
|  4 | O | Request Mapping Information (if Needed)   |
|  4 | O | Callback on Completion                    |
|  4 | O | SG List/Data Buffer Pointer               |
|  4 | O | Data Transfer Length                      |
|  4 | O | Sense Info Buffer Pointer                 |
|  4 | O | Sense Info Buffer Length                  |
|  1 | O | CDB Length                                |
|  2 | O | Number of Scatter/Gather Entries          |
|  4 |   | VU Field                                  |
|  1 |I/O| SCSI Status       (SCSI status to be sent |
|    |   |                    to initiator)          |
|  2 |   | Autosense Residual Length                 |
|  2 |   | Reserved OSD                              |
|  4 | O | Residual Length                           |
|  12|   | CDB                                       |
|  4 | O | Timeout Value                             |
|  4 |   | Message Buffer Pointer                    |
|  4 |   | Message Buffer Length                     |
|  2 |   | VU Flags                                  |
|  1 | O | Tag Queue Action                          |
|  1 | O | Tag ID          (Original tag value)      |
|  1 | O | Initiator ID                              |
|  1 |   | Reserved                                  |
|  n |   | Private Data                              |
+====================================================+

Fields Described:

The following lists the possible CAM status values of the CONTINUE
TARGET I/O CCB.
    -   Request in Progress - Request accepted by SIM. 
    -   Request Aborted by Host.  
    -   Request Completed Without Error - Request completed successfully. 
        
    -   Bus Reset - This SIM is recovering from a bus reset.  
    -   Bus Device Reset - This SIM is recovering from a BUS DEVICE RESET
        message.  
    -   Target Bus phase sequence failure 
    -   Uncorrectable Parity error detected
    -   Unexpected Bus Free
    -   Command Timeout - Time period specified expired 
    -   Path Invalid 
    -   Unexpected Bus Free
    -   Unacknowledged Event by Host - An event has not been acknowledged
        by the Host Target Mode peripheral driver.

The following bits are valid for the CAM flags field of the CONTINUE
TARGET I/O CCB:
    -   Direction Out - Sending data from the target peripheral device
        to the initiator.
        +  SG List/Data Buffer Pointer and Data Transfer Length fields
           shall be filled in.
    -      Direction In - Receiving data from the initiator to the target 
           peripheral device.
        + SG List/Data Buffer Pointer and Data Transfer Length fields
        shall be filled in.
    - No Direction - No data phase required.
    - Scatter/Gather - Indicates that the Data Buffer Pointer is a
    pointer to a scatter/gather list.
    - Tagged Queue Action Enable - Indicates this is a tagged request
    and the Tag ID shall be filled in.
    - Sense Buffer - Indicates whether the pointer address is virtual
    or physical. 
    - Callback on Completion. 

11.3.11 Disable of a Host Target Mode LUN

When a peripheral driver wishes to disable Host Target Mode for an
enabled LUN, it shall perform the following tasks:

    A)     Issue an ABORT CCB for all ACCEPT TARGET I/O CCBs which were
           sent to the SIM, and have not been returned.

    B)     Wait for processing of all CONTINUE TARGET I/O CCBs sent to
           the SIM to be completed.

    C)     Once all CCBs are owned by the peripheral driver, it shall
           issue an ENABLE LUN CCB to the XPT/SIM with the Number of
           Target CCBs equal to zero (indicating the LUN should be
           disabled).

    D)     Upon successful completion of the disable for the Host Target
           Mode LUN (indicated by a CAM status if Request Completed
           Without Error) the Host Target Mode peripheral driver shall
           own all IMMEDIATE NOTIFY CCBs it sent to the SIM/HBA. The Host
           Target Mode peripheral driver may now free the CCBs if it  so
           desires.

When the SIM receives an ENABLE LUN CCB with the Number of Target CCBs
equal to zero (disable LUN) it shall perform the following tasks:

    A)     If the LUN was never enabled, then the ENABLE LUN CCB shall be
           returned with a CAM status of Invalid Request.

    B)     If there are ACCEPT TARGET I/O CCBs or CONTINUE TARGET I/O
           CCBs still owned by the SIM, then the disable LUN request
           shall fail with Request Completed With Error.

    C)     The SIM/HBA unacknowledged event list shall be cleared.

    D)     All subsequent ACCEPT TARGET I/O and CONTINUE TARGET I/O CCBs
           received by the SIM prior to the receipt of another ENABLE LUN
           CCB that enables the LUN shall be returned with a CAM status
           of Invalid Request.

11.3.12 Exception Conditions
 
11.3.12.1 BUS RESET

When a bus reset (hard reset) is sent or received, the following
sequence of events shall occur: 

    A)     The SIM/HBA shall:

        1)     Clear any outstanding target I/O's owned by the SIM for the
               bus that suffered the reset by calling the callback
               completion function with a CAM status of Bus Reset. 
               Requests owned by the SIM/HBA are:

           a)     Any I/O currently on the bus.

           b)     Any CONTINUE TARGET I/O requests which are currently
                  queued in the SIM/HBA.
        
        2)     Cause the Host Target Mode peripheral driver asynch
               callback function to be called as part of the normal asynch
               callback notification.

        3)     Any new command received from any initiator shall complete
               with a SCSI status of BUSY, until the SIM/HBA receives an
               applicable NOTIFY ACKNOWLEDGE CCB.

        4)     Any CONTINUE TARGET I/O or ACCEPT TARGET I/O CCBs that are
               received by the SIM while  the reset recovery is in
               progress shall be returned with a CAM status of Bus Reset.

        5)     Reset recovery shall be complete when the peripheral driver
               issues a NOTIFY ACKNOWLEDGE CCB with  the Reset Cleared
               field set, and the Sequence Identifier equal to zero.

        6)     The SIM/HBA unacknowledged event list shall be cleared for
               all registered LUNs on the bus which experienced the bus
               reset.
        
    B)     The Host Target Mode peripheral driver asynch callback routine
           shall:

        1)     Clear all pending sense data.

        2)     Cease processing on any outstanding requests owned by the
               peripheral driver. These are ACCEPT TARGET I/O or CONTINUE
               TARGET I/O CCBs being processed by the peripheral driver.

        3)     Sense data shall be saved indicating the UNIT ATTENTION
               condition caused as a result of the bus reset.

        4)     Issue a NOTIFY ACKNOWLEDGE CCB with the Reset Cleared field
               set and the Sequence Identifier equal to zero. 

        5)     If necessary, the Host Target Mode peripheral driver shall
               issue/reissue ACCEPT TARGET I/O CCB(s) so that the SIM/HBA
               can resume normal processing.

11.3.12.2 BUS DEVICE RESET message

When a BUS DEVICE RESET message is sent/received, the following
sequence of events shall occur: 

    A)     The SIM/HBA shall:

        1)     Clear any outstanding target I/O's owned by the SIM/HBA for
               the target that received the BUS DEVICE RESET message by
               calling the callback completion function with a CAM status
               of Bus Device Reset.  Requests owned by the SIM/HBA are:
           a)     Any I/O currently on the bus.

           b)     Any CONTINUE TARGET I/O requests which are currently
                  queued in the SIM.

        2)     Cause the Host Target Mode peripheral driver asynch
               callback function to be called as part of the normal asynch
               callback notification.

        3)     Any new command received from any initiator shall complete
               with a SCSI status of BUSY, until the SIM/HBA receives an
               applicable NOTIFY ACKNOWLEDGE CCB.

        4)     Any CONTINUE TARGET I/O or ACCEPT TARGET I/O CCBs that are
               received by the SIM while the reset recovery is in progress
               shall be returned with a CAM status of Bus Device Reset. 

        5)     Reset recovery shall be complete when the peripheral driver
               issues an NOTIFY ACKNOWLEDGE CCB with the Reset Cleared
               field set and the Sequence Identifier equal to zero.

        6)     The SIM/HBA unacknowledged event lists shall cleared for
               all enabled LUNs on the target that received the BUS DEVICE
               RESET message.

        
    B)     The Host Target Mode peripheral driver asynch callback routine
           shall:

        1)     Clear all pending sense data.

        2)     Cease processing on any outstanding requests owned by the
               peripheral driver. These are ACCEPT TARGET I/O or CONTINUE
               TARGET I/O CCBs being processed by the peripheral driver.

        3)     Sense data shall be saved indicating the UNIT ATTENTION
               condition caused as a result of the receipt of the BUS
               DEVICE RESET message.

        4)     Issue a NOTIFY ACKNOWLEDGE CCB with the Reset Cleared field
               set and the Sequence Identifier equal to zero. 

        5)     If necessary, the Host Target Mode peripheral driver shall
               issue/reissue ACCEPT TARGET I/O CCB(s) so that the SIM/HBA
               can resume normal processing.

11.3.13 CDB Reception on a Non Enabled LUN

When a CDB is received by a SIM/HBA for a LUN that is not enabled, one
of the following sequences shall occur depending on the commnad
received:

    A)     INQUIRY Command

        If the SIM receives a CDB for the INQUIRY command for a
        non-enabled LUN, the SIM shall return only byte 0 of the inquiry
        data set to 3FH:
        -  The peripheral qualifier is set to 01B indicating the target
           is capable of supporting a physical device on this logical
           unit, however the physical device is not currently connected
           to this LUN.
        -  The peripheral device type set to 1FH indicating unknown
           device type.

    B)     REQUEST SENSE Command

        If a REQUEST SENSE command is received for a non-enabled LUN, the
        SIM shall return sense data in which the sense key shall be set
        to ILLEGAL REQUEST and the additional sense code shall be set to
        LOGICAL UNIT NOT SUPPORTED.

    C)     All other commands

        If a command other than INQUIRY or REQUEST SENSE is received for
        a non-enabled LUN, the SCSI status returned shall be CHECK
        CONDITION. Any subsequent REQUEST SENSE command shall behave as
        in Item B.

11.3.14 Retrieving unused ACCEPT TARGET I/O CCBs from the SIM

If a Host Target Mode peripheral driver wishes to retrieve an ACCEPT
TARGET I/O CCB which was sent to the SIM (probably due to the lack of
resources) the peripheral driver may issue an ABORT CCB.  This shall
result in the CDB completion function of the ACCEPT TARGET I/O CCB
being called with a CAM status of Request Aborted by Host.


12  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.

12.1  Engine inquiry 

This function is used to gather information about the data processing
engines installed in the HBA hardware. 

                               Table 28 - Engine inquiry CCB 
+====-===-======================================+
|Size|Dir|  Engine inquiry                      |
|----+---+--------------------------------------|
|  4 | O | Address of this CCB                  |
|    | 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                            |
|  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 a CAM Status other than Request in
Progress.
    -   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. 

12.2  Execute engine request (optional)

To accommodate buffering associated with the engine, the CAM flag SG
list/data (bit 7) 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. The CAM Flag SG List/Data (bit 5) shall signify whether
the address(es) is Virtual or Physical.

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 29 - 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                            |
|  4 | O | Peripheral driver pointer            |
|  4 | O |   Reserved                           |
|  4 | O | Request mapping information          |
|  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                           |
|  1 |   |   Reserved                           |
|  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                           |
|  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 (non
Request in Progress status) or through use of the Callback on
Completion field. 



                                   ANNEX A
                                (informative)
              Physical/logical translation in 80x86 environment


A.1  OSD formatting of disk drives 

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

The following "C" routines have been adopted by CAM as representing
the most efficient utilization 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
           accommodated. 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 (int13) 
 */ 

 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 partition 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 
                                (informative)
                         Target application examples 


The following are examples of how a target application can operate the
target mode capabilities defined in clause 17.

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 3nable 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 





                                   Annex C
                                (informative)
                          UNIVOS OSD data structures
 

/*  This file contains the definitions and data structures for the CAM Subsystem
    interface.  The contents of this file should match the data structures and
    constants that are specified in the CAM document, X3T9.2/90-186 Rev 5.0. 
*/

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

/* Defines for the XPT function codes, Table 3 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 */
#define XPT_SCAN_BUS                0x07   /* Scan the SCSI Bus */

/* 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_ACCEPT_TARGET_IO     0x32   /* Accept Host Target Mode CDB */
#define XPT_CONT_TARGET_IO          0x33   /* Continue Host Target I/O Connection */
#define XPT_IMMED_NOTIFY            0x34   /* Notify Host Target driver of event */
#define XPT_NOTIFY_ACK              0x35   /* Acknowledgement of event */

#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 */ 
    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 cdb_un
{
    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_getdev
{
    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_pathinq
{
    CCB_HEADER cam_ch;                  /* Header information fields */
    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_relsim
{
CCB_HEADER cam_ch;                      /* Header information fields */
} CCB_RELSIM;

/* SCSI I/O request CCB */
typedef struct ccb_scsiio
{
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_sense_resid;                    /* Autosense resid length: 2's comp */
u_char cam_osd_rsvd1[2];                   /* 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_tag_id;                         /* tag id from initiator (target mode) */
u_char cam_init_id;                            /* initiator id of who selected */
u_char cam_iorsvd0[1];                     /* Reserved field, for alignment */
u_char cam_sim_priv[ SIM_PRIV ];           /* SIM private data area */
} CCB_SCSIIO;

/* Set async callback CCB */
typedef struct ccb_setasync
{
    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_setdev
{
    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_abort
{
    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_resetbus
{
    CCB_HEADER cam_ch;              /* Header information fields */
} CCB_RESETBUS;

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

/* Terminate I/O process request CCB */
typedef struct ccb_termio
{
    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_en_lun
{
    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_eng_inq
{
    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 ccb_eng_exec                /* 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 cam_sim_entry
{
    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_RESRC_UNAVAIL        0x34   /* Resource unavailable */
#define CAM_UNACKED_EVENT        0x35   /* Unacknowledged event by host */
#define CAM_MESSAGE_RECV         0x36   /* Message received in Host Target Mode */
#define CAM_INVALID_CDB             0x37   /* Invalid CDB received in Host Target
                                           Mode */
#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               0x3D   /* The SCSI CDB has been received */
#define CAM_LUN_ALRDY_ENA        0x3E   /* The LUN is already enabled */
#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_SIM_QFRZDIS             0x00000400 /* Disable the SIM Q frozen state */
#define CAM_ENG_SYNC                0x00000200 /* 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 */

/* Phase cognizant mode flags */
#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 */

/* Host Target Mode flags */
#define CAM_SEND_STATUS             0x80000000 /* Send status after data phase (if
                                    any) */
#define CAM_DISCONNECT              0x40000000 /* Disconnects are mandatory after
                                    cdb recv */
#define CAM_TERM_IO                 0x20000000 /* Terminate I/O Message supported */
#define CAM_TGT_PHASE_MODE       0x08000000 /* The SIM will run in phase mode */

#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          0x50   /* 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 PIT_DISCONNECT       0x20   /* Disconnects supported in target mode */
#define PIT_TERM_IO              0x10   /* Terminate I/O message support in target
                                        mode */
#define PIT_GRP_6                0x08   /* Group 6 commands supported */
#define PIT_GRP_7                0x04   /* Group 7 commands supported */  

#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 sg_elem
{
    u_char *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*/

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

/* UNIVOS 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_size_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 cam_edt_entry
{
    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 peripheral driver's ownership */
    char cam_inq_data[ INQLEN ];    /* storage for the inquiry data */
} CAM_EDT_ENTRY;
/* ---------------------------------------------------------------------- */
