/*
     File:       SCSI.h
 
     Contains:   SCSI Family Interfaces.
 
     Version:    Technology: SCSI 4.3
                 Release:    QuickTime 6.0.2
 
     Copyright:  (c) 1986-2001 by Apple Computer, Inc., all rights reserved
 
     Bugs?:      For bug reports, consult the following page on
                 the World Wide Web:
 
                     http://developer.apple.com/bugreporter/
 
*/
#ifndef __SCSI__
#define __SCSI__

#ifndef __MACTYPES__
#include "MacTypes.h"
#endif

#ifndef __MIXEDMODE__
#include "MixedMode.h"
#endif




#if PRAGMA_ONCE
#pragma once
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if PRAGMA_IMPORT
#pragma import on
#endif

#if PRAGMA_STRUCT_ALIGN
    #pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
    #pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
    #pragma pack(2)
#endif

/* SCSI Manager errors. These are generated by Inside Mac IV calls only. */
enum {
    scCommErr                   = 2,                            /* communications error, operation timeout */
    scArbNBErr                  = 3,                            /* arbitration timeout waiting for not BSY */
    scBadParmsErr               = 4,                            /* bad parameter or TIB opcode */
    scPhaseErr                  = 5,                            /* SCSI bus not in correct phase for attempted operation */
    scCompareErr                = 6,                            /* data compare error */
    scMgrBusyErr                = 7,                            /* SCSI Manager busy  */
    scSequenceErr               = 8,                            /* attempted operation is out of sequence */
    scBusTOErr                  = 9,                            /* CPU bus timeout */
    scComplPhaseErr             = 10                            /* SCSI bus wasn't in Status phase */
};

/* TIB opcodes */
enum {
    scInc                       = 1,
    scNoInc                     = 2,
    scAdd                       = 3,
    scMove                      = 4,
    scLoop                      = 5,
    scNop                       = 6,
    scStop                      = 7,
    scComp                      = 8
};

/* Signatures */
enum {
    sbSIGWord                   = 0x4552,                       /* signature word for Block 0 ('ER') */
    sbMac                       = 1,                            /* system type for Mac */
    pMapSIG                     = 0x504D,                       /* partition map signature ('PM') */
    pdSigWord                   = 0x5453
};

enum {
    oldPMSigWord                = pdSigWord,
    newPMSigWord                = pMapSIG
};

/* Driver Descriptor Map */

struct Block0 {
    unsigned short                  sbSig;                      /* unique value for SCSI block 0 */
    unsigned short                  sbBlkSize;                  /* block size of device */
    unsigned long                   sbBlkCount;                 /* number of blocks on device */
    unsigned short                  sbDevType;                  /* device type */
    unsigned short                  sbDevId;                    /* device id */
    unsigned long                   sbData;                     /* not used */
    unsigned short                  sbDrvrCount;                /* driver descriptor count */
    unsigned long                   ddBlock;                    /* 1st driver's starting block */
    unsigned short                  ddSize;                     /* size of 1st driver (512-byte blks) */
    unsigned short                  ddType;                     /* system type (1 for Mac+) */
    unsigned short                  ddPad[243];                 /* ARRAY[0..242] OF INTEGER; not used */
};
typedef struct Block0                   Block0;
/* Driver descriptor */

struct DDMap {
    unsigned long                   ddBlock;                    /* 1st driver's starting block */
    unsigned short                  ddSize;                     /* size of 1st driver (512-byte blks) */
    unsigned short                  ddType;                     /* system type (1 for Mac+) */
};
typedef struct DDMap                    DDMap;
/* Partition Map Entry */

struct Partition {
    unsigned short                  pmSig;                      /* unique value for map entry blk */
    unsigned short                  pmSigPad;                   /* currently unused */
    unsigned long                   pmMapBlkCnt;                /* # of blks in partition map */
    unsigned long                   pmPyPartStart;              /* physical start blk of partition */
    unsigned long                   pmPartBlkCnt;               /* # of blks in this partition */
    unsigned char                   pmPartName[32];             /* ASCII partition name */
    unsigned char                   pmParType[32];              /* ASCII partition type */
    unsigned long                   pmLgDataStart;              /* log. # of partition's 1st data blk */
    unsigned long                   pmDataCnt;                  /* # of blks in partition's data area */
    unsigned long                   pmPartStatus;               /* bit field for partition status */
    unsigned long                   pmLgBootStart;              /* log. blk of partition's boot code */
    unsigned long                   pmBootSize;                 /* number of bytes in boot code */
    unsigned long                   pmBootAddr;                 /* memory load address of boot code */
    unsigned long                   pmBootAddr2;                /* currently unused */
    unsigned long                   pmBootEntry;                /* entry point of boot code */
    unsigned long                   pmBootEntry2;               /* currently unused */
    unsigned long                   pmBootCksum;                /* checksum of boot code */
    unsigned char                   pmProcessor[16];            /* ASCII for the processor type */
    unsigned short                  pmPad[188];                 /* ARRAY[0..187] OF INTEGER; not used */
};
typedef struct Partition                Partition;
/* TIB instruction */

struct SCSIInstr {
    unsigned short                  scOpcode;
    long                            scParam1;
    long                            scParam2;
};
typedef struct SCSIInstr                SCSIInstr;
/* SCSI Phases (used by SIMs to support the Original SCSI Manager */
enum {
    kDataOutPhase               = 0,                            /* Encoded MSG, C/D, I/O bits */
    kDataInPhase                = 1,
    kCommandPhase               = 2,
    kStatusPhase                = 3,
    kPhaseIllegal0              = 4,
    kPhaseIllegal1              = 5,
    kMessageOutPhase            = 6,
    kMessageInPhase             = 7,
    kBusFreePhase               = 8,                            /* Additional Phases */
    kArbitratePhase             = 9,
    kSelectPhase                = 10,
    kMessageInPhaseNACK         = 11                            /* Message In Phase with ACK hanging on the bus */
};


#if CALL_NOT_IN_CARBON
EXTERN_API( OSErr )
SCSIReset                       (void)                                                      TWOWORDINLINE(0x4267, 0xA815);

EXTERN_API( OSErr )
SCSIGet                         (void)                                                      THREEWORDINLINE(0x3F3C, 0x0001, 0xA815);

EXTERN_API( OSErr )
SCSISelect                      (short                  targetID)                           THREEWORDINLINE(0x3F3C, 0x0002, 0xA815);

EXTERN_API( OSErr )
SCSICmd                         (Ptr                    buffer,
                                 short                  count)                              THREEWORDINLINE(0x3F3C, 0x0003, 0xA815);

EXTERN_API( OSErr )
SCSIRead                        (Ptr                    tibPtr)                             THREEWORDINLINE(0x3F3C, 0x0005, 0xA815);

EXTERN_API( OSErr )
SCSIRBlind                      (Ptr                    tibPtr)                             THREEWORDINLINE(0x3F3C, 0x0008, 0xA815);

EXTERN_API( OSErr )
SCSIWrite                       (Ptr                    tibPtr)                             THREEWORDINLINE(0x3F3C, 0x0006, 0xA815);

EXTERN_API( OSErr )
SCSIWBlind                      (Ptr                    tibPtr)                             THREEWORDINLINE(0x3F3C, 0x0009, 0xA815);

EXTERN_API( OSErr )
SCSIComplete                    (short *                stat,
                                 short *                message,
                                 unsigned long          wait)                               THREEWORDINLINE(0x3F3C, 0x0004, 0xA815);

EXTERN_API( short )
SCSIStat                        (void)                                                      THREEWORDINLINE(0x3F3C, 0x000A, 0xA815);

EXTERN_API( OSErr )
SCSISelAtn                      (short                  targetID)                           THREEWORDINLINE(0x3F3C, 0x000B, 0xA815);

EXTERN_API( OSErr )
SCSIMsgIn                       (short *                message)                            THREEWORDINLINE(0x3F3C, 0x000C, 0xA815);

EXTERN_API( OSErr )
SCSIMsgOut                      (short                  message)                            THREEWORDINLINE(0x3F3C, 0x000D, 0xA815);


#endif  /* CALL_NOT_IN_CARBON */

enum {
    scsiVERSION                 = 43
};


/*
 * SCSI Callback Procedure Prototypes. Several of these are only callable
 * from SCSI Manager 4.3 SIM and XPT contexts. 
 */
typedef CALLBACK_API_C( void , AENCallbackProcPtr )(void );
typedef CALLBACK_API_C( OSErr , SIMInitProcPtr )(Ptr SIMinfoPtr);
typedef CALLBACK_API_C( void , SIMActionProcPtr )(void *scsiPB, Ptr SIMGlobals);
typedef CALLBACK_API_C( void , SCSIProcPtr )(void );
typedef CALLBACK_API_C( void , SCSIMakeCallbackProcPtr )(void *scsiPB);
/* SCSIInterruptPollProcPtr is obsolete (use SCSIInterruptProcPtr) but still here for compatibility */
typedef CALLBACK_API_C( long , SCSIInterruptPollProcPtr )(Ptr SIMGlobals);
typedef CALLBACK_API_C( long , SCSIInterruptProcPtr )(Ptr SIMGlobals);
typedef STACK_UPP_TYPE(AENCallbackProcPtr)                      AENCallbackUPP;
typedef STACK_UPP_TYPE(SIMInitProcPtr)                          SIMInitUPP;
typedef STACK_UPP_TYPE(SIMActionProcPtr)                        SIMActionUPP;
typedef STACK_UPP_TYPE(SCSIProcPtr)                             SCSIUPP;
typedef STACK_UPP_TYPE(SCSIMakeCallbackProcPtr)                 SCSIMakeCallbackUPP;
typedef STACK_UPP_TYPE(SCSIInterruptPollProcPtr)                SCSIInterruptPollUPP;
typedef STACK_UPP_TYPE(SCSIInterruptProcPtr)                    SCSIInterruptUPP;
typedef CALLBACK_API( void , SCSICallbackProcPtr )(void *scsiPB);
typedef STACK_UPP_TYPE(SCSICallbackProcPtr)                     SCSICallbackUPP;
#if OPAQUE_UPP_TYPES
#if CALL_NOT_IN_CARBON
    EXTERN_API(AENCallbackUPP)
    NewAENCallbackUPP              (AENCallbackProcPtr      userRoutine);

    EXTERN_API(SIMInitUPP)
    NewSIMInitUPP                  (SIMInitProcPtr          userRoutine);

    EXTERN_API(SIMActionUPP)
    NewSIMActionUPP                (SIMActionProcPtr        userRoutine);

    EXTERN_API(SCSIUPP)
    NewSCSIUPP                     (SCSIProcPtr             userRoutine);

    EXTERN_API(SCSIMakeCallbackUPP)
    NewSCSIMakeCallbackUPP         (SCSIMakeCallbackProcPtr userRoutine);

    EXTERN_API(SCSIInterruptPollUPP)
    NewSCSIInterruptPollUPP        (SCSIInterruptPollProcPtr userRoutine);

    EXTERN_API(SCSIInterruptUPP)
    NewSCSIInterruptUPP            (SCSIInterruptProcPtr    userRoutine);

    EXTERN_API(SCSICallbackUPP)
    NewSCSICallbackUPP             (SCSICallbackProcPtr     userRoutine);

    EXTERN_API(void)
    DisposeAENCallbackUPP          (AENCallbackUPP          userUPP);

    EXTERN_API(void)
    DisposeSIMInitUPP              (SIMInitUPP              userUPP);

    EXTERN_API(void)
    DisposeSIMActionUPP            (SIMActionUPP            userUPP);

    EXTERN_API(void)
    DisposeSCSIUPP                 (SCSIUPP                 userUPP);

    EXTERN_API(void)
    DisposeSCSIMakeCallbackUPP     (SCSIMakeCallbackUPP     userUPP);

    EXTERN_API(void)
    DisposeSCSIInterruptPollUPP    (SCSIInterruptPollUPP    userUPP);

    EXTERN_API(void)
    DisposeSCSIInterruptUPP        (SCSIInterruptUPP        userUPP);

    EXTERN_API(void)
    DisposeSCSICallbackUPP         (SCSICallbackUPP         userUPP);

    EXTERN_API(void)
    InvokeAENCallbackUPP           (AENCallbackUPP          userUPP);

    EXTERN_API(OSErr)
    InvokeSIMInitUPP               (Ptr                     SIMinfoPtr,
                                    SIMInitUPP              userUPP);

    EXTERN_API(void)
    InvokeSIMActionUPP             (void *                  scsiPB,
                                    Ptr                     SIMGlobals,
                                    SIMActionUPP            userUPP);

    EXTERN_API(void)
    InvokeSCSIUPP                  (SCSIUPP                 userUPP);

    EXTERN_API(void)
    InvokeSCSIMakeCallbackUPP      (void *                  scsiPB,
                                    SCSIMakeCallbackUPP     userUPP);

    EXTERN_API(long)
    InvokeSCSIInterruptPollUPP     (Ptr                     SIMGlobals,
                                    SCSIInterruptPollUPP    userUPP);

    EXTERN_API(long)
    InvokeSCSIInterruptUPP         (Ptr                     SIMGlobals,
                                    SCSIInterruptUPP        userUPP);

    EXTERN_API(void)
    InvokeSCSICallbackUPP          (void *                  scsiPB,
                                    SCSICallbackUPP         userUPP);

#endif  /* CALL_NOT_IN_CARBON */

#else
    enum { uppAENCallbackProcInfo = 0x00000001 };                   /* no_return_value Func() */
    enum { uppSIMInitProcInfo = 0x000000E1 };                       /* 2_bytes Func(4_bytes) */
    enum { uppSIMActionProcInfo = 0x000003C1 };                     /* no_return_value Func(4_bytes, 4_bytes) */
    enum { uppSCSIProcInfo = 0x00000001 };                          /* no_return_value Func() */
    enum { uppSCSIMakeCallbackProcInfo = 0x000000C1 };              /* no_return_value Func(4_bytes) */
    enum { uppSCSIInterruptPollProcInfo = 0x000000F1 };             /* 4_bytes Func(4_bytes) */
    enum { uppSCSIInterruptProcInfo = 0x000000F1 };                 /* 4_bytes Func(4_bytes) */
    enum { uppSCSICallbackProcInfo = 0x000000C0 };                  /* pascal no_return_value Func(4_bytes) */
    #define NewAENCallbackUPP(userRoutine)                          (AENCallbackUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppAENCallbackProcInfo, GetCurrentArchitecture())
    #define NewSIMInitUPP(userRoutine)                              (SIMInitUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSIMInitProcInfo, GetCurrentArchitecture())
    #define NewSIMActionUPP(userRoutine)                            (SIMActionUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSIMActionProcInfo, GetCurrentArchitecture())
    #define NewSCSIUPP(userRoutine)                                 (SCSIUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSCSIProcInfo, GetCurrentArchitecture())
    #define NewSCSIMakeCallbackUPP(userRoutine)                     (SCSIMakeCallbackUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSCSIMakeCallbackProcInfo, GetCurrentArchitecture())
    #define NewSCSIInterruptPollUPP(userRoutine)                    (SCSIInterruptPollUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSCSIInterruptPollProcInfo, GetCurrentArchitecture())
    #define NewSCSIInterruptUPP(userRoutine)                        (SCSIInterruptUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSCSIInterruptProcInfo, GetCurrentArchitecture())
    #define NewSCSICallbackUPP(userRoutine)                         (SCSICallbackUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppSCSICallbackProcInfo, GetCurrentArchitecture())
    #define DisposeAENCallbackUPP(userUPP)                          DisposeRoutineDescriptor(userUPP)
    #define DisposeSIMInitUPP(userUPP)                              DisposeRoutineDescriptor(userUPP)
    #define DisposeSIMActionUPP(userUPP)                            DisposeRoutineDescriptor(userUPP)
    #define DisposeSCSIUPP(userUPP)                                 DisposeRoutineDescriptor(userUPP)
    #define DisposeSCSIMakeCallbackUPP(userUPP)                     DisposeRoutineDescriptor(userUPP)
    #define DisposeSCSIInterruptPollUPP(userUPP)                    DisposeRoutineDescriptor(userUPP)
    #define DisposeSCSIInterruptUPP(userUPP)                        DisposeRoutineDescriptor(userUPP)
    #define DisposeSCSICallbackUPP(userUPP)                         DisposeRoutineDescriptor(userUPP)
    #define InvokeAENCallbackUPP(userUPP)                           CALL_ZERO_PARAMETER_UPP((userUPP), uppAENCallbackProcInfo)
    #define InvokeSIMInitUPP(SIMinfoPtr, userUPP)                   (OSErr)CALL_ONE_PARAMETER_UPP((userUPP), uppSIMInitProcInfo, (SIMinfoPtr))
    #define InvokeSIMActionUPP(scsiPB, SIMGlobals, userUPP)         CALL_TWO_PARAMETER_UPP((userUPP), uppSIMActionProcInfo, (scsiPB), (SIMGlobals))
    #define InvokeSCSIUPP(userUPP)                                  CALL_ZERO_PARAMETER_UPP((userUPP), uppSCSIProcInfo)
    #define InvokeSCSIMakeCallbackUPP(scsiPB, userUPP)              CALL_ONE_PARAMETER_UPP((userUPP), uppSCSIMakeCallbackProcInfo, (scsiPB))
    #define InvokeSCSIInterruptPollUPP(SIMGlobals, userUPP)         (long)CALL_ONE_PARAMETER_UPP((userUPP), uppSCSIInterruptPollProcInfo, (SIMGlobals))
    #define InvokeSCSIInterruptUPP(SIMGlobals, userUPP)             (long)CALL_ONE_PARAMETER_UPP((userUPP), uppSCSIInterruptProcInfo, (SIMGlobals))
    #define InvokeSCSICallbackUPP(scsiPB, userUPP)                  CALL_ONE_PARAMETER_UPP((userUPP), uppSCSICallbackProcInfo, (scsiPB))
#endif
/* support for pre-Carbon UPP routines: NewXXXProc and CallXXXProc */
#define NewAENCallbackProc(userRoutine)                         NewAENCallbackUPP(userRoutine)
#define NewSIMInitProc(userRoutine)                             NewSIMInitUPP(userRoutine)
#define NewSIMActionProc(userRoutine)                           NewSIMActionUPP(userRoutine)
#define NewSCSIProc(userRoutine)                                NewSCSIUPP(userRoutine)
#define NewSCSIMakeCallbackProc(userRoutine)                    NewSCSIMakeCallbackUPP(userRoutine)
#define NewSCSIInterruptPollProc(userRoutine)                   NewSCSIInterruptPollUPP(userRoutine)
#define NewSCSIInterruptProc(userRoutine)                       NewSCSIInterruptUPP(userRoutine)
#define NewSCSICallbackProc(userRoutine)                        NewSCSICallbackUPP(userRoutine)
#define CallAENCallbackProc(userRoutine)                        InvokeAENCallbackUPP(userRoutine)
#define CallSIMInitProc(userRoutine, SIMinfoPtr)                InvokeSIMInitUPP(SIMinfoPtr, userRoutine)
#define CallSIMActionProc(userRoutine, scsiPB, SIMGlobals)      InvokeSIMActionUPP(scsiPB, SIMGlobals, userRoutine)
#define CallSCSIProc(userRoutine)                               InvokeSCSIUPP(userRoutine)
#define CallSCSIMakeCallbackProc(userRoutine, scsiPB)           InvokeSCSIMakeCallbackUPP(scsiPB, userRoutine)
#define CallSCSIInterruptPollProc(userRoutine, SIMGlobals)      InvokeSCSIInterruptPollUPP(SIMGlobals, userRoutine)
#define CallSCSIInterruptProc(userRoutine, SIMGlobals)          InvokeSCSIInterruptUPP(SIMGlobals, userRoutine)
#define CallSCSICallbackProc(userRoutine, scsiPB)               InvokeSCSICallbackUPP(scsiPB, userRoutine)
/* SCSI Manager 4.3 function codes */
enum {
    SCSINop                     = 0x00,                         /* Execute nothing                          */
    SCSIExecIO                  = 0x01,                         /* Execute the specified IO                  */
    SCSIBusInquiry              = 0x03,                         /* Get parameters for entire path of HBAs           */
    SCSIReleaseQ                = 0x04,                         /* Release the frozen SIM queue for particular LUN      */
    SCSIAbortCommand            = 0x10,                         /* Abort the selected Control Block             */
    SCSIResetBus                = 0x11,                         /* Reset the SCSI bus                         */
    SCSIResetDevice             = 0x12,                         /* Reset the SCSI device                      */
    SCSITerminateIO             = 0x13,                         /* Terminate any pending IO                    */
    SCSIGetVirtualIDInfo        = 0x80,                         /* Find out which bus old ID is on                */
    SCSILoadDriver              = 0x82,                         /* Load a driver for a device ident             */
    SCSIOldCall                 = 0x84,                         /* XPT->SIM private call for old-API            */
    SCSICreateRefNumXref        = 0x85,                         /* Register a DeviceIdent to drvr RefNum xref          */
    SCSILookupRefNumXref        = 0x86,                         /* Get DeviceIdent to drvr RefNum xref              */
    SCSIRemoveRefNumXref        = 0x87,                         /* Remove a DeviceIdent to drvr RefNum xref        */
    SCSIRegisterWithNewXPT      = 0x88,                         /* XPT has changed - SIM needs to re-register itself  */
    vendorUnique                = 0xC0                          /* 0xC0 thru 0xFF */
};


/* Allocation length defines for some of the fields */
enum {
    handshakeDataLength         = 8,                            /* Handshake data length */
    maxCDBLength                = 16,                           /* Space for the CDB bytes/pointer */
    vendorIDLength              = 16                            /* ASCII string len for Vendor ID  */
};

/* Define DeviceIdent structure */

struct DeviceIdent {
    UInt8                           diReserved;                 /* reserved           */
    UInt8                           bus;                        /* SCSI - Bus Number   */
    UInt8                           targetID;                   /* SCSI - Target SCSI ID  */
    UInt8                           LUN;                        /* SCSI - LUN            */
};
typedef struct DeviceIdent              DeviceIdent;
/* Command Descriptor Block structure */

union CDB {
    BytePtr                         cdbPtr;                     /* pointer to the CDB, or */
    UInt8                           cdbBytes[16];               /* the actual CDB to send */
};
typedef union CDB                       CDB;
typedef CDB *                           CDBPtr;
/* Scatter/gather list element (Deprecated for MacOS8) */

struct SGRecord {
    Ptr                             SGAddr;
    UInt32                          SGCount;
};
typedef struct SGRecord                 SGRecord;

#define SCSIPBHdr                      \
  struct SCSIHdr* qLink;              \
  short           scsiReserved1;      \
  UInt16          scsiPBLength;       \
  UInt8           scsiFunctionCode;   \
  UInt8           scsiReserved2;      \
  volatile OSErr  scsiResult;         \
  DeviceIdent     scsiDevice;         \
  SCSICallbackUPP scsiCompletion;     \
  UInt32          scsiFlags;          \
  UInt8 *         scsiDriverStorage;  \
  Ptr             scsiXPTprivate;     \
  long            scsiReserved3;


struct SCSIHdr {
    struct SCSIHdr *                qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
};
typedef struct SCSIHdr                  SCSIHdr;

struct SCSI_PB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
};
typedef struct SCSI_PB                  SCSI_PB;

struct SCSI_IO {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */

    UInt16                          scsiResultFlags;            /* <- Flags which modify the scsiResult field     */
    UInt16                          scsiReserved3pt5;           /* -> Reserved                           */
    BytePtr                         scsiDataPtr;                /* -> Pointer to the data buffer or the S/G list      */
    UInt32                          scsiDataLength;             /* -> Data transfer length                   */
    BytePtr                         scsiSensePtr;               /* -> Ptr to autosense data buffer            */
    UInt8                           scsiSenseLength;            /* -> size of the autosense buffer              */
    UInt8                           scsiCDBLength;              /* -> Number of bytes for the CDB               */
    UInt16                          scsiSGListCount;            /* -> num of scatter gather list entries           */
    UInt32                          scsiReserved4;              /* <-     reserved for output                   */
    UInt8                           scsiSCSIstatus;             /* <- Returned scsi device status               */
    SInt8                           scsiSenseResidual;          /* <- Autosense residual length             */
    UInt16                          scsiReserved5;              /* <-     reserved for output                 */
    long                            scsiDataResidual;           /* <- Returned Transfer residual length          */
    CDB                             scsiCDB;                    /* -> Actual CDB or pointer to CDB            */
    long                            scsiTimeout;                /* -> Timeout value (Time Mgr format) (CAM timeout) */
    BytePtr                         scsiReserved5pt5;           /* -> Reserved                           */
    UInt16                          scsiReserved5pt6;           /* -> Reserved                           */
    UInt16                          scsiIOFlags;                /* -> additional I/O flags                      */
    UInt8                           scsiTagAction;              /* -> What to do for tag queuing                */
    UInt8                           scsiReserved6;              /* ->     reserved for input                   */
    UInt16                          scsiReserved7;              /* ->     reserved for input                   */
    UInt16                          scsiSelectTimeout;          /* -> Select timeout value                 */
    UInt8                           scsiDataType;               /* -> Data description type (i.e. buffer, TIB, S/G)   */
    UInt8                           scsiTransferType;           /* -> Transfer type (i.e. Blind vs Polled)       */
    UInt32                          scsiReserved8;              /* ->     reserved for input                  */
    UInt32                          scsiReserved9;              /* ->     reserved for input                  */
    UInt16                          scsiHandshake[8];           /* -> handshaking points (null term'd)    */
    UInt32                          scsiReserved10;             /* ->     reserved for input                  */
    UInt32                          scsiReserved11;             /* ->   reserved for input                   */
    struct SCSI_IO *                scsiCommandLink;            /* -> Ptr to the next PB in linked cmd chain      */

    UInt8                           scsiSIMpublics[8];          /* ->     reserved for input to 3rd-party SIMs     */
    UInt8                           scsiAppleReserved6[8];      /* -> reserved for input                     */

                                                                /* XPT layer privates (for old-API emulation) */

    UInt16                          scsiCurrentPhase;           /* <- phase upon completing old call            */
    short                           scsiSelector;               /* -> selector specified in old calls            */
    OSErr                           scsiOldCallResult;          /* <- result of old call                     */
    UInt8                           scsiSCSImessage;            /* <- Returned scsi device message (for SCSIComplete)*/
    UInt8                           XPTprivateFlags;            /* <> various flags                       */
    UInt8                           XPTextras[12];              /*                              */
};
typedef struct SCSI_IO                  SCSI_IO;

typedef SCSI_IO                         SCSIExecIOPB;
/* Bus inquiry PB */

struct SCSIBusInquiryPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */

    UInt16                          scsiEngineCount;            /* <- Number of engines on HBA                */
    UInt16                          scsiMaxTransferType;        /* <- Number of transfer types for this HBA      */

    UInt32                          scsiDataTypes;              /* <- which data types are supported by this SIM  */

    UInt16                          scsiIOpbSize;               /* <- Size of SCSI_IO PB for this SIM/HBA          */
    UInt16                          scsiMaxIOpbSize;            /* <- Size of max SCSI_IO PB for all SIM/HBAs        */

    UInt32                          scsiFeatureFlags;           /* <- Supported features flags field           */

    UInt8                           scsiVersionNumber;          /* <- Version number for the SIM/HBA           */
    UInt8                           scsiHBAInquiry;             /* <- Mimic of INQ byte 7 for the HBA           */
    UInt8                           scsiTargetModeFlags;        /* <- Flags for target mode support           */
    UInt8                           scsiScanFlags;              /* <- Scan related feature flags            */

    UInt32                          scsiSIMPrivatesPtr;         /* <- Ptr to SIM private data area              */
    UInt32                          scsiSIMPrivatesSize;        /* <- Size of SIM private data area           */
    UInt32                          scsiAsyncFlags;             /* <- Event cap. for Async Callback           */

    UInt8                           scsiHiBusID;                /* <- Highest path ID in the subsystem         */
    UInt8                           scsiInitiatorID;            /* <- ID of the HBA on the SCSI bus           */
    UInt16                          scsiBIReserved0;            /*                                  */

    UInt32                          scsiBIReserved1;            /* <-                                */
    UInt32                          scsiFlagsSupported;         /* <- which scsiFlags are supported           */

    UInt16                          scsiIOFlagsSupported;       /* <- which scsiIOFlags are supported           */
    UInt16                          scsiWeirdStuff;             /* <-                               */
    UInt16                          scsiMaxTarget;              /* <- maximum Target number supported           */
    UInt16                          scsiMaxLUN;                 /* <- maximum Logical Unit number supported    */

    char                            scsiSIMVendor[16];          /* <- Vendor ID of SIM (or XPT if bus<FF)        */
    char                            scsiHBAVendor[16];          /* <- Vendor ID of the HBA                */
    char                            scsiControllerFamily[16];   /* <- Family of SCSI Controller           */
    char                            scsiControllerType[16];     /* <- Specific Model of SCSI Controller used  */

    char                            scsiXPTversion[4];          /* <- version number of XPT              */
    char                            scsiSIMversion[4];          /* <- version number of SIM              */
    char                            scsiHBAversion[4];          /* <- version number of HBA              */

    UInt8                           scsiHBAslotType;            /* <- type of "slot" that this HBA is in       */
    UInt8                           scsiHBAslotNumber;          /* <- slot number of this HBA                  */
    UInt16                          scsiSIMsRsrcID;             /* <- resource ID of this SIM                  */

    UInt16                          scsiBIReserved3;            /* <-                               */
    UInt16                          scsiAdditionalLength;       /* <- additional BusInquiry PB len              */
};
typedef struct SCSIBusInquiryPB         SCSIBusInquiryPB;
/* Abort SIM Request PB */

struct SCSIAbortCommandPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
    SCSI_IO *                       scsiIOptr;                  /* Pointer to the PB to abort        */
};
typedef struct SCSIAbortCommandPB       SCSIAbortCommandPB;
/* Terminate I/O Process Request PB */

struct SCSITerminateIOPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
    SCSI_IO *                       scsiIOptr;                  /* Pointer to the PB to terminate        */
};
typedef struct SCSITerminateIOPB        SCSITerminateIOPB;
/* Reset SCSI Bus PB */

struct SCSIResetBusPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
};
typedef struct SCSIResetBusPB           SCSIResetBusPB;
/* Reset SCSI Device PB */

struct SCSIResetDevicePB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
};
typedef struct SCSIResetDevicePB        SCSIResetDevicePB;
/* Release SIM Queue PB */

struct SCSIReleaseQPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    BytePtr                         scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
};
typedef struct SCSIReleaseQPB           SCSIReleaseQPB;
/* SCSI Get Virtual ID Info PB */

struct SCSIGetVirtualIDInfoPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    Ptr                             scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
    UInt16                          scsiOldCallID;              /* -> SCSI ID of device in question   */
    Boolean                         scsiExists;                 /* <- true if device exists        */
    SInt8                           filler;
};
typedef struct SCSIGetVirtualIDInfoPB   SCSIGetVirtualIDInfoPB;
/* Create/Lookup/Remove RefNum for Device PB */

struct SCSIDriverPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    Ptr                             scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
    short                           scsiDriver;                 /* -> DriverRefNum, For SetDriver, <- For GetNextDriver */
    UInt16                          scsiDriverFlags;            /* <> Details of driver/device       */
    DeviceIdent                     scsiNextDevice;             /* <- DeviceIdent of the NEXT Item in the list  */
};
typedef struct SCSIDriverPB             SCSIDriverPB;
/* Load Driver PB */

struct SCSILoadDriverPB {
    SCSIHdr *                       qLink;                      /* (internal use, must be nil on entry)   */
    short                           scsiReserved1;              /* ->     reserved for input          */
    UInt16                          scsiPBLength;               /* -> Length of the entire PB        */
    UInt8                           scsiFunctionCode;           /* -> function selector           */
    UInt8                           scsiReserved2;              /* <-     reserved for output          */
    volatile OSErr                  scsiResult;                 /* <- Returned result               */
    DeviceIdent                     scsiDevice;                 /* -> Device Identifier (bus+target+lun)*/
    SCSICallbackUPP                 scsiCompletion;             /* -> Callback on completion function     */
    UInt32                          scsiFlags;                  /* -> assorted flags            */
    Ptr                             scsiDriverStorage;          /* <> Ptr for driver private use   */
    Ptr                             scsiXPTprivate;             /* private field for use in XPT      */
    long                            scsiReserved3;              /* reserved                    */
    short                           scsiLoadedRefNum;           /* <- SIM returns refnum of driver      */
    Boolean                         scsiDiskLoadFailed;         /* -> if true, indicates call after failure to load */
    SInt8                           filler;
};
typedef struct SCSILoadDriverPB         SCSILoadDriverPB;

/* Defines for the scsiTransferType field */
enum {
    scsiTransferBlind           = 0,
    scsiTransferPolled          = 1
};

enum {
    scsiErrorBase               = -7936
};

enum {
    scsiRequestInProgress       = 1,                            /* 1   = PB request is in progress          */
                                                                /* Execution failed  00-2F */
    scsiRequestAborted          = scsiErrorBase + 2,            /* -7934 = PB request aborted by the host        */
    scsiUnableToAbort           = scsiErrorBase + 3,            /* -7933 = Unable to Abort PB request          */
    scsiNonZeroStatus           = scsiErrorBase + 4,            /* -7932 = PB request completed with an err   */
    scsiUnused05                = scsiErrorBase + 5,            /* -7931 =                        */
    scsiUnused06                = scsiErrorBase + 6,            /* -7930 =                        */
    scsiUnused07                = scsiErrorBase + 7,            /* -7929 =                        */
    scsiUnused08                = scsiErrorBase + 8,            /* -7928 =                        */
    scsiUnableToTerminate       = scsiErrorBase + 9,            /* -7927 = Unable to Terminate I/O PB req        */
    scsiSelectTimeout           = scsiErrorBase + 10,           /* -7926 = Target selection timeout        */
    scsiCommandTimeout          = scsiErrorBase + 11,           /* -7925 = Command timeout              */
    scsiIdentifyMessageRejected = scsiErrorBase + 12,           /* -7924 =                        */
    scsiMessageRejectReceived   = scsiErrorBase + 13,           /* -7923 = Message reject received           */
    scsiSCSIBusReset            = scsiErrorBase + 14,           /* -7922 = SCSI bus reset sent/received    */
    scsiParityError             = scsiErrorBase + 15,           /* -7921 = Uncorrectable parity error occured     */
    scsiAutosenseFailed         = scsiErrorBase + 16,           /* -7920 = Autosense: Request sense cmd fail  */
    scsiUnused11                = scsiErrorBase + 17,           /* -7919 =                        */
    scsiDataRunError            = scsiErrorBase + 18,           /* -7918 = Data overrun/underrun error     */
    scsiUnexpectedBusFree       = scsiErrorBase + 19,           /* -7917 = Unexpected BUS free              */
    scsiSequenceFailed          = scsiErrorBase + 20,           /* -7916 = Target bus phase sequence failure  */
    scsiWrongDirection          = scsiErrorBase + 21,           /* -7915 = Data phase was in wrong direction  */
    scsiUnused16                = scsiErrorBase + 22,           /* -7914 =                        */
    scsiBDRsent                 = scsiErrorBase + 23,           /* -7913 = A SCSI BDR msg was sent to target  */
    scsiTerminated              = scsiErrorBase + 24,           /* -7912 = PB request terminated by the host  */
    scsiNoNexus                 = scsiErrorBase + 25,           /* -7911 = Nexus is not established        */
    scsiCDBReceived             = scsiErrorBase + 26,           /* -7910 = The SCSI CDB has been received        */
                                                                /* Couldn't begin execution  30-3F */
    scsiTooManyBuses            = scsiErrorBase + 48,           /* -7888 = Register failed because we're full */
    scsiBusy                    = scsiErrorBase + 49,           /* -7887 = SCSI subsystem is busy           */
    scsiProvideFail             = scsiErrorBase + 50,           /* -7886 = Unable to provide requ. capability */
    scsiDeviceNotThere          = scsiErrorBase + 51,           /* -7885 = SCSI device not installed/there    */
    scsiNoHBA                   = scsiErrorBase + 52,           /* -7884 = No HBA detected Error           */
    scsiDeviceConflict          = scsiErrorBase + 53,           /* -7883 = sorry, max 1 refNum per DeviceIdent    */
    scsiNoSuchXref              = scsiErrorBase + 54,           /* -7882 = no such RefNum xref              */
    scsiQLinkInvalid            = scsiErrorBase + 55,           /* -7881 = pre-linked PBs not supported      */
                                                                /*   (The QLink field was nonzero)          */
                                                                /* Parameter errors  40-7F */
    scsiPBLengthError           = scsiErrorBase + 64,           /* -7872 = (scsiPBLength is insuf'ct/invalid  */
    scsiFunctionNotAvailable    = scsiErrorBase + 65,           /* -7871 = The requ. func is not available    */
    scsiRequestInvalid          = scsiErrorBase + 66,           /* -7870 = PB request is invalid           */
    scsiBusInvalid              = scsiErrorBase + 67,           /* -7869 = Bus ID supplied is invalid        */
    scsiTIDInvalid              = scsiErrorBase + 68,           /* -7868 = Target ID supplied is invalid      */
    scsiLUNInvalid              = scsiErrorBase + 69,           /* -7867 = LUN supplied is invalid         */
    scsiIDInvalid               = scsiErrorBase + 70,           /* -7866 = The initiator ID is invalid     */
    scsiDataTypeInvalid         = scsiErrorBase + 71,           /* -7865 = scsiDataType requested not supported */
    scsiTransferTypeInvalid     = scsiErrorBase + 72,           /* -7864 = scsiTransferType field is too high     */
    scsiCDBLengthInvalid        = scsiErrorBase + 73            /* -7863 = scsiCDBLength field is too big        */
};

/* New errors for SCSI Family         */
enum {
    scsiUnused74                = scsiErrorBase + 74,           /* -7862 =                          */
    scsiUnused75                = scsiErrorBase + 75,           /* -7861 =                          */
    scsiBadDataLength           = scsiErrorBase + 76,           /* -7860 = a zero data length in PB        */
    scsiPartialPrepared         = scsiErrorBase + 77,           /* -7859 = could not do full prepare mem for I/O*/
    scsiInvalidMsgType          = scsiErrorBase + 78,           /* -7858 = Invalid message type (internal)       */
    scsiUnused79                = scsiErrorBase + 79,           /* -7857 =                              */
    scsiBadConnID               = scsiErrorBase + 80,           /* -7856 = Bad Connection ID                */
    scsiUnused81                = scsiErrorBase + 81,           /* -7855 =                          */
    scsiIOInProgress            = scsiErrorBase + 82,           /* -7854 = Can't close conn, IO in prog      */
    scsiTargetReserved          = scsiErrorBase + 83,           /* -7853 = Target already reserved          */
    scsiUnused84                = scsiErrorBase + 84,           /* -7852 =                          */
    scsiUnused85                = scsiErrorBase + 85,           /* -7851 =                          */
    scsiBadConnType             = scsiErrorBase + 86,           /* -7850 = Bad connection type              */
    scsiCannotLoadPlugin        = scsiErrorBase + 87            /* -7849 = No matching service category      */
};

/* +++ */
/*
 * scsiFamilyInternalError and scsiPluginInternalError are intended to handle consistency check failures.
 * For example, if the family stores a record on a lookaside queue, but does not find that record
 * it can use this error to report this failure. SCSI Manager 4.3 uses dsIOCoreErr in a few places,
 * but this is probably not the best error. In general, internal errors should be reported as bugs.
 *
 * The following range of errors is provided for third-party (non-Apple) SCSI SIM and device driver vendors.
 * In general, they would be used for error conditions that are not covered by the standardized errors.
 * They should not normally be conveyed to normal applications, but might be used for communication between
 * a plug-in and a vendor-provided device driver (for example, to manage RAID hot-swapping).
 *
 * Note: I don't know how many SCSI errors are reserved in the error code architecture. Don't assume that
 * we'll actually get sixteen, but we should reserve at least one.
 */
enum {
    scsiFamilyInternalError     = scsiErrorBase + 87,           /* -7849 = Internal consistency check failed  */
    scsiPluginInternalError     = scsiErrorBase + 88,           /* -7848 = Internal consistency check failed  */
    scsiVendorSpecificErrorBase = scsiErrorBase + 128,          /* ??    = Start of third-party error range     */
    scsiVendorSpecificErrorCount = 16                           /* Number of third-party errors             */
};

/* --- */
enum {
    scsiExecutionErrors         = scsiErrorBase,
    scsiNotExecutedErrors       = scsiTooManyBuses,
    scsiParameterErrors         = scsiPBLengthError
};

/* Defines for the scsiResultFlags field */
enum {
    scsiSIMQFrozen              = 0x0001,                       /* The SIM queue is frozen w/this err        */
    scsiAutosenseValid          = 0x0002,                       /* Autosense data valid for target         */
    scsiBusNotFree              = 0x0004                        /* At time of callback, SCSI bus is not free  */
};

/* Defines for the bit numbers of the scsiFlags field in the PB header for the SCSIExecIO function */
enum {
    kbSCSIDisableAutosense      = 29,                           /* Disable auto sense feature               */
    kbSCSIFlagReservedA         = 28,                           /*                             */
    kbSCSIFlagReserved0         = 27,                           /*                             */
    kbSCSICDBLinked             = 26,                           /* The PB contains a linked CDB             */
    kbSCSIQEnable               = 25,                           /* Target queue actions are enabled          */
    kbSCSICDBIsPointer          = 24,                           /* The CDB field contains a pointer          */
    kbSCSIFlagReserved1         = 23,                           /*                               */
    kbSCSIInitiateSyncData      = 22,                           /* Attempt Sync data xfer and SDTR          */
    kbSCSIDisableSyncData       = 21,                           /* Disable sync, go to async            */
    kbSCSISIMQHead              = 20,                           /* Place PB at the head of SIM Q          */
    kbSCSISIMQFreeze            = 19,                           /* Return the SIM Q to frozen state          */
    kbSCSISIMQNoFreeze          = 18,                           /* Disallow SIM Q freezing                 */
    kbSCSIDoDisconnect          = 17,                           /* Definitely do disconnect               */
    kbSCSIDontDisconnect        = 16,                           /* Definitely don't disconnect              */
    kbSCSIDataReadyForDMA       = 15,                           /* Data buffer(s) are ready for DMA          */
    kbSCSIFlagReserved3         = 14,                           /*                               */
    kbSCSIDataPhysical          = 13,                           /* SG/Buffer data ptrs are physical          */
    kbSCSISensePhysical         = 12,                           /* Autosense buffer ptr is physical          */
    kbSCSIFlagReserved5         = 11,                           /*                               */
    kbSCSIFlagReserved6         = 10,                           /*                               */
    kbSCSIFlagReserved7         = 9,                            /*                               */
    kbSCSIFlagReserved8         = 8,                            /*                               */
    kbSCSIDataBufferValid       = 7,                            /* Data buffer valid                 */
    kbSCSIStatusBufferValid     = 6,                            /* Status buffer valid                 */
    kbSCSIMessageBufferValid    = 5,                            /* Message buffer valid                */
    kbSCSIFlagReserved9         = 4                             /*                             */
};

/* Defines for the bit masks of the scsiFlags field */
enum {
    scsiDirectionMask           = (long)0xC0000000,             /* Data direction mask                 */
    scsiDirectionNone           = (long)0xC0000000,             /* Data direction (11: no data)          */
    scsiDirectionReserved       = 0x00000000,                   /* Data direction (00: reserved)       */
    scsiDirectionOut            = (long)0x80000000,             /* Data direction (10: DATA OUT)       */
    scsiDirectionIn             = 0x40000000,                   /* Data direction (01: DATA IN)          */
    scsiDisableAutosense        = 0x20000000,                   /* Disable auto sense feature          */
    scsiFlagReservedA           = 0x10000000,                   /*                           */
    scsiFlagReserved0           = 0x08000000,                   /*                           */
    scsiCDBLinked               = 0x04000000,                   /* The PB contains a linked CDB          */
    scsiQEnable                 = 0x02000000,                   /* Target queue actions are enabled      */
    scsiCDBIsPointer            = 0x01000000,                   /* The CDB field contains a pointer      */
    scsiFlagReserved1           = 0x00800000,                   /*                           */
    scsiInitiateSyncData        = 0x00400000,                   /* Attempt Sync data xfer and SDTR         */
    scsiDisableSyncData         = 0x00200000,                   /* Disable sync, go to async          */
    scsiSIMQHead                = 0x00100000,                   /* Place PB at the head of SIM Q       */
    scsiSIMQFreeze              = 0x00080000,                   /* Return the SIM Q to frozen state      */
    scsiSIMQNoFreeze            = 0x00040000,                   /* Disallow SIM Q freezing              */
    scsiDoDisconnect            = 0x00020000,                   /* Definitely do disconnect             */
    scsiDontDisconnect          = 0x00010000,                   /* Definitely don't disconnect          */
    scsiDataReadyForDMA         = 0x00008000,                   /* Data buffer(s) are ready for DMA      */
    scsiFlagReserved3           = 0x00004000,                   /*  */
    scsiDataPhysical            = 0x00002000,                   /* SG/Buffer data ptrs are physical      */
    scsiSensePhysical           = 0x00001000,                   /* Autosense buffer ptr is physical      */
    scsiFlagReserved5           = 0x00000800,                   /*                         */
    scsiFlagReserved6           = 0x00000400,                   /*                           */
    scsiFlagReserved7           = 0x00000200,                   /*                           */
    scsiFlagReserved8           = 0x00000100                    /*                           */
};

/* bit masks for the scsiIOFlags field in SCSIExecIOPB */
enum {
    scsiNoParityCheck           = 0x0002,                       /* disable parity checking                 */
    scsiDisableSelectWAtn       = 0x0004,                       /* disable select w/Atn                    */
    scsiSavePtrOnDisconnect     = 0x0008,                       /* do SaveDataPointer upon Disconnect msg          */
    scsiNoBucketIn              = 0x0010,                       /* don't bit bucket in during this I/O           */
    scsiNoBucketOut             = 0x0020,                       /* don't bit bucket out during this I/O        */
    scsiDisableWide             = 0x0040,                       /* disable wide transfer negotiation           */
    scsiInitiateWide            = 0x0080,                       /* initiate wide transfer negotiation           */
    scsiRenegotiateSense        = 0x0100,                       /* renegotiate sync/wide before issuing autosense     */
    scsiDisableDiscipline       = 0x0200,                       /* disable parameter checking on SCSIExecIO calls */
    scsiIOFlagReserved0080      = 0x0080,                       /*                                */
    scsiIOFlagReserved8000      = 0x8000                        /*                                  */
};

/* Defines for the Bus Inquiry PB fields. */
/* scsiHBAInquiry field bits */
enum {
    scsiBusMDP                  = 0x80,                         /* Supports Modify Data Pointer message               */
    scsiBusWide32               = 0x40,                         /* Supports 32 bit wide SCSI                    */
    scsiBusWide16               = 0x20,                         /* Supports 16 bit wide SCSI                    */
    scsiBusSDTR                 = 0x10,                         /* Supports Sync Data Transfer Req message              */
    scsiBusLinkedCDB            = 0x08,                         /* Supports linked CDBs                         */
    scsiBusTagQ                 = 0x02,                         /* Supports tag queue message                    */
    scsiBusSoftReset            = 0x01                          /* Supports soft reset                           */
};

/* Defines for the scsiDataType field */
enum {
    scsiDataBuffer              = 0,                            /* single contiguous buffer supplied            */
    scsiDataTIB                 = 1,                            /* TIB supplied (ptr in scsiDataPtr)           */
    scsiDataSG                  = 2,                            /* scatter/gather list supplied             */
    scsiDataIOTable             = 3                             /*#(7/11/95) Prepared by Block Storage         */
};

/* scsiDataTypes field bits  */
/*  bits 0->15 Apple-defined, 16->30 3rd-party unique, 31 = reserved */
enum {
    scsiBusDataTIB              = (1 << scsiDataTIB),           /* TIB supplied (ptr in scsiDataPtr)   */
    scsiBusDataBuffer           = (1 << scsiDataBuffer),        /* single contiguous buffer supplied      */
    scsiBusDataSG               = (1 << scsiDataSG),            /* scatter/gather list supplied        */
    scsiBusDataIOTable          = (1 << scsiDataIOTable),       /* (2/6/95) Prepare Memory for IO*/
    scsiBusDataReserved         = (long)0x80000000              /*                            */
};

/* scsiScanFlags field bits */
enum {
    scsiBusScansDevices         = 0x80,                         /* Bus scans for and maintains device list         */
    scsiBusScansOnInit          = 0x40,                         /* Bus scans performed at power-up/reboot        */
    scsiBusLoadsROMDrivers      = 0x20                          /* may load ROM drivers to support targets       */
};

/* scsiFeatureFlags field bits */
enum {
    scsiBusLVD                  = 0x00000400,                   /* HBA is Low Voltage Differential Bus         */
    scsiBusUltra3SCSI           = 0x00000200,                   /* HBA supports Ultra3 SCSI               */
    scsiBusUltra2SCSI           = 0x00000100,                   /* HBA supports Ultra2 SCSI               */
    scsiBusInternalExternalMask = 0x000000C0,                   /* bus internal/external mask           */
    scsiBusInternalExternalUnknown = 0x00000000,                /* not known whether bus is inside or outside     */
    scsiBusInternalExternal     = 0x000000C0,                   /* bus goes inside and outside the box       */
    scsiBusInternal             = 0x00000080,                   /* bus goes inside the box                */
    scsiBusExternal             = 0x00000040,                   /* bus goes outside the box             */
    scsiBusCacheCoherentDMA     = 0x00000020,                   /* DMA is cache coherent                */
    scsiBusOldCallCapable       = 0x00000010,                   /* SIM is old call capable                */
    scsiBusUltraSCSI            = 0x00000008,                   /* HBA supports Ultra SCSI                 */
    scsiBusDifferential         = 0x00000004,                   /* Single Ended (0) or Differential (1)    */
    scsiBusFastSCSI             = 0x00000002,                   /* HBA supports fast SCSI                  */
    scsiBusDMAavailable         = 0x00000001                    /* DMA is available                  */
};

/* scsiWeirdStuff field bits */
enum {
    scsiOddDisconnectUnsafeRead1 = 0x0001,                      /* Disconnects on odd byte boundries are unsafe with DMA and/or blind reads */
    scsiOddDisconnectUnsafeWrite1 = 0x0002,                     /* Disconnects on odd byte boundries are unsafe with DMA and/or blind writes */
    scsiBusErrorsUnsafe         = 0x0004,                       /* Non-handshaked delays or disconnects during blind transfers may cause a crash */
    scsiRequiresHandshake       = 0x0008,                       /* Non-handshaked delays or disconnects during blind transfers may cause data corruption */
    scsiTargetDrivenSDTRSafe    = 0x0010,                       /* Targets which initiate synchronous negotiations are supported */
    scsiOddCountForPhysicalUnsafe = 0x0020,                     /* If using physical addrs all counts must be even, and disconnects must be on even boundries */
    scsiAbortCmdFixed           = 0x0040,                       /* Set if abort command is fixed to properly make callbacks */
    scsiMeshACKTimingFixed      = 0x0080                        /* Set if bug allowing Mesh to release ACK prematurely is fixed */
};

/* scsiHBAslotType values */
enum {
    scsiMotherboardBus          = 0x00,                         /* A built in Apple supplied bus            */
    scsiNuBus                   = 0x01,                         /* A SIM on a NuBus card                   */
    scsiPDSBus                  = 0x03,                         /*    "  on a PDS card                    */
    scsiPCIBus                  = 0x04,                         /*    "  on a PCI bus card                   */
    scsiPCMCIABus               = 0x05,                         /*    "  on a PCMCIA card                  */
    scsiFireWireBridgeBus       = 0x06                          /*    "  connected through a FireWire bridge   */
};

/* Defines for the scsiDriverFlags field (in SCSIDriverPB) */
enum {
    scsiDeviceSensitive         = 0x0001,                       /* Only driver should access this device          */
    scsiDeviceNoOldCallAccess   = 0x0002                        /* no old call access to this device            */
};

/*  SIMInitInfo PB */
/* directions are for SCSIRegisterBus call ( -> parm, <- result)            */

struct SIMInitInfo {
    Ptr                             SIMstaticPtr;               /* <- alloc. ptr to the SIM's static vars           */
    long                            staticSize;                 /* -> num bytes SIM needs for static vars           */
    SIMInitUPP                      SIMInit;                    /* -> pointer to the SIM init routine               */
    SIMActionUPP                    SIMAction;                  /* -> pointer to the SIM action routine           */
    SCSIInterruptUPP                SIM_ISR;                    /*      reserved                           */
    SCSIInterruptUPP                SIMInterruptPoll;           /* -> pointer to the SIM interrupt poll routine      */
    SIMActionUPP                    NewOldCall;                 /* -> pointer to the SIM NewOldCall routine          */
    UInt16                          ioPBSize;                   /* -> size of SCSI_IO_PBs required for this SIM      */
    Boolean                         oldCallCapable;             /* -> true if this SIM can handle old-API calls      */
    UInt8                           simInfoUnused1;             /*      reserved                             */
    long                            simInternalUse;             /* xx not affected or viewed by XPT               */
    SCSIUPP                         XPT_ISR;                    /*    reserved                             */
    SCSIUPP                         EnteringSIM;                /* <- ptr to the EnteringSIM routine            */
    SCSIUPP                         ExitingSIM;                 /* <- ptr to the ExitingSIM routine               */
    SCSIMakeCallbackUPP             MakeCallback;               /* <- the XPT layer's SCSIMakeCallback routine            */
    UInt16                          busID;                      /* <- bus number for the registered bus             */
    UInt8                           simSlotNumber;              /* <- Magic cookie to place in scsiHBASlotNumber (PCI)    */
    UInt8                           simSRsrcID;                 /* <- Magic cookie to place in scsiSIMsRsrcID  (PCI)  */
    Ptr                             simRegEntry;                /* -> The SIM's RegEntryIDPtr            (PCI)  */
};
typedef struct SIMInitInfo              SIMInitInfo;
/* Glue between SCSI calls and SCSITrap format */
enum {
    xptSCSIAction               = 0x0001,
    xptSCSIRegisterBus          = 0x0002,
    xptSCSIDeregisterBus        = 0x0003,
    xptSCSIReregisterBus        = 0x0004,
    xptSCSIKillXPT              = 0x0005,                       /* kills Mini-XPT after transition */
    xptSCSIInitialize           = 0x000A                        /* Initialize the SCSI manager */
};

/*
 * SCSI bus status. These values are returned by the SCSI target in the status phase.
 * They are not related to Macintosh status values (except that values other than
 * scsiStatusGood will result in scsiResult set to scsiNonZeroStatus).
 */
enum {
    scsiStatGood                = 0x00,                         /* Good Status*/
    scsiStatCheckCondition      = 0x02,                         /* Check Condition*/
    scsiStatConditionMet        = 0x04,                         /* Condition Met*/
    scsiStatBusy                = 0x08,                         /* Busy*/
    scsiStatIntermediate        = 0x10,                         /* Intermediate*/
    scsiStatIntermedMet         = 0x14,                         /* Intermediate - Condition Met*/
    scsiStatResvConflict        = 0x18,                         /* Reservation conflict*/
    scsiStatTerminated          = 0x22,                         /* Command terminated*/
    scsiStatQFull               = 0x28                          /* Queue full*/
};

/* SCSI messages*/
enum {
    kCmdCompleteMsg             = 0,
    kExtendedMsg                = 1,                            /* 0x01*/
    kSaveDataPointerMsg         = 2,                            /* 0x02*/
    kRestorePointersMsg         = 3,                            /* 0x03*/
    kDisconnectMsg              = 4,                            /* 0x04*/
    kInitiatorDetectedErrorMsg  = 5,                            /* 0x05*/
    kAbortMsg                   = 6,                            /* 0x06*/
    kMsgRejectMsg               = 7,                            /* 0x07*/
    kNoOperationMsg             = 8,                            /* 0x08*/
    kMsgParityErrorMsg          = 9,                            /* 0x09*/
    kLinkedCmdCompleteMsg       = 10,                           /* 0x0a*/
    kLinkedCmdCompleteWithFlagMsg = 11,                         /* 0x0b*/
    kBusDeviceResetMsg          = 12,                           /* 0x0c*/
    kAbortTagMsg                = 13,                           /* 0x0d*/
    kClearQueueMsg              = 14,                           /* 0x0e*/
    kInitiateRecoveryMsg        = 15,                           /* 0x0f*/
    kReleaseRecoveryMsg         = 16,                           /* 0x10*/
    kTerminateIOProcessMsg      = 17,                           /* 0x11*/
    kSimpleQueueTag             = 0x20,                         /* 0x20*/
    kHeadOfQueueTagMsg          = 0x21,                         /* 0x21*/
    kOrderedQueueTagMsg         = 0x22,                         /* 0x22*/
    kIgnoreWideResidueMsg       = 0x23                          /* 0x23*/
};


/* moveq #kSCSIx, D0;  _SCSIAtomic */
                                                                                            #if TARGET_OS_MAC && TARGET_CPU_68K && !TARGET_RT_MAC_CFM
                                                                                            #pragma parameter __D0 SCSIAction(__A0)
                                                                                            #endif
EXTERN_API( OSErr )
SCSIAction                      (SCSI_PB *              parameterBlock)                     TWOWORDINLINE(0x7001, 0xA089);

#if CALL_NOT_IN_CARBON
                                                                                            #if TARGET_OS_MAC && TARGET_CPU_68K && !TARGET_RT_MAC_CFM
                                                                                            #pragma parameter __D0 SCSIRegisterBus(__A0)
                                                                                            #endif
EXTERN_API( OSErr )
SCSIRegisterBus                 (SIMInitInfo *          parameterBlock)                     TWOWORDINLINE(0x7002, 0xA089);

                                                                                            #if TARGET_OS_MAC && TARGET_CPU_68K && !TARGET_RT_MAC_CFM
                                                                                            #pragma parameter __D0 SCSIDeregisterBus(__A0)
                                                                                            #endif
EXTERN_API( OSErr )
SCSIDeregisterBus               (SCSI_PB *              parameterBlock)                     TWOWORDINLINE(0x7003, 0xA089);

                                                                                            #if TARGET_OS_MAC && TARGET_CPU_68K && !TARGET_RT_MAC_CFM
                                                                                            #pragma parameter __D0 SCSIReregisterBus(__A0)
                                                                                            #endif
EXTERN_API( OSErr )
SCSIReregisterBus               (SIMInitInfo *          parameterBlock)                     TWOWORDINLINE(0x7004, 0xA089);

                                                                                            #if TARGET_OS_MAC && TARGET_CPU_68K && !TARGET_RT_MAC_CFM
                                                                                            #pragma parameter __D0 SCSIKillXPT(__A0)
                                                                                            #endif
EXTERN_API( OSErr )
SCSIKillXPT                     (SIMInitInfo *          parameterBlock)                     TWOWORDINLINE(0x7005, 0xA089);


#endif  /* CALL_NOT_IN_CARBON */


#if PRAGMA_STRUCT_ALIGN
    #pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
    #pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
    #pragma pack()
#endif

#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif

#ifdef __cplusplus
}
#endif

#endif /* __SCSI__ */

