-- File: DiskIOPrivate.mesa
-- Last edited by Levin:  11-May-81 14:38:34

DIRECTORY
  AltoDefs USING [BYTE],
  AltoHardware USING [DA, DC, DFS, DH, DL, DS, InvalidDA],
  DiskIODefs USING [DISK, CompletionProcedure, CompletionStatus, RequestID, vDA, vDC],
  Mopcodes USING [zAND];

DiskIOPrivate: DEFINITIONS =

  BEGIN

  -- Types and Related Constants --

  DA: TYPE = AltoHardware.DA;
  DC: TYPE = AltoHardware.DC;
  DH: TYPE = AltoHardware.DH;
  DL: TYPE = AltoHardware.DL;
  DS: TYPE = AltoHardware.DS;
  DFS: TYPE = AltoHardware.DFS;

  DISK: TYPE = DiskIODefs.DISK;

  CompletionProcedure: TYPE = DiskIODefs.CompletionProcedure;
  RequestID: TYPE = DiskIODefs.RequestID;

  CB: TYPE = MACHINE DEPENDENT RECORD [
    nextCB: CBPtr,
    status: DS,
    command: DC,
    headerAddress: POINTER TO DH,
    labelAddress: POINTER TO DL,
    dataAddress: POINTER,
    normalWakeups: WORD,
    errorWakeups: WORD,
    header: DH,
    label: DL,
    nextOnQueue: CBPtr,
    requestID: RequestID,
    postProc: CompletionProcedure,
    omitRestore: BOOLEAN,
    fill: [0..77777B]];

  CBPtr: TYPE = POINTER TO CB;
  CBQueueTail: TYPE = POINTER TO CBPtr;

  vDC: TYPE = DiskIODefs.vDC;

  DCs: ARRAY vDC OF DC = [
	DC[DCseal, DiskRead,  DiskRead,  DiskRead,  0, 0],  --  ReadHLD
	DC[DCseal, DiskCheck, DiskRead,  DiskRead,  0, 0],  --  ReadLD
	DC[DCseal, DiskCheck, DiskCheck, DiskRead,  0, 0],  --  ReadD
	DC[DCseal, DiskWrite, DiskWrite, DiskWrite, 0, 0],  --  WriteHLD
	DC[DCseal, DiskCheck, DiskWrite, DiskWrite, 0, 0],  --  WriteLD
	DC[DCseal, DiskCheck, DiskCheck, DiskWrite, 0, 0],  --  WriteD
	DC[DCseal, DiskCheck, DiskCheck, DiskCheck, 1, 0],  --  SeekOnly
	DC[DCseal, DiskCheck, DiskCheck, DiskCheck, 0, 0]]; --  DoNothing

  DiskSeal: TYPE = AltoDefs.BYTE;

  DCseal: DiskSeal = 110B;
  DCunseal: DiskSeal = 0B;

  DSfree: CARDINAL = 1;
  DSfake: CARDINAL = 3;
  DSdone: CARDINAL = 17B;
  DSmaskStatus: DS = DS[0, DSdone, 1, 0, 1, 1, 0, 1, LAST[DFS]];
  DSgoodStatus: DS = DS[0, DSdone, 0, 0, 0, 0, 0, 0, CommandComplete];
  DSfakeStatus: DS = DS[0, DSfake, 0, 0, 0, 0, 0, 0, CommandComplete];

  InvalidDA: DA = AltoHardware.InvalidDA;
  
  nDisks: CARDINAL = 1;
  nHeads: CARDINAL = 2;
  nTracks: CARDINAL = 203;
  nSectors: CARDINAL = 12;
  
  standardDisk: DISK = [nDisks, nTracks, nHeads, nSectors];
 
  nSafetyDCBs: CARDINAL = 2 + 1; -- two for skip chaining, one for xfer chaining

  IOSynch: TYPE = POINTER TO SynchRecord;

  SynchRecord: TYPE = MONITORED RECORD [
    status: DiskIODefs.CompletionStatus, lastDone: CONDITION];

  diskInterruptLevel: CARDINAL = 13;

  -- Procedures, Variables, and Signals --

  sysDisk: DISK;

  GetCBs: PROCEDURE [n: CARDINAL, wait: BOOLEAN] RETURNS [cb: CBPtr];
  -- allocates 'n' CBs and initializes them.  If the requested number of CBs is not
  -- available and 'wait' is TRUE, GetCBs will wait until the request can be satisfied.
  -- If 'wait' is FALSE, GetCBs will return NIL.  The CBs will be circularly linked
  -- together through their 'nextOnQueue' field.

  FreeCB: PROCEDURE [cb: CBPtr];
  -- frees the argument CB.

  EnqueueCB: PROCEDURE [tail: CBQueueTail, cb: CBPtr];
  -- adds the argument CB to the end of the list identified by 'tail'.  The client is
  -- responsible for appropriate mutual exclusion of EnqueueCB and DequeueCB.

  DequeueCB: PROCEDURE [tail: CBQueueTail] RETURNS [cb: CBPtr];
  -- removes the front CB from the list identified by tail and returns it.  The client
  -- is responsible for appropriate mutual exclusion of EnqueueCB and DequeueCB.

  SpliceLists: PROCEDURE [first, second: CBQueueTail];
  -- appends the second list to the first.  The client is responsible for the
  -- appropriate mutual exclusion.

  EnqueueForDisk: PROCEDURE [cbList: CBQueueTail];
  -- enters the argument list of CBs on the list of current tasks.  It is assumed that
  -- the 'nextCB' fields have already been filled in, and thus the blocks are linearly
  -- linked through 'nextCB'.

  SimulateCompletion: PROCEDURE [cbList: CBQueueTail];
  -- causes the CBs on the specified list to be fed to the completion mechanism.  The
  -- status passed to the CompletionProcedure for such CBs will be 'neverStarted'.

  VirtualDA: PROCEDURE [da: DA] RETURNS [DiskIODefs.vDA];
  -- transforms a real disk address to a virtual one.

  RealDA: PROCEDURE [v: DiskIODefs.vDA] RETURNS [da: DA];
  -- transforms a virtual disk address to a real one.
  
  TransformStatus: PROCEDURE [status: DS] RETURNS [DiskIODefs.CompletionStatus];
  -- maps hardware status information to a simpler form for completion procedures to
  -- handle.

  MaskDS: PROCEDURE [a, b: DS] RETURNS [DS] = MACHINE CODE {Mopcodes.zAND};

  WriteErrorToLog: PROCEDURE [cb:CBPtr];
  -- records a (possibly recoverable) error on secondary storage.

  DiskInterruptHandler: PROCEDURE;
  -- the low-level interrupt handling procedure.

  FinalizeInterruptHandler: PROCEDURE;
  -- cleans up the interrupt handling process.

  Completer: PROCEDURE;
  -- the caller of completion procedures.

  FinalizeCompleter: PROCEDURE;
  -- cleans up the completer process.

  scratchPage: POINTER;
  -- general purpose bit bucket.

  maxOps: CARDINAL;
  -- maximum permitted operations in a single command chain.

  loggingEnabled: BOOLEAN;
  -- indicates whether statistics logging is enabled.

  diskReads, diskWrites: LONG CARDINAL;
  -- counts of actual operations for statistical purposes.

  END.