{***********************************************************************}
{									}
{ __InsIsr    Install an Interrupt Service Routine.			}
{									}
{ procedure __InsIsr(var IsrBlock     : _IsrCtrl;			}
{			 IsrIntType   : byte;				}
{			 IsrStackSize : word;				}
{			 IsrStackNum  : word;				}
{			 IsrAddress   : pointer;			}
{			 IsrIdent     : _IdentStr);			}
{									}
{	      IsrBlock	The ISR Control Block contains the information	}
{			used by the ISR dispatcher to invoke the ISR.	}
{	      IsrIntType						}
{			The interrupt vector number to be set.		}
{	      IsrStackSize						}
{			The number of bytes to allocate for the ISR	}
{			stack.	Each time the ISR is invoked the	}
{			specified number of bytes is provided on the	}
{			stack. This value must be at least as large as	}
{			needed by the ISR for allocation of automatic	}
{			variables and parameters.			}
{	      IsrStackNum						}
{			Maximum depth of nested invocations allowed for }
{			the ISR.  The value must be at least one.	}
{	      IsrAddress						}
{			The address of the Pascal routine which 	}
{			services the interrupt.  The actual parameter	}
{			can be passed as @ProcName, where ProcName is	}
{			the name of the ISR procedure.			}
{	      IsrIdent	An identifying string for the ISR.  This field	}
{			can be used to determine that the ISR has been	}
{			installed. See __IsInsIsr.			}
{									}
{ Description __InsIsr installs the address of the ISR Control Block	}
{	      into the specified interrupt vector.  The first bytes of	}
{	      the ISR Control Block make a call to the ISR dispatcher,	}
{	      placing the address of the ISR Control Block information	}
{	      on the stack.  In this way, the dispatcher has access to	}
{	      the information in the ISR Control Block. 		}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc.  1987		}
{_______________________________________________________________________}

procedure __InsIsr(var IsrBlock     : _IsrCtrl;
		       IsrIntType   : byte;
		       IsrStackSize : word;
		       IsrStackNum  : word;
		       IsrAddress   : pointer;
		       IsrIdent     : _IdentStr);

  var
    StackSpacePtr  : pointer;
    StackSpaceSize : longint;

  begin {__InsIsr}

    with IsrBlock do
      begin
	_IsrFarCode := $9A90;			 { NOP followed by CALL }
	_IsrDispPtr := _ExecIsrAddr;		 { Dispatcher address	}

	{ Round the stack size up so that it is an even number of	}
	{ paragraphs (this is required by the dispatcher), and make	}
	{ sure that the nesting level is at least one.			}

	_IsrStackPar   := (IsrStackSize + 15) shr 4;  { Size in paras	}
	_IsrStackSize  := _IsrStackPar shl 4;	      { Size in bytes	}

	if (IsrStackNum <= 0) then
	   _IsrLimit := 1
	else
	   _IsrLimit := IsrStackNum;

	{ Now allocate space for the ISR stack on the heap.  The size	}
	{ must be large enough to accommodate IsrStackNum occurrences	}
	{ of IsrStackSize stacks.  Moreover, the space is allocated so	}
	{ that the beginning of the stack area is paragraph aligned.	}

	StackSpaceSize := _IsrStackSize * _IsrLimit + 15;
	GetMem(StackSpacePtr,StackSpaceSize);
	_IsrStackSeg := _VectorAddr(StackSpacePtr)._Seg;
	if (_VectorAddr(StackSpacePtr)._Ofs <> 0) then
	   Inc(_IsrStackSeg);

	{ Initialize the working variables needed by the dispatcher.	}
	{ The _IsrStackDepth is the current offset (in paragraphs) of	}
	{ the ISR stack segment (SS) from the beginning of the space	}
	{ allocated for the ISR stack.					}

	_IsrStackDepth := 0;
	_IsrSS	       := _IsrStackSeg;
	_IsrSP	       := _IsrStackSize;
	_IsrDS	       := DSeg;
	_IsrAddress    := IsrAddress;
	_IsrPSP        := PrefixSeg;
	_IsrLevel      := 0;
	_IsrIdent      := IsrIdent;
	_IsrSignature  := 'BCI';
	GetIntVec(IsrIntType,_IsrPreVector);
      end;

    { Now set the vector to point to the far call op code of the ISR	}
    { Control Block.  When the ISR dispatcher gains control, the	}
    { address immediately on the stack points the ISR control block	}
    { _IsrStackSeg member.						}

    SetIntVec(IsrIntType,@IsrBlock)

  end;	{__InsIsr}
