DIRECTORY Checksum USING [ComputeChecksum], DebuggerSwap USING [CallDebugger], Process USING [ Detach, GetPriority, MsecToTicks, Pause, Priority, priorityBackground, priorityForeground, SetPriority, SetTimeout, Ticks, Yield], PrincOpsUtils USING [AllocateNakedCondition, DeallocateNakedCondition, LongCopy], NSPilotSystem USING [broadcastHostNumber, HostNumber, nullNetworkNumber, echoerSocket], NSTypes USING [BufferBody], NewEthernetFace USING [ AddCleanup, DeviceHandle, GetNextDevice, GetPacketLength, GetPacketsMissed, GetRetries, GetStatus, nullDeviceHandle, QueueInput, QueueOutput, Status, TurnOff, TurnOn], NewEthernetFaceExtras USING [SetModeFor10MBEther], EtherTesterOps USING [ Buffer, BufferBody, counter, bumpPacketNumber, broadcasting, check, doChecksum, dallyBeforeOutput, dallyIfBehind, dest, Header, hwMode, me, numberOfRecvBuffers, numberOfSendBuffers, pattern, promiscuous, recvSize, sendSize, showGarbage, showOnlyBadAlign, ShowPacket, showRunts, showStrangeStatus, showWrongData, showWrongLength, source, stats, StatsInit, StatsPeek, StatsPrint, TestMode, ticksBeforeSend, UpdateNumbers, AllocateOneBuffer, FreeOneBuffer, AllocateOneIOCB, FreeOneIOCB], EtherTesterViewer USING [UpdateStatsBoxes]; EtherTesterMainImpl: MONITOR IMPORTS Checksum, DebuggerSwap, PrincOpsUtils, Process, NewEthernetFace, NewEthernetFaceExtras, EtherTesterOps, EtherTesterViewer EXPORTS EtherTesterOps = BEGIN OPEN EtherTesterOps; activeProcesses: PUBLIC CARD16 _ 0; lensPattern: ARRAY [0..4) OF BYTE = [0, 125B, 377B, 125B]; ether: NewEthernetFace.DeviceHandle; pleaseStop: BOOL; priorityIOLow: Process.Priority = 5; --from ProcessPriorities.mesa ns: WORD = 3000B; nullChecksum: WORD = 177777B; lastInputBuffer, lastOutputBuffer: Buffer; oldMissed, recvSequenceNumber, sendSequenceNumber: CARD16; inInterruptBits, outInterruptBits: WORD; inputWait, outputWait: LONG POINTER TO CONDITION _ NIL; letBackgroundRun, waitToStart, oneTick, fiveSeconds: CONDITION; endMarker: CARD16 = 119; -- Just a random number. . . StartTest: PUBLIC PROC [test: TestMode, board: CARD16] RETURNS [status: BOOL] = BEGIN IF ~InitEther[board] THEN RETURN[FALSE]; EtherTesterViewer.UpdateStatsBoxes[]; SELECT test FROM SendOnly => Start[EtherOutput, NIL]; ReceiveOnly => Start[EtherInput, NIL]; SendAndReceive => Start[EtherInput, EtherOutput]; EchoServer => Start[EtherServer, NIL]; EchoUser => Start[EtherUser, NIL]; ENDCASE; RETURN[TRUE]; END; InitEther: PROC [board: CARD16] RETURNS [status: BOOL] = BEGIN ether _ NewEthernetFace.nullDeviceHandle; THROUGH [1..board] DO ether _ NewEthernetFace.GetNextDevice[ether]; IF ether = NewEthernetFace.nullDeviceHandle THEN EXIT; ENDLOOP; IF ether = NewEthernetFace.nullDeviceHandle THEN RETURN[FALSE]; NewEthernetFace.AddCleanup[ether]; Process.SetTimeout[@oneTick, 1]; Process.SetTimeout[@fiveSeconds, Process.MsecToTicks[5000]]; RETURN[TRUE]; END; StopTheWorld: PUBLIC PROC = BEGIN pleaseStop _ TRUE; UNTIL activeProcesses = 0 DO Process.Pause[1]; PokeEverybody[]; ENDLOOP; END; EtherInput: ENTRY PROC = BEGIN this: Buffer _ SetupInputBuffers[]; UNTIL pleaseStop DO status: NewEthernetFace.Status _ WaitForInputToArrive[this]; IF status = pending THEN LOOP; CollectInputStats[this, status]; IF status = ok AND this.header.dest = me AND this.header.source = dest THEN BEGIN IF check THEN CheckBuffer[this]; IF doChecksum THEN CheckChecksum[this]; END; AppendInput[this]; this _ this.next; ENDLOOP; UNTIL this.idle DO status: NewEthernetFace.Status _ WaitForInputToArrive[this]; IF status = pending THEN EXIT; CollectInputStats[this, status]; IF status = ok AND this.header.dest = me AND this.header.source = dest THEN BEGIN IF check THEN CheckBuffer[this]; IF doChecksum THEN CheckChecksum[this]; END; this.idle _ TRUE; this _ this.next; ENDLOOP; ReturnInputBuffers[]; Stopping[]; END; EtherOutput: ENTRY PROC = BEGIN this: Buffer _ SetupOutputBuffers[TRUE]; UNTIL pleaseStop DO status: NewEthernetFace.Status _ WaitUntilBufferHasBeenSent[this]; IF status = pending THEN LOOP; CollectOutputStats[this, status]; IF dallyIfBehind AND ((sendSequenceNumber - recvSequenceNumber) >= numberOfSendBuffers) THEN BEGIN stats.dallyForEcho _ stats.dallyForEcho + 1; WAIT letBackgroundRun; END; SendBuffer[this]; this _ this.next; ENDLOOP; UNTIL this.idle DO status: NewEthernetFace.Status _ WaitUntilBufferHasBeenSent[this]; IF status = pending THEN EXIT; CollectOutputStats[this, status]; this.idle _ TRUE; this _ this.next; ENDLOOP; ReturnOutputBuffers[]; Stopping[]; END; EtherServer: ENTRY PROC = BEGIN this: Buffer _ SetupInputBuffers[]; that: Buffer _ SetupOutputBuffers[FALSE]; UNTIL pleaseStop DO status: NewEthernetFace.Status _ WaitForInputToArrive[this]; IF status = pending THEN LOOP; CollectInputStats[this, status]; IF status = ok AND this.header.packetType = ns AND this.body.destination.socket = NSPilotSystem.echoerSocket AND this.body.packetType = echo AND this.body.echoType = echoRequest THEN BEGIN outStatus: NewEthernetFace.Status_ IF that.idle THEN ok ELSE NewEthernetFace.GetStatus[that.iocb]; IF doChecksum THEN CheckChecksum[this]; IF outStatus # pending THEN BEGIN IF ~that.idle THEN CollectOutputStats[that, outStatus]; IF sendSize < NewEthernetFace.GetPacketLength[this.iocb] THEN BEGIN stats.packetsTooLongToEcho _ stats.packetsTooLongToEcho + 1; AppendInput[this]; this _ this.next; LOOP; END; that.header.dest _ this.header.source; that.header.source _ source; that.header.packetType _ ns; that.length _ NewEthernetFace.GetPacketLength[this.iocb]; PrincOpsUtils.LongCopy[ to: @that.body, from: @this.body, nwords: that.length - SIZE[Header]]; that.body.transportControl _ [FALSE, 0, 0]; that.body.packetType _ echo; that.body.destination _ this.body.source; that.body.source _ this.body.destination; that.body.source.host _ source; -- might be broadcast that.body.echoType _ echoResponse; IF doChecksum THEN SetChecksum[that] ELSE that.body.checksum _ nullChecksum; that.idle _ FALSE; AppendOutput[that]; that _ that.next; stats.packetsEchoed _ stats.packetsEchoed + 1; END ELSE stats.packetsNotEchoed _ stats.packetsNotEchoed + 1; END; AppendInput[this]; this _ this.next; ENDLOOP; UNTIL that.idle DO status: NewEthernetFace.Status _ WaitUntilBufferHasBeenSent[that]; IF status = pending THEN EXIT; CollectOutputStats[that, status]; that.idle _ TRUE; that _ that.next; ENDLOOP; UNTIL this.idle DO status: NewEthernetFace.Status _ WaitForInputToArrive[this]; IF status = pending THEN EXIT; CollectInputStats[this, status]; IF status = ok AND this.header.dest = me AND this.header.source = dest THEN BEGIN IF check THEN CheckBuffer[this]; IF doChecksum THEN CheckChecksum[this]; END; this.idle _ TRUE; this _ this.next; ENDLOOP; ReturnOutputBuffers[]; ReturnInputBuffers[]; Stopping[]; END; EtherUser: ENTRY PROC = BEGIN this: Buffer _ SetupInputBuffers[]; that: Buffer _ SetupOutputBuffers[TRUE]; dally: BOOL _ TRUE; UNTIL pleaseStop DO IF dallyIfBehind AND dally AND ((sendSequenceNumber - recvSequenceNumber) >= numberOfSendBuffers) THEN BEGIN stats.dallyForEcho _ stats.dallyForEcho + 1; dally _ FALSE; WAIT letBackgroundRun; END ELSE BEGIN -- input packets are piling up while we WAIT status: NewEthernetFace.Status _ WaitUntilBufferHasBeenSent[that]; IF status # pending THEN BEGIN CollectOutputStats[that, status]; SendBuffer[that]; that _ that.next; END; dally _ TRUE; END; UNTIL pleaseStop DO -- look all of the packets that have arrived status: NewEthernetFace.Status _ NewEthernetFace.GetStatus[this.iocb]; IF status = pending THEN EXIT; CollectInputStats[this, status]; ProcessEchoBuffer[this, status]; this _ this.next; ENDLOOP; ENDLOOP; UNTIL that.idle DO status: NewEthernetFace.Status; THROUGH [0..1000) DO status _ NewEthernetFace.GetStatus[that.iocb]; IF status # pending THEN EXIT; ENDLOOP; IF status = pending THEN EXIT; CollectOutputStats[that, status]; that.idle _ TRUE; that _ that.next; ENDLOOP; UNTIL this.idle DO status: NewEthernetFace.Status _ WaitForInputToArrive[this]; IF status = pending THEN EXIT; CollectInputStats[this, status]; ProcessEchoBuffer[this, status]; this.idle _ TRUE; this _ this.next; ENDLOOP; ReturnInputBuffers[]; ReturnOutputBuffers[]; Stopping[]; END; SendBuffer: INTERNAL PROC [that: Buffer] = BEGIN IF check THEN FillBuffer[that] ELSE BEGIN IF bumpPacketNumber THEN sendSequenceNumber _ sendSequenceNumber + 1; that.body.echoWords[0] _ sendSequenceNumber; END; IF doChecksum THEN SetChecksum[that] ELSE that.body.checksum _ nullChecksum; IF dallyBeforeOutput THEN WAIT letBackgroundRun; DelayBeforeSending[]; AppendOutput[that]; END; ProcessEchoBuffer: INTERNAL PROC[this: Buffer, status: NewEthernetFace.Status] = BEGIN IF status = ok AND this.header.dest = me AND this.header.source = dest AND this.body.echoType = echoResponse THEN BEGIN thisSequenceNumber: CARD16 _ this.body.echoWords[0]; IF doChecksum THEN CheckChecksum[this]; IF bumpPacketNumber THEN recvSequenceNumber _ recvSequenceNumber + 1; SELECT LOOPHOLE[thisSequenceNumber - recvSequenceNumber, INTEGER] FROM 0 => BEGIN stats.packetsEchoed _ stats.packetsEchoed + 1; IF check THEN CheckBuffer[this]; END; > 0 => BEGIN -- Early, we must have lost something UNTIL recvSequenceNumber = thisSequenceNumber DO stats.echosMissed _ stats.echosMissed + 1; IF bumpPacketNumber THEN recvSequenceNumber_ recvSequenceNumber + 1; ENDLOOP; stats.packetsEchoed _ stats.packetsEchoed + 1; IF check THEN CheckBuffer[this]; END; < 0 => BEGIN stats.lateEchos _ stats.lateEchos + 1; IF bumpPacketNumber THEN recvSequenceNumber_ recvSequenceNumber - 1; END; ENDCASE => ERROR; END; AppendInput[this]; END; SetupInputBuffers: INTERNAL PROC RETURNS [Buffer] = BEGIN recvSequenceNumber _ 0; lastInputBuffer _ AllocateBuffer[recvSize]; lastInputBuffer.next _ lastInputBuffer; THROUGH [1..numberOfRecvBuffers) DO temp: Buffer _ AllocateBuffer[recvSize]; temp.next _ lastInputBuffer.next; lastInputBuffer.next _ temp; ENDLOOP; oldMissed _ NewEthernetFace.GetPacketsMissed[ether]; FOR finger: Buffer _ lastInputBuffer.next, finger.next DO AppendInput[finger]; IF finger = lastInputBuffer THEN EXIT; ENDLOOP; WAIT waitToStart; RETURN[lastInputBuffer.next]; END; ReturnInputBuffers: PROC = BEGIN finger: Buffer _ lastInputBuffer.next; lastInputBuffer.next _ NIL; TurnEtherOff[]; UNTIL finger = NIL DO temp: Buffer _ finger.next; FreeBuffer[finger]; finger _ temp; ENDLOOP; END; SetupOutputBuffers: INTERNAL PROC [start: BOOL] RETURNS [Buffer] = BEGIN sendSequenceNumber _ 0; lastOutputBuffer _ AllocateBuffer[sendSize]; lastOutputBuffer.next _ lastOutputBuffer; THROUGH [1..numberOfSendBuffers) DO temp: Buffer _ AllocateBuffer[sendSize]; temp.next _ lastOutputBuffer.next; lastOutputBuffer.next _ temp; ENDLOOP; FOR finger: Buffer _ lastOutputBuffer.next, finger.next DO DelayBeforeSending[]; FillBuffer[finger]; IF doChecksum THEN SetChecksum[finger] ELSE finger.body.checksum _ nullChecksum; IF start THEN AppendOutput[finger] ELSE finger.idle _ TRUE; IF finger = lastOutputBuffer THEN EXIT; ENDLOOP; RETURN[lastOutputBuffer.next]; END; ReturnOutputBuffers: PROC = BEGIN finger: Buffer _ lastOutputBuffer.next; lastOutputBuffer.next _ NIL; THROUGH [0..1000) DO Process.Yield[]; ENDLOOP; TurnEtherOff[]; UNTIL finger = NIL DO temp: Buffer _ finger.next; FreeBuffer[finger]; finger _ temp; ENDLOOP; END; WaitForInputToArrive: INTERNAL PROC[b: Buffer] RETURNS[status: NewEthernetFace.Status] = BEGIN status _ pending; UNTIL pleaseStop OR (status _ NewEthernetFace.GetStatus[b.iocb]) # pending DO WAIT inputWait; ENDLOOP; END; CollectInputStats: INTERNAL PROC[this: Buffer, status: NewEthernetFace.Status] = BEGIN length: CARD16 = NewEthernetFace.GetPacketLength[this.iocb]; temp: CARD16 _ NewEthernetFace.GetPacketsMissed[ether]; IF this.endPlusOne^ # endMarker THEN BEGIN ShowPacket["Microcode wrote past the end of the buffer", this]; DebuggerSwap.CallDebugger["Microcode wrote past the end of the buffer"L]; END; stats.missed _ stats.missed + (temp - oldMissed); oldMissed _ temp; counter[2] _ counter[2] + 1; IF length < SIZE[Header] THEN BEGIN stats.runts _ stats.runts + 1; IF status = ok THEN stats.runtsMarkedOk _ stats.runtsMarkedOk + 1; IF ~promiscuous AND this.header.dest # me AND this.header.dest # NSPilotSystem.broadcastHostNumber THEN stats.multicastRunts _ stats.multicastRunts + 1; IF showRunts THEN ShowPacket["Runt", this]; RETURN; END; SELECT status FROM ok => BEGIN stats.pktsIn _ stats.pktsIn + 1; stats.wdsIn _ stats.wdsIn + length; SELECT this.header.dest FROM NSPilotSystem.broadcastHostNumber => BEGIN stats.bc _ stats.bc + 1; stats.bcWords _ stats.bcWords + length; END; me => stats.toMe _ stats.toMe + 1; ENDCASE => stats.toOther _ stats.toOther + 1; SELECT this.header.source FROM me => stats.fromMe _ stats.fromMe + 1; ENDCASE => NULL; IF this.header.dest = me AND this.header.source = dest THEN BEGIN IF length # sendSize THEN BEGIN IF length < sendSize THEN stats.shortIn _ stats.shortIn + 1; IF length > sendSize THEN stats.longIn _ stats.longIn + 1; IF showWrongLength THEN ShowPacket["Wrong length packet marked ok", this]; END; END; END; ENDCASE => BEGIN counter[0] _ counter[0] + 1; stats.errsIn _ stats.errsIn + 1; SELECT status FROM packetTooLong => stats.shortBuffer _ stats.shortBuffer + 1; badAlignmentButOkCrc => BEGIN stats.itIn _ stats.itIn + 1; IF showOnlyBadAlign THEN ShowPacket["Only bad alignment", this]; END; crc => stats.crcIn _ stats.crcIn + 1; crcAndBadAlignment => stats.crcItIn _ stats.crcItIn + 1; overrun => stats.overrunIn _ stats.overrunIn + 1; ENDCASE => BEGIN stats.funnyIn _ stats.funnyIn + 1; IF showStrangeStatus THEN BEGIN ShowPacket["Funny input status", this]; Pause[]; -- don't print out too much END; END; IF showGarbage THEN ShowPacket["Garbage packet", this]; END; END; DelayBeforeSending: INTERNAL PROC = { THROUGH [0..ticksBeforeSend) UNTIL pleaseStop DO WAIT oneTick; ENDLOOP }; WaitUntilBufferHasBeenSent: INTERNAL PROC [b: Buffer] RETURNS [status: NewEthernetFace.Status] = BEGIN UNTIL (status _ NewEthernetFace.GetStatus[b.iocb]) # pending DO IF pleaseStop THEN RETURN[pending]; WAIT outputWait; ENDLOOP; END; CollectOutputStats: INTERNAL PROC[this: Buffer, status: NewEthernetFace.Status] = BEGIN counter[5] _ counter[5] + 1; SELECT status FROM ok => BEGIN retries: CARD16 = NewEthernetFace.GetRetries[this.iocb]; stats.pktsOut _ stats.pktsOut + 1; stats.wdsOut _ stats.wdsOut + this.length; stats.collisions _ stats.collisions + retries; SELECT retries FROM 0 => NULL; 1 => stats.coll1 _ stats.coll1 + 1; 2 => stats.coll2 _ stats.coll2 + 1; 3 => stats.coll3 _ stats.coll3 + 1; 4 => stats.coll4 _ stats.coll4 + 1; 5 => stats.coll5 _ stats.coll5 + 1; 6 => stats.coll6 _ stats.coll6 + 1; 7 => stats.coll7 _ stats.coll7 + 1; 8 => stats.coll8 _ stats.coll8 + 1; 9 => stats.coll9 _ stats.coll9 + 1; 10 => stats.coll10 _ stats.coll10 + 1; 11 => stats.coll11 _ stats.coll11 + 1; 12 => stats.coll12 _ stats.coll12 + 1; 13 => stats.coll13 _ stats.coll13 + 1; 14 => stats.coll14 _ stats.coll14 + 1; 15 => stats.coll15 _ stats.coll15 + 1; ENDCASE => BEGIN stats.collx _ stats.collx + 1; IF showStrangeStatus THEN ShowPacket["Funny retransmission mask", this]; END; END; ENDCASE => BEGIN counter[0] _ counter[0] + 1; stats.errsOut _ stats.errsOut + 1; SELECT status FROM tooManyCollisions => stats.loadOverflow _ stats.loadOverflow + 1; underrun => stats.overrunOut _ stats.overrunOut + 1; lateCollision => BEGIN stats.lateCollisions _ stats.lateCollisions + 1; IF showGarbage THEN ShowPacket["Late Collision", this]; END; ENDCASE => BEGIN stats.funnyOut _ stats.funnyOut + 1; IF showStrangeStatus THEN ShowPacket["Funny output status", this]; Pause[]; -- don't print out too much END; END; END; FillBuffer: PROC [this: Buffer] = BEGIN end: CARD16 = sendSize - SIZE[Header] - SIZE[echo NSTypes.BufferBody] - 1; IF bumpPacketNumber THEN sendSequenceNumber _ sendSequenceNumber + 1; IF end < sendSize THEN SELECT pattern FROM zeros => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 0; ENDLOOP; ones => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 177777B; ENDLOOP; alternating => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 125252B; ENDLOOP; pairs => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 146314B; ENDLOOP; oneTwentyFive => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 125B; ENDLOOP; countBytes => FOR i: CARD16 IN (0..end) DO k: CARD16 _ i*2; this.body.echoWords[i] _ k*400B + k + 1; ENDLOOP; countWords, ignore => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ i; ENDLOOP; lenOne => FOR i: CARD16 IN [2..2*end) DO this.body.echoBytes[i] _ lensPattern[i/1 MOD 4]; ENDLOOP; lenSix => FOR i: CARD16 IN [2..2*end) DO this.body.echoBytes[i] _ lensPattern[i/6 MOD 4]; ENDLOOP; ENDCASE => FOR i: CARD16 IN (0..end) DO this.body.echoWords[i] _ 1000B; ENDLOOP; this.header.dest _ IF broadcasting THEN NSPilotSystem.broadcastHostNumber ELSE dest; this.header.source _ source; this.header.packetType _ ns; this.body _ [ checksum:, pktLength: 2*(sendSize - SIZE[Header]), transportControl: [FALSE, 0, 0], packetType: echo, destination: [NSPilotSystem.nullNetworkNumber, dest, NSPilotSystem.echoerSocket], source: [NSPilotSystem.nullNetworkNumber, source, LOOPHOLE[sendSequenceNumber]], nsBody: echo[echoType: echoRequest, echoBody:]]; this.body.echoWords[0] _ sendSequenceNumber; END; CheckBuffer: PROC [this: Buffer] = BEGIN end: CARD16 = sendSize - SIZE[Header] - SIZE[echo NSTypes.BufferBody] - 1; bad: CARD16 _ 0; length: CARD16 = NewEthernetFace.GetPacketLength[this.iocb]; IF length # sendSize THEN { stats.wrongLength _ stats.wrongLength + 1; RETURN }; IF end < sendSize THEN SELECT pattern FROM ignore => NULL; zeros => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # 0 THEN bad _ bad + 1; ENDLOOP; ones => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # 177777B THEN bad _ bad + 1; ENDLOOP; alternating => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # 125252B THEN bad _ bad + 1; ENDLOOP; pairs => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # 146314B THEN bad _ bad + 1; ENDLOOP; oneTwentyFive => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # 125B THEN bad _ bad + 1; ENDLOOP; countBytes => FOR i: CARD16 IN (0..end) DO k: CARD16 _ i*2; IF this.body.echoWords[i] # k*400B + k + 1 THEN bad _ bad + 1; ENDLOOP; countWords => FOR i: CARD16 IN (0..end) DO IF this.body.echoWords[i] # i THEN bad _ bad + 1; ENDLOOP; lenOne => FOR i: CARD16 IN [2..end) DO IF this.body.echoBytes[i] # lensPattern[i/1 MOD 4] THEN bad _ bad + 1; ENDLOOP; lenSix => FOR i: CARD16 IN [2..end) DO IF this.body.echoBytes[i] # lensPattern[i/6 MOD 4] THEN bad _ bad + 1; ENDLOOP; ENDCASE => NULL; IF bad # 0 THEN BEGIN stats.wrongPackets _ stats.wrongPackets + 1; stats.wrongWords _ stats.wrongWords + bad; IF showWrongData THEN ShowPacket["Data mismatch", this]; END; END; SetChecksum: PROC [b: Buffer] = BEGIN words: CARD16; words _ (b.body.pktLength - 1)/2; IF words < SIZE[Header] + SIZE[echo NSTypes.BufferBody] THEN b.body.checksum _ nullChecksum ELSE b.body.checksum _ Checksum.ComputeChecksum[ nWords: words, p: @b.body.pktLength]; END; CheckChecksum: PROC [b: Buffer] = BEGIN words: CARD16; checksum: WORD; IF b.body.checksum = nullChecksum THEN RETURN; words _ (b.body.pktLength - 1)/2; IF words > b.length THEN RETURN; checksum _ Checksum.ComputeChecksum[nWords: words, p: @b.body.pktLength]; IF b.body.checksum # checksum THEN ShowPacket["Bad Software Checksum", b]; END; AppendInput: PROC [new: Buffer] = BEGIN p: LONG POINTER _ @new.header; FOR i: CARD16 IN [0..20) DO (p + i)^ _ 0; ENDLOOP; NewEthernetFace.QueueInput[ether, @new.header, new.length, new.iocb]; END; AppendOutput: PROC [new: Buffer] = { NewEthernetFace.QueueOutput[ether, @new.header, new.length, new.iocb] }; AllocateBuffer: PROC [size: CARD16] RETURNS [b: Buffer] = BEGIN b_ AllocateOneBuffer[SIZE[BufferBody] + size]; b.length _ size; b.idle _ FALSE; b.endPlusOne _ LOOPHOLE[@b.header + size]; b.endPlusOne^ _ endMarker; b.iocb _ AllocateOneIOCB[]; END; FreeBuffer: PROC [b: Buffer] = BEGIN FreeOneIOCB[b.iocb]; FreeOneBuffer[b]; END; InitializeCSBs: PUBLIC PROC = BEGIN [inputWait, inInterruptBits] _ PrincOpsUtils.AllocateNakedCondition[]; [outputWait, outInterruptBits] _ PrincOpsUtils.AllocateNakedCondition[]; Process.SetTimeout[inputWait, 100]; Process.SetTimeout[outputWait, 100]; END; CleanThingsUp: PUBLIC PROC = BEGIN DoIt: PROC [who: POINTER TO LONG POINTER TO CONDITION] = BEGIN IF who^ = NIL THEN RETURN; PrincOpsUtils.DeallocateNakedCondition[who^]; who^ _ NIL; END; DoIt[@inputWait]; DoIt[@outputWait]; END; TurnEtherOn: PROC = BEGIN host: NSPilotSystem.HostNumber; host _ IF promiscuous THEN NSPilotSystem.broadcastHostNumber ELSE source; []_ NewEthernetFaceExtras.SetModeFor10MBEther[hwMode]; NewEthernetFace.TurnOn[ether, host, inInterruptBits, outInterruptBits, NIL]; END; TurnEtherOff: PROC = { NewEthernetFace.TurnOff[ether] }; Pause: INTERNAL PROC = { WAIT fiveSeconds }; StartOne: ENTRY PROC [who: PROC] = BEGIN activeProcesses _ activeProcesses + 1; Process.Detach[FORK who[]]; END; Start: PROC [a, b: PROC] = BEGIN oldPriority: Process.Priority = Process.GetPriority[]; activeProcesses _ 0; -- input watcher pleaseStop _ FALSE; StatsInit[]; TurnEtherOn[]; Process.SetPriority[priorityIOLow]; StartOne[WaitForStop]; Process.SetPriority[Process.priorityForeground]; IF a # NIL THEN StartOne[a]; IF b # NIL THEN StartOne[b]; Process.SetPriority[Process.priorityBackground]; Process.Detach[FORK Watcher[]]; Process.SetPriority[oldPriority]; END; Watcher: PROC = BEGIN THROUGH [0..100) DO Process.Yield[]; ENDLOOP; counter _ [-1, 0, 0, 0, 0, 0, 0, -1]; StartEverybody[]; UNTIL activeProcesses = 0 DO StatsPeek[]; Process.Yield[]; StartEverybody[]; UpdateNumbers[]; ENDLOOP; StatsPrint[FALSE]; END; StartEverybody: ENTRY PROC = BEGIN BROADCAST waitToStart; BROADCAST letBackgroundRun; END; PokeEverybody: ENTRY PROC = BEGIN NOTIFY inputWait^; NOTIFY outputWait^; END; DontBeAHog: PUBLIC PROC RETURNS [stop: BOOL] = BEGIN Process.Yield[]; RETURN[pleaseStop]; END; WaitForStop: PROC = BEGIN halfSecond: Process.Ticks = Process.MsecToTicks[500]; UNTIL pleaseStop DO Process.Pause[5]; -- don't hang on our ML if sender is swamped ENDLOOP; EnterStopping[]; END; EnterStopping: ENTRY PROC = { Stopping[] }; Stopping: INTERNAL PROC = BEGIN activeProcesses _ activeProcesses - 1; pleaseStop _ TRUE; BROADCAST fiveSeconds; BROADCAST inputWait^; END; END. ΞEtherTesterMainImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Last Edited by: Willie-Sue, April 7, 1988 2:30:00 pm PDT lifted from EtherTesterMain.mesa, AOF, 26-Sep-83 16:22:43 ProcessPriorities USING [priorityIOLow], NSConstants USING [echoerSocket], Global Data Private Data Ethernet packet types: Start receive before send to avoid lost packets Caution: sendSize must be large enough to hold echo packet! Copy of code above for normal case put on front of chain put on front of chain Give output a chance to unwind so we don't generate a bad packet must be a bad length field in the packet We're allocating more than we need. The driver thinks the buffer ends at @b.header + size and it really ends at @b.header + size + SIZE[Header] + SIZE[echo NSTypes.BufferBody]. marks the end of the buffer so we can see if the microcode overshoots IF UserInput.UserAbort[log] THEN pleaseStop _ TRUE; IF UserInput.UserAbort[log] THEN pleaseStop _ TRUE; Κ ˜šΟb™Icode™˜QJšœžœF˜YJ˜Jšœ žœ™!Jšœžœ˜JšœžœΆ˜ΛJ˜Jšœžœ˜2J˜Jšœžœ‹˜ŸJšœžœ˜+—J˜šΟnœž˜šž˜Jšœ}˜}—Jšžœ˜Jšžœžœ˜—J˜Jšœ ™ J˜Jšœžœžœ˜#J˜Jšœ žœžœžœ˜:J˜Jšœ ™ J˜J˜$Jšœ žœ˜J˜J˜CJ˜Jšœ™Jšœžœ ˜Jšœžœ ˜J˜J˜*Jšœ3žœ˜:J˜Jšœ#žœ˜(Jš œžœžœžœž œžœ˜7Jšœ5ž œ˜?J˜Jšœ žœ Οc˜6J˜š Ÿ œžœžœžœžœ žœ˜Sšž˜Jšžœžœžœžœ˜(Jšœ%˜%šžœž˜Jšœžœ˜$Jšœ!žœ˜&J˜1—šœ/™/Jšœ!žœ˜&Jšœžœ˜"—Jšžœ˜Jšžœžœ˜ —Jšžœ˜—J˜š Ÿ œžœ žœžœ žœ˜8šž˜J˜)šžœ ž˜J˜-Jšžœ*žœžœ˜6—Jšžœ˜Jšžœ*žœžœžœ˜?J˜"J˜ J˜—Jšžœ˜—Jšžœ˜—J˜š Ÿœžœžœ žœžœ ˜Bšž˜J˜J˜,J˜)šžœž˜#J˜(—šœ™J˜"J˜—Jšžœ˜šžœ5ž˜:J˜J˜šžœ žœ˜&Jšžœ%˜)—Jšžœžœžœžœ˜;Jšžœžœžœ˜'—Jšžœ˜Jšžœ˜—Jšžœ˜—J˜šŸœžœ˜šž˜J˜'Jšœžœ˜—šœ@™@Jšžœ žœžœ˜.J˜šžœ žœž˜J˜>—Jšžœ˜—Jšžœ˜—J˜šŸœžœžœ žœ"˜Xšž˜J˜šžœ žœ8ž˜MJšžœ ˜—Jšžœ˜—Jšžœ˜—J˜šŸœžœžœ0˜Pšž˜Jšœžœ.˜—Jšžœ˜—˜ šžœžœžœ ž˜Jšžœžœžœ˜:——˜ šžœžœžœ ž˜Jšžœ*žœžœ˜F—Jšžœ˜—˜ šžœžœžœ ž˜Jšžœ*žœžœ˜F—Jšžœ˜—Jšžœžœ˜——šžœ ž˜šž˜J˜,J˜*Jšžœžœ#˜8—Jšžœ˜——Jšžœ˜—J˜šŸ œžœ˜šž˜Jšœžœ˜J˜!šžœ žœ žœž˜