-- ChecksumsImpl.mesa -- last edit by: HGM March 5, 1981 3:47 PM -- last edit by: BLyon January 16, 1981 9:54 AM DIRECTORY BufferDefs USING [OisBuffer], Checksums USING [ComputeChecksum], CommunicationInternal USING [], CommUtilDefs USING [thisIsAnAlto], Inline USING [BITAND, BITNOT, BITOR, BITSHIFT], Mopcodes USING [zADD, zDADD, zEXCH, zJ2, zJNE3, zLIN1, zLI0, zPUSH], OISCPTypes USING [BufferBody]; ChecksumsImpl: PROGRAM IMPORTS Checksums, Inline 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: WORD ← LOOPHOLE[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 ← Inline.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 Inline; RETURN[BITOR[BITSHIFT[val, dist], BITSHIFT[val, dist - 16]]]; END; OnesSub: PROCEDURE [a, b: CARDINAL] RETURNS [CARDINAL] = INLINE BEGIN RETURN[OnesAdd[a, Inline.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; Mopcodes.zLI0; Mopcodes.zEXCH; Mopcodes.zLI0; Mopcodes.zDADD; Mopcodes.zADD; Mopcodes.zLIN1; Mopcodes.zJNE3; Mopcodes.zLI0; Mopcodes.zJ2; Mopcodes.zPUSH; END; END. -- ChecksumsImpl