-- File: ChecksumsImpl.mesa - last edit:
-- AOF                 13-Aug-87 16:42:23
-- Copyright (C) 1984, 1986, 1987 by Xerox Corporation. All rights reserved. 

DIRECTORY
  Checksums USING [ComputeChecksum],
  Environment USING [bytesPerWord],
  Inline USING [BITAND, BITNOT, BITROTATE],
  Mopcodes USING [zADD, zACD, zDUP, zINC, zJNEB, zLIN1, zLI0],
  NSBuffer USING [Body],
  NSTypes USING [base, BufferBody, TransportControl];

ChecksumsImpl: PROGRAM
  IMPORTS Checksums, Inline
  EXPORTS Checksums
  SHARES NSTypes =

  BEGIN
  RawWords: TYPE = LONG POINTER TO RawWord;
  RawWord: TYPE = RECORD[SEQUENCE COMPUTED WORD OF WORD];

  bpw: NATURAL = Environment.bytesPerWord;
  transportControlOffset: CARDINAL =
    LOOPHOLE[@NSTypes.base.pktLength, CARDINAL] +
    SIZE[CARDINAL --pktLength field--];

  -- These procedures sets the checksum field of the NS Packet.
  SetChecksum: PUBLIC PROC[b: NSBuffer.Body] =
    BEGIN
    b.checksum ← Checksums.ComputeChecksum[
      0, (b.pktLength + bpw - 1) / bpw - 1, @b.pktLength];
    END;

  -- These procedures checks the checksum field of the NS Packet,
  -- and returns TRUE or FALSE.  The buffer is always a system buffer

  TestChecksum: PUBLIC PROC[b: NSBuffer.Body]
    RETURNS [BOOLEAN] =
    BEGIN
    cs: CARDINAL;  --local used so we can look at cs with debugger
    IF b.checksum = 177777B THEN RETURN[TRUE];
    cs ← Checksums.ComputeChecksum[
      0, (b.pktLength + bpw - 1) / bpw - 1, @b.pktLength];
    RETURN[b.checksum = cs];
    END;

  SlowlyComputeChecksum: PUBLIC PROC[
    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 NS Packet
  -- after it increments the nsTransportControl.

  IncrNSTransportControlAndUpdateChecksum: PUBLIC PROC[b: NSBuffer.Body] =
    BEGIN
    resisdual: INTEGER;
    newVal, oldVal: WORD;
    raw: RawWords = LOOPHOLE[b];
    oldVal ← raw[transportControlOffset];  --save the old value before mods
    b.transportControl.hopCount ← SUCC[b.transportControl.hopCount];  --modify
    IF b.checksum = 177777B THEN RETURN;
    newVal ← raw[transportControlOffset];  --capture the new value
    resisdual ← Inline.BITAND[
      (b.pktLength + bpw - 1) / bpw - transportControlOffset, 17B];
    b.checksum ← OnesAdd[
      b.checksum, Inline.BITROTATE[OnesSub[newVal, oldVal], resisdual]];
    END; -- UpdateChecksum

  OnesAdd: PROC[a, b: WORD] RETURNS [CARDINAL] = MACHINE CODE
    BEGIN
    -- c ← a + b;  IF c < a THEN c ← c + 1; IF c=177777B THEN c ← 0; 
    Mopcodes.zLI0;
    Mopcodes.zACD;
    Mopcodes.zADD;
    Mopcodes.zDUP;
    Mopcodes.zLIN1;
    Mopcodes.zJNEB, 3;
    Mopcodes.zINC;
    END;

  OnesSub: PROC[a, b: WORD] RETURNS [CARDINAL] = INLINE
    {RETURN[OnesAdd[a, Inline.BITNOT[b]]]};

  END.  -- ChecksumsImpl

LOG
17-May-84 10:21:03  AOF  Post Klamath
18-Aug-86 15:48:41  AOF  Trying to get back bytes for 14.0 BufferMgr
13-Aug-87 13:25:58  AOF  Computing increment checksums correctly