TITLE QUASAR -- QUASAR Controller - version 2 SUBTTL C.D. O'Toole L.S. Samberg 11 Oct 76 ;***Copyright (C) 1974, 1975, 1976, Digital Equipment Corp., Maynard, Mass.*** SEARCH QSRMAC ;PARAMETER FILE PROLOGUE(QUASAR) ;GENERATE THE NECESSARY SYMBOLS LOC 41 ;INSTALL CALL TO LUUO HANDLER PUSHJ P,LUUO LOC 137 ;INSTALL OUR VERSION NUMBER BYTE (3)QSRWHO (9)QSRVER (6)QSRMIN (18)QSREDT RELOC 0 ;BACK TO RELOCATABLE CODE ; STOPCDs found in QUASAR Main Module ;ILU ILLEGAL LOCAL UUO ;QNR QUASAR NOT RESTARTABLE SUBTTL Global Variables G$BEG: ;BEGINNING OF GLOBAL VARIABLES G$ENT:: BLOCK 1 ;ADDRESS OF CURRENT IPC ENTRY G$SND:: BLOCK 1 ;SENDER OF CURRENT REQUEST (PID) G$SID:: BLOCK 1 ;OWNER ID OF CURRENT SENDER G$CDI:: BLOCK 1 ;CONNECTED DIRECTORY OF SENDER G$NOW:: BLOCK 1 ;"NOW" IN INTERNAL DATE-TIME FORMAT G$ERR:: BLOCK 1 ;ERROR CODE FOR ACK'ING THIS REQUEST G$QPID:: BLOCK 1 ;QUASAR'S PID G$NBW:: BLOCK 1 ;NUMBER OF BLKS WRITTEN IN MASTER QUEUES G$SPRT:: BLOCK 1 ;PROTECTION OF SPOOLED FILES G$PRVS:: BLOCK 1 ;ENABLED PRIVS OF CURRENT SENDER G$CRAC:: BLOCK 24 ;CRASH INFORMATION BLOCK G$ACK:: BLOCK 1 ;NON-ZERO IF CALLER WANTS A RESPONSE G$MPS:: BLOCK 1 ;MAX IPCF PACKET SIZE G$MCOR:: BLOCK 1 ;MINIMUM VALUE OF /CORE G$ITEM:: BLOCK NITEMS ;COUNTER ITEMS G$END==.-1 ;END OF GLOBAL VARIABLES ;LOCAL STORAGE STFLAG: -1 ;FLAG TO MAKE SURE WE AREN'T RESTARTED PDL:: BLOCK 50 ;PUSHDOWN LIST SUBTTL Initialization ;WARNING THE ORDERING OF THE FOLLOWING CALLS TO THE VARIOUS ; INITIALIZATION ROUTINES IS FIXED, AND SHOULD NOT BE ; CHANGED UNDER ANY CIRCUMSTANCES. QUASAR: MOVE P,[IOWD 50,PDL] ;GET A PUSHDOWN LIST AOSE STFLAG ;MAKE SURE WE AREN'T RESTARTED STOPCD(QNR,FATAL) ;++QUASAR NOT RESTARTABLE ZERO STGBPT ;CLEAR A FEW INTERNAL WORDS FIRST MOVE S1,[G$BEG,,G$BEG+1] SETZM G$BEG ;THIS IS ESSENTIALLY G$INIT, TO BLT S1,G$END ; CLEAR OUT ALL GLOBAL VARIABLES PUSHJ P,I$INIT## ;INITIALIZE THE SYSTEM INTERFACE PUSHJ P,M$INIT## ;THE MEMORY MANAGER PUSHJ P,A$INIT## ;ADMINISTRATIVE FUNCTIONS PUSHJ P,Q$INIT## ;THE QUEUE DATABASE MANAGER PUSHJ P,F$INIT## ;THE FAILSOFT SYSTEM!! PUSHJ P,S$INIT## ;THE TASK SCHEDULER PUSHJ P,C$INIT## ;GET A PID SUBTTL Main Processing Loop MAIN: PUSHJ P,I$NOW## ;GET "NOW" PUSHJ P,C$GET## ;GET A MESSAGE JUMPN AP,MAIN.1 ;JUMP IF WE'VE GOT SOMETHING PUSHJ P,I$SLP## ;AND SLEEP SOME SKIPE HDRIPS##+.QHLNK ;ANY MESSAGES THAT DIDN'T MAKE IT PUSHJ P,C$RSND## ;YES, TRY RESENDING OLD MESSAGES PUSHJ P,C$GET## ;GET A MESSAGE JUMPN AP,MAIN.1 ;GOT ONE!! PUSHJ P,M$GCOL## ; "AN OUNCE OF PREVENTION..." JRST MAIN.3 ;NOW CHECK THE AFTER QUEUE MAIN.1: MOVEM AP,G$ENT ;SAVE ADDRESS OF THE ENTRY ZERO G$ERR ;CLEAR PREVIOUS ERROR INDICATOR MOVE T1,IPCSDR(AP) ;GET SENDERS PID MOVEM T1,G$SND ;AND SAVE IT MOVE T1,IPCSID(AP) ;GET SENDERS OWNER ID MOVEM T1,G$SID ;AND SAVE IT MOVE T1,IPCCDI(AP) ;GET SENDER'S CONNECTED DIRECTORY MOVEM T1,G$CDI ;SAVE IT MOVE T1,IPCPRV(AP) ;GET SENDERS CAPABILITIES MOVEM T1,G$PRVS ;SAVE THAT AS WELL LOAD M,IPCMES(AP),IPM.AD ;GET ADDRESS OF THE MESSAGE MOVE T1,IPCFLG(AP) ;GET THE FLAG WORD MOVE T3,G$MPS ;IPCF SHORT MESSAGE SIZE TXNN T1,IP.CFV ;A PAGE MODE MESSAGE ? JRST MAIN.2 ;NO, M AND T3 ARE STRAIGHT PG2ADR M ;POINT TO THE MESSAGE MOVEI T3,1000 ;PAGE MODE LENGTH MAIN.2: LOAD P1,.MSTYP(M),MS.TYP ;GET MESSAGE TYPE TXNE T1,IP.CFM ;A RETURNED MESSAGE JRST RTNMSG ;YES, PROCESS IT OVER THERE TXNE T1,IP.CFC ;A SYSTEM MESSAGE JRST SYSMSG ;YES, DISPATCH THEM DIFFERENTLY LOAD S1,IPCRCR(AP) ;GET PID MESSAGE WAS SENT TO CAMN S1,G$QPID ;TO [SYSTEM]QUASAR JRST QSRMSG ;YES, DISPATCH IT RELMSG: MOVE AP,G$ENT ;GET ADDRESS OF IPC ENTRY PUSHJ P,C$PUT## ;RETURN IT TO THE FREE SPACE MAIN.3: PUSHJ P,Q$CKAF## ;CHECK THE AFTER QUEUE PUSHJ P,S$SCHD## ;DO ANY SCHEDULING JRST MAIN ;AND LOOP SUBTTL Message Dispatch Handlers ;HERE UPON RECEIPT OF AN UNDELIVERABLE PACKET ; T1 = PACKET FLAGS RTNMSG: TXNE T1,IP.CFP ;REQUESTING PRIVILEGES JRST RELMSG ;YES, IGNORE THEM MOVE S1,G$SND ;PID THAT WENT AWAY PUSHJ P,G$SFAL ;TELL ALL CONCERNED JRST RELMSG ;AND RELEASE THE MESSAGE ;HERE TO DISPATCH SYSTEM MESSAGES. ; P1 = THE MESSAGE TYPE ; T1 = THE PACKET FLAGS SYSMSG: TXNE T1,IP.CFP ;REQUESTING PRIVILEGES JRST RELMSG ;YES, IGNORE IT MOVEI S1,.POPJ## ;IN CASE WE DON'T FIND ONE CAIN P1,.IPCSU ;SPOOLING MESSAGE MOVEI S1,Q$SPOOL## ;YES, SET UP DISPATCH CAIN P1,.IPCSL ;LOGOUT MESSAGE MOVEI S1,Q$LOGOUT## ;YES, SET UP DISPATCH PUSHJ P,0(S1) ;CALL THE HANDLER JRST RELMSG ;AND DISMISS THE MESSAGE ;HERE WHEN A MESSAGE IS DIRECTED AT [SYSTEM]QUASAR ; P1 = THE MESSAGE TYPE ; M = THE MESSAGE PROPER ; T3 = THE MAXIMUM MESSAGE SIZE POSSIBLE ( 1000 OR G$MPS ) ; T1 = PACKET FLAGS QSRMSG: TXNE T1,IP.CFP ;REQUESTING PRIVILEGES JRST RELMSG ;YES, IGNORE THEM LOAD T4,.MSTYP(M),MS.ACK ;GET "ACK" CODE MOVEM T4,G$ACK ;REMEMBER IF USER WANTS ONE ZERO .MSTYP(M),MS.ACK ;CLEAR REQUEST IN MESSAGE PROPER LOAD T4,.MSTYP(M),MS.CNT ;GET THE LENGTH FROM THE USER CAILE T4,(T3) ;SPECIFY AN IMPOSSIBLE LENGTH? MOVEI P1,QSRLEN+1 ;YES, SET TO SAY "TOO LONG" CAILE P1,QSRLEN ;AN UNKNOWN MESSAGE ZERO P1 ;YES, MAKE IT LOOK INVALID MOVE S1,QSRTAB(P1) ;ADDRESS OF PROCESSING ROUTINE PUSHJ P,(S1) ;AND CALL THE ROUTINE SKIPE G$ERR ;DID AN ERROR OCCUR SKIPL QSRTAB(P1) ;YES, A KNOWN COMPONENT TYPE CALL SKIPE G$ACK ;NO, DOES USER WANT A RETURN MESSAGE PUSHJ P,STGSND ;YES, BUILD STRING ANSWER AND SEND IT JRST RELMSG ;AND DISMISS THE MESSAGE SUBTTL Message Dispatch Tables ;THE DISPATCH TABLE IS ORDERED BY MESSAGE TYPE AND CONTAINS THE ADDRESS OF THE ; CORRECT PROCESSING ROUTINE FOR THAT MESSAGE. ;BY DEFINITION, ANY ROUTINE CALLED THROUGH THIS DISPATCH IS A TOP LEVEL ROUTINE ;THE SIGN BIT (1B0) IS USED TO INDICATE THOSE MESSAGES THAT PROBABLY CAME FROM ; A KNOWN COMPONENT (OR SOMEONE TRYING TO BECOME ONE) AND IS USED TO ; DETERMINE IF A RESPONSE IS TO BE SENT ON ERRORS (EVEN IF DIDN'T ASK FOR THEM) QSRTAB: 0,,E$IMT ;FUNCTION 0 400000,,A$HELLO## ;FUNCTION 1 HELLO 400000,,Q$RELEA## ;FUNCTION 2 RELEASE 400000,,Q$CHECK## ;FUNCTION 3 CHECKPOINT 400000,,Q$REQUE## ;FUNCTION 4 REQUEUE 0,,E$IMT ;FUNCTION 5 NEXTJOB (SENT BY QUASAR) 0,,E$IMT ;FUNCTION 6 ABORT (SENT BY QUASAR) 0,,Q$CREATE## ;FUNCTION 7 CREATE 0,,Q$LIST## ;FUNCTION 10 LIST 0,,Q$MODIFY## ;FUNCTION 11 MODIFY 0,,Q$KILL## ;FUNCTION 12 KILL 0,,E$IMT ;FUNCTION 13 LISTANSWER (SENT BY QUASAR) 0,,E$IMT ;FUNCTION 14 TEXT (SENT BY QUASAR) 0,,E$IMT ;FUNCTION 15 REQUEST FOR CHECKPOINT (SENT BY QUASAR) 0,,Q$DEFER## ;FUNCTION 16 DEFER 0,,A$ROUTE## ;FUNCTION 17 ROUTING INFORMATION 0,,A$COUNT## ;FUNCTION 20 COUNT 0,,E$IMT ;FUNCTION 21 COUNTANSWER (SENT BY QUASAR) QSRLEN==<.-QSRTAB>-1 ;HIGHEST LEGAL MESSAGE FROM USER TO QUASAR 0,,E$MTL ;HIGHEST + 1 = MESSAGE TOO LONG SUBTTL Tables for Error Codes Reported DEFINE X(SUFFIX,TEXT),< E$'SUFFIX:: PUSHJ P,RPTERR ;DISPATCH TO ERROR HANDLER > ;END OF DEFINE X ERRTBL: ERRCDS ;EXPAND THE DISPATCH TABLE DEFINE X(SUFFIX,TEXT),< EXP [ASCIZ\TEXT\] ;TABLE OF MESSAGES > ;END OF DEFINE X TXTTBL: EXP [BYTE (7)0] ;0 IS NOT REALLY AN ERROR ERRCDS ;DEFINE THE REST OF THEM DEFINE X(SUFFIX,TEXT),< TX.FAT!INSVL.(,TX.SUF) > ;END OF DEFINE X STSTBL: TX.NMS ;0 HAS NO TEXT ASSOCIATED ERRCDS ;EXPAND THE REST NOW ;HERE WHEN SOMEONE CALLS (OR EXITS THROUGH) ANY OF THE E$xxx ERROR CODES ; THIS STORES THE RELATIVE ERROR NUMBER INTO G$ERR RPTERR: EXCH T1,(P) ;SAVE T1, GET ERROR DISPATCH SUBI T1,ERRTBL ;CONVERT TO ERROR INDEX HRRZM T1,G$ERR ;SET GLOBAL ERROR INDICATOR PJRST .T1PJ## ;RESTORE T1 AND RETURN SUBTTL String Utilities for TEXT Message ;SUBROUTINE TO COPY AN ASCIZ STRING INTO THE CURRENT TEXT MESSAGE ;CALL WITH S1 AS THE ADDRESS OF THE STRING TO BE INCLUDED ;DESTROYS S1 AND S2 INTERN G$CSTG G$CSTG: HRLI S1,(POINT 7,0) ;MAKE A BYTE POINTER CSTG.1: ILDB S2,S1 ;GET A CHARACTER PJUMPE S2,.POPJ## ;STOP AT THE NULL PUSHJ P,STGSTC ;STUFF IT AWAY JRST CSTG.1 ;GET THEM ALL ;SUBROUTINE TO INSERT A SIXBIT VALUE INTO THE CURRENT TEXT MESSAGE ;CALL WITH S1 CONTAINING THE SIXBIT QUANTITY ;DESTROYS S1 AND S2 INTERN G$CSIX G$CSIX: PUSHJ P,.SAVE1## ;SAVE P1 FIRST MOVE P1,[POINT 6,S1] ;AND GET A SIXBIT BYTE POINTER CSIX.1: ILDB S2,P1 ;GET A CHARACTER PJUMPE S2,.POPJ## ;ALL DONE AT A BLANK ADDI S2," " ;TO ASCII PUSHJ P,STGSTC ;STICK A CHARACTER TLNE P1,770000 ;GET ALL SIX YET JRST CSIX.1 ;NO, GET ANOTHER POPJ P, ;RETURN ;SUBROUTINE TO INSERT A SINGLE ASCII CHARACTER INTO THE CURRENT TEXT MESSAGE ;CALL WITH S1 CONTAINING THE CHARACTER RIGHT JUSTIFIED ;DESTROYS S1 AND S2 INTERN G$CCHR G$CCHR: MOVE S2,S1 ;MOVE FOR STGSTC PJRST STGSTC ;EXIT TRHOUGH THE CHARACTER STICKER ;SUBROUTINE TO INSERT A DECIMAL NUMBER INTO THE CURRENT TEXT MESSAGE ;CALL WITH S1 CONTAINING THE BINARY NUMBER ;DESTROYS S1 AND S2 INTERN G$CDEC G$CDEC: IDIVI S1,^D10 ;A STANDARD DECIMAL ROUTINE HRLM S2,(P) ;SAVE ROOM ON THE STACK SKIPE S1 ;DONE YET PUSHJ P,G$CDEC ;NO, RECURSE A LITTLE HLRZ S2,(P) ;RETRIEVE A DIGIT ADDI S2,"0" ;CONVERT TO ASCII ;FALL INTO CHARACTER STICKER STGSTC: SKIPE STGBPT ;STRING STARTED YET JRST STGS.1 ;YES, JUST INSERT ONE PUSH P,S2 ;SAVE THE CHARACTER MOVE S2,[POINT 7,ACKMSG+TEX.MS] ;INIT THE BYTE POINTER MOVEM S2,STGBPT ;TUCK IT AWAY POP P,S2 ;RESTORE THE CHARACTER STGS.1: IDPB S2,STGBPT ;INCLUDE THIS CHARACTER POPJ P, ;RETURN FOR THE NEXT STGBPT: BLOCK 1 ;POINTER TO CURRENT STRING (0 IF NONE) ;ROUTINE TO STORE THE CURRENT ERROR CODE INTO THE TEXT MESSAGE STGSND: MOVE P1,G$ERR ;GET THE ERROR CODE (EVEN IF ZERO) MOVE S1,TXTTBL(P1) ;THE ASSOCIATED MESSAGE PUSHJ P,G$CSTG ;STORE THE MESSAGE MOVE S1,STSTBL(P1) ;GET THE FLAGS AND PREFIX ;FALL INTO THE GLOBAL ROUTINE TO SEND THE MESSAGE TO THE USER ;SUBROUTINE TO SEND THE CURRENT STRING TO THE USER (G$SND) ;CALL WITH S1 CONTAINING THE FLAGS AND PREFIX TO STORE INTO TEX.ST ;DESTROYS S1 AND S2 INTERN G$MSND G$MSND: PUSHJ P,.SAVE1## ;SAVE A REG SAVE AP ;SAVE ANOTHER TXNN S1,TX.MOR ;GOING TO GENERATE ANOTHER AFTER THIS ZERO G$ACK ;NO, CLEAR ACK REQUEST MOVEM S1,ACKMSG+TEX.ST ;STORE REQUESTED STATUS INFORMATION ZERO S2 ;GET A NULL BYTE PUSHJ P,STGSTC ;STUFF IT TO END THE MESSAGE HRRZ P1,STGBPT ;NOW COMPUTE THE LENGTH ZERO STGBPT ;BUT FIRST, INDICATE NO MESSAGE SUBI P1,ACKMSG-1 ;P1 = THE MESSAGE LENGTH STORE P1,ACKMSG+.MSTYP,MS.CNT ;STORE IN THE MESSAGE HEADER HRLM P1,MSND.A+.IPCFP ;AND AS PACKET LENGTH MOVX S2,.QOTEX ;MESSAGE TYPE STORE S2,ACKMSG+.MSTYP,MS.TYP ;STORE THE TYPE MOVEI S2,ACKMSG ;POINT AT THE MESSAGE HRRM S2,MSND.A+.IPCFP ;NOW HAS LENGTH,,ADDR ZERO MSND.A+.IPCFL ;CLEAR FLAGS MOVE S2,G$SND ;GET CURRENT SENDER MOVEM S2,MSND.A+.IPCFR ;AS THE RECEIVER CAMG P1,G$MPS ;SHOULD THIS REALLY BE PAGED JRST MSND.1 ;NO, ALL READY TO SEND PUSHJ P,M$ACQP## ;YES, GET A PAGE HRRM AP,MSND.A+.IPCFP ;STORE THE PAGE NUMBER MOVEI S1,1000 ;LENGTH OF A PAGE HRLM S1,MSND.A+.IPCFP ;AND STORE THAT MOVX S1,IP.CFV ;GET BIT INDICATING PAGED MOVEM S1,MSND.A+.IPCFL ;STORE THE FLAG HRLI S1,ACKMSG ;ADDRESS OF ORIGINAL MESSAGE PG2ADR AP ;CONVERT TO AN ADDRESS HRRI S1,(AP) ;S1 NOW READY FOR THE BLT ADDI P1,-1(AP) ;P1 = LAST LOC TO COPY BLT S1,(P1) ;MOVE DATA TO THE PAGE MSND.1: MOVEI AP,MSND.A ;PDB FOR C$SEND PJRST C$SEND## ;SEND THE MESSAGE AND RETURN MSND.A: BLOCK IPCHSZ ;RESERVE CORE FOR THE PDB ACKMSG: BLOCK 20 ;SPACE FOR MESSAGE SUBTTL G$SFAL -- Notify all Processors of Unknown PID ;CALLED WITH S1 = THE NOW INVALID PID ;THIS IN TURN, CALLS ANYONE WHO WORRYS ABOUT THAT SITUATION INTERN G$SFAL G$SFAL: PJRST A$KLPD## ;TELL QUASAR - QUEUE MANIPULATOR AND RETURN SUBTTL LUUO -- Local UUO Handler for QUASAR ;THIS ROUTINE GETS CALLED WHENEVER A LOCAL UUO IS EXECUTED. ; ITS RESPONSIBILITY IS TO SAVE ALL ACCUMULATORS, DISPATCH THE ; UUO, AND THEN RESTORE THE ACCUMULATORS. ;ROUTINES CALLED WITH: S1 = THE AC FIELD OF THE UUO ; S2 = THE E FIELD OF THE UUO LUUO: MOVEM 0,G$CRAC+0 ;SAVE ALL REGISTERS MOVE 0,[1,,G$CRAC+1] ;IN THE CRASH BLOCK BLT 0,G$CRAC+17 ;GET THEM ALL LDB S1,[POINT 4,40,12] ;GET THE ACCUMULATOR FIELD HRRZ S2,40 ;AND THE EFFECTIVE ADDRESS HLRZ T1,40 ;NOW FIND THE OPCODE ANDI T1,777000 ;ONLY THE OPCODE CAIN T1,(.STCD.) ;STOPCD UUO HRROI T1,I$STCD## ;GET, POINT TO HANDLER TLNN T1,-1 ;FIND A KNOWN UUO STOPCD(ILU,FATAL) ;++ILLEGAL LOCAL UUO PUSHJ P,0(T1) ;DISPATCH THE UUO MOVSI 17,G$CRAC ;FOR RESTORE BLT 17,17 ;GET ALL THE REGS BACK POPJ P, ;CALLED BY PUSHJ IN 41 END QUASAR