-- DiagnosticsImplA.mesa  -  edited by:
-- Poskanzer	12-Sep-83 17:11:55
-- Paul		17-Jul-84 17:51:29

DIRECTORY
  ByeOps USING [ResumeBouncing, StopBouncing],
  CH USING [zeroMaxLengthNames],
  CHStubInternal USING [FindDomainAddr],
  CommOnlineDiagnostics USING [PatternType, WordsInPacket],
  DiagnosticsOps USING [
    AppendServers, ConfirmIndex, Data, DataDisplayed, DataHandle, EchoUserTest, 
    FloppyCleanReadWriteHeads, FloppyCommandFileTest,
    FloppyDisplayErrorLog, FloppyExerciser, FloppyFormatDiskette,
    FloppyStandardTest, FloppyTest, Help, KeyboardAndMouseTest, LFDisplayTest,
    Operation, PlotPattern, PlotScreen, PlotterType, PrintPattern, PutLine,
    RS232CLoopBackTest, RS232LineType, SendCommand, StringIndex,
    Tests, Two90Mode, Two90Pattern, Two90Test],
  Format USING [HostNumber, NetworkNumber, StringProc],
  FormSW USING [
    AllocateItemDescriptor, BooleanItem, ClientItemsProcType, CommandItem,
    Destroy, Display, DisplayItem, Enumerated, EnumeratedItem,
    EnumeratedNotifyProcType, FindItem, ItemHandle, newLine, 
    nullIndex, NumberItem, ProcType, StringItem],
  GreenFace USING [Command, Status],
  Heap USING [systemZone],
  Msg USING [FeedBack, SetWindow],
  NetworkStream USING [AssignNetworkAddress],
  OnlineDiagnostics USING [ErrorHandling, SectorLength],
  Process USING [Detach],
  Profile USING [GetDefaultDomain, GetDefaultOrganization, String],
  RS232C USING [LineSpeed],
  RS232CEnvironment USING [LineSpeed],
  String USING [
    AppendNumber, AppendString, AppendStringAndGrow, Copy, CopyToNewString],
  System USING [NetworkAddress, switches],
  Tool USING [Create, MakeFileSW, MakeFormSW, MakeSWsProc, UnusedLogName],
  ToolWindow USING [Activate, Deactivate, TransitionProcType],
  UserInput USING [CreatePeriodicNotify, PeriodicProcType],
  UserTerminal USING [BlinkDisplay],
  Window USING [GetChild, GetParent, Handle, rootWindow, Stack, ValidateTree],
  WindowFont USING [FontHeight];

DiagnosticsImplA: MONITOR
  IMPORTS
    ByeOps, CH, CHStubInternal, DiagnosticsOps, Format, FormSW,  
    Heap, Msg, NetworkStream, Process, Profile, String, System, Tool,
    ToolWindow, UserInput, UserTerminal, Window, WindowFont
  EXPORTS DiagnosticsOps =
  BEGIN

  -- TYPEs

  FormIndex: TYPE = {
    help, start, cancel, addCommand, deleteCommand, test, floppyTest,
    currOrganization, currDomain, thisEthernetID, thisProcessorID, listFS, listPS,
    listMS, testEthernetID, testProcessorID, realFeedBack, dataPattern,
    minPacketSize, maxPacketSize, waitResponse, delayBetween, displayServers,
    lineType, lineSpeed, pattern, constant, doubleDensity, doubleSided,
    sectorsPerTrack, sectorLength, errorHandling, operation, cmdFile, trackNumber,
    startingSector, sectorCount, increment, dataWord, loopCount, dataDisplayed,
    two90TestType, two90PlotterType, two90Status, two90Mode, two90command,
    plotprint};

  -- Variable declarations.

  oldMsgwh: Window.Handle ← NIL; --where Msg window was
  diagnosticwh: PUBLIC Window.Handle ← NIL;  -- Tool's window
  toolData: PUBLIC DiagnosticsOps.DataHandle ← NIL;  -- Tool's data
  z: UNCOUNTED ZONE = Heap.systemZone;
  -- Some of the following should probably be in toolData.
  -- to let the GetXXXProc's know when ConfirmCommand has been bugged
  confirmation: PUBLIC CONDITION;  
  cmdMax: CARDINAL = 100;
  running: PUBLIC BOOLEAN ← FALSE;  -- whether there is a detached process running
  probing: BOOLEAN ← FALSE;  -- whether we are probing the ethernet; like running
  calledByBye: PUBLIC BOOLEAN ← FALSE;  -- whether we were activated by Bye
  active: BOOLEAN ← FALSE;  -- whether the tool is currently active

  -- FormSW support routines.

  ConfirmCommand: ENTRY FormSW.ProcType =
    BEGIN
    ENABLE UNWIND => NULL;
    IF NOT toolData.confirming THEN UserTerminal.BlinkDisplay[]
    ELSE
      BEGIN
      toolData.latestConfirm ← LOOPHOLE[index, DiagnosticsOps.ConfirmIndex];
      NOTIFY confirmation;
      END;
    END;

  ActionCommand: FormSW.ProcType =
    BEGIN
    IF toolData.confirming OR running THEN
      BEGIN
      DiagnosticsOps.PutLine["There is already a command running.  Please wait."L];
      UserTerminal.BlinkDisplay[];
      END
    ELSE
      BEGIN
      SELECT LOOPHOLE[index, FormIndex] FROM
        help => DiagnosticsOps.Help[toolData.test];
        start =>
          BEGIN  --start--
          SELECT toolData.test FROM
            display =>
              BEGIN  --display--
              IF calledByBye THEN ByeOps.StopBouncing[];
              DiagnosticsOps.LFDisplayTest[];
              UglyHackToGetAroundBugInFormSW[];
              IF calledByBye THEN ByeOps.ResumeBouncing[];
              END --display-- ;
            keyboard =>
              BEGIN  --keyboard--
              IF calledByBye THEN ByeOps.StopBouncing[];
              DiagnosticsOps.KeyboardAndMouseTest[];
              UglyHackToGetAroundBugInFormSW[];
              IF calledByBye THEN ByeOps.ResumeBouncing[];
              END --keyboard-- ;
            RS232C =>
              BEGIN  --RS232C Loopback
              DiagnosticsOps.RS232CLoopBackTest[
                host: toolData.strings[thisProcessorID],
                hostNet: toolData.strings[thisEthernetID],
                lineType: toolData.lineType, lineSpeed: toolData.lineSpeed,
                pattern: toolData.pattern, constant: toolData.constant,
                minPacketSize: toolData.minPacketSize,
                maxPacketSize: toolData.maxPacketSize];
              END --RS232C Loopback-- ;
            ethernet =>
              IF probing THEN
                BEGIN
                DiagnosticsOps.PutLine["Probing the ethernet.  Please wait."L];
                UserTerminal.BlinkDisplay[];
                END
              ELSE
                DiagnosticsOps.EchoUserTest[
                  currDomain: toolData.strings[currDomain],
                  currOrganization: toolData.strings[currOrganization],
                  usernet: toolData.strings[thisEthernetID],
                  user: toolData.strings[thisProcessorID],
                  targetnet: toolData.strings[testEthernetID],
                  target: toolData.strings[testProcessorID],
                  realFeedBack: toolData.realFeedBack,
                  waitResponse: toolData.waitResponse,
                  dataPattern: toolData.dataPattern,
                  minPacketSize: toolData.minPacketSize,
                  maxPacketSize: toolData.maxPacketSize,
                  delayBetween: toolData.delayBetween];
            floppy =>
              BEGIN  --floppy--
              running ← TRUE;
              SELECT toolData.floppyTest FROM
                clean =>
                  Process.Detach[FORK DiagnosticsOps.FloppyCleanReadWriteHeads[]];
                standard =>
                  Process.Detach[FORK DiagnosticsOps.FloppyStandardTest[]];
                summary =>
                  Process.Detach[FORK DiagnosticsOps.FloppyDisplayErrorLog[]];
                format =>
                  Process.Detach[FORK DiagnosticsOps.FloppyFormatDiskette[]];
                exercise => Process.Detach[FORK DiagnosticsOps.FloppyExerciser[]];
                cmdFile =>
                  BEGIN  --cmdFile--
                  IF toolData.inALoop THEN
                    BEGIN
                    CmdAppend["E,"L];
                    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[cmdFile]]];
                    END;
                  Process.Detach[
                    FORK DiagnosticsOps.FloppyCommandFileTest[
                    toolData.doubleDensity, toolData.doubleSided,
                    toolData.sectorsPerTrack, toolData.sectorLength,
                    toolData.errorHandling, toolData.strings[cmdFile]]];
                  END --cmdFile-- ;
                ENDCASE;
              END --floppy-- ;
	    two90 =>
	      BEGIN  --two90--
	      t: DiagnosticsOps.PlotterType ← toolData.two90Plotter;
	      IF System.switches['g] = down THEN {
                SELECT toolData.two90test FROM
	          command =>
		    Process.Detach[
		      FORK DiagnosticsOps.SendCommand[t, toolData.two90Command]];
		  output =>
		    SELECT toolData.two90Output FROM
		      plot => Process.Detach[FORK DiagnosticsOps.PlotPattern[t]];
		      print =>  Process.Detach[
		        FORK DiagnosticsOps.PrintPattern[t]];
		      screen => Process.Detach[FORK DiagnosticsOps.PlotScreen[t]];
		      ENDCASE => ERROR;
		  ENDCASE => ERROR} 
	      ELSE Msg.FeedBack["290 Not Enabled"L, warning, TRUE];
	      END; --two90--
            none => NULL;
            ENDCASE;
          END --start-- ;
        cancel =>
          IF probing THEN
            BEGIN
            DiagnosticsOps.PutLine["Probing the ethernet.  Please wait."L];
            UserTerminal.BlinkDisplay[];
            END
          ELSE [] ← ToolWindow.Deactivate[diagnosticwh];
        addCommand =>
          BEGIN  --addCommand--
          temp: LONG STRING = [100];
          SELECT toolData.operation FROM
            initialize => CmdAppend["I,"L];
            recalibrate => CmdAppend["RC,"L];
            readStatus => CmdAppend["RAST,"L];
            readHeader =>
              BEGIN  --readHeader--
              String.Copy[temp, "RAH,"L];
              IF AppendTrackNumber[temp] THEN
                IF toolData.inALoop THEN
                  BEGIN IF AppendIncrement[temp] THEN CmdAppend[temp]; END
                ELSE CmdAppend[temp];
              END --readHeader-- ;
            readSectors =>
              BEGIN  --readSectors--
              String.Copy[temp, "RASE,"L];
              IF AppendTrackNumber[temp] THEN
                IF AppendStartingSector[temp] THEN
                  IF toolData.inALoop THEN
                    BEGIN IF AppendIncrement[temp] THEN CmdAppend[temp]; END
                  ELSE BEGIN IF AppendSectorCount[temp] THEN CmdAppend[temp]; END;
              END --readSectors-- ;
            writeSectors, writeDeletedSectors =>
              BEGIN  --write--
              IF toolData.operation = writeSectors THEN String.Copy[temp, "WS,"L]
              ELSE String.Copy[temp, "WD,"L];
              IF AppendTrackNumber[temp] THEN
                IF AppendStartingSector[temp] THEN
                  IF toolData.inALoop THEN
                    BEGIN
                    IF AppendIncrement[temp] THEN
                      IF AppendDataWord[temp] THEN CmdAppend[temp];
                    END
                  ELSE
                    BEGIN
                    IF AppendSectorCount[temp] THEN
                      IF AppendDataWord[temp] THEN CmdAppend[temp];
                    END;
              END --write-- ;
            verify => CmdAppend["V,"L];
            loop =>
              BEGIN  --loop--
              IF toolData.inALoop THEN CmdAppend["E,"L]
              ELSE
                BEGIN
                String.Copy[temp, "S,"L];
                String.AppendNumber[temp, toolData.loopCount, 10];
                String.AppendString[temp, ","L];  --!! Diag2Pack.mesa uses "'", but this works.
                CmdAppend[temp];
                END;
              ToggleInALoop[];
              END --loop-- ;
            displayData =>
              CmdAppend[
                SELECT toolData.dataDisplayed FROM
                  status => "DST,"L,
                  header => "DH,"L,
                  sector => "DSE,"L,
                  summary => "DL,"L,
                  ENDCASE => "DST,"L];
            clearLog => CmdAppend["C,"L];
            log => CmdAppend["L,"L];
            ENDCASE;
          END --addCommand-- ;
        deleteCommand => CmdDelete[];
        ENDCASE => DiagnosticsOps.PutLine["Unknown command - should never happen!?!?"L];
      END;
    END;

  KamikazeProc: UserInput.PeriodicProcType =
    BEGIN FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[start]]]; END;

  UglyHackToGetAroundBugInFormSW: PROCEDURE =
    BEGIN
    [] ← UserInput.CreatePeriodicNotify[
      proc: KamikazeProc, window: Window.rootWindow, rate: 0];
    END;

  CmdAppend: PROCEDURE [string: LONG STRING] =
    BEGIN
    IF toolData.cmdCount < cmdMax THEN
      BEGIN
      String.AppendStringAndGrow[@toolData.strings[cmdFile], string, z];
      toolData.cmdCount ← toolData.cmdCount + 1;
      toolData.cmdIndexes[toolData.cmdCount] ← toolData.strings[cmdFile].length;
      FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[cmdFile]]];
      END;
    END;

  CmdDelete: PROCEDURE =
    BEGIN
    IF toolData.cmdCount > 0 THEN
      BEGIN
      ch: CHARACTER ← toolData.strings[cmdFile][
        toolData.cmdIndexes[toolData.cmdCount - 1]];
      IF ch = 'E OR ch = 'S THEN ToggleInALoop[];
      toolData.cmdCount ← toolData.cmdCount - 1;
      toolData.strings[cmdFile].length ← toolData.cmdIndexes[toolData.cmdCount];
      FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[cmdFile]]];
      END;
    END;

  AppendTrackNumber: PROCEDURE [cmd: LONG STRING] RETURNS [ok: BOOLEAN] =
    BEGIN
    IF toolData.trackNumber > 76 THEN
      BEGIN
      DiagnosticsOps.PutLine["Track number invalid - must be between 0 and  76."L];
      ok ← FALSE;
      END
    ELSE
      BEGIN
      String.AppendNumber[cmd, toolData.trackNumber, 10];
      String.AppendString[cmd, ",0,"L];  --!! what is the 0? "keyHead", 0 or 1
      ok ← TRUE;
      END;
    END;
    
  AppendStartingSector: PROCEDURE [cmd: LONG STRING] RETURNS [ok: BOOLEAN] =
    BEGIN
    IF toolData.startingSector < 1
      OR toolData.startingSector > toolData.sectorsPerTrack THEN
      BEGIN
      DiagnosticsOps.PutLine[
        "Starting sector invalid - must be between 1 and # of sectors per track."L];
      ok ← FALSE;
      END
    ELSE
      BEGIN
      String.AppendNumber[cmd, toolData.startingSector, 10];
      String.AppendString[cmd, ","L];
      ok ← TRUE;
      END;
    END;
    
  AppendIncrement: PROCEDURE [cmd: LONG STRING] RETURNS [ok: BOOLEAN] =
    BEGIN
    IF toolData.increment < -2000 OR toolData.increment > 2000 THEN
      BEGIN
      DiagnosticsOps.PutLine["Increment invalid - must be between -2000 and 2000."L];
      ok ← FALSE;
      END
    ELSE
      BEGIN
      IF toolData.increment < 0 THEN String.AppendString[cmd, "-"L]
      ELSE String.AppendString[cmd, "+"L];
      String.AppendNumber[cmd, ABS[toolData.increment], 10];
      String.AppendString[cmd, ","L];
      ok ← TRUE;
      END;
    END;
    
  AppendSectorCount: PROCEDURE [cmd: LONG STRING] RETURNS [ok: BOOLEAN] =
    BEGIN
    IF toolData.sectorCount < 1 OR toolData.sectorCount > toolData.sectorsPerTrack
      THEN
      BEGIN
      DiagnosticsOps.PutLine[
        "Sector count invalid - must be between 1 and # of sectors per track."L];
      ok ← FALSE;
      END
    ELSE
      BEGIN
      String.AppendNumber[cmd, toolData.sectorCount, 10];
      String.AppendString[cmd, ","L];
      ok ← TRUE;
      END;
    END;
    
  AppendDataWord: PROCEDURE [cmd: LONG STRING] RETURNS [ok: BOOLEAN] =
    BEGIN
    String.AppendNumber[cmd, toolData.dataWord, 16];
    String.AppendString[cmd, ","L];
    ok ← TRUE;
    END;

  ToggleInALoop: PROCEDURE =
    BEGIN
    toolData.inALoop ← NOT toolData.inALoop;
    IF toolData.test = floppy AND toolData.floppyTest = cmdFile THEN
      OperationNotify[
        toolData.formSW, FormSW.FindItem[
        toolData.formSW, ORD[FormIndex[operation]]], ORD[FormIndex[operation]],
        toolData.operation];
    END;

  TestNotify: FormSW.EnumeratedNotifyProcType =
    BEGIN
    SELECT LOOPHOLE[oldValue, DiagnosticsOps.Tests] FROM
      RS232C =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisEthernetID]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisProcessorID]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[minPacketSize]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[maxPacketSize]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[lineType]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[lineSpeed]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[pattern]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[constant]]].flags.invisible ← TRUE;
        END;
      ethernet =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[currOrganization]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[currDomain]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisEthernetID]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisProcessorID]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisProcessorID]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[listFS]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[listPS]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[listMS]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[testEthernetID]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[testProcessorID]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[realFeedBack]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[dataPattern]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[minPacketSize]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[maxPacketSize]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[waitResponse]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[delayBetween]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[displayServers]]].flags.invisible ← TRUE;
        END;
      floppy =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[floppyTest]]].flags.invisible ← TRUE;
        END;
      two90 =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90TestType]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90PlotterType]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90Status]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90Mode]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90command]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[plotprint]]].flags.invisible ← TRUE;
        END;
      none =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[start]]].flags.invisible ← FALSE;
        END;
      ENDCASE;
    SELECT toolData.test FROM
      RS232C =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[thisEthernetID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[thisProcessorID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[minPacketSize]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[maxPacketSize]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[lineType]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[lineSpeed]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[pattern]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[constant]]].flags.invisible ← FALSE;
        END;
      ethernet =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[currOrganization]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[currDomain]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[thisEthernetID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[thisProcessorID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[listFS]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[listPS]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[listMS]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[testEthernetID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[testProcessorID]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[realFeedBack]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[dataPattern]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[minPacketSize]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[maxPacketSize]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[waitResponse]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[delayBetween]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[displayServers]]].flags.invisible ←
          FALSE;
        END;
      floppy =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[floppyTest]]].flags.invisible ← FALSE;
        END;
      two90 =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90TestType]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[two90PlotterType]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[two90Status]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90Mode]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[two90command]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[plotprint]]].flags.invisible ← FALSE;
        END;
      none =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[start]]].flags.invisible ← TRUE;
        END;
      ENDCASE;
    IF LOOPHOLE[oldValue, DiagnosticsOps.Tests] = floppy
      AND toolData.floppyTest = cmdFile THEN
      BEGIN
      toolData.floppyTest ← clean;
      FloppyTestNotify[
        sw, FormSW.FindItem[sw, ORD[FormIndex[floppyTest]]], ORD[
        FormIndex[floppyTest]], DiagnosticsOps.FloppyTest[cmdFile]];
      END;
    IF toolData.reDisplay THEN
      BEGIN FormSW.Display[sw]; toolData.reDisplay ← FALSE; END;
    END;

  FloppyTestNotify: FormSW.EnumeratedNotifyProcType =
    BEGIN
    SELECT LOOPHOLE[oldValue, DiagnosticsOps.FloppyTest] FROM
      cmdFile =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[addCommand]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[deleteCommand]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[doubleDensity]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[doubleSided]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorsPerTrack]]].flags.invisible ←
          TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorLength]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[errorHandling]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[operation]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[cmdFile]]].flags.invisible ← TRUE;
        --SetCurrent[sw, nullIndex];
        END;
      ENDCASE;
    SELECT toolData.floppyTest FROM
      cmdFile =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[addCommand]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[deleteCommand]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[doubleDensity]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[doubleSided]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorsPerTrack]]].flags.invisible ←
          FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorLength]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[errorHandling]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[operation]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[cmdFile]]].flags.invisible ← FALSE;
        END;
      ENDCASE;
    IF LOOPHOLE[oldValue, DiagnosticsOps.FloppyTest] = cmdFile THEN
      BEGIN
      oldOperation: DiagnosticsOps.Operation ← toolData.operation;
      toolData.operation ← initialize;
      OperationNotify[
        sw, FormSW.FindItem[sw, ORD[FormIndex[operation]]], ORD[
        FormIndex[operation]], oldOperation];
      END;
    IF toolData.reDisplay THEN
      BEGIN FormSW.Display[sw]; toolData.reDisplay ← FALSE; END;
    END;

  OperationNotify: FormSW.EnumeratedNotifyProcType =
    BEGIN
    SELECT LOOPHOLE[oldValue, DiagnosticsOps.Operation] FROM
      readHeader =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← TRUE;
        --SetCurrent[sw, nullIndex];
        END;
      readSectors =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[startingSector]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorCount]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← TRUE;
        --SetCurrent[sw, nullIndex];
        END;
      writeSectors, writeDeletedSectors =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[startingSector]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[sectorCount]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[dataWord]]].flags.invisible ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← TRUE;
        --SetCurrent[sw, nullIndex];
        END;
      loop =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[loopCount]]].flags.invisible ← TRUE;
        --SetCurrent[sw, nullIndex];
        END;
      displayData =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[dataDisplayed]]].flags.invisible ← TRUE;
        END;
      ENDCASE;
    SELECT toolData.operation FROM
      readHeader =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← FALSE;
        IF toolData.inALoop THEN
          FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← FALSE;
        END;
      readSectors =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[startingSector]]].flags.invisible ←
          FALSE;
        IF toolData.inALoop THEN
          FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← FALSE
        ELSE
          FormSW.FindItem[sw, ORD[FormIndex[sectorCount]]].flags.invisible ← FALSE;
        END;
      writeSectors, writeDeletedSectors =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[trackNumber]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[startingSector]]].flags.invisible ←
          FALSE;
        IF toolData.inALoop THEN
          FormSW.FindItem[sw, ORD[FormIndex[increment]]].flags.invisible ← FALSE
        ELSE
          FormSW.FindItem[sw, ORD[FormIndex[sectorCount]]].flags.invisible ← FALSE;
        FormSW.FindItem[sw, ORD[FormIndex[dataWord]]].flags.invisible ← FALSE;
        END;
      loop =>
        IF NOT toolData.inALoop THEN
          BEGIN
          toolData.reDisplay ← TRUE;
          FormSW.FindItem[sw, ORD[FormIndex[loopCount]]].flags.invisible ← FALSE;
          END;
      displayData =>
        BEGIN
        toolData.reDisplay ← TRUE;
        FormSW.FindItem[sw, ORD[FormIndex[dataDisplayed]]].flags.invisible ← FALSE;
        END;
      ENDCASE;
    IF toolData.reDisplay THEN
      BEGIN FormSW.Display[sw]; toolData.reDisplay ← FALSE; END;
    END;

  -- Setup and support routines.

  ClientTransition: ToolWindow.TransitionProcType =
    BEGIN
    SELECT TRUE FROM
      old = inactive =>
        BEGIN
        IF toolData = NIL THEN toolData ← z.NEW[DiagnosticsOps.Data ← []];
        active ← TRUE;
        END;
      new = inactive =>
        BEGIN
        IF toolData # NIL THEN
          BEGIN
          FormSW.Destroy[toolData.formSW];
          z.FREE[@toolData.strings[cmdFile]];
          z.FREE[@toolData];
          END;
        IF calledByBye THEN
          BEGIN calledByBye ← FALSE; ByeOps.ResumeBouncing[]; END;
        active ← FALSE;
        END;
      ENDCASE
    END;

  DiagnosticsActivate: PUBLIC PROCEDURE =
    BEGIN
    calledByBye ← TRUE;
    IF diagnosticwh = NIL THEN Init[];
    ToolWindow.Activate[diagnosticwh];
    Window.Stack[
      diagnosticwh, Window.GetChild[Window.GetParent[diagnosticwh]]];  -- top me
    Window.ValidateTree[];
    END;

  Init: PROCEDURE =
    BEGIN
    -- Make the tool window and its subwindows.
    diagnosticwh ← Tool.Create[
      makeSWsProc: MakeSWs, initialState: inactive,
      clientTransition: ClientTransition, name: "Diagnostics"L,
      initialBox: [[512, 0], [512, 808]], tinyName1: "Diag"L,
      tinyName2: "nostics"L];
    END;

  MakeSWs: Tool.MakeSWsProc =
    BEGIN
    old: Window.Handle;
    logName: STRING ← [40];
    Tool.UnusedLogName[unused: logName, root: "Diagnostics.log"L];
    toolData.confirmSW ← Tool.MakeFormSW[
      window: window, formProc: MakeConfirm, zone: z,
      h: 2 * WindowFont.FontHeight[]];  -- should be 1
    toolData.formSW ← Tool.MakeFormSW[
      window: window, formProc: MakeForm, zone: z,
      h: 45 * WindowFont.FontHeight[]];
    probing ← TRUE;
    Process.Detach[FORK SetupEthernetItems[]];
    toolData.fileSW ← Tool.MakeFileSW[
      window: window, name: logName, allowTypeIn: FALSE];
      -- jfung
--    old ← Msg.SetWindow[toolData.fileSW];
 --   IF old # NIL THEN [] ← Msg.SetWindow[old] ELSE oldMsgwh ← old;
    END;

  MakeConfirm: FormSW.ClientItemsProcType =
    BEGIN OPEN FormSW;
    -- This procedure creates the confirmation FormSW.
    formItems: 
     LONG POINTER TO ARRAY DiagnosticsOps.ConfirmIndex OF FormSW.ItemHandle ← NIL;
    items ← AllocateItemDescriptor[
      nItems: DiagnosticsOps.ConfirmIndex.LAST.ORD + 1, z: z];
    formItems ← LOOPHOLE[BASE[items]];
    formItems↑ ← [
      confirm: CommandItem[
      tag: "Confirm"L, place: newLine, drawBox: TRUE, invisible: TRUE,
      proc: ConfirmCommand],
      yes: CommandItem[
      tag: "Yes"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand],
      no: CommandItem[
      tag: "No"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand],
      continue: CommandItem[
      tag: "Continue"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand],
      loop: CommandItem[
      tag: "Loop"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand],
      display: CommandItem[
      tag: "Display"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand],
      exit: CommandItem[
      tag: "Exit"L, drawBox: TRUE, invisible: TRUE, proc: ConfirmCommand]];
    RETURN[items: items, freeDesc: TRUE]
    END;

  MakeForm: FormSW.ClientItemsProcType =
    BEGIN OPEN FormSW;
    -- This procedure creates the main FormSW.
    formItems: LONG POINTER TO ARRAY FormIndex OF FormSW.ItemHandle ← NIL;
    dataPatterns: ARRAY [0..5) OF FormSW.Enumerated ← [
      ["All 0s"L, CommOnlineDiagnostics.WordsInPacket[all0s]], [
      "All 1s"L, CommOnlineDiagnostics.WordsInPacket[all1s]], [
      "Incr Words"L, CommOnlineDiagnostics.WordsInPacket[incrWords]], [
      "All Constant"L, CommOnlineDiagnostics.WordsInPacket[allConstant]], [
      "Dont Care"L, CommOnlineDiagnostics.WordsInPacket[dontCare]]];

    lineTypes: ARRAY [0..2) OF FormSW.Enumerated ← [
      ["bitSynchronous"L, DiagnosticsOps.RS232LineType[bitSynchronous]], [
      "asynchronous"L, DiagnosticsOps.RS232LineType[asynchronous]]];

    lineSpeeds: ARRAY [0..4) OF FormSW.Enumerated ← [[
      "1200"L, RS232CEnvironment.LineSpeed[bps1200]], [
      "2400"L, RS232CEnvironment.LineSpeed[bps2400]], [
      "4800"L, RS232CEnvironment.LineSpeed[bps4800]], [
      "9600"L, RS232CEnvironment.LineSpeed[bps9600]]];

    patterns: ARRAY [0..4) OF FormSW.Enumerated ← [
      ["All 0s"L, CommOnlineDiagnostics.PatternType[zero]], [
      "All 1s"L, CommOnlineDiagnostics.PatternType[ones]], [
      "Incrementing"L, CommOnlineDiagnostics.PatternType[byteIncr]], [
      "Constant"L, CommOnlineDiagnostics.PatternType[constant]]];
      
    testtwo90: ARRAY [0..2) OF FormSW.Enumerated ← [
      ["Command"L, DiagnosticsOps.Two90Test[command]],
      ["Output"L, DiagnosticsOps.Two90Test[output]]];
      
    plottertwo90: ARRAY [0..7) OF FormSW.Enumerated ← [
      ["v80"L, DiagnosticsOps.PlotterType[v80]],
      ["v8222"L, DiagnosticsOps.PlotterType[v8222]],
      ["v8224"L, DiagnosticsOps.PlotterType[v8224]],
      ["v8236"L, DiagnosticsOps.PlotterType[v8236]],
      ["v8242"L, DiagnosticsOps.PlotterType[v8242]],
      ["v8272"L, DiagnosticsOps.PlotterType[v8272]],
      ["pdq"L, DiagnosticsOps.PlotterType[pdq]]];
      
    statustwo90: ARRAY [0..11) OF FormSW.Enumerated ← [
      ["null"L, GreenFace.Status[null]],
      ["inplot"L, GreenFace.Status[inplot]],
      ["inprint"L, GreenFace.Status[inprint]],
      ["overrun"L, GreenFace.Status[overrun]],
      ["unrecognized"L, GreenFace.Status[unrecognized]],
      ["illegalsequence"L, GreenFace.Status[illegalsequence]],
      ["parityerror"L, GreenFace.Status[parityerror]],
      ["framingerror"L, GreenFace.Status[framingerror]],
      ["busyinprogress"L, GreenFace.Status[busyinprogress]],
      ["offline"L, GreenFace.Status[offline]],
      ["plotterready"L, GreenFace.Status[plotterready]]];
      
    modetwo90: ARRAY [0..2) OF FormSW.Enumerated ← [
      ["Plot", DiagnosticsOps.Two90Mode[plot]], 
      ["Print", DiagnosticsOps.Two90Mode[print]]];
      
    commandtwo90: ARRAY [0..11) OF FormSW.Enumerated ← [
      ["null"L, GreenFace.Command[null]],
      ["plot"L, GreenFace.Command[plot]],
      ["print"L, GreenFace.Command[print]],
      ["clear"L, GreenFace.Command[clear]],
      ["rlter"L, GreenFace.Command[rlter]],
      ["rffed"L, GreenFace.Command[rffed]],
      ["reotr"L, GreenFace.Command[reotr]],
      ["receivebyte"L, GreenFace.Command[receivebyte]],
      ["senseplot"L, GreenFace.Command[senseplot]],
      ["sensestatus"L, GreenFace.Command[sensestatus]],
      ["reset"L, GreenFace.Command[reset]]];
      
    outputtwo90: ARRAY [0..3) OF FormSW.Enumerated ← [
      ["plot"L, DiagnosticsOps.Two90Pattern[plot]],
      ["print"L, DiagnosticsOps.Two90Pattern[print]],
      ["screen"L, DiagnosticsOps.Two90Pattern[screen]]];


    EnumSeq: TYPE = RECORD [seq: SEQUENCE n: CARDINAL OF FormSW.Enumerated];
    testSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [7]];
    floppyTestSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [6]];
    sectorLengthSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [4]];
    errorHandlingSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [3]];
    operationSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [12]];
    dataDisplayedSeq: LONG POINTER TO EnumSeq ← z.NEW[EnumSeq [4]];
    testSeq[0] ← ["Display"L, DiagnosticsOps.Tests[display]];
    testSeq[1] ← ["Keyboard"L, DiagnosticsOps.Tests[keyboard]];
    testSeq[2] ← ["Echo"L, DiagnosticsOps.Tests[ethernet]];
    testSeq[3] ← ["RS232C Loopback"L, DiagnosticsOps.Tests[RS232C]];
    testSeq[4] ← ["Floppy Drive"L, DiagnosticsOps.Tests[floppy]];
    testSeq[5] ← ["290 Interface"L, DiagnosticsOps.Tests[two90]];
    testSeq[6] ← ["None"L, DiagnosticsOps.Tests[none]];
    floppyTestSeq[0] ← ["Clean Heads"L, DiagnosticsOps.FloppyTest[clean]];
    floppyTestSeq[1] ← ["Standard"L, DiagnosticsOps.FloppyTest[standard]];
    floppyTestSeq[2] ← ["Summary"L, DiagnosticsOps.FloppyTest[summary]];
    floppyTestSeq[3] ← ["Format"L, DiagnosticsOps.FloppyTest[format]];
    floppyTestSeq[4] ← ["Exerciser"L, DiagnosticsOps.FloppyTest[exercise]];
    floppyTestSeq[5] ← ["Command File"L, DiagnosticsOps.FloppyTest[cmdFile]];
    sectorLengthSeq[0] ← ["128 bytes"L, OnlineDiagnostics.SectorLength[one28]];
    sectorLengthSeq[1] ← ["256 bytes"L, OnlineDiagnostics.SectorLength[two56]];
    sectorLengthSeq[2] ← ["512 bytes"L, OnlineDiagnostics.SectorLength[five12]];
    sectorLengthSeq[3] ← ["1024 bytes"L, OnlineDiagnostics.SectorLength[one024]];
    errorHandlingSeq[0] ← [
      "No Error Checking"L, OnlineDiagnostics.ErrorHandling[noChecking]];
    errorHandlingSeq[1] ← [
      "Stop on Errors"L, OnlineDiagnostics.ErrorHandling[stopOnError]];
    errorHandlingSeq[2] ← [
      "Loop on Errors"L, OnlineDiagnostics.ErrorHandling[loopOnError]];
    operationSeq[0] ← ["Initialize floppy drive"L, DiagnosticsOps.Operation[initialize]];
    operationSeq[1] ← ["Recalibrate"L, DiagnosticsOps.Operation[recalibrate]];
    operationSeq[2] ← ["Read Status"L, DiagnosticsOps.Operation[readStatus]];
    operationSeq[3] ← ["Read Header"L, DiagnosticsOps.Operation[readHeader]];
    operationSeq[4] ← ["Read Sectors"L, DiagnosticsOps.Operation[readSectors]];
    operationSeq[5] ← ["Write Sectors"L, DiagnosticsOps.Operation[writeSectors]];
    operationSeq[6] ← ["Write Deleted Sectors"L, DiagnosticsOps.Operation[writeDeletedSectors]];
    operationSeq[7] ← ["Verify"L, DiagnosticsOps.Operation[verify]];
    operationSeq[8] ← ["Start/Stop Loop"L, DiagnosticsOps.Operation[loop]];
    operationSeq[9] ← ["Display Data"L, DiagnosticsOps.Operation[displayData]];
    operationSeq[10] ← ["Clear Status Log"L, DiagnosticsOps.Operation[clearLog]];
    operationSeq[11] ← ["Log Status"L, DiagnosticsOps.Operation[log]];
    toolData.cmdCount ← 0;
    toolData.cmdIndexes[toolData.cmdCount] ← 0;
    toolData.inALoop ← FALSE;
    dataDisplayedSeq[0] ← ["Status"L, DiagnosticsOps.DataDisplayed[status]];
    dataDisplayedSeq[1] ← ["Header"L, DiagnosticsOps.DataDisplayed[header]];
    dataDisplayedSeq[2] ← ["Sector"L, DiagnosticsOps.DataDisplayed[sector]];
    dataDisplayedSeq[3] ← ["Summary Log"L, DiagnosticsOps.DataDisplayed[summary]];
    items ← AllocateItemDescriptor[nItems: FormIndex.LAST.ORD + 1, z: z];
    formItems ← LOOPHOLE[BASE[items]];
    formItems↑ ← [
      help: CommandItem[
      tag: "Help"L, place: newLine, drawBox: TRUE, invisible: FALSE,
      proc: ActionCommand],
      start: CommandItem[
      tag: "Start"L, drawBox: TRUE, invisible: TRUE, proc: ActionCommand],
      cancel: CommandItem[
      tag: "Cancel"L, drawBox: TRUE, invisible: FALSE, proc: ActionCommand],
      addCommand: CommandItem[
      tag: "Add Command to file"L, drawBox: TRUE, invisible: TRUE,
      proc: ActionCommand],
      deleteCommand: CommandItem[
      tag: "Delete Previous Command"L, drawBox: TRUE, invisible: TRUE,
      proc: ActionCommand],
      test: EnumeratedItem[
      tag: "Test"L, place: newLine, invisible: FALSE, 
      feedback: all, value: @toolData.test, copyChoices: TRUE, 
      choices: DESCRIPTOR[testSeq↑], proc: TestNotify],
      floppyTest: EnumeratedItem[
      tag: "Type of test"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.floppyTest, copyChoices: TRUE,
      choices: DESCRIPTOR[floppyTestSeq↑], proc: FloppyTestNotify],
      currOrganization: StringItem[
      tag: "Current Organization"L, place: newLine, invisible: TRUE,
      readOnly: TRUE, inHeap: TRUE, string: @toolData.strings[currOrganization]],
      currDomain: StringItem[
      tag: "Current Domain"L, place: newLine, invisible: TRUE, readOnly: TRUE,
      inHeap: TRUE, string: @toolData.strings[currDomain]],
      thisEthernetID: StringItem[
      tag: "Source Ethernet ID"L, place: newLine, invisible: TRUE,
      inHeap: TRUE, string: @toolData.strings[thisEthernetID]],
      thisProcessorID: StringItem[
      tag: "Source Processor ID number"L, place: newLine, invisible: TRUE,
      inHeap: TRUE, string: @toolData.strings[thisProcessorID]],
      listFS: StringItem[
      tag: "FS"L, place: newLine, invisible: TRUE, readOnly: TRUE, inHeap: TRUE,
      string: @toolData.strings[listFS]],
      listPS: StringItem[
      tag: "PS"L, place: newLine, invisible: TRUE, readOnly: TRUE, inHeap: TRUE,
      string: @toolData.strings[listPS]],
      listMS: StringItem[
      tag: "MS"L, place: newLine, invisible: TRUE, readOnly: TRUE, inHeap: TRUE,
      string: @toolData.strings[listMS]],
      testEthernetID: StringItem[
      tag: "Destination Ethernet ID number"L, place: newLine, 
      invisible: TRUE, inHeap: TRUE, string: @toolData.strings[testEthernetID]],
      testProcessorID: StringItem[
      tag: "Destination Processor ID number"L, place: newLine,
      invisible: TRUE, inHeap: TRUE, string: @toolData.strings[testProcessorID]],
      realFeedBack: BooleanItem[
      tag: "Display Real Time Feedback"L, place: newLine, invisible: TRUE,
      drawBox: TRUE, switch: @toolData.realFeedBack],
      dataPattern: EnumeratedItem[
      tag: "Set Data Pattern"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.dataPattern, copyChoices: TRUE,
      choices: DESCRIPTOR[dataPatterns]],
      minPacketSize: NumberItem[
      tag: "Minimum Packet Size(2-512 bytes)"L, place: newLine, invisible: TRUE,
      value: @toolData.minPacketSize, notNegative: TRUE, signed: FALSE],
      maxPacketSize: NumberItem[
      tag: "Maximum Packet Size(2-512 bytes)"L, place: newLine, invisible: TRUE,
      value: @toolData.maxPacketSize, notNegative: TRUE, signed: FALSE],
      waitResponse: BooleanItem[
      tag: "Wait for response before sending packet"L, place: newLine,
      invisible: TRUE, drawBox: TRUE, switch: @toolData.waitResponse],
      delayBetween: NumberItem[
      tag: "Delay between packets (milliseconds)"L, place: newLine,
      invisible: TRUE, value: @toolData.delayBetween, notNegative: TRUE,
      signed: FALSE],
      displayServers: BooleanItem[
      tag: "Display Server List"L, place: newLine, invisible: TRUE, drawBox: TRUE,
      switch: @toolData.displayServers],
      lineType: EnumeratedItem[
      tag: "Mode"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.lineType, copyChoices: TRUE,
      choices: DESCRIPTOR[lineTypes]],
      lineSpeed: EnumeratedItem[
      tag: "Data Rate (bps)"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.lineSpeed, copyChoices: TRUE,
      choices: DESCRIPTOR[lineSpeeds]],
      pattern: EnumeratedItem[
      tag: "Set Data Pattern"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.pattern, copyChoices: TRUE, choices: DESCRIPTOR[patterns]],
      constant: NumberItem[
      tag: "Pattern:"L, invisible: TRUE, value: @toolData.constant,
      notNegative: TRUE, signed: FALSE],
      doubleDensity: BooleanItem[
      tag: "Double Density"L, place: newLine, invisible: TRUE,
      switch: @toolData.doubleDensity],
      doubleSided: BooleanItem[
      tag: "Double Sided"L, invisible: TRUE, switch: @toolData.doubleSided],
      sectorsPerTrack: NumberItem[
      tag: "Sectors per Track"L, invisible: TRUE, value:
      @toolData.sectorsPerTrack, notNegative: TRUE, signed: FALSE],
      sectorLength: EnumeratedItem[
      tag: "Sector Length"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.sectorLength, copyChoices: TRUE,
      choices: DESCRIPTOR[sectorLengthSeq↑]],
      errorHandling: EnumeratedItem[
      tag: "Error Handling"L, place: newLine, invisible: TRUE, feedback: all,
      value: @toolData.errorHandling, copyChoices: TRUE,
      choices: DESCRIPTOR[errorHandlingSeq↑]],
      operation: EnumeratedItem[
      tag: "Command File Operation"L, place: newLine, invisible: TRUE,
      feedback: one, value: @toolData.operation, copyChoices: TRUE,
      choices: DESCRIPTOR[operationSeq↑], proc: OperationNotify],
      cmdFile: StringItem[
      tag: "Commands"L, place: newLine, invisible: TRUE, readOnly: TRUE,
      inHeap: TRUE, string: @toolData.strings[cmdFile]],
      trackNumber: NumberItem[
      tag: "Track number"L, place: newLine, invisible: TRUE,
      value: @toolData.trackNumber, notNegative: TRUE, signed: FALSE],
      startingSector: NumberItem[
      tag: "Starting Sector"L, place: newLine, invisible: TRUE,
      value: @toolData.startingSector, notNegative: TRUE, signed: FALSE],
      sectorCount: NumberItem[
      tag: "Sector Count"L, place: newLine, invisible: TRUE,
      value: @toolData.sectorCount, notNegative: TRUE, signed: FALSE],
      increment: NumberItem[
      tag: "Increment (+ or -) by"L, place: newLine, invisible: TRUE,
      value: @toolData.increment, notNegative: FALSE, signed: TRUE],
      dataWord: NumberItem[
      tag: "Data Word"L, place: newLine, invisible: TRUE,
      value: @toolData.dataWord, radix: octal, notNegative: TRUE, signed: FALSE],
      loopCount: NumberItem[
      tag: "Loop Count"L, place: newLine, invisible: TRUE,
      value: @toolData.loopCount, notNegative: TRUE, signed: FALSE],
      dataDisplayed: EnumeratedItem[
      tag: "Data to Be Displayed"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.dataDisplayed, copyChoices: TRUE,
      choices: DESCRIPTOR[dataDisplayedSeq↑]],
      two90TestType: EnumeratedItem[
      tag: "Type of test"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90test, copyChoices: TRUE,
      choices: DESCRIPTOR[testtwo90]],
      two90PlotterType: EnumeratedItem[
      tag: "Plotter Type"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90Plotter, copyChoices: TRUE,
      choices: DESCRIPTOR[plottertwo90]],
      two90Status: EnumeratedItem[
      tag: "Plotter Status"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90Status, copyChoices: TRUE,
      choices: DESCRIPTOR[statustwo90]],
      two90Mode: EnumeratedItem[
      tag: "Plotter Mode"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90Mode, copyChoices: TRUE,
      choices: DESCRIPTOR[modetwo90]],
      two90command: EnumeratedItem[
      tag: "Command To Send"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90Command, copyChoices: TRUE,
      choices: DESCRIPTOR[commandtwo90]],
      plotprint: EnumeratedItem[
      tag: "Print/Plot Output test"L, place: newLine, invisible: TRUE, 
      feedback: all, value: @toolData.two90Output, copyChoices: TRUE,
      choices: DESCRIPTOR[outputtwo90]]];
    z.FREE[@testSeq];
    z.FREE[@floppyTestSeq];
    z.FREE[@sectorLengthSeq];
    z.FREE[@errorHandlingSeq];
    z.FREE[@operationSeq];
    z.FREE[@dataDisplayedSeq];
    RETURN[items: items, freeDesc: TRUE]
    END;

  SetupEthernetItems: PROCEDURE =
    BEGIN  --SetupEthernetItems--
    thisNetworkAddress: System.NetworkAddress;
    -- Get the current domain and organization.
    Profile.GetDefaultOrganization[GetCurrOrganization];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[currOrganization]]];
    Profile.GetDefaultDomain[GetCurrDomain];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[currDomain]]];
    -- Get the current network and host number.
    thisNetworkAddress ← NetworkStream.AssignNetworkAddress[];
    Format.NetworkNumber[
      GetThisEthernetID, thisNetworkAddress.net, productSoftware];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[thisEthernetID]]];
    Format.HostNumber[
      GetThisProcessorID, thisNetworkAddress.host, productSoftware];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[thisProcessorID]]];
    -- List the file servers, print servers, and mail servers.
    IF toolData.displayServers THEN {
      DiagnosticsOps.AppendServers[DESCRIPTOR[toolData.strings], z];
      FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[listFS]]];
      FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[listPS]]];
      FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[listMS]]]};
    GetClearingHouse[];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[testEthernetID]]];
    FormSW.DisplayItem[toolData.formSW, ORD[FormIndex[testProcessorID]]];
    probing ← FALSE;
    END --SetupEthernetItems-- ;

  GetCurrOrganization: PROCEDURE [s: Profile.String] =
    BEGIN toolData.strings[currOrganization] ← String.CopyToNewString[s, z]; END;
  GetCurrDomain: PROCEDURE [s: Profile.String] =
    BEGIN toolData.strings[currDomain] ← String.CopyToNewString[s, z]; END;
  GetThisEthernetID: Format.StringProc =
    BEGIN toolData.strings[thisEthernetID] ← String.CopyToNewString[s, z]; END;
  GetThisProcessorID: Format.StringProc =
    BEGIN toolData.strings[thisProcessorID] ← String.CopyToNewString[s, z]; END;
  GetTestEthernetID: Format.StringProc =
    BEGIN toolData.strings[testEthernetID] ← String.CopyToNewString[s, z]; END;
  GetTestProcessorID: Format.StringProc =
    BEGIN toolData.strings[testProcessorID] ← String.CopyToNewString[s, z]; END;

  GetClearingHouse: PROCEDURE =
    BEGIN  --GetClearingHouse--
    CHAddr: System.NetworkAddress ← CHStubInternal.FindDomainAddr[
      CH.zeroMaxLengthNames];
    Format.NetworkNumber[GetTestEthernetID, CHAddr.net, productSoftware];
    Format.HostNumber[GetTestProcessorID, CHAddr.host, productSoftware];
    END --GetClearingHouse-- ;

  -- Mainline code.

  Init[];

  END...