ChecksumsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
HGM March 5, 1981 3:47 PM
BLyon January 16, 1981 9:54 AM
DIRECTORY
BufferDefs USING [OisBuffer],
Checksums USING [ComputeChecksum],
CommunicationInternal USING [],
CommUtilDefs USING [thisIsAnAlto],
PrincOpsUtils USING [BITAND, BITNOT, BITOR, BITSHIFT],
PrincOps USING [zADD, zDADD, zEXCH, zJ2, zJNE3, zLIN1, zLI0, zPUSH],
OISCPTypes USING [BufferBody];
ChecksumsImpl: PROGRAM
IMPORTS Checksums, PrincOpsUtils
EXPORTS CommunicationInternal, Checksums
SHARES BufferDefs =
BEGIN OPEN Checksums;
These procedures sets the checksum field of the Ois Packet.
SetChecksum: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] =
BEGIN
b.ois.checksum ←
IF CommUtilDefs.thisIsAnAlto THEN SlowlyComputeChecksum[
0, (b.ois.pktLength + 1)/2 - 1, @b.ois.pktLength]
ELSE ComputeChecksum[0, (b.ois.pktLength + 1)/2 - 1, @b.ois.pktLength];
END;
These procedures checks the checksum field of the Ois Packet,
and returns TRUE or FALSE. The buffer is always a system buffer
TestChecksum: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] RETURNS [BOOLEAN] =
BEGIN
cs: CARDINAL ← 0;
IF b.ois.checksum = 177777B THEN RETURN[TRUE];
cs ←
IF CommUtilDefs.thisIsAnAlto THEN SlowlyComputeChecksum[
cs, (b.ois.pktLength + 1)/2 - 1, @b.ois.pktLength]
ELSE ComputeChecksum[cs, (b.ois.pktLength + 1)/2 - 1, @b.ois.pktLength];
RETURN[b.ois.checksum = cs];
END;
SlowlyComputeChecksum: PUBLIC PROCEDURE [
cs: CARDINAL, nWords: CARDINAL, p: LONG POINTER] RETURNS [CARDINAL] =
BEGIN
t: CARDINAL;
THROUGH [0..nWords) DO
IF cs > (t ← cs + p^) THEN cs ← t + 1 ELSE cs ← t;
IF cs >= 100000B THEN cs ← cs*2 + 1 ELSE cs ← cs*2;
p ← p + 1;
ENDLOOP;
IF cs = 177777B THEN cs ← 0;
RETURN[cs];
END;
This procedure updates the checksum field of the Ois Packet
after it increments the oisTransportControl.
zz: PRIVATE POINTER TO OISCPTypes.BufferBody = NIL;
transportControlOffset: CARDINAL =
LOOPHOLE[@zz.transCntlAndPktTp, CARDINAL] - LOOPHOLE[zz, CARDINAL];
IncrOisTransportControlAndUpdateChecksum: PUBLIC PROCEDURE [
b: BufferDefs.OisBuffer] =
BEGIN
oldVal: WORDLOOPHOLE[b.ois.transCntlAndPktTp, CARDINAL];
resisdual: INTEGER;
b.ois.transCntlAndPktTp.transportControl.hopCount ←
b.ois.transCntlAndPktTp.transportControl.hopCount + 1;
IF b.ois.checksum = 177777B THEN RETURN;
resisdual ← PrincOpsUtils.BITAND[
(b.ois.pktLength + 1)/2 - transportControlOffset, 17B];
b.ois.checksum ← OnesAdd[
b.ois.checksum, LeftCycle[
OnesSub[LOOPHOLE[b.ois.transCntlAndPktTp, CARDINAL], oldVal], resisdual]];
END; -- UpdateChecksum
LeftCycle: PROCEDURE [val: CARDINAL, dist: INTEGER] RETURNS [CARDINAL] = INLINE
BEGIN OPEN PrincOpsUtils;
RETURN[BITOR[BITSHIFT[val, dist], BITSHIFT[val, dist - 16]]];
END;
OnesSub: PROCEDURE [a, b: CARDINAL] RETURNS [CARDINAL] = INLINE
BEGIN RETURN[OnesAdd[a, PrincOpsUtils.BITNOT[b]]]; END;
Beware: Making this work on a real Alto is quite tricky. If you get it wrong, it will do things like store 0 in the word the new checksum points at.
OnesAdd: PROCEDURE [a, b: CARDINAL] RETURNS [c: CARDINAL] = MACHINE CODE
BEGIN
c ← a + b; IF c<a THEN c ← c + 1; IF c=177777B THEN c ← 0;
PrincOps.zLI0;
PrincOps.zEXCH;
PrincOps.zLI0;
PrincOps.zDADD;
PrincOps.zADD;
PrincOps.zLIN1;
PrincOps.zJNE3;
PrincOps.zLI0;
PrincOps.zJ2;
PrincOps.zPUSH;
END;
END. -- ChecksumsImpl