Article 5796 of vmsnet.pdp-11:
> Alain Martineau (Alain.Martineau@ccr.hydro.qc.ca) wrote:
> : I have to write a RSX11m plus task that processes interupts as fast as
> : possible. All I got is the 3-4 pages from the directive manual. Anyone
> : has got some code that I could use as template. 

Attached is a copy of a paper originally written by James Wayda
and extensively edited by me.   It was used as a handout for
many DECUS presentations in the mid to late 1980's, as well as
the real-time seminars that I taught for DEC's Educational Services.

I apologize for the length of it (about 27 printed pages), but
I don't have time today to edit it down.   There are a few diagrams
towards the end that are missing the hand-drawn lines showing the
APR mapping.   If you (or anyone else) need them, send me your FAX
number and I will send copies.   Two working examples of CINT$
(and AST) code are included.

Obviously, this is the output from RUNOFF.   If anyone wants to
put this document in some kind of archive and needs the .RNO
file, just let me know.

--  Alan E. Frisbie               Frisbie@Flying-Disk.Com
--  Flying Disk Systems, Inc.
--  4759 Round Top Drive          (213) 256-2575 (voice)
--  Los Angeles, CA 90065         (213) 258-3585 (FAX)

-------------------- Start attachment --------------------








         
             Using the Connect to Interrupt Vector (CINT$) Directive
             -------------------------------------------------------


        Presented by:                        Original paper by:

        Alan E. Frisbie                      James G. Wayda
        Flying Disk Systems                  Fairchild Weston Systems



        The  RSX-11M  Connect  to  Interrupt  Vector  Directive  (CINT$)
        provides an efficient method of servicing Non-Dec, user designed
        peripherials,  provided  the  limitations  and interrupt service
        routine mapping are given careful consideration.  

        The  connect  to interrupt vector directive should be considered
        as an alternative to writing a device driver only if  the  peri-
        pheral is to be accessed by a single task,and the interrupt ser-
        vice routine and the data that  the  interrupt  service  routine
        references  will  fit  within a 4K word area.  If multiple tasks
        must access the peripheral (queueing of I/O is required), multi-
        ple  controllers  are to be serviced, or large buffers are to be
        accomodated, a conventional device driver should be  considered.
        A  device  driver  will  permit the use of large buffers without
        limiting the size of the interrupt service routine code, because
        these  buffers  are  not mapped by the same APR as the interrupt
        service routine.  Also a conventional device driver  facilitates
        the use of device timeouts, power fail recovery, and more easily
        accomodates NPR devices due to the services provided by the exe-
        cutive.  

        The  main problem encountered by the first time user of the con-
        nect to interrupt vector directive is in deciding how the inter-
        rupt service routine is to be mapped for the requirements of the
        particular application.  Some of these mapping  methods  require
        that a bias be added to all absolute addresses referenced by the
        interrupt service routine so that these addresses are within the
        APR5 mapping area.  Other methods of mapping do not require this
        bias, but the tradeoff here is that the maximum size of the  in-
        terrupt  service  routine  is  reduced.  The selection of one of
        these possible methods will depend upon the size of  your  task,
        the required size of the interrupt service routine, and the type
        of access that the task requires to the executive and  I/O  page
        in the user state.  This article provides a detailed description
        of these considerations along with two examples.  









































        Using the Connect to Interrupt Directive



        The CINT$ Directive Parameter Block
        -----------------------------------

        The  Directive  Parameter  Block (DPB) of the CINT$ Directive is
        generated in the current psect using the "$" form of the  macro.
        A  description of the arguments used to issue the directive fol-
        lows - 

                  CINT$   VEC, BASE, ISR, EDIR, PRI, AST

        VEC -     Interrupt  Vector address of the peripheral to be sup-
                  ported.  This Vector must be in the range of 60 (8) to
                  the  highest  Interrupt Vector specified during sysgen
                  (V$$CTR) and must also be a multiple of 4.  

                  (VEC = New PC, Vec+2 = New PSW)

        BASE -    This is the virtual base address of the Interrupt Ser-
                  vice Routine (ISR).  THIS ADDRESS DEFINES  A  4K  WORD
                  AREA  THAT MUST CONTAIN THE INTERRUPT SERVICE ROUTINE,
                  THE ENABLE/DISABLE INTERRUPT  ROUTINE,  AND  ANY  DATA
                  THAT THESE ROUTINES ACCESS.  

        ISR -     Virtual  address  of  the  Interrupt  Service Routine.
                  This address must be within the 4k Word Area described
                  above.  If the value of this argument is 0, the Execu-
                  tive will "disconnect" from the vector.  

        EDIR -     Virtual   Address  of  the  Enable/Disable  Interrupt
                  Routine.  When the CINT$ Directive is successfully ex-
                  ecuted,  this  routine is called with the carry clear.
                  The Routine detects the carry clear condition, and ex-
                  ecutes  the following instruction to Enable Interrupts
                  from the peripheral.  

                         "BIS #100,@#CSR"

                  When  the  disconnect  directive  is successfully exe-
                  cuted, this routine is called with the carry set.  The
                  Routine  detects the carry set condition, and executes
                  the following instruction to disable  Interrupts  from
                  the peripheral.  

                         "BIC #100,@#CSR"

        PRI -     This  is the Processor Priority at which the ISR is to
                  execute.  This priority is specified as PR4, PR5, PR6,
                  PR7.   These symbols can be defined at assembly by is-
                  sueing the Macro HWDDF$, found in [1,1] EXEMC.MLB,  or
                  they will be resolved by the task builder.  

        AST -     Virtual  address  of an AST Routine to be entered from
                  the Fork Level.  THIS ROUTINE  DOES  NOT  NEED  TO  BE
                  WITHIN THE 4K WORD AREA DEFINED ABOVE.  






























        Using the Connect to Interrupt Directive






                           Levels of Interrupt Processing
                           ------------------------------


        1)   Interrupt  Level - When  an  Interrupt  occurs,  control is
             transferred, via the Interrupt Transfer  Block  (ITB)  that
             has been allocated by the CINT$ directive, to the Executive
             routine $INTSC (Figure 1).  $INTSC then  transfers  control
             to  the Interrupt Service Routine specified by the argument
             "ISR" in the CINT$ Directive.  The processor  is  executing
             at  the  priority  level specified by the argument "PRI" in
             the CINT$ Directive, and is in the  System  State.   There-
             fore, Executive Directives may not be issued at this level,
             or a System Crash will result.  Note also  that  interrupts
             at the Level "PRI" and below are "Locked Out".  By Standard
             Convention, the total time executing at this  level  should
             not exceed 500 us.  

        2)   Fork Level - the Fork Level routine executes at a processor
             priority of Zero, and should be entered  if  processing  at
             the  Interrupt  Level will exceed 500 us.  This routine al-
             lows other Interrupts, and more time dependent tasks to  be
             serviced promptly.  If required, the Fork Level Routine can
             set a Local Event Flag, or Queue an AST to the AST  Routine
             specified  in  the  CINT$  Directive.   Note that Executive
             Directives are not permitted from the Fork  Level,  because
             the Processor is still in the System State.  

        3)   Task  Level - The Task Level is entered from the Fork Level
             by Queueing an AST, or setting a Local Event Flag that  the
             main  code is waiting for.  At the Task Level the processor
             has access to all of the tasks Virtual Address  space,  and
             Executive Directives are permitted from this level.  




        Using the Connect to Interrupt Directive



                   Connect to Interrupt Vector Directive Operation
                   -----------------------------------------------

        The basic operation performed by the CINT$ Directive in the Exe-
        cutive Module DRCIN is as follows:  

             *1)  The Vector is checked to determine if it is a multiple
                  of 4.  

             *2)  The Vector is checked to determine if it is within the
                  range of  the  lowest  Vector  Address  60(8)  to  the
                  highest Vector Address specified at sysgen time.  

             *3)  The  Vector  is  then checked to determine if it is in
                  use.  All unused Vectors on an RSX-11M System are ini-
                  tialized when the system is booted to point to the Ex-
                  ecutive Address $NONSI.  

                  This  Address simply contains a "RTI" instruction, and
                  is referred to as the  "Nonsense  Interrupt  Address".
                  If  the Vector points to $NONSI, then it is not in use
                  and may be connected to by the  CINT$  Directive.   If
                  the  Vector  does not point to $NONSI, then some other
                  peripheral is using it, and the Directive is rejected. 

             *4)  The  Address  of the Interrupt Service Routine and the
                  Enable/Disable Interrupt Routine are checked  to  make
                  sure  that they are not greater then 4k Words from the
                  Address "Base" specified in the CINT$ Directive.  

             5)   The    Task   is   set   to   Non-Checkpointable   and
                  Non-Shufflable.  

             6)   A  block of Memory is allocated in the Dynamic Storage
                  Region for the Interrupt Transfer Block (ITB).  

             7)   The  Virtual  Address "Base" is truncated to a 32 word
                  boundary by stripping bits 0-5.   The  truncated  base
                  address is then converted to a physical address (Block
                  Number) and saved at the location "X.REL" in  the  In-
                  terrupt  Transfer Block (Figure 2).  This address will
                  be loaded into Kernal APR5 to map the ISR when the In-
                  terrupt  occurs.  This physical address corresponds to
                  Virtual Address "120000" (First Address for APR5  map-
                  ping).  







































        Using the Connect to Interrupt Directive



             8)   The  APR5  Virtual  Address  of the ISR is computed as
                  follows and stored at  location  "X.ISR"  in  the  ITB
                  (Figure 2).  

                  ISR (APR5)  = ISR -(BASE & 177700) + 120000
                                .      .         .      .  .
                                .       .       .        ..
                                .        .     .       
                                .         .   .       APR5 BIAS
                                .          . .
                                .           .
                                .     Truncated Base
                                .        Address
                                  .         .
                                    .     .
                                      . .
                                       .
                          Distance from Truncated Base
                                     to ISR


        *NOTE:    If  the  CINT$  Directive  fails  any of these initial
                  checks, the directive is rejective, and  the  location
                  $DSW  will  contain  the  Error  Code.  (See Executive
                  Reference Manual for Error Codes).  

        9)   The  APR5  Virtual  Address of the Enable/Disable Interrupt
             Routine is computed as follows and stored at  the  location
             "X.DIS" in the ITB.  (Figure 2) 

             EDIR (APR5)  = EDIR -(Base & 177700) + 120000
                            .     .            .     .  .
                            .       .        .        ..
                            .         .    .        
                            .           ..          APR5 Bias
                            .     Truncated Base
                            .        Address
                              .         .
                                .     .
                                   .
                        Distance from Truncated
                              Base to EDIR


        10)  The opcode for "JSR R5, @#" (004737) is placed at the loca-
             tion "X.JSR" in the ITB, followed by the  Absolute  Address
             of the Executive Routine $INTSC (Figure 2).  

        11)  The  Interrupt  Vector is then loaded to point to the loca-
             tion "X.JSR" in the ITB.  (Figure 2).  


































        Using the Connect to Interrupt Directive



        12)  The  Enable/Disable  Interrupt  Routine is then called with
             the Carry Clear to allow the user to Enable Interrupts from
             the Peripheral.  

        13)  The "Return" instruction in the users Enable/Disable Inter-
             rupt routine causes a return to the task level code at  the
             instruction  following the "DIR$" that executed the connect
             directive.  


                                 An Interrupt Occurs
                                 -------------------

        1)   When  an Interrupt occurs, the current PC and PSW are saved
             on the stack.  the new PC and PSW are loaded from "VEC" and
             "VEC+2" respectively.  

        2)   The  Processor resumes execution at the JSR R5,@#$INTSC in-
             struction in the ITB.  (Figure 2).  

        3)   The  Executive Routine $INTSC, then loads the new processor
             priority from "X.PSW" in the ITB, and calls  the  ISR  from
             the pointer "X.ISR".  


                             Task Mapping Considerations
                             ---------------------------

        Any task that uses the CINT$ Directive must be built privileged.
        However, it is legal to use the /PR:0 switch to have  32k  words
        of  Virtual Address space available to the task.  As stated ear-
        lier, the 4k word area beginning as the Truncated Address "Base"
        must contain the following:  

        a)   The Interrupt Service Routine
        b)   The Enable/Disable Interrupt Routine
        c)   Any Data that is referenced by A or B above.

        Figure  3  illustrates  the mapping of a task that is built with
        the /PR:0 switch.  This mapping would be used by a task that can
        be up to 32K words in length, does not require access to the ex-
        ecutive and I/O page at the task level, but requires the maximum
        size  of  4K  words  for  the  interrupt  service  routine area.
        (ISR,EDIR,AND DATA REFERENCED BY THESE ROUTINES) When an  Inter-
        rupt  occurs, Kernal APR5 is loaded from location "X.REL" in the
        ITB to map the 4k Word Area starting at  the  truncated  Address
        "Base".  (Base & 177700) Kernal APR's 0-4 map the Executive, and
        APR7 maps the I/O Page.  Therefore, a task  with  /PR:0  mapping
        has access to the Executive and I/O Page from the Interrupt Ser-
        vice Routine or the Enable/Disable Interrupt Routine.  


































        Using the Connect to Interrupt Directive



        Only  Addresses  within  the  4k  word  APR5 mapping area may be
        referenced.  For example in Figure 3, to move the  absolute  Ad-
        dress "Data" to R4, the APR5 Address of Data must be used.  

        1)   Determine the APR5 Address of Data - 

             Data (APR5) = Data - (Base & 177700) + 120000
                           .        .         .      .  .
                           .          .     .         ..
                           .            . .
                           .             .         APR5 Bias
                           .       Truncated Base
                           .          Address
                           .             .
                             .         .
                                .    .
                                  ..
                        Distance from truncated
                       Base to the Address "Data"

        2)   The Instruction Executed would be - 

             Mov #Data - (Base & 177700) + 120000, R4.  

             To move the Word contained in the Address "Data" to R4, the
             following instruction would be executed - 

             Mov @#Data - (Base & 177700) + 120000, R4 

             NOTE:   If the interrupt service routine is writing data to
             a buffer and the user forgets to use the  APR5  address  of
             the  buffer,  disruption  of the executive will result, and
             probably cause a system crash.  In user state APR0 maps the
             user  task beginning at the task header, but in kernal mode
             APR0 maps the executive.   Thus  writing  to  absolute  ad-
             dresses  that  do not have the APR5 bias applied will write
             over part of the executive!  

             The  Address  relocation  described  above  could have been
             eliminated by using a PC Relative reference  to  "Data"  as
             follows - 

             Mov Data, R4 









































        Using the Connect to Interrupt Directive



             The  PC Relative reference is possible within the Interrupt
             Service Routine because the distance from the Mov  Instruc-
             tion to the Address "Data" is always constant, because Ker-
             nal APR5  Maps  both  addresses.   Note  that  PC  Relative
             references  should  not  be used to access the Executive or
             I/O page, because these Addresses are fixed, and the  Rela-
             tive  offsets  generated at assembly time do not apply when
             the APR5 mapping is in effect.  Therefore,  all  references
             from  the  ISR  to  the  Executive  or  I/O  Page  must  be
             absolute.* 

             Example-

             BIS #100,@#CSR               ;Enable Interrupts
             Call @#$Fork2                ;Creates a System Process

        *NOTE:    These  references may be made PC Relative provided the
                  argument "Base" in the CINT$ directive is set  to  the
                  constant "120000" and the task is built with the /PR:5
                  switch.  This will be explained in detail later.  

        Figure  4  illustrates  the mapping of a task that is built with
        the /PR:5 switch.  This mapping would be used by a task that can
        be up to 8K words in length and requires access to the executive
        and I/O page at the task level.  (12K WORDS IF ACCESS TO THE I/O
        PAGE  IS  NOT  REQUIRED) This method also provides for a maximum
        size of 4K words for the interrupt service routine.  (User APR's
        0-4 map the executive, APR7 maps the I/O page, and APR5 maps the
        task beginning at the header) 

        When an Interrupt occurs, the following mapping is in effect - 

        1)  Kernal APR's 0-4 map the Executive
        2)  Kernal APR7 maps the I/O Page
        3)  Kernal APR5 maps the ISR beginning at the truncated address
            "Base". (Note that any addresses before the truncated Base
            Address are not mapped.)

        Figure  5 is similar to Figure 4, except that the Address "Base"
        in the CINT$ Directive  has  been  replaced  with  the  constant
        "120000".  When the Interrupt occurs, Kernal APR5 is loaded from
        the ITB to map the task beginning at the header.  As can be seen
        from  Figure  5, the APR5 mapping of task at the Interrupt Level
        is exactly the same as before the absolute Interrupt occured  at
        the task level.  THEREFORE, APR5 BIASING OF ADDRESSES IS NOT RE-
        QUIRED.  ALSO REFERENCES TO THE EXECUTIVE OR  I/O  PAGE  MAY  BE
        MADE ABSOLUTE OR PC RELATIVE.  





































        Using the Connect to Interrupt Directive



        This  method  would be used by a task that can be up to 8K words
        in length and requires access to the executive and I/O  page  at
        the task level.  (12K WORDS IF ACCESS TO THE I/O PAGE IS NOT RE-
        QUIRED) Since APR5 biasing of addresses is not required,  coding
        of  the  interrupt  service routine is simplified, but one major
        disadvantage still exists -- 

        The  total  maximum  size  of the Interrupt Service Routine Area
        (ISR, EDIR and DATA these routines reference) is limited to - 

        8192 - (Header Size) - (Stack Size) - (Main Task Code and Data 
        Size.)

        This  could  limit the size of the ISR to a rather small area if
        the main task contains a lot of code and data.   An  alternative
        to  this method is illustrated in Figure 6.  In this example the
        location of the main task code and data and the  Interrupt  Ser-
        vice  Routine have been interchanged.  The total maximum size of
        the Interrupt Service Routine area is now limited to - 

        8192 - (Header Size) - (Stack Size)

        and  is  no longer dependent on the amount of main task code and
        data.  (Note that any Addresses and Data manipulated by the  In-
        terrupt  Service  Routine  must still be within the APR5 4k Word
        Mapping area.) The size of the entire task could be a maximum of
        12k Words, thus overmapping the I/O page in user mode.  Although
        at the Interrupt level, APR7 will still map the I/O Page.  












        Using the Connect to Interrupt Directive



                   Interrupt Service Routine Entry Conditions
                   ------------------------------------------

        When  the Interrupt Service Routine is entered, R5 points to the
        Fork Block in the ITB, (Figure 2) and R4 is saved and free to be
        used.  If the ISR uses registers 0-3, it must be responsible for
        saving and restoring them.  If  one  Interrupt  Service  Routine
        Services  multiple Vectors, the interrupting Vector can be iden-
        tified as follows - 

        MOV X.VEC - X.FORK (R5), R4

        R4  is  now  loaded with the Vector Address specified in the ITB
        for the Interrupting peripheral.  

        If  the  Interrupt  can be serviced within 500 us, the Interrupt
        Service Routine should execute a "Return" to dismiss the  inter-
        rupt.   Otherwise  the  Interrupt Service Routine should execute
        the following call - 

        Call @#$Fork2
        (Notice that Absolute Addressing must be used and the stack must
        be in the same state as when the ISR was entered) 

        This  routine creates a system process by saving the current PC,
        (Pointing at the instruction after call @#$Fork2) R5 and  R4  in
        the  Fork  Block  in the ITB.  (Figure 2) When the executive re-
        turns control to the ISR, execution will resume at the  instruc-
        tion  following  call  @#$Fork2,  and  the  processor will be at
        priority level 0.  R4 and R5 are the same  as  when  $Fork2  was
        called,  and  R3-R0 are saved and free to be used.  The instruc-
        tion immediately following Call @#$Fork2  must  always  be  "CLR
        @R3"  to  declare  the Fork Block Free.  Otherwise, the next at-
        tempt to enter the Fork Level routine  will  fail,  because  the
        Fork  Block  will appear to the executive as being in use.  Pro-
        cessing may then continue at the Fork Level until  a  return  is
        executed to dismiss the Interrupt, or the Fork Level Routine can
        set a local event Flag, or Queue the AST specified in the  CINT$
        directive.   To set a local event Flag, the following inputs are
        required - 

           R0 = Event Flag Number
           R5 = Task Control Block (TCB) address of the current task.
           The TCB Address is derived from the ITB as follows -
           (Figure 2)  (Note R5 points to X.Fork in the ITB).
           MOV X.TCB - X.Fork(R5),R5  ;R5 Now contains the 
                                      ;TCB Address
           MOV #EFN,R0                ;# of Event Flag to set
           CALL @#$SETF               ;Set the Event Flag

        Note  that  the Executive Directive to set an Event Flag (SETF$)
        could not have been used because the processor is  operating  in
        the System State, and a System Crash would result.  































        Using the Connect to Interrupt Directive



        To  Queue  the  AST  to  the  AST Routine specified in the CINT$
        directive, the following call is executed.  

        CALL @#$QASTC 

        The  AST  Routine  has complete access to the entire virtual ad-
        dress space of the task, and Executive Directives  can  be  exe-
        cuted  from this level.  To return from the AST, the AST Routine
        must pop one word (The Vector Address) off the Stack,  and  then
        execute  the  AST  Exit  Directive  (ASTX$S).  Execution is then
        resumed at the instruction following the Call @#$QASTC  instruc-
        tion.  


                        Enable/Disable Interrupt Routine
                        --------------------------------

        This  routine  is  called  when  the  main task issues the CINT$
        Directive.  If the CINT$ Directive successfully connected to the
        Interrupt  Vector,  this routine is called with the carry clear,
        and should execute the following instruction  to  Enable  inter-
        rupts from the peripheral - 

           BIS #100,@#CSR     ;Enable Interrupts
           Return             ;Return to main Task Code

        To  disconnect  from  an Interrupt Vector, the task executes the
        CINT$ Directive with the argument ISR = 0.  The following  func-
        tions are performed by the Disconnect Directive - 

        1)  Deallocated the ITB from the Dynamic Storage Region.  
        2)  Loads  the  Interrupt Vector to point to the Nonsense Inter-
            rupt Service Routine in the Executive.  ($NONSI).  
        3)  The  Task is set to checkpointable and shufflable regardless
            of its original condition.  





        Using the Connect to Interrupt Directive



        The  User  Enable/Disable Interrupt Routine is again called, but
        this time with the carry set.  The routine  should  execute  the
        following instruction to disable interrupts from the peripheral. 

            BIC #100,@#CSR     ;Disable Interrupts
            Return             ;Return to Main Task Code


                                    Examples
                                    --------

        The programs CONNECT and CONNECT1 perform the same function, and
        are described below.  CONNECT uses mapping that is identical  to
        Figure  4,  and  therefore requires APR5 biasing of absolute ad-
        dresses.  CONNECT1 uses mapping that is identical to  Figure  5.
        The  constant  "120000"  is  used  as the argument "base" in the
        CINT$ Directive, and APR5 biasing of absolute addresses  is  not
        required.  


                    CONNECT and CONNECT1 Program Description
                    ----------------------------------------

        These  routines  print a message to the Console Terminal by ser-
        vicing the transmit Interrupt within the task.  The Routine then
        enters  the  Fork  Level,  and  Queues  an AST.  The AST Routine
        prints a message to the users TI, and returns to the Fork Level.
        The Fork Level Routine then sets a local Event Flag to "Wake-Up"
        the main code.  The main code then disconnects from  the  Inter-
        rupt  Vector, restores the original system valuse to the Vector,
        prints a message, and exits.  

        **NOTE - These  routines must NOT be run from the console termi-
        nal, or a System Crash will result.  






        Using the Connect to Interrupt Directive



                              Detailed Description
                              --------------------

        1)   Save  the Console Interrupt Service Routine Address and PSW
             in the locations PCHLD and PSHLD respectively.  

        2)   Load  the Interrupt Vector to point to $NONSI.  This is re-
             quired for the CINT$ Directive to  be  successful,  because
             this Vector is already in use by the system.  

        3)   Issue the CINT$ Directive using the DIR$ Macro.  

        4)   the  Enable/Disable  Interrupt  Routine  (EDINT) is entered
             with the carry clear.  This routine enables the  Interrupt,
             and returns.  

        5)   Execution  resumes  at  the  instruction following the DIR$
             #CINT Directive (BCS Error).  

        6)   If  the Carry Flag is set, a branch to the Error Routine is
             executed.  The Error Routine (Error) saves the DSW in R1 to
             show  the  cause  of  the error, and then issues an IOT in-
             struction to terminate  program  execution,  and  dump  all
             registers.  

        7)   The  Main  Task  Code is then suspended by issuing the Wait
             for Single Event Flag Directive (WTSE$$ #2).  

        8)   The  Console  Terminal interrupts to request data.  The In-
             terrupt Service Routine is entered at the location "INTSER"
             at  PR4.   The Routine outputs the following message to the
             console terminal- 

                  Connect to Interrupt Vector Complete.
                  ISR will now go to the Fork Level and Queue the AST.

        9)   The  ISR  issues  a  call  to $Fork2 at the label "Done" to
             create a System Process.  

        10)  Execution  then  resumes  at  PR0 with the instruction "CLR
             @R3".  This instruction declares the Fork Block free.  

        11)  The  Fork  Level  Routine  then  issues a call to $QASTC to
             Queue the AST.  

        12)  The AST Routine is then entered at the label "TAST", and is
             at the task level.  





































        Using the Connect to Interrupt Directive



        13)  A  QIOW$S  Directive  is then issued to print the following
             message to the users TI - 

                  At the AST Level --- will now return to the main-line
             level.

        14)  An  AST  Exit Directive (ASTX$S) is then executed to return
             to the Fork Level.  

        15)  Execution   resumes   at  the  instruction  following  Call
             @#$QASTC (Mov #2,R0).  

        16)  The  address of the Task Control Block is then derived from
             the ITB using the following instruction.  

                  MOV X.TCB-X.Fork (R5),R5

             NOTE - When this instruction if executed, R5 points
                    to X.Fork in the ITB. (Figure 2)

        17)  A  call  to  the Executive Routine $SETF is executed to set
             Event Flag #2, and wake-up the main code.  A return is then
             executed to return from interrupt.  

        18)  The  Main  Task Code then resumes with the instruction fol-
             lowing the wait for event flag directive.  (DIR$ #DCINT) 

        19)  The disconnect from Interrupt Vector Directive is executed,
             and the Enable/Disable Interrupt Routine is entered at  the
             label  "EDINT"  with  the carry set.  This routine disables
             interrupts and returns.  

        20)  Execution  resumes at the instruction immediately following
             the Disconnect Directive (MOV PCHLD,TVEC).  

             The  Console  Interrupt Service Routine Address and PSW are
             restored.  The task then outputs the following  message  to
             the users TI, and Exits - 

                  Main Code Running --- Task will now exit.












































        Using the Connect to Interrupt Directive



                                   Conclusions
                                   -----------

        We  have  seen  that  the  connect to Interrupt Vector Directive
        provides and excellent method of servicing a peripheral  when  a
        device driver is not required.  The mapping considerations shown
        in Figures 5 and 6 should be used to eliminate APR5  biasing  of
        absolute  addresses  and  simplify  coding, unless the main task
        size or Interrupt Service Routine size does not permit.   Other-
        wise,  the  method shown in Figure 3 could be used to provide up
        to 32k words of Virtual Address space with a  maximum  Interrupt
        Service Routine size of 4k words, or the mapping shown in Figure
        4 if access to the Executive and I/O Page  is  required  at  the
        Task Level, and the Total Task size is less than 8k words.  (12k
        words if I/O Page access is not required at the Task Level).  

        References -

        1)   RSX-11M Executive Reference Manual
        2)   RSX-11M System Logic Manual
        3)   RSX-11M V4.0 Executive Source Code:
             SYSTX Module
             DRCIN Module

















        Using the Connect to Interrupt Directive



                    Control flow during interrupt processing



                  ---------------------
                  |                   |
                  |   VECTOR AREA     | ------>----+
                  |                   |            |
                  ---------------------            |
                  |                   |            |
                  |                   |            V
                  |                   |            |
                  |                   |            |
                  |   RSX EXECUTIVE   |            |
                  |                   |            |
                  |                   |            |
                  |     $INTSC        | <----------|-------+
                  | (Interrupt Save)  |            |       |
                  |   JSR  PC,ISR     | ----->-----|------------------+
                  |                   |            |       |          |
                  ---------------------            |       |          |
                  |                   |            V       |          V
                  |                   |            |       |          |
                  |                   |            |       |          |
                  |       POOL        |            |       |          |
                  |                   |            |       |          |
                  |                   |            |       |          |
                  |     Interrupt     | <----------+       |          |
                  |  Transfer Block   |                    |          |
                  |  JSR  R5,@#INTSC  | ----->-------------+          |
                  |                   |                               |
                  |                   |                               |
                  |                   |                               |
                  ---------------------                               |
                  |                   |                               |
                  |                   |                               |
                  |   GEN Partition   |                               V
                  |                   |                               |
                  |                   |                               |
                  |                   |                               |
                  |                   |                               |
                  |...................|                               |
                  |                   |                               |
                  |    Your task      |                               |
                  |                   |                               |
                  |                   |                               |
                  |    Your ISR       | <-----------------------------+
                  |                   |
                  |...................|
                  |                   |
                  |                   |
                  |                   |

                                    Figure 1






























        Using the Connect to Interrupt Directive



        Interrupt Vector

        Points to JSR R5, @#$INTSC
         |
         |
         |     ------------------------------------------------
         |     |               LINK TO NEXT ITB               | 0 X.LNK
         |     |----------------------------------------------|
         ----->|  004737                                      | 2 X.JSR
               |----------------JSR R5,@ #$INTSC              |
               |  ADDRESS OF $INTSC                           | 4
               |----------------------------------------------|
               |      UNUSED          |LOW BYTE OF PSW FOR ISR| 6 X.PSW
               |----------------------|-----------------------|
               |INTERRUPT SERVICE ROUTINE ADDR(APR 5 MAPPING) |10 X.ISR
               |----------------------------------------------|
               |                 LINK TO NEXT FORK BLOCK      |12 X.FORK
               |----             -----------------------------|
               |                          SAVED PC            |
               |----  FORKBLOCK  -----------------------------|
               |                          SAVED R5            |
               |----             -----------------------------|
               |                          SAVED R4            |
               |----------------------------------------------|
               |         RELOCATION BIAS FOR APR5             |   X.REL
               |----------------------------------------------|
               |  ADDRESS OF DISABLE INTERRUPT ROUTINE        |   X.DIS
               |----------------------------------------------|
               |        TCB ADDRESS OF OWNING TASK            |   X.TCB
               |----------------------------------------------|
               |           A.DQSR FOR AST BLOCK               |
               |----------------------------------------------|
               |                                              |   X.AST
               |----------                        ------------|
               |----------                        ------------|
               |----------                        ------------|
               |                                              |
               |----------      AST BLOCK         ------------|
               |                                              |
               |----------                        ------------|
               |                                              |
               |----------                        ------------|        1
               |              VECTOR ADDRESS                  |   X.VEC
               |----------------------------------------------|
               |              SAVED VECTOR PC                 |   X.VPC
               |----------------------------------------------| 

                1. IF AST SUPPORT THIS IS FIRST AND ONLY AST PARAMETER


                                    FIGURE 2

































        Using the Connect to Interrupt Directive



                                    TASK/PR:0

        Before INT occurs                          After INT occurs
        User APR's                                 Kernal APR's

        --------   VA=0 ----------------           -------- 
        | APR0 |        |   HEADER     |           | APR0 |  
        --------        ----------------           --------   
                        |   STACK      |                         -------
        --------        ----------------           ---------     |  E  |
        | APR1 |        |              |           | APR1  |     |  X  |
        --------        |              |           ---------     |  E  |
                        |              |                         |  C  |
        --------        | CODE & DATA  |           ---------     |  U  |
        | APR2 |        |              |           | APR2  |     |  T  |
        --------        |              |           ---------     |  I  |
                        |              |                         |  V  |
        --------        |              |           ---------     |  E  |
        | APR3 |        ----------------Base       | APR3  |     -------
        --------        |              |(VA120000) ---------
                  EDIR- | INT  SERVICE |-Data      
        --------        |   ROUTINE    |-ISR       ---------
        | APR4 |        |              |           | APR4  |
        --------        ----------------           ---------

        --------                                   ---------
        | APR5 |                                   | APR5  |
        --------                                   ---------

        --------                                   ---------
        | APR6 |                                   | APR6  |
        --------                                   ---------
                                                                 -------
        --------                                   ---------     | I/O |
        | APR7 |                                   | APR7  |     |PAGE |
        --------                                   ---------     -------

        Upon  entry  to the Interrupt Service Routine, APR5 maps the ISR
        and all data used by the ISR.  It does not map the Header, Stack
        or Code & Data before the Address "Base".  

        1)  The  Virtual Address "Base" is truncated to a Block Boundary
            (32 Word Boundary).  
        2)  This  Virtual  Address is then converted to a physical Block
            Number.  (Actual physical Address/100(8)).  
        3)  When  the interrupt occurs, this address is loaded into Ker-
            nal APR5 to map the ISR 4k Word Area starting at  the  trun-
            cated  Base  Address.   Therefore, Virtual Address 120000 is
            the truncated Base Address of the ISR.  (Base & 177700).  
        4)  An  absolute reference to the Address "Data" is performed as
            follows:  
                 Data (APR5) = Data-(Base & 177700) + 120000 

                                      FIGURE 3






























        Using the Connect to Interrupt Directive



                                    TASK/PR:5

                 Before INT occurs                 After INT occurs
                 User APR's                        Kernal APR's
                                  VA=120000
                  --------        -----------      -------- 
                  | APR0 |        | HEADER  |      | APR0 |  
                  --------        -----------      --------   
                                  | STACK   |                    -------
        -----     --------        -----------      ---------     |  E  |
        | E |     | APR1 |        |         |      | APR1  |     |  X  |
        | X |     --------        |         |      ---------     |  E  |
        | E |                     |         |                    |  C  |
        | C |     --------        |  CODE   |      ---------     |  U  |
        | U |     | APR2 |        |   &     |      | APR2  |     |  T  |
        | T |     --------        |  DATA   |      ---------     |  I  |
        | I |                     |         |                    |  V  |
        | V |     --------        |         |      ---------     |  E  |
        | E |     | APR3 |        -----------      | APR3  |     -------
        -----     --------        |   INT   |BASE  ---------
                            EDIR- | SERVICE |(VA120000)
                  --------        | ROUTINE |-DATA ---------
                  | APR4 |        |         |-ISR  | APR4  |
                  --------        -----------      ---------

                  --------                         ---------
                  | APR5 |                         | APR5  |
                  --------                         ---------

                  --------                         ---------
                  | APR6 |                         | APR6  |
                  --------                         ---------
        -------                                                  -------
        | I/O |   --------                         ---------     | I/O |
        |PAGE |   | APR7 |                         | APR7  |     |PAGE |
        -------   --------                         ---------     -------

        Upon  entry  to the Interrupt Service Routine, APR5 maps the ISR
        and all data used by the ISR.  It does not map the Header, Stack
        or Code & Data before the Address "Base".  

        1)  The  Virtual Address "Base" is truncated to a Block Boundary
            (32 Word Boundary).  
        2)  This  Virtual  Address is then converted to a physical Block
            Number.  (Actual physical Address/100(8)).  
        3)  When  the interrupt occurs, this address is loaded into Ker-
            nal APR5 to map the ISR 4k Word Area starting at  the  trun-
            cated  Base  Address.   Therefore, Virtual Address 120000 is
            the truncated Base Address of the ISR.  (Base octal 177700). 
        4)  An  absolute reference to the Address "Data" is performed as
            follows:  
                 Data (APR5) = Data-(Base octal 177700) + 120000 

                                      FIGURE 4






























        Using the Connect to Interrupt Directive



                       TASK/PR:5 (ARGUMENT "BASE"=120000)

                  Before INT occurs               After INT occurs
                  User APR's                      Kernal APR's

                              BASE            BASE
                              (VA120000)      (VA=120000)
                  --------        -----------      -------- 
                  | APR0 |        | HEADER  |      | APR0 |  
                  --------        -----------      --------   
                                  | STACK   |                    -------
        -----     --------        -----------      ---------     |  E  |
        | E |     | APR1 |        |         |      | APR1  |     |  X  |
        | X |     --------        |         |      ---------     |  E  |
        | E |                     |         |                    |  C  |
        | C |     --------        |  CODE   |      ---------     |  U  |
        | U |     | APR2 |        |   &     |      | APR2  |     |  T  |
        | T |     --------        |  DATA   |      ---------     |  I  |
        | I |                     |         |                    |  V  |
        | V |     --------        |         |      ---------     |  E  |
        | E |     | APR3 |        -----------      | APR3  |     -------
        -----     --------        |   INT   |-DATA ---------
                            EDIR- | SERVICE |-ISR
                  --------        | ROUTINE |      ---------
                  | APR4 |        |         |      | APR4  |
                  --------        -----------      ---------

                  --------                         ---------
                  | APR5 |                         | APR5  |
                  --------                         ---------

                  --------                         ---------
                  | APR6 |                         | APR6  |
                  --------                         ---------

        -------   --------                         ---------     -------
        | I/O |   | APR7 |                         | APR7  |     | I/O |
        |PAGE |   --------                         ---------     |PAGE |
        -------                                                  -------

        Upon  entry  to the Interrupt Service Routine, APR5 maps the en-
        tire task (Header, Stack, Code &  Data,  Int  Service  Routine).
        Therefore,  the  relocation  value in Kernal APR5 is the same as
        the same as the relocation value in user APR5 before the  Inter-
        rupt  occured.   This method preserves the original APR5 mapping
        and thus all address references from within the  Interrupt  Ser-
        vice  Routine  do  not require APR5 biasing.  Also references to
        the Executive and I/O Page can be made absolute or PC Relative. 

                                    FIGURE 5


































        Using the Connect to Interrupt Directive



                       TASK/PR:5 (ARGUMENT "BASE"=120000)

                   Before INT occurs               After INT occurs
                   User APR's                      Kernal APR's

                              BASE            BASE
                              (VA120000)      (VA=120000)
                  --------        -----------      -------- 
                  | APR0 |        | HEADER  |      | APR0 |  
                  --------        -----------      --------   
                                  | STACK   |                    -------
        -----     --------        -----------      ---------     |  E  |
        | E |     | APR1 |  EDIR- |         |-DATA | APR1  |     |  X  |
        | X |     --------        |  INT    |-ISR  ---------     |  E  |
        | E |                     | SERVICE |                    |  C  |
        | C |     --------        | ROUTINE |      ---------     |  U  |
        | U |     | APR2 |        |         |      | APR2  |     |  T  |
        | T |     --------        -----------      ---------     |  I  |
        | I |                     |         |                    |  V  |
        | V |     --------        |         |      ---------     |  E  |
        | E |     | APR3 |        |  CODE   |      | APR3  |     -------
        -----     --------        |   &     |       ---------
                                  |  DATA   |
                  --------        |         |      ---------
                  | APR4 |        |         |      | APR4  |
                  --------        -----------      ---------

                  --------                         ---------
                  | APR5 |                         | APR5  |
                  --------                         ---------

                  --------                         ---------
                  | APR6 |                         | APR6  |
                  --------                         ---------

        -------   --------                         ---------     -------
        | I/O |   | APR7 |                         | APR7  |     | I/O |
        |PAGE |   --------                         ---------     |PAGE |
        -------                                                  -------

        Upon  entry  to the Interrupt Service Routine, APR5 maps the en-
        tire task (Header, Stack, Code and Data,  Int  Service  Routine)
        therefore,  the  relocation  value in Kernal APR5 is the same as
        the relocation value in user APR5 before the interrupt  occured.
        This  method  preserves  the original APR5 mapping, and thus all
        address references from the Interrupt Service Routine do not re-
        quire  APR5  biasing.  Also, references to the Executive and I/O
        Page can be made absolute or PC relative.  This  method  permits
        the  Interrupt  Service  Routine area to be larger than when the
        mapping in figure 5 is used.  

                                    FIGURE 6
































        Using the Connect to Interrupt Directive



                                .TITLE  CONNECT
                                .IDENT  /02/
        ;
        ;
        ; THIS TASK DEMONSTRATES THE USE OF THE CONNECT TO INTERRUPT
        ; VECTOR DIRECTIVE BY SERVICING THE CONSOLE TERMINAL TRANSMIT
        ; INTERRUPT FROM AN INTERRUPT SERVICE ROUTINE CONTAINED WITHIN
        ; THIS TASK.
        ; THE ORIGINAL SYSTEM VALUE IS THEN RESTORED TO THE INTERRUPT
        ; VECTOR.
        ;
        ;***************************************************************
        ;NOTE--THIS TASK MUST NOT BE RUN FROM THE CONSOLE TERMINAL (TT0)
        ;***************************************************************
        ;
        ; ASSEMBLY INSTRUCTIONS:
        ;       MAC CONNECT,CONNECT=CONNECT
        ;
        ; TASK BUILD INSTRUCTIONS:
        ;       TKB CONNECT/PR:5,CONNECT=CONNECT,[1,54]RSX11M.STB/SS
        ;
        ;
                        .MCALL  CINT$,EXIT$S,ASTX$S,DIR$,WTSE$S,QIOW$S
                        .NLIST  BEX
        ;
        ;   DEFINITIONS-----
        ;
                CR=15                   ;CARRIAGE RETURN
                LF=12                   ;LINE FEED
                RCSR=177560             ;CONSOLE RECEIVE CSR
                RBUF=177562             ;CONSOLE RECEIVE DATA BUFFER
                TCSR=177564             ;CONSOLE XMIT CSR
                TBUF=177566             ;CONSOLE XMIT DATA BUFFER
                TVEC=64                 ;CONSOLE XMIT INTERRUPT VECTOR
                TPSW=66                 ;CONSOLE XMIT PSW
        ;
        PCHLD:  .WORD   0       ;TEMP STORAGE FOR RSX INT PC
        PSHLD:  .WORD   0       ;TEMP STORAGE FOR RSX INT PSW
        ;
        ;
        CINT:   CINT$   TVEC,ISRBAS,INTSER,EDINT,PR4,TAST  ;CONNECT DPB
        DCINT:  CINT$   TVEC                            ;DISCONNECT DPB
        ;
        MSG1:   .ASCII  <CR><LF><LF>
                .ASCII  /At the AST level -- Will now return to the /
                .ASCII  /main-line level./
        LMSG1=.-MSG1                            ;LENGTH OF MSG1
        MSG2:   .ASCII  <CR><LF>
                .ASCII  /Main-line code running -- task will now exit./
        LMSG2=.-MSG2                            ;LENGTH OF MSG2
                .EVEN
        ;
        ;
        ;






























        Using the Connect to Interrupt Directive



        START:  BIC     #100,RCSR       ;DISABLE RECEIVE INTERRUPTS
                MOV     @#TVEC,PCHLD    ;SAVE RSX INT PC
                MOV     @#TPSW,PSHLD    ;SAVE RSX INT PS
                MOV     #$NONSI,@#TVEC  ;DECLARE TVEC FREE TO BE USED
        ;                               ;(USE $NS0 ON M-PLUS)
                DIR$    #CINT           ;CONNECT TO INTERRUPT
                BCS     ERROR           ;IF ERROR--EXIT
                WTSE$S  #2              ;PUT TASK TO SLEEP
                DIR$    #DCINT          ;DISCONNECT FROM INTERRUPT
                MOV     PCHLD,@#TVEC    ;RESTORE RSX INT PC
                MOV     PSHLD,@#TPSW    ;RESTORE RSX INT PS
                QIOW$S  #IO.WLB,#5,#1,,,,<#MSG2,#LMSG2,#40>
        ;                               ;PRINT MSG2 TO TI:
                BIS     #100,RCSR       ;ENABLE RECEIVE INTERRUPTS
                EXIT$S
        ;
        ;
        ERROR:  MOV     $DSW,R1         ;GET DSW TO SHOW ERROR
                IOT                     ;TRAP AND DUMP REGISTERS
        ;
        ;
        ;===============================================================
        ;
        ; THIS ROUTINE IS ENTERED WHEN CALL @#$QASTC IS EXECUTED FROM
        ; THE FORK LEVEL.
        ; THIS ROUTINE IS AT THE TASK LEVEL AND HAS COMPLETE ACCESS TO
        ; EXECUTIVE DIRECTIVES.
        ;
        TAST:   QIOW$S  #IO.WLB,#5,#1,,,,<#MSG1,#LMSG1,#40>
        ;                                       ;PRINT AST MSG TO TI
                TST     (SP)+                   ;POP VECTOR FROM STACK
                ASTX$S                          ;EXIT THE AST
        ;
        ;===============================================================
        ;
        ; ISRBAS DEFINES A 4K WORD AREA THAT THE EXECUTIVE WILL MAP
        ; USING KERNAL APR 5 UPON ENTRANCE TO THE INTERRUPT SERVICE
        ; ROUTINE.
        ; THIS AREA MUST CONTAIN THE ENABLE/DISABLE ROUTINE, THE
        ; INTERRUPT SERVICE ROUTINE,AND THE DATA AREAS THAT THESE
        ; ROUTINES WILL MANIPULATE OR ACCESS.
        ;
        ;
        ISRBAS:
        ;
        CCNT:   .WORD   0               ;CURRENT CHARACTER COUNT
        MSG:    .ASCII  <CR><LF><LF>
                .ASCII  /Connect to interrupt vector complete./
                .ASCII  <CR><LF>
                .ASCII  /ISR will now go to the fork level/
                .ASCII  / and queue the AST./<15><12>
        LMSG=.-MSG
                .EVEN
        ;






























        Using the Connect to Interrupt Directive



        ;===============================================================
        ;
        ; ENABLE/DISABLE INTERRUPT ROUTINE -- THIS ROUTINE IS CALLED
        ; WHEN THE TASK CONNECTS OR DISCONNECTS FROM THE INTERRUPT
        ; VECTOR.
        ; IT IS ALSO CALLED IF THE TASK IS ABORTED TO DISABLE INTERRUPTS
        ;
        ;
        EDINT:  BCS     DIS             ;IF CARRY=1--DISABLE INTERRUPTS
                BIS     #100,@#TCSR     ;ENABLE INTERRUPTS
                RETURN                  ;RETURN TO CALLER
        DIS:    BIC     #100,@#TCSR     ;DISABLE INTERRUPTS
                RETURN                  ;RETURN TO CALLER
        ;
        ;===============================================================
        ;
        ; INTERRUPT SERVICE ROUTINE -- THIS ROUTINE IS ENTERED AT
        ; PRIORITY LEVEL 4 WHEN THE TERMINAL INTERRUPTS AND IS READY
        ; FOR ANOTHER CHARACTER.
        ; THIS ROUTINE AND THE DATA IT REFERENCES (BEGINNING AT ISRBAS)
        ; IS MAPPED BY KERNAL APR 5. (ISRBAS=VIRTUAL ADDRESS 120000)
        ;
        ; R4 = SAVED
        ; R5 = ADDRESS OF FORK BLOCK IN ITB.
        ;
        ;
        INTSER:CMP      #LMSG,CCNT      ;ALL OF MESSAGE OUTPUT YET ?
                BEQ     DONE            ;YES
                MOV     #MSG-<ISRBAS&177700>+120000,R4
        ;                       ; RELOCATE MESSAGE TO APR5 MAPPING
                ADD     CCNT,R4         ;POINT R4 AT NEXT CHARACTER
                MOVB    @R4,@#TBUF      ;OUTPUT THE CHARACTER
                INC     CCNT            ;POINT AT NEXT CHARACTER
                RETURN                  ;GO BACK TO SLEEP
        ;
        DONE:   CALL    @#$FORK2        ;CREATE A SYSTEM PROCESS
                CLR     @R3             ;DECLARE THE FORK BLOCK FREE
                CALL    @#$QASTC        ;QUE THE AST (GO TO TASK LEVEL)
                MOV     #2,R0           ;# OF EVENT FLAG TO SET
                MOV     X.TCB-X.FORK(R5),R5     ;R5 POINTS TO OUR TCB
                CALL    @#$SETF         ;SET EVENT FLAG FOR WAKE-UP
                                        ;OF THE MAIN CODE
                RETURN                  ;EXIT THE SERVICE ROTUINE
                .END    START








































        Using the Connect to Interrupt Directive



                                .TITLE  CONNECT1
                                .IDENT  /02/
        ;
        ; THIS TASK DEMONSTRATES THE USE OF THE CONNECT TO INTERRUPT
        ; VECTOR DIRECTIVE BY SERVICING THE CONSOLE TERMINAL TRANSMIT
        ; INTERRUPT FROM AN INTERRUPT SERVICE ROUTINE CONTAINED WITHIN
        ; THIS TASK.
        ; THE ORIGINAL SYSTEM VALUE IS THEN RESTORED TO THE INTERRUPT
        ; VECTOR.
        ;
        ;***************************************************************
        ;NOTE--THIS TASK MUST NOT BE RUN FROM THE CONSOLE TERMINAL (TT0)
        ;***************************************************************
        ;
        ; ASSEMBLY INSTRUCTIONS:
        ;       MAC CONNECT1,CONNECT1=CONNECT1
        ;
        ; TASK BUILD INSTRUCTIONS:
        ;       TKB CONNECT1/PR:5,CONNECT1=CONNECT1,[1,54]RSX11M.STB/SS
        ;
        ;
                        .MCALL  CINT$,EXIT$S,ASTX$S,DIR$,WTSE$S,QIOW$S
                        .NLIST  BEX
        ;
        ;   DEFINITIONS-----
        ;
                CR=15                   ;CARRIAGE RETURN
                LF=12                   ;LINE FEED
                RCSR=177560             ;CONSOLE RECEIVE CSR
                RBUF=177562             ;CONSOLE RECEIVE DATA BUFFER
                TCSR=177564             ;CONSOLE XMIT CSR
                TBUF=177566             ;CONSOLE XMIT DATA BUFFER
                TVEC=64                 ;CONSOLE XMIT INTERRUPT VECTOR
                TPSW=66                 ;CONSOLE XMIT PSW
        ;
        PCHLD:  .WORD   0       ;TEMP STORAGE FOR RSX INT PC
        PSHLD:  .WORD   0       ;TEMP STORAGE FOR RSX INT PSW
        ;
        ;
        ;
        CINT:   CINT$   TVEC,120000,INTSER,EDINT,PR4,TAST   ;CONNECT DPB
        DCINT:  CINT$   TVEC                            ;DISCONNECT DPB
        ;
        CCNT:   .WORD   0                       ;CURRENT CHARACTER COUNT
        ;
        MSG:    .ASCII  <CR><LF><LF>
                .ASCII  /Connect to interrupt vector complete./
                .ASCII  <CR><LF>
                .ASCII  /ISR will now go to the fork level/
                .ASCII  / and queue the AST./<15><12>
        LMSG=.-MSG
        ;
        MSG1:   .ASCII  <CR><LF><LF>
                .ASCII  /At the AST level -- will now return to the /






























        Using the Connect to Interrupt Directive



                .ASCII  /main-line level./
        LMSG1=.-MSG1                            ;LENGTH OF MSG1
        ;
        MSG2:   .ASCII  <CR><LF>
                .ASCII  /Main-line code running---task will now exit./
        LMSG2=.-MSG2                            ;LENGTH OF MSG2
                .EVEN
        ;
        ;
        ;
        START:  BIC     #100,RCSR       ;DISABLE RECEIVE INTERRUPTS
                MOV     @#TVEC,PCHLD    ;SAVE RSX INT PC
                MOV     @#TPSW,PSHLD    ;SAVE RSX INT PS
                MOV     #$NONSI,@#TVEC  ;DECLARE TVEC FREE TO BE USED
        ;                               ;(USE $NS0 ON M-PLUS)
                DIR$    #CINT           ;CONNECT TO INTERRUPT
                BCS     ERROR           ;IF ERROR--EXIT
                WTSE$S  #2              ;PUT TASK TO SLEEP
                DIR$    #DCINT          ;DISCONNECT FROM INTERRUPT
                MOV     PCHLD,@#TVEC    ;RESTORE RSX INT PC
                MOV     PSHLD,@#TPSW    ;RESTORE RSX INT PS
                QIOW$S  #IO.WLB,#5,#1,,,,<#MSG2,#LMSG2,#40>
        ;                               ;PRINT MSG2 TO TI:
                BIS     #100,RCSR       ;ENABLE RECEIVE INTERRUPTS
                EXIT$S
        ;
        ;
        ERROR:  MOV     $DSW,R1         ;GET DSW TO SHOW ERROR
                IOT                     ;TRAP AND DUMP REGISTERS
        ;
        ;
        ;===============================================================
        ;
        ; THIS ROUTINE IS ENTERED WHEN CALL @#$QASTC IS EXECUTED FROM
        ; THE FORK LEVEL.
        ; THIS ROUTINE IS AT THE TASK LEVEL AND HAS COMPLETE ACCESS TO
        ; EXECUTIVE DIRECTIVES.
        ;
        TAST:   QIOW$S  #IO.WLB,#5,#1,,,,<#MSG1,#LMSG1,#40>
        ;                                       ;PRINT AST MSG TO TI
                TST     (SP)+                   ;POP VECTOR FROM STACK
                ASTX$S                          ;EXIT THE AST
        ;
        ;===============================================================
        ;
        ; ENABLE/DISABLE INTERRUPT ROUTINE -- THIS ROUTINE IS CALLED
        ; WHEN THE TASK CONNECTS OR DISCONNECTS FROM THE INTERRUPT
        ; VECTOR.
        ; IT IS ALSO CALLED IF THE TASK IS ABORTED TO DISABLE INTERRUPTS
        ;
        ;
        EDINT:  BCS     DIS             ;IF CARRY=1--DISABLE INTERRUPTS
                BIS     #100,@#TCSR     ;ENABLE INTERRUPTS
                RETURN                  ;RETURN TO CALLER






























        Using the Connect to Interrupt Directive



        DIS:    BIC     #100,@#TCSR     ;DISABLE INTERRUPTS
                RETURN                  ;RETURN TO CALLER
        ;
        ;===============================================================
        ;
        ; INTERRUPT SERVICE ROUTINE -- THIS ROUTINE IS ENTERED AT
        ; PRIORITY LEVEL 4 WHEN THE TERMINAL INTERRUPTS AND IS READY
        ; FOR ANOTHER CHARACTER.
        ;
        ; R4 = SAVED
        ; R5 = ADDRESS OF FORK BLOCK IN ITB.
        ;
        ;
        INTSER:CMP      #LMSG,CCNT      ;ALL OF MESSAGE OUTPUT YET ?
                BEQ     DONE            ;YES
                MOV     #MSG,R4         ;ADDRESS OF MESSAGE TO R4
                ADD     CCNT,R4         ;POINT R4 AT NEXT CHARACTER
                MOVB    @R4,@#TBUF      ;OUTPUT THE CHARACTER
                INC     CCNT            ;POINT AT NEXT CHARACTER
                RETURN                  ;GO BACK TO SLEEP
        ;
        DONE:   CALL    @#$FORK2        ;CREATE A SYSTEM PROCESS
                CLR     @R3             ;DECLARE THE FORK BLOCK FREE
                CALL    @#$QASTC        ;QUE THE AST (GO TO TASK LEVEL)
                MOV     #2,R0           ;# OF EVENT FLAG TO SET
                MOV     X.TCB-X.FORK(R5),R5     ;R5 POINTS TO OUR TCB
                CALL    @#$SETF         ;SET EVENT FLAG FOR TASK WAKE-UP
        ;                               ;OF THE MAIN CODE
                RETURN                  ;EXIT THE SERVICE ROTUINE
                .END    START










-------------------- End attachment --------------------