perm filename MSSNGR.SAI[AID,HE] blob sn#378664 filedate 1978-09-06 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY
C00004 00003	!  Notes from 10 to 11
C00006 00004	!  INIT, PEEK, POKE, PEEKARRAY, POKEARRAY
C00014 00005	!  GETNOTE, SNDNOTE, SNDN1
C00017 00006	REAL PROCEDURE RFVAL(INTEGER WORD1,WORD2)
C00019 00007	INTERNAL PROCEDURE EVAL(INTEGER ARRAY REQ INTEGER REQLENGTH
C00026 ENDMK
C⊗;
ENTRY;

BEGIN "MSSNGR"

REQUIRE "ABBREV.SAI[AL,HE]" SOURCE_FILE;

! This program is going to be used as a replacement for the more elegant program
ALAID(.SAI) for strict two-way question-answer communication between a program on
the pdp-10 which should use MSSNGR as a load module (e.g. the current AL run time
debugger DEBAL) and another communicating program on the pdp-11 (e.g. ALAID(.PAL)
currently a member of the AL run time system). ;



    PROCEDURE COMERR
      (STRING MESSG;RECORD_POINTER(ANY_CLASS) CONTXT (NULL_RECORD));
        !  Non-fatal warnings;
        BEGIN
        USERERR(0,1,"HAH!  "&MESSG);
        END;

!  Notes from 10 to 11;
DEFINE GETBUF = '1;
DEFINE USEBUF = '2;
DEFINE RELBUF = '3;

!  Notes from 11 to 10;
DEFINE BUFALC = '101;
DEFINE TAKBUF = '102;

!  Offsets in message buffers;
DEFINE MESID = 0;
DEFINE MESTYP = 2;
    DEFINE FROMTEN = '1;
    DEFINE FROMELF = '2;
    DEFINE REQUEST = '4;
    DEFINE RESPONSE = '10;
DEFINE MESLTH = 4;
DEFINE MESBEG = 6;

INTEGER MSGNO;  !  Always even, numbers the last message originating at the 10;

DEFINE MAP_OFFSET = "'320000";  ! Converts virtual addresses to physical ones;
DEFINE NOTB10 = "'160000";  ! The notebox from 11 to the 10 (byte address);
DEFINE NOTB11 = "'160020";  ! The notebox from 10 to the 11 (byte address);
DEFINE NOTSIZ = "3"; ! In WORDS!;

! DEFINE OUTTST = "OUTSTR";
  DEFINE OUTTST = "! ";

INTEGER BRCHAR;	 ! Break character;

!  Sources:;
DEFINE USER = 1;
DEFINE ELFIE = 2;
!  INIT, PEEK, POKE, PEEKARRAY, POKEARRAY;

INTEGER ELFCHAN;  !  Channel number for I/O to ELF;

INTERNAL PROCEDURE INIT;
    BEGIN "init" 
    INTEGER COUNT, BRCHAR, EOF, FLAG;
    OWN BOOLEAN ONCE; comment INITIALIZE(ONCE←FALSE);

    !  Only allow one initialization;
    IF ONCE 
    THEN BEGIN
        COMERR("INIT called more than once; it initializes itself now.");
        RETURN
        END
    ELSE ONCE ← TRUE;

    !  Initialize the ELF for output;
    ELFCHAN ← GETCHAN;
    OPEN(ELFCHAN,"ELF",'17,0,0,COUNT,BRCHAR,EOF);
    END "init";

REQUIRE INIT INITIALIZATION[0];

DEFINE MTAPE = "'072000";

INTEGER PROCEDURE PEEK(INTEGER ADR);
    BEGIN "peek"  !  Returns the ELF word at unibus address ADR;
    DEFINE PEEK = "'002000000000";
    LABEL PEK1, PEKMTA, PEK3, PEK4, PEK5;
    INTEGER ANS, ADR1;
    ADR1 ← ADR;

    START_CODE;
	MOVE	1,ADR1   	; !  Prepare MTAPE data in PEK1;
	LSH	1,-1    	;
	HRRM	1,PEK1   	;
	MOVE	1,ELFCHAN	; !  Prepare MTAPE in PEKMTA;
	LSH	1,5	    	;
	ADDI	1,MTAPE 	;
	HRLM	1,PEKMTA   	;
    PEKMTA:
	PEK1             	; !  This will become MTAPE ELFCHAN,PEK1;
	JRST PEK3        	; !  Error;
	JRST PEK4        	; !  OK;
    PEK1:
	PEEK    		;
    PEK5:
	0       		;
    PEK3:
	SETOM   PEK5     	; ! Error result;
    PEK4:
	MOVE    1,PEK5   	;
	MOVEM	1,ANS	   	;
    END;

    IF ANS = -1 THEN COMERR("Couldn't peek at ELF");
    RETURN(ANS);
    END "peek";

PROCEDURE POKE(INTEGER ADR, CONTENTS);
    BEGIN "poke"  !  Stores CONTENTS at unibus address ADR;
    DEFINE POKE = "'003000000000";
    LABEL POK1, POKMTA, POK3, POK4, POK5;
    INTEGER ANS, ADR1, CNTS;

    ADR1 ← ADR;
    CNTS ← CONTENTS;

    START_CODE;
	MOVE	1,ADR1   	; !  Prepare MTAPE data in POK1;
	LSH	1,-1    	;
	HRRM	1,POK1   	;
	MOVE	1,ELFCHAN	; !  Prepare MTAPE in POKMTA;
	LSH	1,5     	;
	ADDI	1,MTAPE 	;
	HRLM	1,POKMTA   	;
	MOVE	1,CNTS   	;
	MOVEM	1,POK5   	;
    POKMTA:
	POK1             	; !  This will become MTAPE ELFCHAN,POK1;
	JRST POK3        	; !  Error;
	JRST POK4        	; !  OK;
    POK1:
	POKE    		;
    POK5:
	0       		;
    POK3:
	SETOM   POK5     	; ! Error result;
    POK4:
	MOVE    1,POK5   	;
	MOVEM	1,ANS	   	;
    END;

    IF ANS = -1 THEN COMERR("Couldn't poke at ELF");
    RETURN;
    END "poke";

PROCEDURE POKEARRAY(INTEGER ADR, LTH; INTEGER ARRAY CONTENTS);
    BEGIN "pokearray" !  Sends the CONTENTS[0:LTH-1] to unibus address ADR
    and higher;
    INTEGER ADR1, LTH1, CNTS;
    LABEL SND1, SND4, SNDUST, SNDIOW, SNDOUT;
    DEFINE USETO = "'075000";
    DEFINE OUT = "'057000";

    ADR1 ← ADR + MAP_OFFSET;
    CNTS ← LOCATION(CONTENTS[0]);
    LTH1 ← LTH;
    START_CODE;
	MOVE	1,ADR1  	; !  Prepare USETO data in SND1;
	LSH	1,-1    	;
	ADDI	1,'400000  	;
	HRRM	1,SND1  	;
	MOVE	1,ELFCHAN	; !  Prepare USETO in SNDUST;
	LSH	1,5     	;
	ADDI	1,USETO 	;
	HRLM	1,SNDUST   	;
    SNDUST:
	SND1             	; !  This will become USETO ELFCHAN,SND1;
	JRST SND4        	; !  OK;
    SND1:
	'400000000000     	; !  one word transfer, don't grab unibus;
    SNDIOW:
	0		     	; !  Will be IOWD [LTH,CNTS];
    SND4:
	MOVN    1,LTH1   	; !  Prepare IOWD in SNDIOW;
	HRLZM	1,SNDIOW   	;
	MOVE	1,CNTS   	;
	SUBI	1,1		;
	HRRM	1,SNDIOW   	;
	MOVE	1,ELFCHAN	; !  Prepare OUT in SNDOUT;
	LSH	1,5     	;
	ADDI	1,OUT   	;
	HRLM	1,SNDOUT  	;
    SNDOUT:
	SNDIOW	    		; !  This will become OUT ELFCHAN,SNDIOW;
	SETZ	1,        	; !  Success return;
	MOVEM	1,ADR1     	; !  Failure return;
    END;

    IF ADR1 ≠ 0 THEN COMERR("POKEARRAY failed");
    RETURN;
    END "pokearray";

PROCEDURE PEEKARRAY(INTEGER ADR, LTH; INTEGER ARRAY CONTENTS);
    BEGIN "peekarray" !  Gets the CONTENTS[0:LTH-1] from unibus address ADR
    and higher;
    INTEGER ADR1, LTH1, CNTS;
    LABEL GET1, GET4, GETUST, GETIOW, GETIN;
    DEFINE USETI = "'074000";
    DEFINE IN = "'056000";

    ADR1 ← ADR + MAP_OFFSET;
    CNTS ← LOCATION(CONTENTS[0]);
    LTH1 ← LTH;
    START_CODE;
	MOVE	1,ADR1  	; !  Prepare USETI data in GET1;
	LSH	1,-1    	;
	ADDI	1,'400000  	;
	HRRM	1,GET1  	;
	MOVE	1,ELFCHAN	; !  Prepare USETI in GETUST;
	LSH	1,5     	;
	ADDI	1,USETI 	;
	HRLM	1,GETUST   	;
    GETUST:
	GET1             	; !  This will become USETI ELFCHAN,GET1;
	JRST	GET4        	; !  OK;
    GET1:
	'400000000000     	; !  one word transfer, don't grab unibus;
    GETIOW:
	0		     	; !  Will be IOWD [LTH,CNTS];
    GET4:
	MOVN	1,LTH1   	; !  Prepare IOWD in GETIOW;
	HRLZM	1,GETIOW   	;
	MOVE	1,CNTS   	;
	SUBI	1,1		;
	HRRM	1,GETIOW   	;
	MOVE	1,ELFCHAN	; !  Prepare IN in GETIN;
	LSH	1,5     	;
	ADDI	1,IN	   	;
	HRLM	1,GETIN  	;
    GETIN:
	GETIOW	    		; !  This will become IN ELFCHAN,GETIOW;
	SETZ	1,        	; !  Success return;
	MOVEM	1,ADR1     	; !  Failure return;
    END;

    IF ADR1 ≠ 0 THEN COMERR("PEEKARRAY failed");
    RETURN;
    END "peekarray";

!  GETNOTE, SNDNOTE, SNDN1;

DEFINE SLEEP = "'047040000031";  ! The SLEEP UUO;

PROCEDURE GETNOTE (INTEGER ARRAY NOTE);
    BEGIN "getnote"
    !  Listens to the notebox from the 11 and returns the note when it
    arrives, in array NOTE[0:NOTSIZ-1];
    WHILE TRUE DO
        BEGIN  "gwaiting"
        INTEGER SGNAL, I;
        SGNAL ← PEEK(NOTB10);
        IF SGNAL = 0
        THEN START_CODE "gnotyet"
                MOVEI 1,0       ;
                SLEEP           ;  ! Sleep for a tick;
             END "gnotyet"
        ELSE BEGIN "ggotit"
            NOTE[0] ← SGNAL;
            FOR I ← 1 STEP 1 UNTIL NOTSIZ-1 DO
                NOTE[I] ← PEEK(NOTB10+I+I);
            OUTTST(CRLF & "Receiving note: " & CVOS(SGNAL));
	    POKE(NOTB10,0);  ! Clear the note;
            RETURN;
            END "ggotit";
        END "gwaiting";
    END "getnote";

PROCEDURE SNDNOTE (INTEGER ARRAY NOTE);
    BEGIN "sndnote"
    !  Sends the note in NOTE[0:NOTSIZ-1] to the 11's notebox as soon
    as it is free;
    WHILE TRUE DO
        BEGIN  "swaiting"
        INTEGER SGNAL, I;
        SGNAL ← PEEK(NOTB11);
        IF SGNAL ≠ 0
        THEN START_CODE "snotyet"
                MOVEI 1,0       ;
                SLEEP           ;  ! Sleep for a tick;
             END "snotyet"
        ELSE BEGIN "sgotit"
            FOR I ← 1 STEP 1 UNTIL NOTSIZ-1 DO
                POKE(NOTB11+I+I,NOTE[I]);
	    POKE(NOTB11,NOTE[0]);  ! Set the note's appearance;
            RETURN;
            END "sgotit"
        END "swaiting";
    END "sndnote";

PROCEDURE SNDN1(INTEGER ARG0, ARG1 (0), ARG2 (0));
    BEGIN "sndn1"
    !  A little note is to be sent.  Send it;
    INTEGER ARRAY LNOTE [0:NOTSIZ-1];
    LNOTE[0] ← ARG0;
    OUTTST(CRLF & "Sending note: " & CVOS(ARG0));
    LNOTE[1] ← ARG1;
    LNOTE[2] ← ARG2;
    SNDNOTE(LNOTE);
    END "sndn1";

REAL PROCEDURE RFVAL(INTEGER WORD1,WORD2);
 BEGIN
 ! This procedure gives the real floating point value of a floating point number
  in WORD1 and WORD2 with F format of pdp-11.;
 REAL X;
 INTEGER SIGN,EXPONENT,FRACTION;
! PRINT(CRLF,"WORD1=",CVOS(WORD1),"    WORD2=",CVOS(WORD2));
 SIGN← WORD1 LSH -15;
 EXPONENT← (WORD1 LSH 21) LSH -28 ;
 FRACTION← (((WORD1 LAND '177) LOR (IF EXPONENT THEN '200 ELSE 0)) LSH 16) LOR WORD2 ;
 IF SIGN=1 THEN BEGIN EXPONENT← LNOT EXPONENT; FRACTION← '100000000 - FRACTION; END;
! PRINT(CRLF,"SIGN=",SIGN,"  EXPONENT=",CVOS(EXPONENT),"   FRACTION=",CVOS(FRACTION));
 MEMLOC(X,INTEGER)← SIGN LSH 35 LOR EXPONENT LSH 27 LOR FRACTION LSH 3 ;
! PRINT(CRLF,CVOS(X));
 RETURN(X);
 END;
INTERNAL PROCEDURE EVAL(INTEGER ARRAY REQ; INTEGER REQLENGTH;
	 			REAL ARRAY ANSWER; REFERENCE INTEGER ANSLENGTH);
 ! A list of pcodes with proper header(s) is in REQ , we only put ALAID headers
  in front of the list and send the whole message to the 11. We then send the 11's
  answer as soon as it is available;

  BEGIN
  INTEGER ARRAY NOTE[0:NOTSIZ-1], MESSAGE[0: 26 MAX REQLENGTH+5];
  INTEGER I;
  SNDN1(GETBUF,REQLENGTH+6);
  GETNOTE(NOTE);
  IF NOTE[0] ≠ BUFALC THEN COMERR("Getting a "&CVS(NOTE[0])
			       &" while expecting a BUFALC (i.e "&CVS(BUFALC)&" )");
  IF NOTE[1] ≠ REQLENGTH+6  THEN COMERR("Alocted buffer's length is wrong !");
  MESSAGE[MESID % 2]← 1; ! Only one message each time;
  MESSAGE[MESTYP % 2]← FROMTEN + REQUEST;
  MESSAGE[MESLTH % 2]← REQLENGTH + 3;

 ! Message keyword is going to be "EVAL  ";
  MESSAGE[3]← "E" + "V" LSH 8;
  MESSAGE[4]← "A" + "L" LSH 8;
  MESSAGE[5]← " " + " " LSH 8;
  FOR I←1 STEP 1 UNTIL REQLENGTH DO
   MESSAGE[I+5]← REQ[I];

 ! Send the message (REQ) to the 11's allocated buffer;
  POKEARRAY(NOTE[2], REQLENGTH+6, MESSAGE);

 ! Tell the 11 to operate on it;
  SNDN1(USEBUF,NOTE[2]);

 ! See where the 11's answer is;
  GETNOTE(NOTE);
  IF NOTE[0] ≠ TAKBUF THEN COMERR("Getting a "&CVS(NOTE[0])
			       &" while expecting a TAKBUF (i.e "&CVS(TAKBUF)&" )");
  ANSLENGTH← PEEK(NOTE[1] + MESLTH + MAP_OFFSET);

 ! Getting the answer ;
  PEEKARRAY(NOTE[1],ANSLENGTH,MESSAGE);
  ANSLENGTH← ANSLENGTH - 3 ;
  FOR I←2 STEP 2 UNTIL ANSLENGTH DO
   ANSWER[I LSH -1]← RFVAL(MESSAGE[I+1],MESSAGE[I+2]);
  ANSLENGTH← ANSLENGTH LSH -1;
 ! Tell the 11 we don't need the buffer anymore;
  SNDN1(RELBUF,NOTE[1]);
  END;
END "MSSNGR"