-- Copyright (C) 1984, 1985  by Xerox Corporation. All rights reserved. 
-- DiskWatcher.mesa, HGM, 14-Sep-85 23:30:51

DIRECTORY
  Device USING [Type],
  DeviceError USING [AwaitPilotDiskError],
  Heap USING [systemZone],
  LogDefs USING [DisplayNumber, ShowLine, ShowNumber],
  PilotDiskFace USING [Op, Operation, Status],
  Process USING [Detach],
  RestartDefs USING [],
  String USING [AppendString, AppendDecimal];

DiskWatcher: PROGRAM
  IMPORTS DeviceError, Heap, LogDefs, Process, String
  EXPORTS RestartDefs =
  BEGIN

  diskErrors: CARDINAL ← 0;

  WatchDiskErrors: PUBLIC PROCEDURE =
    BEGIN
    LogDefs.DisplayNumber["***** Disk Errors"L, [short[@diskErrors]]];
    Process.Detach[FORK DiskErrorWatcher[]];
    END;

  DiskErrorWatcher: PROCEDURE =
    BEGIN
    DO
      operation: PilotDiskFace.Operation;
      deviceType: Device.Type;
      deviceOrdinal: CARDINAL;
      status: PilotDiskFace.Status;
      retriesThisOperation: CARDINAL;
      errorsSinceLastReport: CARDINAL;
      totalCompletions: LONG CARDINAL;
      totalRetries: LONG CARDINAL;
      [operation, deviceType, deviceOrdinal, status, retriesThisOperation, errorsSinceLastReport, totalCompletions, totalRetries] ← DeviceError.AwaitPilotDiskError[];
      ShowDiskError[operation, deviceType, deviceOrdinal, status, retriesThisOperation, errorsSinceLastReport, totalCompletions, totalRetries];
      ENDLOOP;
    END;

  ShowDiskError: PROCEDURE [
      operation: PilotDiskFace.Operation,
      deviceType: Device.Type,
      deviceOrdinal: CARDINAL,
      status: PilotDiskFace.Status,
      retriesThisOperation: CARDINAL,
      errorsSinceLastReport: CARDINAL,
      totalCompletions: LONG CARDINAL,
      totalRetries: LONG CARDINAL] =
    BEGIN
    opStrings: ARRAY PilotDiskFace.Op OF STRING = [
      noOp: "X"L, read: "R"L, write: "W"L, verify: "V"L];
    statusStrings: ARRAY PilotDiskFace.Status OF STRING = [
      inProgress: "inProgress"L,
      goodCompletion: "goodCompletion"L,
      notReady: "notReady"L,
      recalibrateError: "recalibrateError"L,
      seekTimeout: "seekTimeout"L,
      headerCRCError: "headerCRCError"L,
      labelCRCError: "labelCRCError"L,
      dataCRCError: "dataCRCError"L,
      headerNotFound: "headerNotFound"L,
      labelVerifyError: "labelVerifyError"L,
      dataVerifyError: "dataVerifyError"L,
      overrunError: "overrunError"L,
      writeFault: "writeFault"L,
      memoryError: "memoryError"L,
      memoryFault: "memoryFault"L,
      clientError: "clientError"L,
      operationReset: "operationReset"L,
      otherError: "otherError"L];
    log: LONG STRING;
    IF status = labelVerifyError THEN RETURN; -- Temp/Perm file mixup
    log ← Heap.systemZone.NEW[StringBody[500]];
    IF errorsSinceLastReport # 1 THEN
      LogDefs.ShowNumber["*** "L, errorsSinceLastReport, " errors since last report."L];
    diskErrors ← diskErrors + 1;
    String.AppendString[log, "*** Disk error: "L];
    String.AppendString[log, "Cyl: "L];
    String.AppendDecimal[log, operation.clientHeader.cylinder];
    String.AppendString[log, ", Head: "L];
    String.AppendDecimal[log, operation.clientHeader.head];
    String.AppendString[log, ", Sector: "L];
    String.AppendDecimal[log, operation.clientHeader.sector];
    String.AppendString[log, ", Status: "L];
    String.AppendString[log, statusStrings[status]];
    String.AppendString[log, ", Command: "L];
    String.AppendString[log, opStrings[operation.command.header]];
    String.AppendString[log, opStrings[operation.command.label]];
    String.AppendString[log, opStrings[operation.command.data]];
    LogDefs.ShowLine[log];
    Heap.systemZone.FREE[@log];
    END;

  END.