Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-08 - 43,50512/intr.bli
There are no other files named intr.bli in the archive.
%IF %DECLARED(FTSIG)
	%THEN %IF NOT(FTSIG) %THEN %ERROR('INTR.BLI with FTSIG off??') %FI
	%ELSE LITERAL FTSIG=1
	%FI;
!To trigger conditional compilation
FIELD INT_FIELDS=SET		!INTERRUPT block fields

DFF[INT$PISYS,0,0,36,0],	!PISYS. block starts here
 DFF[INT$WHAT,0,0,36,0],	!Device or non-I/O condition
 DFF[INT$CONDITION,0,0,36,0],	!synonym
 DFF[INT$OFFSET,1,18,18,0],	!Offset within interrupt vector
 DFF[INT$REASONS,1,0,18,0],	!Reasons for I/O interrupt, as follows:
   DFF[INT$IN_DONE,1,16,1,0],	!Input done
   DFF[INT$OUT_DONE,1,15,1,0],	!Output done
   DFF[INT$EOF,1,14,1,0],	!End of File
   DFF[INT$IN_ERROR,1,13,1,0],	!Input Error
   DFF[INT$OUT_ERROR,1,12,1,0],	!Output Error
   DFF[INT$OFFLINE,1,11,1,0],	!Device went off-line
   DFF[INT$FULL,1,10,1,0],	!Device Full
   DFF[INT$QUOTA_EX,1,9,1,0],	!Quota exceeded
   DFF[INT$IO_WAIT,1,8,1,0],	!I/O Wait
   DFF[INT$ONLINE,1,7,1,0],	!Device On-line
!DFF[INT$ZERO,2,0,36,0],	!Spare word in PISYS. block MUST BE 0
DFF[INT$PROCESS,3,0,18,0],	!Process that owns this interrupt
DFF[INT$NEXT,4,0,18,0],		!Next interrupt in chain for process
DFF[INT$S_REASONS,4,18,18,0],	!Signal associated condition if these occur
 DFF[INT$S_ALWAYS,4,18,1,0],	!Signal always
 DFF[INT$S_ALLIO,4,25,10,0],	!All I/O conditions
 DFF[INT$S_IN_DONE,4,34,1,0],	!Input done
 DFF[INT$S_OUT_DONE,4,33,1,0],	!Output done
 DFF[INT$S_EOF,4,32,1,0],	!End of File
 DFF[INT$S_IN_ERROR,4,31,1,0],	!Input error
 DFF[INT$S_OUT_ERROR,4,30,1,0],	!Output error
 DFF[INT$S_OFFLINE,4,29,1,0],	!Device went offline
 DFF[INT$S_FULL,4,28,1,0],	!No more room
 DFF[INT$S_QUOTA_EX,4,27,1,0],	!Quota exceeded
 DFF[INT$S_IO_WAIT,4,26,1,0],	!I/O wait
 DFF[INT$S_ONLINE,4,25,1,0],	!Device came online
DFF[INT$PENDING,5,35,1,0],	!This block has a pending SIGNAL already
DFF[INT$TEMP,5,34,1,0],		!This block is temporary (delete it when done)
DFF[INT$SIGNAL_ARGS,5,0,18,0],	!If non-zero, condition to signal
DFF[INT$CODE,6,0,36,0],		!First signal argument, fields within follow
 DFF[INT$SEVERITY,6,0,3,0],	!Warning/Error/Fatal error/Success
  DFF[INT$SUCCESS,6,0,1,0],	!TRUE bit, success bit 
 DFF[INT$STSCODE,6,3,22,0],	!Status code
 DFF[INT$FACCODE,6,25,11,0],	!Facility code
DFF[INT$STATUS,7,0,36,0],		!Status word from vector block
DFF[INT$PC,8,0,36,0],		!PC that interrupt happened at
DFF[INT$REASON,9,0,18,0],	!Reason for interrupt (I/O interrupts only)
   DFF[INT$R_IN_DONE,9,16,1,0],	!Input done
   DFF[INT$R_OUT_DONE,9,15,1,0],!Output done
   DFF[INT$R_EOF,9,14,1,0],	!End of File
   DFF[INT$R_IN_ERROR,9,13,1,0],!Input Error
   DFF[INT$R_OUT_ERROR,9,12,1,0],!Output Error
   DFF[INT$R_OFFLINE,9,11,1,0],	!Device went off-line
   DFF[INT$R_FULL,9,10,1,0],	!Device Full
   DFF[INT$R_QUOTA_EX,9,9,1,0],	!Quota exceeded
   DFF[INT$R_IO_WAIT,9,8,1,0],	!I/O Wait
   DFF[INT$R_ONLINE,9,7,1,0],	!Device On-line
DFF[INT$FILBLK,9,18,18,0]	!File block for device

TES;
LITERAL INT_LEN=10;		!Minimum length of interrupt block

MACRO INT_BLOCK=BLOCK[INT_LEN] FIELD(INT_FIELDS) %;

FIELD INTVEC_FIELDS=SET		!Fields in the interrupt vector blocks

DFF[INTVEC$NEWPC,0,0,36,0],	!Usually points to [CALL INTSIG(INTBLK)]
DFF[INTVEC$OLDPC,1,0,36,0],	!PC where it happened
DFF[INTVEC$REASON,2,0,18,0],!What kind of I/O condition was it?
 DFF[INTVEC$RID,2,16,1,0],	!Input done
 DFF[INTVEC$ROD,2,15,1,0],	!Output done
 DFF[INTVEC$IODONE,2,15,2,0],	!I/O done (sum of the previous 2)
 DFF[INTVEC$REF,2,14,1,0],	!End of File
 DFF[INTVEC$EOF,2,14,1,0],	! " "
 DFF[INTVEC$RIE,2,13,1,0],	!Input Error
 DFF[INTVEC$ROE,2,12,1,0],	!Output Error
 DFF[INTVEC$IOERR,2,12,2,0],!I/O Error
 DFF[INTVEC$RDO,2,11,1,0],	!Device went off-line
  DFF[INTVEC$OFFLINE,2,11,1,0],! " "
 DFF[INTVEC$RDF,2,10,1,0],	!Device Full
 DFF[INTVEC$RQE,2,9,1,0],	!Quota exceeded
 DFF[INTVEC$RWT,2,8,1,0],	!I/O Wait
 DFF[INTVEC$RON,2,7,1,0],	!Device came on-line
 DFF[INTVEC$ONLINE,2,7,1,0],! " "
 DFF[INTVEC$ERROR,2,9,5,0],	!I/O error, dev full or Quota ex or offline
DFF[INTVEC$FLAGS,2,18,18,0],!Control flags as follows
 DFF[INTVEC$VPO,2,34,1,0],	!Disable all interrupts on interrupt
 DFF[INTVEC$VTO,2,33,1,0],	!Disable until DEBRK.
 DFF[INTVEC$VAI,2,32,1,0],	!Don't disable even this block (do not set)
 DFF[INTVEC$VDS,2,31,1,0],	!Dismiss additional interrupts
 DFF[INTVEC$VPM,2,30,1,0],	!Print standard message if any
 DFF[INTVEC$VIP,2,29,1,0],	!Interrupt in progress (clear on restart)
DFF[INTVEC$STATUS,3,0,36,0]	!Status word

TES;

STRUCTURE INTVECSTR[I,O,P,S,E;N]=
	[N*4]
	(INTVECSTR+I+O)<P,S,E>;

MACRO IOWAIT(INT,COND)=
	BEGIN
	MAP INT: REF INT_BLOCK;
	INT[INT$S_ALWAYS]=-1;	!Set all the error signal bits
	INT[%NAME(INT$S_,COND)]=0; !If it wasn't what we're waiting for,error.
	WAIT(.INT)
	END%;

MACRO BUILD_LIST (ARGLST)[ARG]=ARGLST[%COUNT]=ARG %;

MACRO COND_LST=FREG<18,18> %;   !LH of FREG

MACRO ESTABLISH(RTN)=		!Must be before first executable statement!!

	STACKLOCAL ARGLST: VECTOR[%LENGTH+1];

	BUILD_LIST (ARGLST,RTN,%LENGTH-1,%REMAINING);
	COND_LST=ARGLST;		!Handler now established
% ;
MACRO INTERRUPTS(FLAGS,BLOCK)=PISYS(%NAME(PISYSF_,FLAGS),BLOCK) %;
LITERAL 
	PISYSF_OFF=%O'200000',
	PISYSF_ON=%O'100000',
	PISYSF_CLEAR=%O'40000',
	PISYSF_CLEARDEV=%O'20000',
	PISYSF_REMOVE=%O'10000',
	PISYSF_ADD=%O'4000',
	PISYSF_ON_ADD=%O'104000',	!Turn on & add device
	PISYSF_REMOVEC=PISYSF_REMOVE+PISYSF_CLEARDEV;


!Field defs for SIGNAL_ARGS
FIELD	SA_FIELDS=
	SET
	DFF[SA$LENGTH,FIRSTWORD,WRD],	!Length of argument block

	DFF[SA$CODE,NEXTWORD,WRD],	!Condition code
	 DFF[SA$SEVERITY,THISWORD,SEVERITY],	!Severity field
	 DFF[SA$STSCODE,THISWORD,STSCODE],	!code describing error
	 DFF[SA$FACCODE,THISWORD,FACCODE],	!Facility code

	DFF[SA$STATUS,NEXTWORD,WRD],	!Status info from interrupt
	DFF[SA$FORK,THISWORD,WRD],	!Fork that is aborting
	DFF[SA$FB,THISWORD,WRD],	!FILE BLOCK FOR errors but not interrupts

	DFF[SA$PC,NEXTWORD,WRD],	!PC from interrupt
	DFF[SA$QUIT_CODE,THISWORD,WRD],	!abort code as follows
	 DFF[SA$QUIT_STSCODE,THISWORD,STSCODE],	!Reason process aborted
	 DFF[SA$QUIT_SEVERIT,THISWORD,SEVERITY], !Severity indicator
	 DFF[SA$QUIT_FACCODE,THISWORD,FACCODE],	!Facility code

	DFF[SA$REASON,NEXTWORD,RH],	!Reason for interrupt
	   DFF[SA$IN_DONE,THISWORD,16,1,0],	!Input done
	   DFF[SA$OUT_DONE,THISWORD,15,1,0],	!Output done
	   DFF[SA$EOF,THISWORD,14,1,0],		!End of File
	   DFF[SA$IN_ERROR,THISWORD,13,1,0],	!Input Error
	   DFF[SA$OUT_ERROR,THISWORD,12,1,0],	!Output Error
	   DFF[SA$OFFLINE,THISWORD,11,1,0],	!Device went off-line
	   DFF[SA$FULL,THISWORD,10,1,0],	!Device Full
	   DFF[SA$QUOTA_EX,THISWORD,9,1,0],	!Quota exceeded
	   DFF[SA$IO_WAIT,THISWORD,8,1,0],	!I/O Wait
	   DFF[SA$ONLINE,THISWORD,7,1,0],	!Device On-line
	DFF[SA$FILBLK,THISWORD,LH]		!File block for interrupts
	TES;


LITERAL	!Offsets for SIGNAL_ARGS

	SA_LENGTH=0,	!Length of argument block
	SA_CODE=1,	!What happened
	SA_STATUS=2,
	SA_PC=3,
	SA_REASON=4;

LITERAL		!Offsets for MECHANISM_ARGS
	MA_LENGTH=0,
	MA_FRAME=1,
	MA_DEPTH=2,
	MA_VREG=4,
	MA_T2=5,
	MA_T3=6,
	MA_T4=7,
	MA_T5=8,

	MECH_ARGS_LEN=8;


MACRO	$CODE=	BLOCK[.SIGNAL_ARGS,SA$STSCODE]%,
	$SEVERITY=BLOCK[.SIGNAL_ARGS,SA$SEVERITY]%,
	$FACCODE=BLOCK[.SIGNAL_ARGS,SA$FACCODE]%;

MACRO SIGNAL[]=
	BEGIN
	%IF NOT %DECLARED (%NAME('.SIGNL')) %THEN EXTERNAL %NAME('.SIGNL'); %FI
	LOCAL SIGNAL_ARGS: VECTOR[%LENGTH+1];
	BUILD_LIST(SIGNAL_ARGS,%LENGTH,%REMAINING);
	%NAME('.SIGNL')(SIGNAL_ARGS);
	END;
%;

	LITERAL SS$_CONTINUE=1;	!Handler wants to continue 
	LITERAL SS$_RESIGNAL=0;	!Handler passes the buck 
	LITERAL SS$_UNWIND=8;	!Facility code for UNWIND condition

!Process block offsets
FIELD PROCESS_FIELDS=SET

DFF[P$NEXT,0,0,18,0],		!Next process to run
DFF[P$LINK,0,18,18,0],		!Next process at this level or 0
DFF[P$STKL,1,18,18,0],		!Length of stack
DFF[P$STK,1,0,18,0],		!Address of stack
DFF[P$WAIT,2,0,36,0],		!If non-zero, what process is waiting for
DFF[P$INTERRUPTS,3,0,18,0],	!Head of signal chain for process
DFF[P$FREE,3,18,18,0],		!How much storage to free when cleaning up
DFF[P$SUPERIOR,4,0,18,0],	!Process who created this one
DFF[P$INFERIORS,4,18,18,0],	!Pointer to linked list of inferiors
DFF[P$NAME,5,0,36,0],		!Name of process
DFF[P$NDB,6,0,18,0],		!NDB for process, if any
DFF[P$DISPLAY,6,18,18,0]	!Routine to call to display more stuff

TES;

LITERAL P_LEN=7;

MACRO PROCESS_BLOCK=BLOCK[P_LEN] FIELD(PROCESS_FIELDS) %;

%(
FIELD STACK_FIELDS=SET

DFF[S$SREG,3,0,36,0],		!Stored SREG
DFF[S$FREE,17,0,36,0]		!First free location on stack

TES;

MACRO STACK=BLOCK[STACK_LENGTH] FIELD(STACK_FIELDS) %;
)%
LITERAL STACK_LENGTH=1024;
MACRO FORK(RTN)[]=
	BEGIN
	LOCAL V: REF PROCESS_BLOCK;
	EXTERNAL ROUTINE CPROC;
	LOCAL ARGLST: VECTOR[%LENGTH];
	BUILD_LIST(ARGLST,%LENGTH-1,%REMAINING);	!Build argument list
	V=CPROC(RTN,ARGLST,STACK_LENGTH);
	V[P$NAME]=%SIXBIT %STRING(RTN);
	.V
	END%;

MACRO	WAKESET(IB)[REASON]=IB[%NAME(INT$,REASON)]=1%,
	ERRSET(IB)[REASON]=IB[%NAME(INT$,REASON)]=IB[%NAME(INT$S_,REASON)]=1%;

MACRO	NOINTS[]=	BEGIN
			LOCAL NOINTS_VAL;	!Value of block
			EXTERNAL INTENC;
			INTERRUPTS(OFF);
			INTENC=.INTENC+1;
			NOINTS_VAL=(%REMAINING);
			IF (INTENC=.INTENC-1) LEQ 0 THEN
				INTERRUPTS(ON);
			.NOINTS_VAL
			END%;
!System-dependant macro to represent name of process
MACRO PNAME(NAM)=%SIXBIT %STRING(NAM) %;