-- Copyright (C) 1987 by Xerox Corporation.  All rights reserved.
-- Stub file  was translated on February 13, 1987 6:01:58 pm PST by Lupine of February 22, 1986 5:15:54 pm PST
-- Source interface GPIB came from file GPIB.bcd, which was created on February 13, 1987 5:49:49 pm PST with version stamp 234#307#35204215357 from source of February 13, 1987 5:49:47 pm PST.

-- The RPC stub modules for GPIB are:
--   GPIBRpcControl.mesa;
--   GPIBRpcClientImpl.mesa;
--   GPIBRpcBinderImpl.mesa;
--   GPIBRpcServerImpl.mesa.

-- The parameters for this translation are:
--   Target language = Cedar
--   Default parameter passing = VALUE
--   Deallocate server heap arguments = TRUE
--   Inline RpcServerImpl dispatcher stubs = TRUE
--   Declare signals = TRUE
--   Warn about short POINTER ("MDS") allocations = TRUE
--   Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50
--   Acceptable parameter protocols = VersionRange[1..1].


DIRECTORY
  Rope,
  GPIB,
  GPIBRpcControl USING [InterMdsCallsOnly, LupineProtocolVersion, ProcedureIndex,
      SignalIndex],
  RPC USING [EncryptionKey, InterfaceName, Principal, standardZones,
      Zones],
  RPCLupine --USING SOME OF [Call, DataLength, Dispatcher, ExportHandle,
      -- ExportInterface, GetStubPkt, maxDataLength, maxPrincipalLength,
      -- maxShortStringLength, pktOverhead, ReceiveExtraPkt, SendPrelimPkt,
      -- StartCall, StartSignal, StubPkt, UnexportInterface]--,
  LupineRuntime --USING SOME OF [BindingError, CheckPktLength, CopyFromPkt,
      -- CopyFromMultiplePkts, CopyToPkt, CopyToMultiplePkts, defaultZones,
      -- DispatchingError, FinishThisPkt, ListHeader, MarshalingError,
      -- MarshalingExprError, MarshalAtom, MarshalRope, NilHeader, ProtocolError,
      -- RopeHeader, RpcPktDoubleWord, RuntimeError, SequenceHeader, SHORT,
      -- StartNextPkt, StringHeader, StubPktDoubleWord, TranslationError,
      -- UnmarshalingError, UnmarshalingExprError, UnmarshalAtom, UnmarshalRope,
      -- WordsForChars]--,
  Atom --USING SOME OF [GetPName, MakeAtom]--;


GPIBRpcServerImpl: MONITOR
  IMPORTS GPIB, RpcPrivate: RPCLupine, Lupine: LupineRuntime, Atom,
      Rope
  EXPORTS GPIBRpcControl
  SHARES  GPIB, GPIBRpcControl, Rope
  = BEGIN OPEN GPIB, RpcControl: GPIBRpcControl, RpcPublic: RPC;


-- Standard remote binding routines.

  bound: BOOLEAN ← FALSE;
  myInterface: RpcPrivate.ExportHandle;
  paramZones: RpcPublic.Zones ← RpcPublic.standardZones;

  ExportInterface: PUBLIC ENTRY SAFE PROCEDURE [
        interfaceName: RpcPublic.InterfaceName,
        user: RpcPublic.Principal,
        password: RpcPublic.EncryptionKey,
        parameterStorage: RpcPublic.Zones ] =
    TRUSTED BEGIN ENABLE UNWIND => NULL;
    IsNull: PROCEDURE [string: Rope.ROPE] RETURNS [BOOLEAN] =
      INLINE {RETURN[string.Length[] = 0]};
    IF bound THEN Lupine.BindingError;
    myInterface ← RpcPrivate.ExportInterface [
      interface: [
        type: IF ~IsNull[interfaceName.type]
          THEN interfaceName.type ELSE "GPIB~234#307#35204215357",
        instance: interfaceName.instance,
        version: interfaceName.version ],
      user: user,  password: password,
      dispatcher: ServerDispatcher,
      localOnly: RpcControl.InterMdsCallsOnly,
      stubProtocol: RpcControl.LupineProtocolVersion ];
    paramZones ← [
      gc: IF parameterStorage.gc # NIL
        THEN parameterStorage.gc ELSE Lupine.defaultZones.gc,
      heap: IF parameterStorage.heap # NIL
        THEN parameterStorage.heap ELSE Lupine.defaultZones.heap,
      mds: IF parameterStorage.mds # NIL
        THEN parameterStorage.mds ELSE Lupine.defaultZones.mds ];
    bound ← TRUE;
    END;

  UnexportInterface: PUBLIC ENTRY SAFE PROCEDURE =
    TRUSTED BEGIN ENABLE UNWIND => NULL;
    IF ~bound THEN Lupine.BindingError;
    myInterface ← RpcPrivate.UnexportInterface[myInterface];
    paramZones ← RpcPublic.standardZones;
    bound ← FALSE;
    END;


-- Public procedure dispatcher and public signal and error catcher.

  ServerDispatcher: --PROCEDURE [pkt: RPCPkt, callLength: DataLength,
      -- lastPkt: BOOLEAN, localConversation: Conversation] RETURNS [returnLength:
      -- DataLength]-- RpcPrivate.Dispatcher =
    BEGIN

    -- Catch public signals.

      ENABLE BEGIN

      END;  -- Catch public signals.


    -- Call public procedures (still in dispatcher).

    SELECT LOOPHOLE[pkt.data[0], RpcControl.ProcedureIndex] FROM
      Command => RETURN[
        CommandStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,
            localConversation: localConversation]];
      DevicesClear => RETURN[
        DevicesClearStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      GoToLocal => RETURN[
        GoToLocalStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,
            localConversation: localConversation]];
      GroupExecuteTrigger => RETURN[
        GroupExecuteTriggerStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      InterfaceClear => RETURN[
        InterfaceClearStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      LocalLockout => RETURN[
        LocalLockoutStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      RemoteEnable => RETURN[
        RemoteEnableStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      SelectedDeviceClear => RETURN[
        SelectedDeviceClearStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      SelectedGoToLocal => RETURN[
        SelectedGoToLocalStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      SelectedGroupEnableTrigger => RETURN[
        SelectedGroupEnableTriggerStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      SelectedRemoteEnable => RETURN[
        SelectedRemoteEnableStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      ParallelPollConfigure => RETURN[
        ParallelPollConfigureStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      ParallelPollUnconfigure => RETURN[
        ParallelPollUnconfigureStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      SelectedParallelPollConfigure => RETURN[
        SelectedParallelPollConfigureStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      SelectedParallelPollUnconfigure => RETURN[
        SelectedParallelPollUnconfigureStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      PollDevice => RETURN[
        PollDeviceStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,
            localConversation: localConversation]];
      ReadDevice => RETURN[
        ReadDeviceStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,
            localConversation: localConversation]];
      ReadOnInterrupt => RETURN[
        ReadOnInterruptStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      SelectedReadSerialPoll => RETURN[
        SelectedReadSerialPollStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      ReadStatusByte => RETURN[
        ReadStatusByteStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      WriteDevice => RETURN[
        WriteDeviceStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      WriteDeviceBuffered => RETURN[
        WriteDeviceBufferedStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      InitializeController => RETURN[
        InitializeControllerStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      FinalizeController => RETURN[
        FinalizeControllerStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      SRQAsserted => RETURN[
        SRQAssertedStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      WriteDeviceInitial => RETURN[
        WriteDeviceInitialStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      WriteDeviceContinued => RETURN[
        WriteDeviceContinuedStub[pkt: pkt, callLength: callLength,
            lastPkt: lastPkt, localConversation: localConversation]];
      WriteDeviceBlock => RETURN[
        WriteDeviceBlockStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      WriteDMABlock => RETURN[
        WriteDMABlockStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      ReadDeviceInitial => RETURN[
        ReadDeviceInitialStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      ReadDMABlock => RETURN[
        ReadDMABlockStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      ReadDMADone => RETURN[
        ReadDMADoneStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      CheckDMADone => RETURN[
        CheckDMADoneStub[pkt: pkt, callLength: callLength, lastPkt:
            lastPkt, localConversation: localConversation]];
      ENDCASE => RETURN[Lupine.DispatchingError[]];

    END;  -- ServerDispatcher


-- Public procedure dispatcher stubs.

  CommandStub: --PROCEDURE [sendMsg: Rope.ROPE]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    sendMsg: Rope.ROPE;
    pktLength: RpcPrivate.DataLength ← 1;
    BEGIN  -- Unmarshal sendMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN sendMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          sendMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal sendMsg.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    Command[sendMsg];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- CommandStub.

  DevicesClearStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    DevicesClear[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- DevicesClearStub.

  GoToLocalStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    GoToLocal[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- GoToLocalStub.

  GroupExecuteTriggerStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    GroupExecuteTrigger[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- GroupExecuteTriggerStub.

  InterfaceClearStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    InterfaceClear[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- InterfaceClearStub.

  LocalLockoutStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    LocalLockout[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- LocalLockoutStub.

  RemoteEnableStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    RemoteEnable[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- RemoteEnableStub.

  SelectedDeviceClearStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedDeviceClear[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedDeviceClearStub.

  SelectedGoToLocalStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedGoToLocal[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedGoToLocalStub.

  SelectedGroupEnableTriggerStub: --PROCEDURE [device: DeviceAddr]--
      RpcPrivate.Dispatcher =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedGroupEnableTrigger[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedGroupEnableTriggerStub.

  SelectedRemoteEnableStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedRemoteEnable[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedRemoteEnableStub.

  ParallelPollConfigureStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    ParallelPollConfigure[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- ParallelPollConfigureStub.

  ParallelPollUnconfigureStub: --PROCEDURE-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    ParallelPollUnconfigure[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- ParallelPollUnconfigureStub.

  SelectedParallelPollConfigureStub: --PROCEDURE [device: DeviceAddr]--
      RpcPrivate.Dispatcher =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedParallelPollConfigure[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedParallelPollConfigureStub.

  SelectedParallelPollUnconfigureStub: --PROCEDURE [device: DeviceAddr]--
      RpcPrivate.Dispatcher =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    SelectedParallelPollUnconfigure[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- SelectedParallelPollUnconfigureStub.

  PollDeviceStub: --PROCEDURE [device: DeviceAddr, labels: SRQLabels]--
      RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    labels: SRQLabels;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 2;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal labels: SRQLabels from pkt.data[pktLength].
      FOR element1: StatusFlag IN StatusFlag DO
        BEGIN  -- Unmarshal labels[element1]: Rope.ROPE from pkt.data[pktLength].
          ropeIsNIL: Lupine.NilHeader;
          IF pktLength+2 > RpcPrivate.maxDataLength
            THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
                pktLength];
          ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeIsNIL
            THEN labels[element1] ← NIL
            ELSE BEGIN
              ropeLength: Lupine.RopeHeader;
              textRope: Rope.Text;
              ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
              IF ropeLength > LAST[NAT]
                THEN Lupine.UnmarshalingError;
              labels[element1] ← textRope ← Rope.NewText[size: ropeLength];
              pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
                  dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength:
                  Lupine.WordsForChars[ropeLength], alwaysOnePkt: FALSE];
              END;  -- IF ropeIsNIL.
          END;  -- Unmarshal labels[element1].
        ENDLOOP;  -- FOR element1.
      END;  -- Unmarshal labels.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN PollDevice[argPkt.device, labels]
      ELSE PollDevice[device, labels];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- PollDeviceStub.

  ReadDeviceStub: --PROCEDURE [device: DeviceAddr, terminator: Terminator]
      -- RETURNS [recvMsg: Rope.ROPE, end: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    recvMsg: Rope.ROPE;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        terminator (2): Terminator];
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        end (0): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 3];
    [recvMsg, resPkt.end] ←
      ReadDevice[argPkt.device, argPkt.terminator];
    pktLength ← 1;
    BEGIN  -- Marshal recvMsg: Rope.ROPE to pkt.data[pktLength].
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.StartNextPkt[pkt: pkt, pktLength: pktLength];
      pkt.data[pktLength] ← recvMsg=NIL;  pktLength ← pktLength+1;
      IF recvMsg # NIL
        THEN BEGIN
          textRope: Rope.Text = Rope.InlineFlatten[r: recvMsg];
          pkt.data[pktLength] ← textRope.length;  pktLength ← pktLength+1;
          pktLength ← Lupine.CopyToPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[textRope.length],
              alwaysOnePkt: FALSE];
          END;  -- IF recvMsg # NIL.
      END;  -- Marshal recvMsg.
    RETURN[returnLength: pktLength];
    END;  -- ReadDeviceStub.

  ReadOnInterruptStub: --PROCEDURE [device: DeviceAddr, recvMsg: Rope.ROPE,
      -- labels: SRQLabels]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    recvMsg: Rope.ROPE;
    labels: SRQLabels;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 2;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal recvMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN recvMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          recvMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal recvMsg.
    BEGIN  -- Unmarshal labels: SRQLabels from pkt.data[pktLength].
      FOR element1: StatusFlag IN StatusFlag DO
        BEGIN  -- Unmarshal labels[element1]: Rope.ROPE from pkt.data[pktLength].
          ropeIsNIL: Lupine.NilHeader;
          IF pktLength+2 > RpcPrivate.maxDataLength
            THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
                pktLength];
          ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeIsNIL
            THEN labels[element1] ← NIL
            ELSE BEGIN
              ropeLength: Lupine.RopeHeader;
              textRope: Rope.Text;
              ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
              IF ropeLength > LAST[NAT]
                THEN Lupine.UnmarshalingError;
              labels[element1] ← textRope ← Rope.NewText[size: ropeLength];
              pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
                  dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength:
                  Lupine.WordsForChars[ropeLength], alwaysOnePkt: FALSE];
              END;  -- IF ropeIsNIL.
          END;  -- Unmarshal labels[element1].
        ENDLOOP;  -- FOR element1.
      END;  -- Unmarshal labels.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN ReadOnInterrupt[argPkt.device, recvMsg, labels]
      ELSE ReadOnInterrupt[device, recvMsg, labels];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- ReadOnInterruptStub.

  SelectedReadSerialPollStub: --PROCEDURE [device: DeviceAddr] RETURNS
      -- [statusByte: CHAR]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        statusByte (0): CHAR];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    [resPkt.statusByte] ← SelectedReadSerialPoll[argPkt.device];
    pktLength ← 1;
    RETURN[returnLength: pktLength];
    END;  -- SelectedReadSerialPollStub.

  ReadStatusByteStub: --PROCEDURE [device: DeviceAddr] RETURNS [char:
      -- CHAR]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        char (0): CHAR];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    [resPkt.char] ← ReadStatusByte[argPkt.device];
    pktLength ← 1;
    RETURN[returnLength: pktLength];
    END;  -- ReadStatusByteStub.

  WriteDeviceStub: --PROCEDURE [device: DeviceAddr, sendMsg: Rope.ROPE]--
      RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    sendMsg: Rope.ROPE;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 2;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal sendMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN sendMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          sendMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal sendMsg.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN WriteDevice[argPkt.device, sendMsg]
      ELSE WriteDevice[device, sendMsg];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- WriteDeviceStub.

  WriteDeviceBufferedStub: --PROCEDURE [device: DeviceAddr, sendMsg:
      -- Rope.ROPE, hold: BOOL]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    sendMsg: Rope.ROPE;
    hold: BOOL;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        hold (2): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 3;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device, hold: hold] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal sendMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN sendMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          sendMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal sendMsg.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN WriteDeviceBuffered[argPkt.device, sendMsg, argPkt.hold]
      ELSE WriteDeviceBuffered[device, sendMsg, hold];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- WriteDeviceBufferedStub.

  InitializeControllerStub: --PROCEDURE RETURNS [open: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        open (0): BOOL];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    [resPkt.open] ← InitializeController[];
    pktLength ← 1;
    RETURN[returnLength: pktLength];
    END;  -- InitializeControllerStub.

  FinalizeControllerStub: --PROCEDURE-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    FinalizeController[];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- FinalizeControllerStub.

  SRQAssertedStub: --PROCEDURE RETURNS [asserted: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        asserted (0): BOOL];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    [resPkt.asserted] ← SRQAsserted[];
    pktLength ← 1;
    RETURN[returnLength: pktLength];
    END;  -- SRQAssertedStub.

  WriteDeviceInitialStub: --PROCEDURE [device: DeviceAddr, sendMsg:
      -- Rope.ROPE]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    sendMsg: Rope.ROPE;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 2;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal sendMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN sendMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          sendMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal sendMsg.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN WriteDeviceInitial[argPkt.device, sendMsg]
      ELSE WriteDeviceInitial[device, sendMsg];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- WriteDeviceInitialStub.

  WriteDeviceContinuedStub: --PROCEDURE [device: DeviceAddr, sendMsg:
      -- Rope.ROPE, last: BOOL]-- RpcPrivate.Dispatcher =
    INLINE BEGIN
    device: DeviceAddr;
    sendMsg: Rope.ROPE;
    last: BOOL;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        last (2): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 3;
    BEGIN  -- OnePkt.
    onePkt: BOOLEAN = lastPkt;
    IF ~onePkt THEN BEGIN  -- Must move statics from pkt now.
      [device: device, last: last] ← argPkt↑;
      END;
    BEGIN  -- Unmarshal sendMsg: Rope.ROPE from pkt.data[pktLength].
      ropeIsNIL: Lupine.NilHeader;
      IF pktLength+2 > RpcPrivate.maxDataLength
        THEN pktLength ← Lupine.FinishThisPkt[pkt: pkt, pktLength:
            pktLength];
      ropeIsNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
      IF ropeIsNIL
        THEN sendMsg ← NIL
        ELSE BEGIN
          ropeLength: Lupine.RopeHeader;
          textRope: Rope.Text;
          ropeLength ← pkt.data[pktLength];  pktLength ← pktLength+1;
          IF ropeLength > LAST[NAT]
            THEN Lupine.UnmarshalingError;
          sendMsg ← textRope ← Rope.NewText[size: ropeLength];
          pktLength ← Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,
              dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],
              alwaysOnePkt: FALSE];
          END;  -- IF ropeIsNIL.
      END;  -- Unmarshal sendMsg.
    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
    IF onePkt
      THEN WriteDeviceContinued[argPkt.device, sendMsg, argPkt.last]
      ELSE WriteDeviceContinued[device, sendMsg, last];
    END;  -- OnePkt.
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- WriteDeviceContinuedStub.

  WriteDeviceBlockStub: --PROCEDURE [device: DeviceAddr, lp: LONG POINTER
      -- TO WORD, quadWordCnt: CARDINAL, last: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    lp: LONG POINTER TO WORD;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        quadWordCnt (2): CARDINAL, last (3): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 4;
    MaxHeapAllocs: CARDINAL = 1;
    heapAllocVector: ARRAY [1..MaxHeapAllocs] OF LONG POINTER←ALL[NIL];
    BEGIN ENABLE UNWIND => BEGIN  -- Free storage.
        FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
          IF heapAllocVector[ptr] = NIL THEN EXIT;
          paramZones.heap.FREE[@heapAllocVector[ptr]];
          ENDLOOP;
        END;  -- Free storage.
      BEGIN  -- Unmarshal lp: LONG POINTER TO WORD from pkt.data[pktLength].
        isNIL: Lupine.NilHeader;
        isNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
        IF isNIL
          THEN lp ← NIL
          ELSE BEGIN
            lp ← (heapAllocVector[1] ← paramZones.heap.NEW[WORD]);
            BEGIN
            lp↑ ← pkt.data[pktLength];  pktLength ← pktLength+1;
            END;
            END;  -- IF isNIL.
        END;  -- Unmarshal lp.
      Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
      WriteDeviceBlock[argPkt.device, lp, argPkt.quadWordCnt, argPkt.last];
      pktLength ← 0;
      END;  -- ENABLE UNWIND => Free storage.
    FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
      IF heapAllocVector[ptr] = NIL THEN EXIT;
      paramZones.heap.FREE[@heapAllocVector[ptr]];
      ENDLOOP;
    RETURN[returnLength: pktLength];
    END;  -- WriteDeviceBlockStub.

  WriteDMABlockStub: --PROCEDURE [device: DeviceAddr, multiBusAddress:
      -- LONG POINTER TO WORD, byteCnt: CARDINAL, last: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    multiBusAddress: LONG POINTER TO WORD;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        byteCnt (2): CARDINAL, last (3): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 4;
    MaxHeapAllocs: CARDINAL = 1;
    heapAllocVector: ARRAY [1..MaxHeapAllocs] OF LONG POINTER←ALL[NIL];
    BEGIN ENABLE UNWIND => BEGIN  -- Free storage.
        FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
          IF heapAllocVector[ptr] = NIL THEN EXIT;
          paramZones.heap.FREE[@heapAllocVector[ptr]];
          ENDLOOP;
        END;  -- Free storage.
      BEGIN  -- Unmarshal multiBusAddress: LONG POINTER TO WORD from
          -- pkt.data[pktLength].
        isNIL: Lupine.NilHeader;
        isNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
        IF isNIL
          THEN multiBusAddress ← NIL
          ELSE BEGIN
            multiBusAddress ← (heapAllocVector[1] ← paramZones.heap.NEW[WORD]);
            BEGIN
            multiBusAddress↑ ← pkt.data[pktLength];  pktLength ← pktLength+1;
            END;
            END;  -- IF isNIL.
        END;  -- Unmarshal multiBusAddress.
      Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
      WriteDMABlock[argPkt.device, multiBusAddress, argPkt.byteCnt,
          argPkt.last];
      pktLength ← 0;
      END;  -- ENABLE UNWIND => Free storage.
    FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
      IF heapAllocVector[ptr] = NIL THEN EXIT;
      paramZones.heap.FREE[@heapAllocVector[ptr]];
      ENDLOOP;
    RETURN[returnLength: pktLength];
    END;  -- WriteDMABlockStub.

  ReadDeviceInitialStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    ReadDeviceInitial[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- ReadDeviceInitialStub.

  ReadDMABlockStub: --PROCEDURE [device: DeviceAddr, multiBusAddress:
      -- LONG POINTER TO WORD, byteCnt: CARDINAL, last: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    multiBusAddress: LONG POINTER TO WORD;
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr,
        byteCnt (2): CARDINAL, last (3): BOOL];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength ← 4;
    MaxHeapAllocs: CARDINAL = 1;
    heapAllocVector: ARRAY [1..MaxHeapAllocs] OF LONG POINTER←ALL[NIL];
    BEGIN ENABLE UNWIND => BEGIN  -- Free storage.
        FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
          IF heapAllocVector[ptr] = NIL THEN EXIT;
          paramZones.heap.FREE[@heapAllocVector[ptr]];
          ENDLOOP;
        END;  -- Free storage.
      BEGIN  -- Unmarshal multiBusAddress: LONG POINTER TO WORD from
          -- pkt.data[pktLength].
        isNIL: Lupine.NilHeader;
        isNIL ← pkt.data[pktLength];  pktLength ← pktLength+1;
        IF isNIL
          THEN multiBusAddress ← NIL
          ELSE BEGIN
            multiBusAddress ← (heapAllocVector[1] ← paramZones.heap.NEW[WORD]);
            BEGIN
            multiBusAddress↑ ← pkt.data[pktLength];  pktLength ← pktLength+1;
            END;
            END;  -- IF isNIL.
        END;  -- Unmarshal multiBusAddress.
      Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];
      ReadDMABlock[argPkt.device, multiBusAddress, argPkt.byteCnt,
          argPkt.last];
      pktLength ← 0;
      END;  -- ENABLE UNWIND => Free storage.
    FOR ptr: CARDINAL IN [1..LENGTH[heapAllocVector]] DO
      IF heapAllocVector[ptr] = NIL THEN EXIT;
      paramZones.heap.FREE[@heapAllocVector[ptr]];
      ENDLOOP;
    RETURN[returnLength: pktLength];
    END;  -- ReadDMABlockStub.

  ReadDMADoneStub: --PROCEDURE [device: DeviceAddr]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
        transferIndex (0): RpcControl.ProcedureIndex, device (1): DeviceAddr];
    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];
    ReadDMADone[argPkt.device];
    pktLength ← 0;
    RETURN[returnLength: pktLength];
    END;  -- ReadDMADoneStub.

  CheckDMADoneStub: --PROCEDURE RETURNS [anonP1id4481431: BOOL]-- RpcPrivate.Dispatcher
      =
    INLINE BEGIN
    ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [
        anonP1id4481431 (0): BOOL];
    resPkt: LONG POINTER TO ResultOverlay = @pkt.data[0];
    pktLength: RpcPrivate.DataLength;
    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];
    [resPkt.anonP1id4481431] ← CheckDMADone[];
    pktLength ← 1;
    RETURN[returnLength: pktLength];
    END;  -- CheckDMADoneStub.


-- No module initialization.

END.  -- GPIBRpcServerImpl.