EtherTesterControlImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
last edited by Willie-Sue, April 7, 1988 2:30:29 pm PDT
taken from: EtherTesterTajo.mesa, AOF, 26-Sep-83 17:13:41
DIRECTORY
Atom,
BasicTime USING [Now],
Booting USING [switches],
Buttons USING [ButtonProc],
Commander USING [CommandProc, Handle, Register],
Containers USING [ChildXBound, ChildYBound],
DebuggerSwap USING [CallDebugger],
FS USING [Error, SetKeep],
IO,
Labels USING [Create],
Loader USING [BCDBuildTime, MakeGlobalFrameResident, MakeProcedureResident],
Menus USING [Menu, MenuProc, AppendMenuEntry, CreateEntry, CreateMenu],
ProcessorFace USING [processorID],
Rope USING [ROPE, Length],
Rules USING [Create],
TypeScript USING [Create],
SystemVersion USING [machineType],
VFonts,
ViewerIO USING [CreateViewerStreams],
ViewerOps,
Unformat USING [HostNumberToRope],
NSPilotSystem USING [HostNumber],
NewEthernetFace USING [Status, GetPacketLength, GetStatus, GetRetries, TurnOn],
EtherTesterOps USING [
StartTest, StopTheWorld, DontBeAHog, InitializeCSBs, CleanThingsUp, Buffer,
Pattern, activeProcesses, HWTestMode],
EtherTesterViewer;
EtherTesterControlImpl: MONITOR
IMPORTS
BasicTime, Booting, Commander, Containers, DebuggerSwap, FS, IO, Labels, Loader, Menus, ProcessorFace, Rope, Rules, SystemVersion, TypeScript, Unformat, ViewerIO, ViewerOps,
NewEthernetFace, EtherTesterOps, EtherTesterViewer
EXPORTS EtherTesterOps, EtherTesterViewer =
BEGIN OPEN IO, EtherTesterViewer;
Global Data
ROPE: TYPE = Rope.ROPE;
counter: PUBLIC ARRAY [0..8) OF INT;
tsOut: PUBLIC STREAMNIL;
me, source, dest: PUBLIC NSPilotSystem.HostNumber← LOOPHOLE[ProcessorFace.processorID];
variables used for testing
recvSize: PUBLIC CARDINAL← defaultRecvSize;
sendSize: PUBLIC CARDINAL← defaultSendSize;
ticksBeforeSend: PUBLIC CARDINAL← defaultTicksBeforeSend;
promiscuous: PUBLIC BOOLEANFALSE;
broadcasting: PUBLIC BOOLEANFALSE;
check: PUBLIC BOOLEANFALSE;
flipem: PUBLIC BOOLEANFALSE;
doChecksum: PUBLIC BOOLEANTRUE;
doStats: PUBLIC BOOLEANTRUE;
showRunts, showGarbage, dallyBeforeOutput: PUBLIC BOOLEANFALSE;
defaultNumberOfRecvBuffers: CARDINAL = 6;
numberOfRecvBuffers: PUBLIC CARDINAL ← defaultNumberOfRecvBuffers;
defaultNumberOfSendBuffers: CARDINAL = 1;
numberOfSendBuffers: PUBLIC CARDINAL ← defaultNumberOfSendBuffers;
showStrangeStatus, showWrongLength: PUBLIC BOOLEANTRUE;
showWrongData, showOnlyBadAlign: PUBLIC BOOLEANTRUE;
bumpPacketNumber, dallyIfBehind: PUBLIC BOOLEANTRUE;
hwMode: PUBLIC EtherTesterOps.HWTestMode← normal;
Private Data
defNumOfRecvBuffers: ROPE = "6";
defNumOfSendBuffers: ROPE = "1";
etherNetBoard: CARDINAL ← defaultEtherNetBoard;
herald: ROPE;
etherTesterLogName: ROPE = "EtherTester.log";
okToRun: BOOLFALSE;
etherTesterController: Viewer← NIL;
testerTS: Viewer← NIL;
boardNum, sourceHost, destHost, myHost: PUBLIC ButtonItem← NIL;
numRecvBuffers, inputBuffLen, numSendBuffers, outputBuffLen: PUBLIC ButtonItem← NIL;
ticksBefore: PUBLIC ButtonItem← NIL;
statsDisplayer: PUBLIC StatsItem;
defaultEtherNetBoard: CARDINAL = 1;
defaultRecvSize: CARDINAL = 2020;
defaultSendSize: CARDINAL = 2000;
defaultTicksBeforeSend: CARDINAL = 0;
defEtherNetBoard: ROPE = "1";
defRecvSize: ROPE = "2020";
defSendSize: ROPE = "2000";
defTicksBeforeSend: ROPE = "0";
myHostNumber: ROPE;
sourceHostNumber: ROPE;
destHostNumber: ROPE;
ParseError: PUBLIC SIGNAL = CODE;
pattern: PUBLIC EtherTesterOps.Pattern ← ignore;
patternButton, hwModeButton: PUBLIC Viewer;
noE2Board: ROPE = "**************** Can't find specified Ethernet(2) board.";
Button Commands
Stop: ENTRY Menus.MenuProc = TRUSTED
BEGIN
EtherTesterOps.StopTheWorld[];
ViewerOps.SetMenu[etherTesterController, readyMenu];
END;
Send: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
IF ComplainIfRunningAndSuch["\nSending..."] THEN RETURN;
PrintDest[];
IF ~EtherTesterOps.StartTest[SendOnly, etherNetBoard] THEN Trouble[noE2Board];
END;
Recv: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
IF ComplainIfRunningAndSuch["\nReceiving..."] THEN RETURN;
PrintSource[];
IF ~EtherTesterOps.StartTest[ReceiveOnly, etherNetBoard] THEN Trouble[noE2Board];
END;
SendAndRecv: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
IF ComplainIfRunningAndSuch["\nSending and Receiving..."] THEN RETURN;
PrintSource[];
PrintDest[];
IF ~EtherTesterOps.StartTest[SendAndReceive, etherNetBoard] THEN Trouble[noE2Board];
END;
EchoServer: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
IF ComplainIfRunningAndSuch["\nEcho Server..."] THEN RETURN;
PrintSource[];
PrintDest[];
IF ~EtherTesterOps.StartTest[EchoServer, etherNetBoard] THEN Trouble[noE2Board];
END;
EchoUser: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
IF ComplainIfRunningAndSuch["\nEcho User..."] THEN RETURN;
PrintSource[];
PrintDest[];
IF ~EtherTesterOps.StartTest[EchoUser, etherNetBoard] THEN Trouble[noE2Board];
END;
Quit: ENTRY Buttons.ButtonProc = TRUSTED
BEGIN
xx: Viewer← etherTesterController;
IF ComplainIfRunningAndSuch["\nQuit...", TRUE] THEN RETURN;
tsOut.Close[];
EtherTesterOps.CleanThingsUp[];
etherTesterController← NIL;
xx.inhibitDestroy← FALSE;
ViewerOps.DestroyViewer[xx];
END;
syntaxError: ROPE = "Syntax error in ";
ComplainIfRunningAndSuch: INTERNAL PROC[header: ROPE, stopping: BOOLFALSE]
  RETURNS[notOK: BOOL] =
BEGIN ENABLE UNWIND => NULL;
BEGIN
IF EtherTesterOps.activeProcesses # 0 THEN
{ tsOut.PutRope["A test is already running. Please Stop it first."]; RETURN[TRUE]};
IF stopping THEN { tsOut.PutRope[header]; RETURN[FALSE] };
ViewerOps.SetMenu[etherTesterController, stopMenu];
source← ReadHostNum[sourceHost.text ! ParseError =>
{Trouble[syntaxError, "Source."]; GOTO quitThis}];
dest← ReadHostNum[destHost.text ! ParseError =>
{Trouble[syntaxError, "Dest."]; GOTO quitThis}];
me← ReadHostNum[myHost.text ! ParseError =>
{Trouble[syntaxError, "MyHostNmber."]; GOTO quitThis}];
etherNetBoard← ReadCard[boardNum ! ParseError =>
{Trouble[syntaxError, "etherNet board number."]; GOTO quitThis}];
ticksBeforeSend← ReadCard[ticksBefore ! ParseError =>
{Trouble[syntaxError, "ticksBeforeSend."]; GOTO quitThis}];
numberOfRecvBuffers← ReadCard[numRecvBuffers ! ParseError =>
{Trouble[syntaxError, "number of Receive buffers."]; GOTO quitThis}];
recvSize← ReadCard[inputBuffLen ! ParseError =>
{Trouble[syntaxError, "input buffer length."]; GOTO quitThis}];
numberOfSendBuffers← ReadCard[numSendBuffers ! ParseError =>
{Trouble[syntaxError, "number of send buffers."]; GOTO quitThis}];
sendSize← ReadCard[outputBuffLen ! ParseError =>
{Trouble[syntaxError, "output buffer length."]; GOTO quitThis}];
IF recvSize < 6 THEN
{Trouble[PutFR["Input buffer too small (%g < 6).", int[recvSize]]]; RETURN[TRUE]};
IF recvSize > 3100 THEN
{Trouble[PutFR["Input buffer too big ( %g > 3100).", int[recvSize]]]; RETURN[TRUE]};
IF sendSize > 3000 THEN
{Trouble[PutFR["Output buffer too big (%g > 3000).", int[sendSize]]]; RETURN[TRUE]};
IF sendSize < 7 THEN
{Trouble[PutFR["Output buffer too small (%g < 7).", int[sendSize]]]; RETURN[TRUE]};
tsOut.PutRope[header];
tsOut.PutRope[PutFR["\n%g Running.....\n", IO.time[]]];
IF sendSize < 30 THEN
tsOut.PutRope[
"\n***** Warning: Sending packets shorter than allowed by Ethernet Spec. (30 words)"];
IF sendSize > 757 THEN
tsOut.PutRope[
 "\n***** Warning: Sending packets longer than allowed by Ethernet Spec. (757 words)"];
RETURN[FALSE]
EXITS
quitThis => RETURN[TRUE];
END;
END;
PrintDest: PROC =
BEGIN
SELECT TRUE FROM
broadcasting => tsOut.PutRope["\nOutput packets will be BROADCAST!\n"];
dest = me => tsOut.PutRope["\nOutput packets will be sent to me.\n"];
ENDCASE =>
tsOut.PutF["\nOutput packets will be sent to %g.\n",
  rope[Unformat.HostNumberToRope[dest]]];
IF check THEN tsOut.PutRope["Output data will be formatted.\n"];
tsOut.PutF["Output packet length is %d words.\n", int[sendSize]];
END;
PrintSource: PROC =
BEGIN
IF promiscuous THEN tsOut.PutRope["\nReading everything.\n"]
ELSE tsOut.PutRope["\nReading just packets for me.\n"];
IF check THEN tsOut.PutRope["Input data will be checked.\n"];
tsOut.PutF["Input buffer length is %d words.\n", int[recvSize]];
END;
building controller and initializing it ************************
blankMenu: Menus.Menu← Menus.CreateMenu[];
stopMenu: Menus.Menu← Menus.CreateMenu[];
readyMenu: Menus.Menu← Menus.CreateMenu[];
BuildController: INTERNAL PROC =
BEGIN
xx, zz: Viewer;
IF etherTesterController # NIL THEN RETURN;
xx← ViewerOps.CreateViewer[
   flavor: $Container,
   info: [name: "Ether Tester", iconic: FALSE, column: left, scrollable: FALSE]];
xx.inhibitDestroy← TRUE;
ViewerOps.SetMenu[xx, blankMenu];
initial line **********
zz← Labels.Create[
info: [name: " Black background means TRUE; White background means FALSE",
parent: xx, wx: 5, wy: 3, wh: entryHeight, border: FALSE]];
zz← Rules.Create[info: [parent: xx, wy: zz.wy+zz.wh+4, ww: xx.ww, wh: 1]];
Containers.ChildXBound[xx, zz];
first line **********
zz← MakeBoolItem[name: "ShowRunts", proc: ShowRunts, sib: zz, init: showRunts,
 newLine: TRUE];
zz← MakeBoolItem[name: "ShowGarbage", proc: ShowGarbage, sib: zz, init: showGarbage];
zz← MakeBoolItem[name: "ShowStrange", proc: ShowStrange, sib: zz, init: showStrangeStatus];
zz← MakeBoolItem[name: "ShowWrongLength", proc: ShowWrongLength, sib: zz,
  init: showWrongLength];
zz← MakeBoolItem[name: "ShowWrongData", proc: ShowWrongData, sib: zz,
 init: showWrongData];
second line **********
zz← MakeBoolItem[name: "ShowOnlyBadAlign", proc: ShowOnlyBadAlign, sib: zz,
 init: showOnlyBadAlign, newLine: TRUE];
zz← MakeBoolItem[name: "DoChecksum", proc: DoChecksum, sib: zz, init: doChecksum];
zz← MakeBoolItem[name: "DoStats", proc: DoStats, sib: zz, init: doStats];
zz← MakeBoolItem[name: "CheckInput", proc: CheckInput, sib: zz, init: check];
zz← MakeBoolItem[name: "BumpPacketNumber", proc: BumpPacketNumber, sib: zz,
 init: bumpPacketNumber];
third line **********
zz← MakeBoolItem[name: "DallyIfBehind", proc: DallyIfBehind, sib: zz,
 init: dallyIfBehind, newLine: TRUE];
zz← MakeBoolItem[name: "DallyBeforeOutput", proc: DallyBeforeOutput, sib: zz,
 init: dallyBeforeOutput];
zz← MakeBoolItem[name: "Promiscuous", proc: Promiscuous, sib: zz, init: promiscuous];
zz← MakeBoolItem[name: "Broadcasting", proc: Broadcasting, sib: zz, init: broadcasting];
fourth line **********
boardNum← ButtonAndText[name: "Board #:", sib: zz, width: 40,
  default: defEtherNetBoard, valType: cardinal, newLine: TRUE];
ticksBefore← ButtonAndText[name: "TicksBeforeSend ", sib: boardNum.text, width: 60,
  default: defTicksBeforeSend, valType: cardinal];
PatternButton[sib: ticksBefore.text];
HWModeButton[sib: patternButton];
fifth line **********
sourceHost← ButtonAndText[name: "Source: ", sib: ticksBefore.text, width: 100,
 default: sourceHostNumber, valType: hostNum, newLine: TRUE];
destHost← ButtonAndText[name: "Dest: ", sib: sourceHost.text, width: 100,
 default: destHostNumber, valType: hostNum];
myHost← ButtonAndText[name: "Me: ", sib: destHost.text, width: 100,
 default: myHostNumber, valType: hostNum];
sixth line **********
numRecvBuffers← ButtonAndText[name: "NumberOfRecvBuffers: ", sib: myHost.text,
  width: 40, newLine: TRUE, default: defNumOfRecvBuffers, valType: cardinal];
inputBuffLen← ButtonAndText[name: "InputBufferLength: ", sib: numRecvBuffers.text,
  width: 100, default: defRecvSize, valType: cardinal];
seventh line **********
numSendBuffers← ButtonAndText[name: "NumberOfSendBuffers: ", sib: inputBuffLen.text,
  width: 40, newLine: TRUE, default: defNumOfSendBuffers, valType: cardinal];
outputBuffLen← ButtonAndText[name: "OutputBufferLength: ", sib: numSendBuffers.text,
  width: 100, default: defRecvSize, valType: cardinal];
zz← outputBuffLen.text;
zz← Rules.Create[ info: [parent: xx, wy: zz.wy+zz.wh+3, ww: xx.ww, wh: 1]];
Containers.ChildXBound[xx, zz];
line of stats which get updated if desired
MakeStatsDisplayers[zz.wy + zz.wh + xFudge, xx];
zz← statsDisplayer.label;
zz← Rules.Create[ info: [parent: xx, wy: zz.wy+zz.wh+3, ww: xx.ww, wh: 1]];
Containers.ChildXBound[xx, zz];
typescript area at end
BEGIN
y: INTEGER← zz.wy + zz.wh + xFudge;
testerTS← TypeScript.Create[
info: [parent: xx, ww: xx.cw, wy: y, wh: xx.ch - y, border: FALSE]];
Containers.ChildYBound[xx, testerTS];
Containers.ChildXBound[xx, testerTS];
FS.SetKeep[etherTesterLogName, 2 ! FS.Error => CONTINUE];
tsOut← ViewerIO.CreateViewerStreams[NIL, testerTS, etherTesterLogName].out;
END;
etherTesterController← xx;
ViewerOps.SetMenu[etherTesterController, readyMenu];
tsOut.PutRope[herald];
END;
Miscellaneous routines
ShowPacket: PUBLIC PROC[why: ROPE, this: EtherTesterOps.Buffer] =
BEGIN
limit: CARDINAL = 30;
length: CARDINAL = NewEthernetFace.GetPacketLength[this.iocb] + 2; -- CRC
p: LONG POINTER ← @this.header;
val: WORD;
IF this = NIL THEN Debugger["AttemptToPrintNilBuffer"L];
tsOut.PutRope[why];
tsOut.PutF[".\nStatus: %g, Length: %d, Used: %d, Retries: %bB.\n",
rope[StatusToRope[NewEthernetFace.GetStatus[this.iocb]]], int[this.length],
int[NewEthernetFace.GetPacketLength[this.iocb]],
int[NewEthernetFace.GetRetries[this.iocb]] ];
tsOut.PutF["Dest: %g, Source: %g, Type: %bB.\n",
rope[Unformat.HostNumberToRope[this.header.dest]],
rope[Unformat.HostNumberToRope[this.header.source]],
int[this.header.packetType]];
tsOut.PutRope["IOCB: "];
FOR i: CARDINAL IN [0..8) DO
{ val← (this.iocb + i)^; tsOut.PutF["%07b ", card[val]]}; ENDLOOP;
FOR i: CARDINAL IN [0..IF TRUE THEN length ELSE MIN[limit, length]) DO
IF (i MOD 8) = 0 THEN
BEGIN
tsOut.PutChar['\n];
IF EtherTesterOps.DontBeAHog[] THEN EXIT;
ShowPacket is called at interrupt level so we must call DontBeAHog to let other guys get a chance to run. Also checks for Stop key.
tsOut.PutF["%4b/ ", card[i]];
END;
val← (p + i)^; tsOut.PutF["%07b ", card[val]];
ENDLOOP;
tsOut.PutChar['\n];
IF FALSE AND length > limit THEN tsOut.PutRope["....\n"];
END;
Debugger: PROC[e: STRING] = { DebuggerSwap.CallDebugger[e] };
Trouble: PROC[txt, txt2: ROPENIL] =
BEGIN
tsOut.PutRope[txt];
IF txt2.Length[] # 0 THEN tsOut.PutRope[txt2];
tsOut.PutChar['\n];
ViewerOps.SetMenu[etherTesterController, readyMenu];
END;
ShowRunts: BoolItemProc = { showRunts← value};
ShowGarbage: BoolItemProc = { showGarbage← value};
ShowStrange: BoolItemProc = { showStrangeStatus← value};
ShowWrongLength: BoolItemProc = { showWrongLength← value};
ShowWrongData: BoolItemProc = { showWrongData← value};
ShowOnlyBadAlign: BoolItemProc = { showOnlyBadAlign← value};
DoChecksum: BoolItemProc = { doChecksum← value};
DoStats: BoolItemProc = { doStats← value};
CheckInput: BoolItemProc = { check← value};
BumpPacketNumber: BoolItemProc = { bumpPacketNumber← value};
DallyIfBehind: BoolItemProc = { dallyIfBehind← value};
DallyBeforeOutput: BoolItemProc = { dallyBeforeOutput← value};
Promiscuous: BoolItemProc = { promiscuous← value};
Broadcasting: BoolItemProc = { broadcasting← value};
UpdateNumbers: PUBLIC PROC = {EtherTesterViewer.UpdateStatsBoxes[]};
Initialization *********************************
EtherTesterProc: ENTRY Commander.CommandProc = TRUSTED
BEGIN
IF etherTesterController # NIL THEN
{ cmd.out.PutRope["EtherTester control window already exists\n"]; RETURN };
cmd.out.PutRope[herald];
IF ~okToRun THEN
{ cmd.out.PutRope[
"The 'b switch needs to be down before EtherTester will run."];
RETURN
};
myHostNumber← Unformat.HostNumberToRope[me];
sourceHostNumber← Unformat.HostNumberToRope[source];
destHostNumber← Unformat.HostNumberToRope[dest];
BuildController[];
END;
InitializeThings: PROC =
BEGIN
SELECT SystemVersion.machineType FROM
dorado => okToRun← TRUE;
dandelion => okToRun← Booting.switches[b];
ENDCASE;
IF ~okToRun THEN RETURN;
Loader.MakeGlobalFrameResident[NewEthernetFace.TurnOn];
Loader.MakeProcedureResident[NewEthernetFace.TurnOn];
herald← PutFR["Ethernet Tester of %g running on host number: %g.\n",
time[Loader.BCDBuildTime[NewEthernetFace.TurnOn]],
rope[Unformat.HostNumberToRope[me]]];
EtherTesterOps.InitializeCSBs[];
Menus.AppendMenuEntry[stopMenu, Menus.CreateEntry["Stop", Stop]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["Send", Send]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["Receive", Recv]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["SendAndRecv", SendAndRecv]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["EchoServer", EchoServer]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["EchoUser", EchoUser]];
Menus.AppendMenuEntry[readyMenu, Menus.CreateEntry["Quit", Quit]];
END;
Commander.Register["EtherTester", EtherTesterProc, "Builds an EtherTester control window"];
InitializeThings[];
END.