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 .ASCII /At the AST level -- Will now return to the / .ASCII /main-line level./ LMSG1=.-MSG1 ;LENGTH OF MSG1 MSG2: .ASCII .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 .ASCII /Connect to interrupt vector complete./ .ASCII .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-+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 .ASCII /Connect to interrupt vector complete./ .ASCII .ASCII /ISR will now go to the fork level/ .ASCII / and queue the AST./<15><12> LMSG=.-MSG ; MSG1: .ASCII .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 .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 --------------------