-- DiskDefs.Mesa  Edited by Sandman on June 30, 1980  5:11 PM
-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  AltoDefs USING [BYTE, PageNumber],
  AltoFileDefs USING [DISK, FP, SN, vDA, vDC];

DiskDefs: DEFINITIONS =
  BEGIN OPEN AltoFileDefs, AltoDefs;

  -- standard disk

  nDisks: CARDINAL = 1;
  nHeads: CARDINAL = 2;
  nTracks: CARDINAL = 203;
  nSectors: CARDINAL = 12;

  StandardDisk: DISK = [nDisks, nTracks, nHeads, nSectors];
  sysDisk: DISK;

  NextDiskCommand: POINTER TO CBptr = LOOPHOLE[521B];
  DiskStatus: POINTER TO DS = LOOPHOLE[522B];
  LastDiskAddress: POINTER TO DA = LOOPHOLE[523B];
  SectorInterrupts: POINTER TO CARDINAL = LOOPHOLE[524B];

  -- physical disk address

  DA: TYPE = MACHINE DEPENDENT RECORD [
    sector: [0..17B], track: [0..777B], head, disk: [0..1], restore: [0..1]];

  -- DAs with special meaning

  InvalidDA: DA = DA[17B, 777B, 1, 1, 1];

  -- disk header

  DH: TYPE = MACHINE DEPENDENT RECORD [packID: CARDINAL, diskAddress: DA];

  -- file identifier

  FID: TYPE = MACHINE DEPENDENT RECORD [version: CARDINAL, serial: SN];

  FreePageFID: FID = FID[177777B, SN[[1, 1, 1], 17777B, 177777B]];

  -- disk label

  DL: TYPE = MACHINE DEPENDENT RECORD [
    next, prev: DA,
    blank: UNSPECIFIED,
    bytes: CARDINAL,
    page: CARDINAL,
    fileID: FID];

  -- disk final status

  DFS: TYPE = {CommandComplete, HardwareError, CheckError, IllegalSector};

  -- disk status word

  DS: TYPE = MACHINE DEPENDENT RECORD [
    sector: [0..17B],
    done: [0..17B],
    seekFailed: [0..1],
    seekInProgress: [0..1],
    notReady: [0..1],
    dataLate: [0..1],
    noTransfer: [0..1],
    checksumError: [0..1],
    finalStatus: DFS];

  -- useful status configurations

  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];
  DSfreeStatus: DS = DS[0, DSfree, 0, 0, 0, 0, 0, 0, CommandComplete];

  -- disk subcommands

  DSC: TYPE = {DiskRead, DiskCheck, DiskWrite};

  -- hardware disk command

  DC: TYPE = MACHINE DEPENDENT RECORD [
    seal: BYTE, header, label, data: DSC, seek, exchange: [0..1]];

  CBptr: TYPE = POINTER TO CB;
  CBNil: CBptr = LOOPHOLE[0];

  -- disk command block (label, page, and zone added)

  CB: TYPE = MACHINE DEPENDENT RECORD [
    nextCB: POINTER TO CB,
    status: DS,
    command: DC,
    headerAddress: POINTER TO DH,
    labelAddress: POINTER TO DL,
    dataAddress: POINTER,
    normalWakeups: WORD,
    errorWakeups: WORD,
    header: DH,
    label: DL,
    page: CARDINAL,
    zone: POINTER TO CBZ];

  nCB: CARDINAL = 3; -- minimun for full disk speed

  lCBZ: CARDINAL = SIZE[CBZ] + nCB*(SIZE[CB] + SIZE[CBptr]);

  -- Note: if there are n CBs, there are n+1 entries in the
  -- cbQueue (an extra one contains a NIL to mark the end).
  -- The extra one is represented by queueVec: ARRAY [0..1)
  -- and thus is included in SIZE[CBZ].

  CBZptr: TYPE = POINTER TO CBZ;

  CBZ: TYPE = MACHINE DEPENDENT RECORD [
    checkError: BOOLEAN,
    errorCount: [0..77777B],
    info: POINTER,
    cleanup: PROCEDURE [CBptr],
    errorDA: vDA,
    currentPage: CARDINAL,
    currentBytes: CARDINAL,
    normalWakeups: WORD,
    errorWakeups: WORD,
    cbQueue: DESCRIPTOR FOR ARRAY OF CBptr,
    qHead, qTail: CARDINAL,
    queueVec: ARRAY [0..1) OF CBptr];

  -- the queue vector starts at queueVec.
  -- after the queue vector there follows
  -- ARRAY OF CB, the CBs for the zone.
  -- Procedures in DiskIO


  RealDA: PROCEDURE [v: vDA] RETURNS [DA];
  VirtualDA: PROCEDURE [da: DA] RETURNS [vDA];

  ResetWaitCell: PROCEDURE;
  SetWaitCell: PROCEDURE [POINTER TO WORD] RETURNS [POINTER TO WORD];

  DDC: TYPE = RECORD [
    cb: CBptr,
    ca: POINTER,
    da: vDA,
    page: PageNumber,
    fp: POINTER TO FP,
    restore: BOOLEAN,
    action: vDC];

  DoDiskCommand: PROCEDURE [arg: POINTER TO DDC];

  RetryCount: CARDINAL = 8;
  RetryableDiskError: SIGNAL [cb: CBptr];
  UnrecoverableDiskError: SIGNAL [cb: CBptr];

  CBinit: TYPE = {clear, dontClear};

  InitializeCBstorage: PROCEDURE [
    zone: CBZptr, nCBs: CARDINAL, page: PageNumber, init: CBinit];

  GetCB: PROCEDURE [zone: CBZptr, init: CBinit] RETURNS [cb: CBptr];

  CleanupCBqueue: PROCEDURE [zone: CBZptr];

  DiskCheckError: SIGNAL [page: PageNumber];

  DiskRequestOption: TYPE = {swap, update, extend};

  DiskRequest: TYPE = RECORD [
    ca: POINTER,
    da: POINTER TO vDA,
    firstPage: PageNumber,
    lastPage: PageNumber,
    fp: POINTER TO FP,
    fixedCA: BOOLEAN,
    action, lastAction: vDC,
    signalCheckError: BOOLEAN,
    option:
      SELECT OVERLAID DiskRequestOption FROM
	swap => [desc: POINTER TO DiskPageDesc],
	update => [cleanup: PROCEDURE [CBptr]],
	extend => [lastBytes: CARDINAL],
	ENDCASE];

  DiskPageDesc: TYPE = RECORD [
    prev, this, next: vDA, page: PageNumber, bytes: CARDINAL];

  SwapPages: PROCEDURE [arg: POINTER TO swap DiskRequest]
    RETURNS [page: PageNumber, byte: CARDINAL];

  END.