;Alto->8086 small-c compiler rev 2.0
C←CODE SEGMENT

$INCLUDE(8086LIB.D)

$INCLUDE(rpcpktio.DEC)

ASSUME CS:C←CODE, DS:C←DATA

; #include <Context.h>

; extern int /*BOOL*/ ReplyToRFA();

; extern SignalInitialize();

; extern int CallFailed;

; extern SendPup();

; extern WaitUntilSent();

; extern struct PBI *GetPBI();

; extern int GetPupHost(); /* returns machine, but can't declare that */

; extern InitPupLevel1();

; extern OpenLevel1Socket(/*lclPort, PortProc, queue*/);

; extern RequestRoute(/*net*/);

; extern InitCalendar(/*retries*/);

; extern int Min();

; extern int/*BOOL*/ MultEq();

; extern int/*BOOL*/ DoubleEq();

; extern ReleasePBI();

; extern int *Dequeue();

; extern Enqueue();

; extern InitQueue();

; extern SetTmr();

; extern int /*BOOL*/ TmrExp();

; extern Block();

; extern CurrentContext();

; extern int DoubleComp();

; extern int DoubleInc();

; extern Move2();

; extern StartNProcess();

; extern int *CallersFrame();

; extern MoveBlock();

; extern Zero();

; union Machine myHost;	/* net,,host */

; struct Queue *myCtxQ;

; int *mySoc;

; static struct CallCount callSequence;	/* pointer to CallCount generator */

; static int sent;	/* statistics */

; static int recvd;

; static int retransmitted;

; static int ReceivePktTooLong; /* SIGNAL */

; static int listenerRunning;	/* set false to abort listener */

; static int signalTimeout;	/* debugging: false to avoid transmission timeouts */

; static int maxTransmissions /* Normally a large constant; reduced during broadcasts. */

; struct Queue	idlerQ;

; static int idlers;	/* CARDINAL; -- number idle servers */

; static int wanting[maxPSBp1];	/* ARRAY PSB.PsbIndex OF BOOLEAN */

; static struct PBI *waiterPkts[maxPSBp1];	/* ARRAY PSB.PsbIndex OF BufferDefs.PupBuffer */

; static struct RPCCtx *contexts[maxPSBp1];	/* contexts corresp. to wanting, for debugging. */

; int broadcastRetransmissions;

; static int minRetransmitPulses; /* Must be set up in initialization code */

; static int minPingPulses;	/*  to above values in some reasonable tick */

; static int maxPingPulses;	/*  units. */

; int rpct;

; static Cl(sig, code, sl)
←Cl:

;   int sig, code, *sl;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   CleanUp(sl);

;	BX ← ←sl
POP BX
PUSH BX
CALL ←CleanUp

;   };
MOV SP,BP
POP BP
RET;

; int /* newLength: */

; PktExchange(inPkt, length, maxLength, state)
←PktExchange:

;   struct PBI *inPkt;

;   int length, maxLength, state;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   struct PBI *reply;

;   struct Seal1 s1, *sl;

;   struct Queue myQ;

;   int myPSB, acked, pingPulses;

;   struct RPCCtx *CtxRunning;

;   struct Header *header, *recvdHeader;

;   struct PktID thisPktID;

;   int newLength, pktLength;

;   int transmissions, retransmitPulses, pLen;

;   int /* BOOL */ isConv;

;   struct PBI *rp;
ADD SP,0FFD0X

;   sl = &s1; s1.data[0] = (int) &reply; reply=0;
;&←s1
LEA BX,[BP-12]

;	←sl ← BX
MOV [BP-14],BX
;&←reply
LEA BX,[BP-6]

;	←s1+4 ← BX
MOV [BP-8],BX
MOV WORD PTR [BP-6],0

;   DISABLE(sl);

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←DISABLE

;   CtxRunning = CurrentContext();
CALL ←CurrentContext

;	←CtxRunning ← BX
MOV [BP-26],BX

;   myPSB = CtxRunning->user.myPSB;

;	BX ← ←CtxRunning
MOV BX,[BP-26]
MOV CX,[BX+26]

;	←myPSB ← CX
MOV [BP-20],CX

;   header = inPkt->pup;

;	BX ← ←inPkt
MOV BX,[BP+6]
MOV CX,[BX+6]

;	←header ← CX
MOV [BP-28],CX

;   myQ.head = 0;
MOV WORD PTR [BP-18],0

;   inPkt->queue = &myQ;

;	BX ← ←inPkt
MOV BX,[BP+6]
;&←myQ
LEA CX,[BP-18]
MOV [BX+2],CX

;   InitQueue(&myQ);
;&←myQ
LEA BX,[BP-18]
CALL ←InitQueue

;   Enqueue(&myQ, inPkt);

;	BX ← ←inPkt
MOV BX,[BP+6]
;&←myQ
LEA CX,[BP-18]
CALL ←Enqueue

;   pingPulses = minPingPulses;
MOV BX,←minPingPulses

;	←pingPulses ← BX
MOV [BP-24],BX

;   header->srceHost.w = myHost.w;

;	BX ← ←header
MOV BX,[BP-28]
MOV CX,WORD PTR ←myHost
MOV [BX+14],CX

;   header->srceSoc.LS = rpcSocket;

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+19],01EX

;   header->srcePSB = myPSB;

;	BX ← ←header
MOV BX,[BP-28]

;	CX ← ←myPSB
MOV CX,[BP-20]
MOV [BX+6],CX

;   maxTransmissions = defaultMaxTransmissions;
MOV ←maxTransmissions,5

;   if (header->destHost.b.host == 0) {

;	BX ← ←header
MOV BX,[BP-28]
MOV AL,[BX+9]
OR AL,AL
JNZ X1

;     maxTransmissions = broadcastRetransmissions;
MOV BX,←broadcastRetransmissions
MOV ←maxTransmissions,BX

;     header->destSoc.LS = rpcBcstSocket;

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+13],025X

;     };
X1:

;   if (header->pktID.pktSeq == 0) {

;	BX ← ←header
MOV BX,[BP-28]
MOV CX,[BX+30]
OR CX,CX
JNZ X2

;     switch (state) {

;	BX ← ←state
MOV BX,[BP-4]
JR X3

;       case calling: header->type.fields = typeCall; break;
X5:

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+3],060X
JR X4

;       case authReq: header->type.fields = typeRFA; break;
X6:

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+3],064X
JR X4

;       default: SIGNAL(ERROR, 0);
X7:
XOR BX,BX
MOV CX,2
CALL ←SIGNAL

;       }; /* endCall */
JR X4
X3:
MOV AL,BH
OR AL,AL
JNZ X7
MOV AL,BL
CMP AL,2
JZ X5
CMP AL,4
JZ X6
JR X7
X4:

;     NewCallNumber(&header->pktID.callCt);

;	BX ← ←header
MOV BX,[BP-28]
ADD BX,01AX
CALL ←NewCallNumber

;     header->pktID.pktSeq=swapped1;

;	BX ← ←header
MOV BX,[BP-28]
MOV WORD PTR [BX+30],0100X

;     };

;   else {
JR X8
X2:

;     switch (state) {

;	BX ← ←state
MOV BX,[BP-4]
JR X9

;       case endCall: header->type.fields = typeData; break;
X11:

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+3],061X
JR X10

;       case calling: /* Subsequent call packets -- we don't do it. */
X12:

;       default: SIGNAL(ERROR, 0);
X13:
XOR BX,BX
MOV CX,2
CALL ←SIGNAL

;       }; /* authReq */
JR X10
X9:
MOV AL,BH
OR AL,AL
JNZ X13
MOV AL,BL
CMP AL,3
JZ X11
CMP AL,2
JZ X12
JR X13
X10:

;     header->pktID.pktSeq += swapped1;

;	BX ← ←header
MOV BX,[BP-28]
ADD WORD PTR [BX+30],0100X

;     };
X8:

;   acked=false;
MOV WORD PTR [BP-22],0

;   MoveBlock(&thisPktID, &header->pktID, lenPktID);
;&←thisPktID
LEA BX,[BP-38]
PUSH BX

;	BX ← ←header
MOV BX,[BP-28]
ADD BX,018X
PUSH BX
MOV BX,4
POP CX
CALL ←MoveBlock
POP DX

;   ENABLE(UNWIND, &Cl, sl);
MOV BX,1
PUSH BX

;	BX ← ←sl
MOV BX,[BP-14]
MOV CX,OFFSET ←Cl
CALL ←ENABLE
POP DX

;   for (;;) { /* loop for Pings */
X14:

;     transmissions = 0;
MOV WORD PTR [BP-44],0

;     retransmitPulses=minRetransmitPulses;
MOV BX,←minRetransmitPulses

;	←retransmitPulses ← BX
MOV [BP-46],BX

;     if (inPkt->convHandle != unencrypted)

;	BX ← ←inPkt
MOV BX,[BP+6]
MOV CX,[BX+4]
OR CX,CX
JZ X16

;       pLen = EncryptPkt(inPkt, length);

;	BX ← ←length
MOV BX,[BP+4]

;	CX ← ←inPkt
MOV CX,[BP+6]
CALL ←EncryptPkt

;	←pLen ← BX
MOV [BP-48],BX

;     else pLen = (length + pktLengthOverhead);
JR X17
X16:

;	BX ← ←length
MOV BX,[BP+4]
ADD BX,015X

;	←pLen ← BX
MOV [BP-48],BX
X17:

;     header->length = swab(pLen<< 1);

;	BX ← ←pLen
MOV BX,[BP-48]
SAL BX
CALL ←swab
MOV CX,BX

;	BX ← ←header
MOV BX,[BP-28]
MOV [BX],CX

;     for (;;) { /* loop for ReTransmissions */
X18:

;       SetWanting(myPSB);

;	BX ← ←myPSB
MOV BX,[BP-20]
CALL ←SetWanting

;       WaitUntilSent(inPkt);	/* make sure transmission's complete??? */

;	BX ← ←inPkt
MOV BX,[BP+6]
CALL ←WaitUntilSent

;       SendPup(inPkt);

;	BX ← ←inPkt
MOV BX,[BP+6]
CALL ←SendPup

;       sent += 1;
INC ←sent

;       for (;;) { /* loop for Receiving each incoming packet (including garbage) */
X20:

; SetWanting(myPSB);

;	BX ← ←myPSB
MOV BX,[BP-20]
CALL ←SetWanting

; reply = MyReceive(myPSB, ((acked)? pingPulses: retransmitPulses));

;	BX ← ←acked
MOV BX,[BP-22]
OR BX,BX
JZ X22

;	BX ← ←pingPulses
MOV BX,[BP-24]
JR X23
X22:

;	BX ← ←retransmitPulses
MOV BX,[BP-46]
X23:

;	CX ← ←myPSB
MOV CX,[BP-20]
CALL ←MyReceive

;	←reply ← BX
MOV [BP-6],BX

; if (reply == 0)

;	BX ← ←reply
MOV BX,[BP-6]
OR BX,BX
JNZ X24

; 	if (acked) goto Ping;

;	BX ← ←acked
MOV BX,[BP-22]
OR BX,BX
JZ X25
JMP ←Ping

; 	else { header->type.fields |= ackField; goto Retransmit; };
X25:

;	BX ← ←header
MOV BX,[BP-28]
OR BYTE PTR [BX+3],8
JMP ←Retransmit
X24:

; recvdHeader = reply->pup;

;	BX ← ←reply
MOV BX,[BP-6]
MOV CX,[BX+6]

;	←recvdHeader ← CX
MOV [BP-30],CX

; if ((recvdHeader->type.fields&classField) == rfa) {

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV AL,[BX+3]
AND AL,7
CMP AL,4
JNZ X26

;         rp=reply;

;	BX ← ←reply
MOV BX,[BP-6]

;	←rp ← BX
POP DX
PUSH BX

;         reply=0;
MOV WORD PTR [BP-6],0

; 	if (ReplyToRFA(rp, header /*encrypted*/,

; 	&thisPktID /*clear*/, inPkt->convHandle)) acked=acked;

;	BX ← ←rp
POP BX
PUSH BX
PUSH BX

;	BX ← ←header
MOV BX,[BP-28]
PUSH BX

;	BX ← ←inPkt
MOV BX,[BP+6]
MOV CX,[BX+4]
MOV BX,CX
;&←thisPktID
LEA CX,[BP-38]
CALL ←ReplyToRFA
ADD SP,4
OR BX,BX
JZ X27

;	BX ← ←acked
MOV BX,[BP-22]

;	←acked ← BX
MOV [BP-22],BX
X27:

; 	continue; };
JR X20
X26:

; isConv = swab(recvdHeader->srceHost.w ↑ header->destHost.w); /* comparison results */

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+14]

;	BX ← ←header
MOV BX,[BP-28]
MOV AX,[BX+8]
XOR CX,AX
MOV BX,CX
CALL ←swab

;	←isConv ← BX
MOV [BP-50],BX

; isConv = (isConv==0 || isConv==recvdHeader->srceHost.b.host); /* equal or near-equal */

;	BX ← ←isConv
MOV BX,[BP-50]
OR BX,BX
JZ X29

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV AL,[BX+15]
XOR AH,AH

;	BX ← ←isConv
MOV BX,[BP-50]
CMP BX,AX
X29:
X28:
JNZ X30
MOV BX,1
JR X31
X30:
XOR BX,BX
X31:

;	←isConv ← BX
MOV [BP-50],BX

; isConv = (DoubleEq(&recvdHeader->conv,&header->conv)  && isConv); /*our conv*/

;	BX ← ←recvdHeader
MOV BX,[BP-30]
ADD BX,014X

;	CX ← ←header
MOV CX,[BP-28]
ADD CX,014X
XCHG BX,CX
CALL ←DoubleEq
OR BX,BX
JZ X32

;	BX ← ←isConv
MOV BX,[BP-50]
OR BX,BX
X32:
JZ X33
MOV BX,1
JR X34
X33:
XOR BX,BX
X34:

;	←isConv ← BX
MOV [BP-50],BX

; if ((inPkt->convHandle != unencrypted) && isConv) {

;	BX ← ←inPkt
MOV BX,[BP+6]
MOV CX,[BX+4]
OR CX,CX
JZ X36

;	BX ← ←isConv
MOV BX,[BP-50]
OR BX,BX
X36:
JZ X35

; 	DecryptPkt(recvdHeader, inPkt->convHandle, &newLength);

;	BX ← ←recvdHeader
MOV BX,[BP-30]
PUSH BX

;	BX ← ←inPkt
MOV BX,[BP+6]
MOV CX,[BX+4]
;&←newLength
LEA BX,[BP-40]
CALL ←DecryptPkt
POP DX

; 	pktLength = newLength + pktLengthOverhead; }

;	BX ← ←newLength
MOV BX,[BP-40]
ADD BX,015X

;	←pktLength ← BX
MOV [BP-42],BX

; else {
JR X37
X35:

; 	pktLength = (swab(recvdHeader->length)) >> 1;

;	DI ← ←recvdHeader
MOV DI,[BP-30]
MOV BX,[DI]
CALL ←swab
SHR BX

;	←pktLength ← BX
MOV [BP-42],BX

; 	newLength = pktLength - pktLengthOverhead; };

;	BX ← ←pktLength
MOV BX,[BP-42]
ADD BX,0FFEBX

;	←newLength ← BX
MOV [BP-40],BX
X37:

; if (isConv && (recvdHeader->pktID.activity == thisPktID.activity))

;	BX ← ←isConv
MOV BX,[BP-50]
OR BX,BX
JZ X39

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+24]

;	BX ← ←thisPktID
MOV BX,[BP-38]
CMP CX,BX
JNZ X39
MOV AL,1
JR X40
X39:
XOR AL,AL
X40:
OR AL,AL
JZ X38

; 	if (DoubleEq(&recvdHeader->pktID.callCt, &thisPktID.callCt))

;	BX ← ←recvdHeader
MOV BX,[BP-30]
ADD BX,01AX
PUSH BX
;&←thisPktID
LEA BX,[BP-36]
POP CX
CALL ←DoubleEq
OR BX,BX
JZ X41

; 	    if (recvdHeader->pktID.pktSeq == swapped1+thisPktID.pktSeq) {

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+30]

;	BX ← ←thisPktID+6
MOV BX,[BP-32]
ADD BX,0100X
CMP CX,BX
JNZ X42

; 			if (state == endCall) /* he's not allowed to generate that pktSeq! */

;	BX ← ←state
MOV BX,[BP-4]
CMP BX,3
JNZ X43

; 	        	SIGNAL(CallFailed, runtimeProtocol);
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
X43:

; 			switch (recvdHeader->type.fields&classField) {

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV AL,[BX+3]
AND AL,7
JR X44

; 	        	case xtraData: break;
X46:
JR X45

; 	        	case ack: {
X47:

; 	        			acked = true;
MOV WORD PTR [BP-22],0FFFFX

; 	        			CleanUp(sl);

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←CleanUp

; 	        			continue; };
JMP X20

; 	        	default: SIGNAL(CallFailed, runtimeProtocol); }; /* call, rfa */
X48:
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
JR X45
X44:
CMP AL,1
JZ X46
CMP AL,2
JZ X47
JR X48
X45:

; 			goto Done; };
JMP ←Done

; 	    else if (recvdHeader->pktID.pktSeq == thisPktID.pktSeq) {
X42:

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+30]

;	BX ← ←thisPktID+6
MOV BX,[BP-32]
CMP CX,BX
JR $+5
X38:
JMP X50
JNZ X49

; 			switch (recvdHeader->type.fields&classField) {

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV AL,[BX+3]
AND AL,7
JR X51

; 				case ack:  { /* acknowledgement of our packet -- */
X53:

; 					if ((header->type.fields&classField) == call) header->destPSB = recvdHeader->srcePSB;

;	BX ← ←header
MOV BX,[BP-28]
JR $+5
X41:
JMP X55
MOV AL,[BX+3]
AND AL,7
OR AL,AL
JNZ X54

;	BX ← ←header
MOV BX,[BP-28]

;	CX ← ←recvdHeader
MOV CX,[BP-30]
MOV DI,CX
MOV CX,[DI+6]
MOV [BX+4],CX
X54:

; 					acked = true;
MOV WORD PTR [BP-22],0FFFFX

; 					if (state == endCall) { CleanUp(sl); goto Done; };

;	BX ← ←state
MOV BX,[BP-4]
CMP BX,3
JNZ X56

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←CleanUp
JMP ←Done

; 		  			else /* state = calling or authReq -- */
X56:

; 		  				CleanUp(sl);

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←CleanUp

; 		  			break; };
JR X52

; 	        	case xtraData: case call: /* retransmission of his packet;
X57:
X58:

; 	        	default: SIGNAL(CallFailed, runtimeProtocol); };
X59:
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
JR X52
X51:
CMP AL,2
JZ X53
CMP AL,1
JZ X57
CMP AL,0
JZ X58
JR X59
X52:

; 			};

; 	    else if (recvdHeader->pktID.pktSeq < thisPktID.pktSeq) CleanUp(sl); /* no need to ack it */
JR X60
X49:

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+30]

;	BX ← ←thisPktID+6
MOV BX,[BP-32]
CMP CX,BX
JGE X61

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←CleanUp

; 	    else SIGNAL(CallFailed, runtimeProtocol);
JR X62
X61:
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
X62:
X60:

; 	else
JR X63
X55:

; 		if (((DoubleComp(&recvdHeader->pktID.callCt, &thisPktID.callCt)+1) > 1) &&

; 			(state == endCall)) {

;	BX ← ←recvdHeader
MOV BX,[BP-30]
ADD BX,01AX
PUSH BX
;&←thisPktID
LEA BX,[BP-36]
POP CX
CALL ←DoubleComp
INC BX
CMP BX,1
JLE X65

;	BX ← ←state
MOV BX,[BP-4]
CMP BX,3
JNZ X65
MOV AL,1
JR X66
X65:
XOR AL,AL
X66:
OR AL,AL
JZ X64

; 		if ((recvdHeader->type.fields&classField) != call) SIGNAL(CallFailed, runtimeProtocol);

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV AL,[BX+3]
AND AL,7
OR AL,AL
JZ X67
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
X67:

; 	    goto Done; };
JMP ←Done

; 	else { /* wrong call; let someone else do it -- */
X64:

; 		recvdHeader->destPSB = nullPSB; EnqueueAgain(reply); reply=0; };

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV WORD PTR [BX+4],0

;	BX ← ←reply
MOV BX,[BP-6]
CALL ←EnqueueAgain
MOV WORD PTR [BP-6],0
X63:

; else { recvdHeader->destPSB = nullPSB; EnqueueAgain(reply); reply=0; };
JR X68
X50:

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV WORD PTR [BX+4],0

;	BX ← ←reply
MOV BX,[BP-6]
CALL ←EnqueueAgain
MOV WORD PTR [BP-6],0
X68:

;         }; /* endloop for each incoming packet */
JMP X20
X21:
←Retransmit:

;       Retransmit:

;         transmissions += 1;
INC WORD PTR [BP-44]

;         if ((transmissions == maxTransmissions) || state == authReq) {
MOV BX,←maxTransmissions

;	CX ← ←transmissions
MOV CX,[BP-44]
CMP CX,BX
JZ X71

;	BX ← ←state
MOV BX,[BP-4]
CMP BX,4
X71:
X70:
JNZ X69

;         if (signalTimeout) SIGNAL(CallFailed, timeout);
MOV BX,←signalTimeout
OR BX,BX
JZ X72
MOV BX,0DX
MOV CX,←CallFailed
CALL ←SIGNAL
X72:

;         transmissions = 0; retransmitPulses = minRetransmitPulses*maxTransmissions;
MOV WORD PTR [BP-44],0
MOV AX,←minRetransmitPulses
MOV BX,←maxTransmissions
IMUL AX,BX

;	←retransmitPulses ← AX
MOV [BP-46],AX

;         };
X69:

;       retransmitted += 1;
INC ←retransmitted

;       retransmitPulses += minRetransmitPulses;
MOV BX,←minRetransmitPulses
ADD [BP-46],BX

;       Block();
CALL ←Block

;       continue;
JMP X18

;       }; /* end loop for retransmissions */
X19:
←Ping:

;     Ping:

;       header->type.fields = typePing;

;	BX ← ←header
MOV BX,[BP-28]
MOV BYTE PTR [BX+3],06AX

;       length=0;
MOV WORD PTR [BP+4],0

;       MoveBlock(&header->pktID, &thisPktID, lenPktID);

;	BX ← ←header
MOV BX,[BP-28]
ADD BX,018X
PUSH BX
MOV BX,4
;&←thisPktID
LEA CX,[BP-38]
CALL ←MoveBlock
POP DX

;       acked=false;
MOV WORD PTR [BP-22],0

;       pingPulses = pingPulses*2;

;	BX ← ←pingPulses
MOV BX,[BP-24]
SAL BX

;	←pingPulses ← BX
MOV [BP-24],BX

;       if ( (pingPulses<0) || (pingPulses>maxPingPulses) ) pingPulses = maxPingPulses;

;	BX ← ←pingPulses
MOV BX,[BP-24]
CMP BX,0
JL X75
MOV BX,←maxPingPulses

;	CX ← ←pingPulses
MOV CX,[BP-24]
CMP CX,BX
JLE X74
X75:
MOV AL,1
JR X76
X74:
XOR AL,AL
X76:
OR AL,AL
JZ X73
MOV BX,←maxPingPulses

;	←pingPulses ← BX
MOV [BP-24],BX
X73:

;       Block();
CALL ←Block

;     }; /* end loop for pings -- */
JMP X14
X15:
←Done:

;   Done: {

;     ClearWanting(myPSB);

;	BX ← ←myPSB
MOV BX,[BP-20]
CALL ←ClearWanting

;     if (reply == 0) {

;	BX ← ←reply
MOV BX,[BP-6]
OR BX,BX
JNZ X77

;       MoveBlock(&header->pktID, &thisPktID, lenPktID);

;	BX ← ←header
MOV BX,[BP-28]
ADD BX,018X
PUSH BX
MOV BX,4
;&←thisPktID
LEA CX,[BP-38]
CALL ←MoveBlock
POP DX

;       return -1;
MOV BX,0FFFFX
MOV SP,BP
POP BP
RET;

;       };
X77:

;     if ((recvdHeader->callSpec.outcome == signal) ||

;       (newLength > maxLength)) SIGNAL(CallFailed, runtimeProtocol);

;	BX ← ←recvdHeader
MOV BX,[BP-30]
MOV CX,[BX+32]
MOV BX,CX
CMP BX,2
JZ X80

;	BX ← ←maxLength
MOV BX,[BP-2]

;	CX ← ←newLength
MOV CX,[BP-40]
CMP CX,BX
JLE X79
X80:
MOV AL,1
JR X81
X79:
XOR AL,AL
X81:
OR AL,AL
JZ X78
MOV BX,0FX
MOV CX,←CallFailed
CALL ←SIGNAL
X78:

;     MoveBlock(header, recvdHeader, pktLength);

;	BX ← ←header
MOV BX,[BP-28]
PUSH BX

;	BX ← ←pktLength
MOV BX,[BP-42]

;	CX ← ←recvdHeader
MOV CX,[BP-30]
CALL ←MoveBlock
POP DX

;     CleanUp(sl);

;	BX ← ←sl
MOV BX,[BP-14]
CALL ←CleanUp

;     Block();
CALL ←Block

;     return newLength;

;	BX ← ←newLength
MOV BX,[BP-40]
MOV SP,BP
POP BP
RET;

;     };

;   SIGNAL(ERROR, 0);
XOR BX,BX
MOV CX,2
CALL ←SIGNAL

;   };
MOV SP,BP
POP BP
RET;

; static CleanUp(sl)
←CleanUp:

;   struct Seal1 *sl;
PUSH BP
MOV BP,SP
PUSH BX

;   { /* UNWIND proc */

;   int myPSB, *lvReply;

;   struct RPCCtx *CtxRunning;
ADD SP,0FFFAX

;   CtxRunning = CurrentContext();
CALL ←CurrentContext

;	←CtxRunning ← BX
POP DX
PUSH BX

;   myPSB = CtxRunning->user.myPSB;

;	BX ← ←CtxRunning
POP BX
PUSH BX
MOV CX,[BX+26]

;	←myPSB ← CX
MOV [BP-4],CX

;   ClearWanting(myPSB);

;	BX ← ←myPSB
MOV BX,[BP-4]
CALL ←ClearWanting

;   lvReply = (int *) sl->data[0];

;	BX ← ←sl
MOV BX,[BP-2]
ADD BX,4
MOV CX,[BX]

;	←lvReply ← CX
MOV [BP-6],CX

;   if (*lvReply != 0) ReleasePBI(*lvReply);

;	DI ← ←lvReply
MOV DI,[BP-6]
MOV BX,[DI]
OR BX,BX
JZ X82

;	DI ← ←lvReply
MOV DI,[BP-6]
MOV BX,[DI]
CALL ←ReleasePBI
X82:

;   *lvReply=0;

;	BX ← ←lvReply
MOV BX,[BP-6]
MOV WORD PTR [BX],0

;   };
MOV SP,BP
POP BP
RET;

; static int NewCallNumber(lvResult)
←NewCallNumber:

;   struct CallCount *lvResult;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   DoubleInc(&callSequence, 1);
MOV BX,1
LEA CX,←callSequence
CALL ←DoubleInc

;   Move2(lvResult, &callSequence);
LEA BX,←callSequence

;	CX ← ←lvResult
POP CX
PUSH CX
CALL ←Move2

;   };
MOV SP,BP
POP BP
RET;

; static SetWanting(myPSB)
←SetWanting:

;   int myPSB;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   wanting[myPSB]=true;

;	BX ← ←myPSB
POP BX
PUSH BX
LEA CX,←wanting
SAL BX
ADD BX,CX
MOV WORD PTR [BX],0FFFFX

;   };
MOV SP,BP
POP BP
RET;

; static ClearWanting(myPSB)
←ClearWanting:

;   int myPSB;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   wanting[myPSB]=false;

;	BX ← ←myPSB
POP BX
PUSH BX
LEA CX,←wanting
SAL BX
ADD BX,CX
MOV WORD PTR [BX],0

;   if (waiterPkts[myPSB]) {

;	BX ← ←myPSB
POP BX
PUSH BX
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV CX,[BX]
OR CX,CX
JZ X83

;     ReleasePBI(waiterPkts[myPSB]);

;	BX ← ←myPSB
POP BX
PUSH BX
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV CX,[BX]
MOV BX,CX
CALL ←ReleasePBI

;     waiterPkts[myPSB] = 0;

;	BX ← ←myPSB
POP BX
PUSH BX
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV WORD PTR [BX],0

;     };
X83:

;   };
MOV SP,BP
POP BP
RET;

; static struct PBI *MyReceive(myPSB, waitTime)
←MyReceive:

;   int myPSB, waitTime;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   int timer;

;     struct PBI *recvd;
ADD SP,0FFFCX

;   timer=0;
MOV WORD PTR [BP-6],0

;   SetTmr(waitTime, &timer);	/* sentTime is implicit, if SetTimer called quickly enuf. */
;&←timer
LEA BX,[BP-6]

;	CX ← ←waitTime
MOV CX,[BP-4]
CALL ←SetTmr

;   for (;;) {
X84:

;     recvd = waiterPkts[myPSB];

;	BX ← ←myPSB
MOV BX,[BP-2]
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV CX,[BX]

;	←recvd ← CX
POP DX
PUSH CX

;     if (recvd) {

;	BX ← ←recvd
POP BX
PUSH BX
OR BX,BX
JZ X86

;       waiterPkts[myPSB] = 0;

;	BX ← ←myPSB
MOV BX,[BP-2]
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV WORD PTR [BX],0

;       return recvd;

;	BX ← ←recvd
POP BX
PUSH BX
MOV SP,BP
POP BP
RET;

;       };
X86:

;     if (TmrExp(&timer)) return 0;
;&←timer
LEA BX,[BP-6]
CALL ←TmrExp
OR BX,BX
JZ X87
XOR BX,BX
MOV SP,BP
POP BP
RET;
X87:

;     Block();
CALL ←Block

;     };
JR X84
X85:

;   };
MOV SP,BP
POP BP
RET;

; IdleReceive(pkt, maxLength)
←IdleReceive:

;   struct PBI *pkt;

;   int maxLength;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   struct PBI *b;

;   struct Header *recvdHeader;

;   int pktLength;
ADD SP,0FFFAX

;   idlers += 1;
INC ←idlers

;   while (idlerQ.head == 0) Block(); /* WAIT idlerCond */
X88:
MOV BX,WORD PTR ←idlerQ
OR BX,BX
JNZ X89
CALL ←Block
JR X88
X89:

;   b = (struct PBI *) Dequeue(&idlerQ);
LEA BX,←idlerQ
CALL ←Dequeue

;	←b ← BX
MOV [BP-6],BX

;   recvdHeader = b->pup;

;	BX ← ←b
MOV BX,[BP-6]
MOV CX,[BX+6]

;	←recvdHeader ← CX
MOV [BP-8],CX

;   pktLength = (swab(recvdHeader->length)) >> 1;

;	DI ← ←recvdHeader
MOV DI,[BP-8]
MOV BX,[DI]
CALL ←swab
SHR BX

;	←pktLength ← BX
POP DX
PUSH BX

;   if (pktLength <= maxLength) MoveBlock(pkt->pup, recvdHeader, pktLength);

;	BX ← ←maxLength
MOV BX,[BP-4]

;	CX ← ←pktLength
POP CX
PUSH CX
CMP CX,BX
JG X90

;	BX ← ←pkt
MOV BX,[BP-2]
MOV CX,[BX+6]
PUSH CX

;	BX ← ←pktLength
MOV BX,[BP-10]

;	CX ← ←recvdHeader
MOV CX,[BP-8]
CALL ←MoveBlock
POP DX
X90:

;   if (rpct) PutChar('i');
MOV BX,←rpct
OR BX,BX
JZ X91
MOV BX,069X
CALL ←PutChar
X91:

;   ReleasePBI(b);

;	BX ← ←b
MOV BX,[BP-6]
CALL ←ReleasePBI

;   if (pktLength > maxLength) SIGNAL(ReceivePktTooLong, 0);

;	BX ← ←maxLength
MOV BX,[BP-4]

;	CX ← ←pktLength
POP CX
PUSH CX
CMP CX,BX
JLE X92
XOR BX,BX
MOV CX,←ReceivePktTooLong
CALL ←SIGNAL
X92:

;   };
MOV SP,BP
POP BP
RET;

; int /*BOOL*/

; EnqueueRecvd(b)
←EnqueueRecvd:

;   struct PBI *b;
PUSH BP
MOV BP,SP
PUSH BX

;   { /* the main scheduler. */

;   struct Header *header;

;   int destPSB;
ADD SP,0FFFCX

;   header = b->pup;

;	BX ← ←b
MOV BX,[BP-2]
MOV CX,[BX+6]

;	←header ← CX
MOV [BP-4],CX

;   if (header->destHost.w != myHost.w) return false;

;	BX ← ←header
MOV BX,[BP-4]
MOV CX,[BX+8]
MOV BX,WORD PTR ←myHost
CMP CX,BX
JZ X93
XOR BX,BX
MOV SP,BP
POP BP
RET;
X93:

;   if ((header->type.fields&subtypeField) != rpc) return false;

;	BX ← ←header
MOV BX,[BP-4]
MOV AL,[BX+3]
AND AL,0E0X
CMP AL,060X
JZ X94
XOR BX,BX
MOV SP,BP
POP BP
RET;
X94:

;   if (((header->type.fields&classField)==call) &&

;     ((header->type.fields&ackField)!=0)) b=b;

;	BX ← ←header
MOV BX,[BP-4]
MOV AL,[BX+3]
AND AL,7
OR AL,AL
JNZ X96

;	BX ← ←header
MOV BX,[BP-4]
MOV AL,[BX+3]
AND AL,8
OR AL,AL
JZ X96
MOV AL,1
JR X97
X96:
XOR AL,AL
X97:
OR AL,AL
JZ X95

;	BX ← ←b
MOV BX,[BP-2]

;	←b ← BX
MOV [BP-2],BX
X95:

;   destPSB = header->destPSB;

;	BX ← ←header
MOV BX,[BP-4]
MOV CX,[BX+4]

;	←destPSB ← CX
POP DX
PUSH CX

;   recvd += 1;
INC ←recvd

;   if ((destPSB <= 0) || (destPSB > maxPSB) || (wanting[destPSB] == false)) {

;	BX ← ←destPSB
POP BX
PUSH BX
CMP BX,0
JLE X100

;	BX ← ←destPSB
POP BX
PUSH BX
CMP BX,0FX
JG X102

;	BX ← ←destPSB
POP BX
PUSH BX
LEA CX,←wanting
SAL BX
ADD BX,CX
MOV CX,[BX]
OR CX,CX
JNZ X101
X102:
MOV AL,1
JR X103
X101:
XOR AL,AL
X103:
OR AL,AL
JZ X99
X100:
MOV AL,1
JR X104
X99:
XOR AL,AL
X104:
OR AL,AL
JZ X98

;     if (idlers == 0) return false; /* server too busy, throw away */
MOV BX,←idlers
OR BX,BX
JNZ X105
XOR BX,BX
MOV SP,BP
POP BP
RET;
X105:

;     Enqueue(&idlerQ, b);

;	BX ← ←b
MOV BX,[BP-2]
LEA CX,←idlerQ
CALL ←Enqueue

;     if (rpct) PutChar('e');
MOV BX,←rpct
OR BX,BX
JZ X106
MOV BX,065X
CALL ←PutChar
X106:

;     idlers -= 1;
DEC ←idlers

;     };

;   else { /* someone wants this packet: give them it -- */
JR X107
X98:

;     if (waiterPkts[destPSB]) return false; /* two packets to same process! */

;	BX ← ←destPSB
POP BX
PUSH BX
LEA CX,←waiterPkts
SAL BX
ADD BX,CX
MOV CX,[BX]
OR CX,CX
JZ X108
XOR BX,BX
MOV SP,BP
POP BP
RET;
X108:

;     waiterPkts[destPSB]=b;

;	BX ← ←destPSB
POP BX
PUSH BX
LEA CX,←waiterPkts
SAL BX
ADD BX,CX

;	CX ← ←b
MOV CX,[BP-2]
MOV [BX],CX

;     if (rpct) PutChar('w');
MOV BX,←rpct
OR BX,BX
JZ X109
MOV BX,077X
CALL ←PutChar
X109:

;     };
X107:

;   return true;
MOV BX,0FFFFX
MOV SP,BP
POP BP
RET;

;   };

; EnqueueAgain(b)
←EnqueueAgain:

;   struct PBI *b;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   if (EnqueueRecvd(b) == false) {

;	BX ← ←b
POP BX
PUSH BX
CALL ←EnqueueRecvd
OR BX,BX
JNZ X110

;     ReleasePBI(b);

;	BX ← ←b
POP BX
PUSH BX
CALL ←ReleasePBI

;     if (rpct) PutChar('d');
MOV BX,←rpct
OR BX,BX
JZ X111
MOV BX,064X
CALL ←PutChar
X111:

;     };
X110:

;   };
MOV SP,BP
POP BP
RET;

; EnqueueBcst(b)
←EnqueueBcst:

;   struct PBI *b;
PUSH BP
MOV BP,SP
PUSH BX

;   { /* Incoming broadcast dispatcher. */

;   struct Header *header;

;   int destPSB;
ADD SP,0FFFCX

;   header = b->pup;

;	BX ← ←b
MOV BX,[BP-2]
MOV CX,[BX+6]

;	←header ← CX
MOV [BP-4],CX

;   header->destHost.b.host = myHost.b.host;

;	BX ← ←header
MOV BX,[BP-4]
MOV AX,WORD PTR ←myHost+1
MOV [BX+9],AL

;   header->destSoc.LS = rpcSocket;

;	BX ← ←header
MOV BX,[BP-4]
MOV BYTE PTR [BX+13],01EX

;   EnqueueAgain(b);

;	BX ← ←b
MOV BX,[BP-2]
CALL ←EnqueueAgain

;   };
MOV SP,BP
POP BP
RET;

; static int generator;

; int NewPSB(context)
←NewPSB:

;   struct RPCCtx *context;
PUSH BP
MOV BP,SP
PUSH BX

;   { /* generates non-null PSB unique to this epoch. */

;   if (++generator > maxPSB) SIGNAL(ERROR, 0);
INC ←generator
MOV BX,←generator
CMP BX,0FX
JLE X112
XOR BX,BX
MOV CX,2
CALL ←SIGNAL
X112:

;   contexts[generator] = context;
MOV BX,←generator
LEA CX,←contexts
SAL BX
ADD BX,CX

;	CX ← ←context
POP CX
PUSH CX
MOV [BX],CX

;   return generator;
MOV BX,←generator
MOV SP,BP
POP BP
RET;

;   };

; RPCInitialize(pCtxQ)
←RPCInitialize:

;   struct Queue *pCtxQ
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   listenerRunning = (signalTimeout = true);
MOV ←signalTimeout,0FFFFX
MOV ←listenerRunning,0FFFFX

;   minRetransmitPulses = minRetransmitMsecs;
MOV ←minRetransmitPulses,0FAX

;   minPingPulses = minPingMsecs;
MOV ←minPingPulses,01388X

;   maxPingPulses = maxPingSecs*1000;
MOV ←maxPingPulses,07530X

;   broadcastRetransmissions = 5;
MOV ←broadcastRetransmissions,5

;   myCtxQ=pCtxQ;

;	BX ← ←pCtxQ
POP BX
PUSH BX
MOV ←myCtxQ,BX

;   SignalInitialize();
CALL ←SignalInitialize

;   Zero(waiterPkts, maxPSB + 1);
MOV BX,010X
LEA CX,←waiterPkts
CALL ←Zero

;   Zero(wanting, maxPSB + 1);
MOV BX,010X
LEA CX,←wanting
CALL ←Zero

;   Zero(contexts, maxPSB + 1);
MOV BX,010X
LEA CX,←contexts
CALL ←Zero

;   ReceivePktTooLong = CODE();
CALL ←CODE
MOV ←ReceivePktTooLong,BX

;   };
MOV SP,BP
POP BP
RET;

; Externals Declared Here
PUBLIC ←myHost
PUBLIC ←myCtxQ
PUBLIC ←mySoc
PUBLIC ←idlerQ
PUBLIC ←broadcastRetransmissions
PUBLIC ←rpct
PUBLIC ←PktExchange
PUBLIC ←EnqueueAgain
PUBLIC ←IdleReceive
PUBLIC ←EnqueueRecvd
PUBLIC ←EnqueueBcst
PUBLIC ←NewPSB
PUBLIC ←RPCInitialize

C←CODE ENDS

; Number of Bytes of Code = 08A9X, (2217)