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

     $RCSfile: HardBlocks.mod $
  Description: File system identifier blocks for hard disks

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

  $VER: hardblocks.h 36.3 (23.8.91)
  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 HardBlocks;

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

IMPORT E := Exec;


(*
**      File System identifier blocks for hard disks
*)


(* --------------------------------------------------------------------
 *
 *      This file describes blocks of data that exist on a hard disk
 *      to describe that disk.  They are not generically accessable to
 *      the user as they do not appear on any DOS drive.  The blocks
 *      are tagged with a unique identifier, checksummed, and linked
 *      together.  The root of these blocks is the RigidDiskBlock.
 *
 *      The RigidDiskBlock must exist on the disk within the first
 *      rdbLocationLIMIT blocks.  This inhibits the use of the zero
 *      cylinder in an AmigaDOS partition: although it is strictly
 *      possible to store the RigidDiskBlock data in the reserved
 *      area of a partition, this practice is discouraged since the
 *      reserved blocks of a partition are overwritten by "Format",
 *      "Install", "DiskCopy", etc.  The recommended disk layout,
 *      then, is to use the first cylinder(s) to store all the drive
 *      data specified by these blocks: i.e. partition descriptions,
 *      file system load images, drive bad block maps, spare blocks,
 *      etc.
 *
 *      Though only 512 byte blocks are currently supported by the
 *      file system, this proposal tries to be forward-looking by
 *      making the block size explicit, and by using only the first
 *      256 bytes for all blocks but the LoadSeg data.
 *
 *------------------------------------------------------------------*)

(*
 *  NOTE
 *      optional block addresses below contain $ffffffff to indicate
 *      a NULL address, as zero is a valid address
 *)

TYPE

  RigidDiskBlockPtr * = CPOINTER TO RigidDiskBlock;
  RigidDiskBlock * = RECORD
    id *                : E.ULONG; (* 4 character identifier *)
    summedLongs *       : E.ULONG; (* size of this checksummed $tructure *)
    chkSum *            : LONGINT; (* block checksum (longword sum to zero) *)
    hostID *            : E.ULONG; (* SCSI Target ID of host *)
    blockBytes *        : E.ULONG; (* size of disk blocks *)
    flags *             : E.ULONG; (* see below for defines *)
    (* block list heads *)
    badBlockList *      : E.ULONG; (* optional bad block list *)
    partitionList *     : E.ULONG; (* optional first partition block *)
    fileSysHeaderList * : E.ULONG; (* optional file system header block *)
    driveInit *         : E.ULONG; (* optional drive-specific init code *)
                                      (* DriveInit(lun,rdb,ior): "C" stk & d0/a0/a1 *)
    reserved1 *         : ARRAY 6 OF E.ULONG;
                                      (* set to $ffffffff *)
    (* physical drive characteristics *)
    cylinders *         : E.ULONG; (* number of drive cylinders *)
    sectors *           : E.ULONG; (* sectors per track *)
    heads *             : E.ULONG; (* number of drive heads *)
    interleave *        : E.ULONG; (* interleave *)
    park *              : E.ULONG; (* landing zone cylinder *)
    reserved2 *         : ARRAY 3 OF E.ULONG;
    writePreComp *      : E.ULONG; (* starting cylinder: write precompensation *)
    reducedWrite *      : E.ULONG; (* starting cylinder: reduced write current *)
    stepRate *          : E.ULONG; (* drive step rate *)
    reserved3 *         : ARRAY 5 OF E.ULONG;
    (* logical drive characteristics *)
    rdbBlocksLo *       : E.ULONG; (* low block of range reserved for hardblocks *)
    rdbBlocksHi *       : E.ULONG; (* high block of range for these hardblocks *)
    loCylinder *        : E.ULONG; (* low cylinder of partitionable disk area *)
    hiCylinder *        : E.ULONG; (* high cylinder of partitionable data area *)
    cylBlocks *         : E.ULONG; (* number of blocks available per cylinder *)
    autoParkSeconds *   : E.ULONG; (* zero for no auto park *)
    highRDSKBlock *     : E.ULONG; (* highest block used by RDSK *)
                                      (* (not including replacement bad blocks) *)
    reserved4 *         : E.ULONG;
    (* drive identification *)
    diskVendor *        : ARRAY 8 OF CHAR;
    diskProduct *       : ARRAY 16 OF CHAR;
    diskRevision *      : ARRAY 4 OF CHAR;
    controllerVendor *  : ARRAY 8 OF CHAR;
    controllerProduct * : ARRAY 16 OF CHAR;
    controllerRevision * : ARRAY 4 OF CHAR;
    reserved5 *         : ARRAY 10 OF E.ULONG;
  END; (* RigidDiskBlock *)

CONST

  idNameRigidDisk        * = 5244534BH;      (* 'RDSK' *)

  rdbLocationLimit      * = 16;

  rdbLast      * = 0;        (* no disks exist to be configured after *)
                             (*   this one on this controller *)
  rdbLastLun   * = 1;        (* no LUNs exist to be configured greater *)
                             (*   than this one at this SCSI Target ID *)
  rdbLastTID   * = 2;        (* no Target IDs exist to be configured *)
                             (*   greater than this one on this SCSI bus *)
  rdbLsatTID   * = rdbLastTID; (* typo *)
  rdbNoReselect * = 3;       (* don't bother trying to perform reselection *)
                             (*   when talking to this drive *)
  rdbDiskID    * = 4;        (* rdbDisk... identification valid *)
  rdbCtrlrID   * = 5;        (* rdbController... identification valid *)

                             (* added 7/20/89 by commodore: *)
  rdbSynch     * = 6;        (* drive supports scsi synchronous mode *)
                             (* CAN BE DANGEROUS TO USE IF IT DOESN'T! *)

(* ------------------------------------------------------------------*)

TYPE

  BadBlockEntryPtr * = CPOINTER TO BadBlockEntry;
  BadBlockEntry * = RECORD
    badBlock *  : E.ULONG;      (* block number of bad block *)
    goodBlock * : E.ULONG;      (* block number of replacement block *)
  END; (* BadBlockEntry *)

  BadBlockBlockPtr * = CPOINTER TO BadBlockBlock;
  BadBlockBlock * = RECORD
    id *          : E.ULONG; (* 4 character identifier *)
    summedLongs * : E.ULONG; (* size of this checksummed $tructure *)
    chkSum *      : LONGINT; (* block checksum (longword sum to zero) *)
    hostID *      : E.ULONG; (* SCSI Target ID of host *)
    next *        : E.ULONG; (* block number of the next BadBlockBlock *)
    reserved *    : E.ULONG;
    blockPairs *  : ARRAY 61 OF BadBlockEntry;
                                (* bad block entry pairs *)
    (* note [61] assumes 512 byte blocks *)
  END; (* BadBlockBlock *)

CONST

  idNameBadBlock         * = 42414442H;      (* 'BADB' *)

(* ------------------------------------------------------------------*)

TYPE

  PartitionBlockPtr * = CPOINTER TO PartitionBlock;
  PartitionBlock * = RECORD
    id *          : E.ULONG;             (* 4 character identifier *)
    summedLongs * : E.ULONG;             (* size of this checksummed $tructure *)
    chkSum *      : LONGINT;             (* block checksum (longword sum to zero) *)
    hostID *      : E.ULONG;             (* SCSI Target ID of host *)
    next *        : E.ULONG;             (* block number of the next PartitionBlock *)
    flags *       : E.ULONG;             (* see below for defines *)
    reserved1 *   : ARRAY 2 OF E.ULONG;
    devFlags *    : E.ULONG;             (* preferred flags for OpenDevice *)
    driveName *   : ARRAY 32 OF CHAR;    (* preferred DOS device name: BSTR form *)
                                           (* (not used if this name is in use) *)
    reserved2 *   : ARRAY 15 OF E.ULONG; (* filler to 32 longwords *)
    environment * : ARRAY 17 OF E.ULONG; (* environment vector for this partition *)
    eReserved *   : ARRAY 15 OF E.ULONG; (* reserved for future environment vector *)
  END; (* PartitionBlock *)

CONST

  idNamePartition        * = 50415254H;      (* 'PART' *)

  pbBootable   * = 0;        (* this partition is intended to be bootable *)
                             (*   (expected directories and files exist) *)
  pbNoMount    * = 1;        (* do not mount this partition (e.g. manually *)
                             (*   mounted, but space reserved here) *)

(* ------------------------------------------------------------------*)

TYPE

  FileSysHeaderBlockPtr * = CPOINTER TO FileSysHeaderBlock;
  FileSysHeaderBlock * = RECORD
    id *          : E.ULONG; (* 4 character identifier *)
    summedLongs * : E.ULONG; (* size of this checksummed $tructure *)
    chkSum *      : LONGINT; (* block checksum (longword sum to zero) *)
    hostID *      : E.ULONG; (* SCSI Target ID of host *)
    next *        : E.ULONG; (* block number of next FileSysHeaderBlock *)
    flags *       : E.ULONG; (* see below for defines *)
    reserved1 *   : ARRAY 2 OF E.ULONG;
    dosType *     : E.ULONG; (* file system description: match this with *)
                                (* partition environment's deDOSTYPE entry *)
    version *     : E.ULONG; (* release version of this code *)
    patchFlags *  : E.ULONG; (* bits set for those of the following that *)
                                (*   need to be substituted into a standard *)
                                (*   device node for this file system: e.g. *)
                                (*   180H to substitute SegList & GlobalVec *)
    type *        : E.ULONG; (* device node type: zero *)
    task *        : E.ULONG; (* standard dos "task" field: zero *)
    lock *        : E.ULONG; (* not used for devices: zero *)
    handler *     : E.ULONG; (* filename to loadseg: zero placeholder *)
    stackSize *   : E.ULONG; (* stacksize to use when starting task *)
    priority *    : LONGINT; (* task priority when starting task *)
    startup *     : LONGINT; (* startup msg: zero placeholder *)
    segListBlocks * : LONGINT; (* first of linked list of LoadSegBlocks: *)
                                  (*   note that this entry requires some *)
                                  (*   processing before substitution *)
    globalVec *   : LONGINT; (* BCPL global vector when starting task *)
    reserved2 *   : ARRAY 23 OF E.ULONG; (* (those reserved by PatchFlags) *)
    reserved3 *   : ARRAY 21 OF E.ULONG;
  END; (* FileSysHeaderBlock *)

CONST

  idNameFileSysHeader    * = 46534844H;      (* 'FSHD' *)

(* ------------------------------------------------------------------*)

TYPE

  LoadSegBlockPtr * = CPOINTER TO LoadSegBlock;
  LoadSegBlock * = RECORD
    id *          : E.ULONG; (* 4 character identifier *)
    summedLongs * : E.ULONG; (* size of this checksummed $tructure *)
    chkSum *      : LONGINT; (* block checksum (longword sum to zero) *)
    hostID *      : E.ULONG; (* Target ID of host *)
    next *        : E.ULONG; (* block number of the next LoadSegBlock *)
    loadData *    : ARRAY 123 OF E.ULONG;  (* data for "loadseg" *)
    (* note [123] assumes 512 byte blocks *)
  END; (* LoadSegBlock *)

CONST

  idNameLoadSeg          * = 4C534547H;      (* 'LSEG' *)


END HardBlocks.
