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

     $RCSfile: CDDevice.mod $
  Description: Interface to cd.device

   Created by: fjc (Frank Copeland)
    $Revision: 3.1 $
      $Author: fjc $
        $Date: 1994/08/08 01:16:03 $

  $VER: cd.h 1.11 (12.8.93)
  Includes Release 40.15

  (C) Copyright 1992-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 CDDevice;

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

IMPORT E := Exec, SYS := SYSTEM;

(**************************************************************************
 *                                                                        *
 *   CD Commands                                                          *
 *                                                                        *
 **************************************************************************)

CONST

  reset *        = 1;
  read *         = 2;
  write *        = 3;
  update *       = 4;
  clear *        = 5;
  stop *         = 6;
  start *        = 7;
  flush *        = 8;
  motor *        = 9;
  seek *         = 10;
  format *       = 11;
  remove *       = 12;
  changeNum *    = 13;
  changeState *  = 14;
  protStatus *   = 15;

  getDriveType * = 18;
  getNumTracks * = 19;
  addChangeInt * = 20;
  remChangeInt * = 21;
  getGeometry *  = 22;
  eject *        = 23;


  info *         = 32;
  config *       = 33;
  tocMSF *       = 34;
  tocLSN *       = 35;

  readXL *       = 36;

  playTrack *    = 37;
  playMSF *      = 38;
  playLSN *      = 39;
  pause *        = 40;
  search *       = 41;

  qCodeMSF *     = 42;
  qCodeLSN *     = 43;
  attenuate *    = 44;

  addFrameInt *  = 45;
  remFrameInt *  = 46;


(**************************************************************************
 *                                                                        *
 *   Device Driver Error Codes                                            *
 *                                                                        *
 **************************************************************************)

CONST

  errOpenFail *       = -1;  (* device/unit failed to open   *)
  errAborted *        = -2;  (* request terminated early             *)
  errNoCmd *          = -3;  (* command not supported by device      *)
  errBadLength *      = -4;  (* invalid length (IO_LENGTH/IO_OFFSET) *)
  errBadAddress *     = -5;  (* invalid address (IO_DATA misaligned) *)
  errUnitBusy *       = -6;  (* device opens ok, but unit is busy    *)
  errSelfTest *       = -7;  (* hardware failed self-test            *)

  errNotSpecified *   = 20;  (* general catchall                     *)
  errNoSecHdr *       = 21;  (* couldn't even find a sector          *)
  errBadSecPreamble * = 22;  (* sector looked wrong                  *)
  errBadSecID *       = 23;  (* ditto                                *)
  errBadHdrSum *      = 24;  (* header had incorrect checksum        *)
  errBadSecSum *      = 25;  (* data had incorrect checksum          *)
  errTooFewSecs *     = 26;  (* couldn't find enough sectors         *)
  errBadSecHdr *      = 27;  (* another "sector looked wrong"        *)
  errWriteProt *      = 28;  (* can't write to a protected disk      *)
  errNoDisk *         = 29;  (* no disk in the drive                 *)
  errSeekError *      = 30;  (* couldn't find track 0                *)
  errNoMem *          = 31;  (* ran out of memory                    *)
  errBadUnitNum *     = 32;  (* asked for a unit > NUMUNITS          *)
  errBadDriveType *   = 33;  (* not a drive cd.device understands    *)
  errDriveInUse *     = 34;  (* someone else allocated the drive     *)
  errPostReset *      = 35;  (* user hit reset; awaiting doom        *)
  errBadDataType *    = 36;  (* data on disk is wrong type   *)
  errInvalidState *   = 37;  (* invalid cmd under current conditions *)

  errPhase *          = 42;  (* illegal or unexpected SCSI phase     *)
  errNoBoard *        = 50;  (* open failed for non-existant board   *)



(**************************************************************************
 *                                                                        *
 * Configuration                                                          *
 *                                                                        *
 *       The drive is configured by TagList items defined as follows:     *
 *                                                                        *
 **************************************************************************)

CONST

  tagPlaySpeed *   = 00001H;
  tagReadSpeed *   = 00002H;
  tagReadXLSpeed * = 00003H;
  tagSectorSize *  = 00004H;
  tagXLECC *       = 00005H;
  tagEjectReset *  = 00006H;


(**************************************************************************
 *                                                                        *
 * Information                                                            *
 *                                                                        *
 *      Information/Status structure describes current speed settings     *
 *      for read and play commands, sector size, audio attenuation        *
 *      precision, and drive status.                                      *
 *                                                                        *
 **************************************************************************)

TYPE

  CDInfoPtr * = CPOINTER TO CDInfo;
  CDInfo  * = RECORD        (*                                Default       *)
    playSpeed *      : E.UWORD; (* Audio play speed       (75)              *)
    readSpeed *      : E.UWORD; (* Data-rate of CD_READ command   (Max)     *)
    readXLSpeed *    : E.UWORD; (* Data-rate of CD_READXL command (75)      *)
    sectorSize *     : E.UWORD; (* Number of bytes per sector     (2048)    *)
    xlECC *          : E.UWORD; (* CDXL ECC enabled/disabled                *)
    ejectReset *     : E.UWORD; (* Reset on eject enabled/disabled          *)
    reserved1 *      : ARRAY 4 OF E.UWORD; (* Reserved for future expansion *)
    maxSpeed *       : E.UWORD; (* Maximum speed drive can handle (75, 150) *)
    audioPrecision * : E.UWORD; (* 0 = no attenuator, 1 = mute only,        *)
                                (* other = (# levels - 1)                   *)
    status *         : E.UWORD; (* See flags below                          *)
    reserved2 *      : ARRAY 4 OF E.UWORD; (* Reserved for future expansion *)
  END;

CONST

(* Flags for Status *)

  stsClosed *    = 0;  (* Drive door is closed                        *)
  stsDisk *      = 1;  (* A disk has been detected                    *)
  stsSpin *      = 2;  (* Disk is spinning (motor is on)              *)
  stsTOC *       = 3;  (* Table of contents read.  Disk is valid.     *)
  stsCDRom *     = 4;  (* Track 1 contains CD-ROM data                *)
  stsPlaying *   = 5;  (* Audio is playing                            *)
  stsPaused *    = 6;  (* Pause mode (pauses on play command)         *)
  stsSearch *    = 7;  (* Search mode (Fast Forward/Fast Reverse)     *)
  stsDirection * = 8;  (* Search direction (0 = Forward, 1 = Reverse) *)

(* Modes for CD_SEARCH *)

  modeNormal *   = 0;  (* Normal play at current play speed    *)
  modeFFwd *     = 1;  (* Fast forward play (skip-play forward)*)
  modeFRev *     = 2;  (* Fast reverse play (skip-play reverse)*)


(**************************************************************************
 *                                                                        *
 * Position Information                                                   *
 *                                                                        *
 *      Position information can be described in two forms: MSF and LSN   *
 *      form.  MSF (Minutes, Seconds, Frames) form is a time encoding.    *
 *      LSN (Logical Sector Number) form is frame (sector) count.         *
 *      The desired form is selected using the io_Flags field of the      *
 *      IOStdReq structure.  The flags and the union are described        *
 *      below.                                                            *
 *                                                                        *
 **************************************************************************)

TYPE

  RMSFPtr * = CPOINTER TO RMSF;
  RMSF  * = RECORD
    reserved * : E.UBYTE;  (* Reserved (always zero) *)
    minute *   : E.UBYTE;  (* Minutes (0-72ish)      *)
    second *   : E.UBYTE;  (* Seconds (0-59)         *)
    frame *    : E.UBYTE;  (* Frame   (0-74)         *)
  END;

  RLSNPtr * = CPOINTER TO RLSN;
  RLSN  * = RECORD
    lsn * : E.ULONG;       (* Logical Sector Number  *)
  END;


(**************************************************************************
 *                                                                        *
 * CD Transfer Lists                                                      *
 *                                                                        *
 *      A CDXL node is a double link node; however only single linkage    *
 *      is used by the device driver.  If you wish to construct a         *
 *      transfer list manually, it is only neccessary to define the       *
 *      mln_Succ pointer of the MinNode.  You may also use the Exec       *
 *      list functions by defining a List or MinList structure and by     *
 *      using the AddHead/AddTail functions to create the list.  This     *
 *      will create a double-linked list.  Although a double-linked       *
 *      list is not required by the device driver, you may wish use it    *
 *      for your own purposes.  Don't forget to initialize the            *
 *      the List/MinList before using it!                                 *
 *                                                                        *
 **************************************************************************)

TYPE

  CDXLPtr * = CPOINTER TO CDXL;
  CDXL  * = RECORD (E.MinNode) (* double linkage                  *)
    buffer *  : E.APTR;        (* data destination (word aligned) *)
    length *  : LONGINT;       (* must be even # bytes            *)
    actual *  : LONGINT;       (* bytes transferred               *)
    intData * : E.APTR;        (* interrupt server data segment   *)
    IntCode * : E.PROC;        (* interrupt server code entry     *)
  END;


(**************************************************************************
 *                                                                        *
 * CD Table of Contents                                                   *
 *                                                                        *
 *      The CD_TOC command returns an array of CDTOC entries.             *
 *      Entry zero contains summary information describing how many       *
 *      tracks the disk has and the play-time of the disk.                *
 *      Entries 1 through N (N = Number of tracks on disk) contain        *
 *      information about the track.                                      *
 *                                                                        *
 **************************************************************************)

TYPE

  TOCSummaryPtr * = CPOINTER TO TOCSummary;
  TOCSummary  * = RECORD
    firstTrack * : E.UBYTE; (* First track on disk (always 1)            *)
    lastTrack *  : E.UBYTE; (* Last track on disk                        *)
  END;

  TOCSummaryMSFPtr * = CPOINTER TO TOCSummaryMSF;
  TOCSummaryMSF  * = RECORD (TOCSummary)
    leadOut * : RMSF;       (* Beginning of lead-out track (end of disk) *)
  END;

  TOCSummaryLSNPtr * = CPOINTER TO TOCSummaryLSN;
  TOCSummaryLSN  * = RECORD (TOCSummary)
    leadOut * : RLSN;       (* Beginning of lead-out track (end of disk) *)
  END;

  TOCEntryPtr * = CPOINTER TO TOCEntry;
  TOCEntry  * = RECORD
    ctlAdr * : E.UBYTE;     (* Q-Code info                  *)
    track *  : E.UBYTE;     (* Track number                 *)
  END;

  TOCEntryMSFPtr * = CPOINTER TO TOCEntryMSF;
  TOCEntryMSF  * = RECORD (TOCEntry)
    position * : RMSF;      (* Start position of this track *)
  END;

  TOCEntryLSNPtr * = CPOINTER TO TOCEntryLSN;
  TOCEntryLSN  * = RECORD (TOCEntry)
    position * : RLSN;      (* Start position of this track *)
  END;

  CDTOCPtr * = CPOINTER TO CDTOC;
  CDTOC  * = RECORD END;

  CDTOCMSFPtr * = CPOINTER TO CDTOCMSF;
  CDTOCMSF  * = RECORD (CDTOC)
    summary * : TOCSummaryMSF; (* First entry (0) is summary information *)
    entry *   : ARRAY 256 OF TOCEntryMSF; (* Entries 1-N are track entries          *)
  END;

  CDTOCLSNPtr * = CPOINTER TO CDTOCLSN;
  CDTOCLSN  * = RECORD (CDTOC)
    summary * : TOCSummaryLSN; (* First entry (0) is summary information *)
    entry *   : ARRAY 256 OF TOCEntryLSN; (* Entries 1-N are track entries          *)
  END;


(**************************************************************************
 *                                                                        *
 * Q-Code Packets                                                         *
 *                                                                        *
 *      Q-Code packets are only returned when audio is playing.           *
 *      Currently, only position packets are returned (ADR_POSITION)      *
 *      The other ADR_ types are almost never encoded on the disk         *
 *      and are of little use anyway.  To avoid making the QCode          *
 *      structure a union, these other ADR_ structures are not defined.   *
 *                                                                        *
 **************************************************************************)

TYPE

  QCodeMSFPtr * = CPOINTER TO QCodeMSF;
  QCodeMSF  * = RECORD
    ctlAdr *        : E.UBYTE; (* Data type / QCode type           *)
    track *         : E.UBYTE; (* Track number                     *)
    index *         : E.UBYTE; (* Track subindex number            *)
    zero *          : E.UBYTE; (* The "Zero" byte of Q-Code packet *)
    trackPosition * : RMSF;    (* Position from start of track     *)
    diskPosition *  : RMSF;    (* Position from start of disk      *)
  END;

  QCodeLSNPtr * = CPOINTER TO QCodeLSN;
  QCodeLSN  * = RECORD
    ctlAdr *        : E.UBYTE; (* Data type / QCode type           *)
    track *         : E.UBYTE; (* Track number                     *)
    index *         : E.UBYTE; (* Track subindex number            *)
    zero *          : E.UBYTE; (* The "Zero" byte of Q-Code packet *)
    trackPosition * : RLSN;    (* Position from start of track     *)
    diskPosition *  : RLSN;    (* Position from start of disk      *)
  END;

CONST

  ctlAdrCtlMask * = 0F0H;  (* Control field *)

  ctlCtlMask *    = 0D0H;  (* To be ANDed with CtlAdr before compared  *)

  ctl2Aud *       = 000H;  (* 2 audio channels without preemphasis     *)
  ctl2AudEmph *   = 010H;  (* 2 audio channels with preemphasis        *)
  ctl4Aud *       = 080H;  (* 4 audio channels without preemphasis     *)
  ctl4AudEmph *   = 090H;  (* 4 audio channels with preemphasis        *)
  ctlData *       = 040H;  (* CD-ROM Data                              *)

  ctlCopyMask *   = 020H;  (* To be ANDed with CtlAdr before compared  *)

  ctlCopy *       = 020H;  (* When true, this audio/data can be copied *)

  ctlAdrAdrMask * = 00FH;  (* Address field                            *)

  adrPosition *   = 001H;  (* Q-Code is position information   *)
  adrUPC *        = 002H;  (* Q-Code is UPC information (not used)     *)
  adrISRC *       = 003H;  (* Q-Code is ISRC (not used)                *)
  adrHybrid *     = 005H;  (* This disk is a hybrid disk               *)

END CDDevice.
