(**************************************************************************

     $RCSfile: SCSIDisk.mod $
  Description: SCSI command definitions

   Created by: fjc (Frank Copeland)
    $Revision: 3.2 $
      $Author: fjc $
        $Date: 1994/08/08 00:47:38 $

  $VER: scsidisk.h 36.2 (7.11.90)
  Includes Release 40.15

  (C) Copyright 1985-1993 Commodore-Amiga, Inc.
      All Rights Reserved

  Oberon-A interface Copyright © 1994, Frank Copeland.
  This file is part of the Oberon-A Interface.
  See Oberon-A.doc for conditions of use and distribution.

***************************************************************************)

MODULE SCSIDisk;

(*
** $C- CaseChk       $I- IndexChk  $L+ LongAdr   $N- NilChk
** $P- PortableCode  $R- RangeChk  $S- StackChk  $T- TypeChk
** $V- OvflChk       $Z- ZeroVars
*)

IMPORT E := Exec;


(*
**
**      SCSI exec-level device command
**
*)


(* --------------------------------------------------------------------
 *
 *   SCSI Command
 *      Several Amiga SCSI controller manufacturers are converging on
 *      standard ways to talk to their controllers.  This include
 *      file describes an exec-device command (e.g. for hddisk.device)
 *      that can be used to issue SCSI commands
 *
 *   UNIT NUMBERS
 *      Unit numbers to the OpenDevice call have encoded in them which
 *      SCSI device is being referred to.  The three decimal digits of
 *      the unit number refer to the SCSI Target ID (bus address) in
 *      the 1's digit, the SCSI logical unit (LUN) in the 10's digit,
 *      and the controller board in the 100's digit.
 *
 *      Examples:
 *                0     drive at address 0
 *               12     LUN 1 on multiple drive controller at address 2
 *              104     second controller board, address 4
 *               88     not valid: both logical units and addresses
 *                      range from 0..7.
 *
 *   CAVEATS
 *      Original 2090 code did not support this command.
 *
 *      Commodore 2090/2090A unit numbers are different.  The SCSI
 *      logical unit is the 100's digit, and the SCSI Target ID
 *      is a permuted 1's digit: Target ID 0..6 maps to unit 3..9
 *      (7 is reserved for the controller).
 *
 *          Examples:
 *                3     drive at address 0
 *              109     drive at address 6, logical unit 1
 *                1     not valid: this is not a SCSI unit.  Perhaps
 *                      it's an ST506 unit.
 *
 *      Some controller boards generate a unique name (e.g. 2090A's
 *      iddisk.device) for the second controller board, instead of
 *      implementing the 100's digit.
 *
 *      There are optional restrictions on the alignment, bus
 *      accessability, and size of the data for the data phase.
 *      Be conservative to work with all manufacturer's controllers.
 *
 *------------------------------------------------------------------*)

CONST

  hdScsiCmd *      = 28;      (* issue a SCSI command to the unit *)
                              (* ioData points to a SCSICmd *)
                              (* ioLength is SIZE (SCSICmd) *)
                              (* ioActual and ioOffset are not used *)

TYPE

  SCSICmdPtr * = CPOINTER TO SCSICmd;
  SCSICmd * = RECORD
    data *        : E.APTR;   (* word aligned data for SCSI Data Phase *)
                              (* (optional) data need not be byte aligned *)
                              (* (optional) data need not be bus accessable *)
    length *      : E.ULONG;  (* even length of Data area *)
                              (* (optional) data can have odd length *)
                              (* (optional) data length can be > 2**24 *)
    actual *      : E.ULONG;  (* actual Data used *)
    command *     : E.APTR;   (* SCSI Command (same options as Data) *)
    cmdLength *   : E.UWORD;  (* length of Command *)
    cmdActual *   : E.UWORD;  (* actual Command used *)
    flags *       : E.BSET;   (* includes intended data direction *)
    status *      : E.UBYTE;  (* SCSI status of command *)
    senseData *   : E.APTR;   (* sense data: filled if [OLD]AUTOSENSE *)
                              (* is set and Status has CHECK CONDITION *)
                              (* (bit 1) set *)
    senseLength * : E.UWORD;  (* size of SenseData, also bytes to *)
                              (* request w/ AUTOSENSE, must be 4..255 *)
    senseActual * : E.UWORD;  (* amount actually fetched (0 means no sense) *)
  END; (* SCSICmd *)

CONST

(* ----- scsiFlags -----*)
  scsiWrite *             = {};      (* intended data direction is out *)
  scsiRead *              = {0};     (* intended data direction is in *)
  scsiReadWrite *         = 0;       (* (the bit to test) *)
  scsiNoSense *           = {};      (* no automatic request sense *)
  scsiAutoSense *         = 1;       (* do standard extended request sense *)
                                     (* on check condition *)
  scsiOldAutoSense *      = 2;       (* do 4 byte non-extended request *)
                                     (* sense on check condition *)

(* ----- SCSI ioError values -----*)
  hfErrSelfUnit *          = 40;      (* cannot issue SCSI command to self *)
  hfErrDMA *               = 41;      (* DMA error *)
  hfErrPhase *             = 42;      (* illegal or unexpected SCSI phase *)
  hfErrParity *            = 43;      (* SCSI parity error *)
  hfErrSelTimeout *        = 44;      (* Select timed out *)
  hfErrBadStatus *         = 45;      (* status and/or sense error *)

(* ----- OpenDevice ioError values -----*)
  hfErrNoBoard *           = 50;      (* Open failed for non-existant board *)


END SCSIDisk.
