.PAGE SIZE 58, 85 .NONUMBER .LEFT MARGIN 10 .RIGHT MARGIN 75 .NO FILL .NO JUSTIFY # .SKIP 5 .CENTER The RSX Multi-Tasker .SKIP .CENTER October, 1988 .SKIP .CENTER "SATCHL:#.WORD##0############; Go White Sox" .SKIP .CENTER Fine Realtime Commentary Since 1975 .SKIP 6 .CENTER ^&Table of Contents\& .SKIP 2 .TAB STOPS 65 Food for Thought RSX-1 The Editor's Corner RSX-1 Tribute RSX-2 Uncut Gems from Your Leadership RSX-3 Submitting Articles to the Multi-Tasker RSX-3 And That's The Way Things Are RSX-4 Event Flags, Significant Events and V4.0 M-Plus RSX-5 Fall 1987 DECUS Q_&A Update RSX-6 More Programming Techniques for User Written Drivers RSX-9 Adding Powerfail Detection to RSX Device Drivers RSX-19 .JUSTIFY .FILL .SKIP 14 .LM +5 .RM -5 Opinions expressed in the editorial section of the ^&Multi-Tasker\& are those of the Editor. They do not represent the official position of the RSX SIG nor that of DECUS leadership in general. .LM -5 .RM +5 .PAGE .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT Food for Thought .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT # .SKIP 7 .AUTOPARAGRAPH .CENTER Food for Thought .SKIP "Why level downward to our dullest perception always, and praise that as common sense? The commonest sense is the sense of men asleep, which they express by snoring." .SKIP 2 .INDENT 30 - Henry D.# Thoreau .INDENT 30 ##"Walden, or Life in the Woods" .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT The Editor's Corner .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .SKIP 9 .CENTER The Editor's Corner .SKIP .CENTER Bruce R. Mitchell .SKIP Thanks in no small part to massive efforts by the West Coast members of the SIG, we once again have enough material to publish an issue of the ^&Multi-Tasker\&. Hint, hint. Gentle reminder. It's no big deal, ladies and gentlemen, to sit down at your terminal for half an hour, pound out a raw article, put it on floppy, and send it to the Editor. Some of you even have departmental secretaries who can put the stamp on the floppy mailer. From that point on out, the Editor takes over, corrects spelling and grammar, checks for technical correctness, formats to fit Newsletter specifications, sends in finished copy. I really don't mind doing these things ^&but\& you've got to send me something to work with. We ^&need\& submissions from RSX rookies and casual users. After ten years in the saddle the SIG leadership can't write introductory articles worth toad squat. That is, when I can even get ^&them\& to write anything. Well, Larry Baker weighs in with an excellent pair of articles this month for all you driver writers. The Editor blushes to disclose that he has a little article on the V4.0 revision to the round-robin scheduler. And DEC responds to some unanswered questions from previous symposia Q_&A sessions. So here we go once more around the track, but first ... it's a twofer this time ... one serious ("editoria seria"), and one funny ("editoria funnya"). .TEST PAGE 6 .SKIP 3 .CENTER ----- Tribute ----- As faithful readers of these pages know by now, the Editor bends the knee to no man. "Civis Romanus sum" is the unspoken motto of the Editor. This month the Editor breaks that tradition to offer tribute. An honorable tribute to an honorable man. All great organizations owe their continued existence to those individuals of clear sight and uncompromising virtue who refuse to sell their purpose. For the laws of thermodynamics apply to organizations as well as to physical systems, and to preserve order in the face of entropy demands resolution of the highest sort. It is to such an individual I would now commend your attention as members of this group we call DECUS. In the face of entrenched bureaucracy, this man stepped forth alone to stand for the right. His election to high office reminded many that office is held by the consent of the governed, and not by permit, writ, charter nor indulgence. He actively sought counsel of the general membership in making decisions affecting all. When control was slowly and subtly wrought from the membership, he worked to return it to them. When he was but one man among many, his voice was heard clear and true. When offered tainted bargains, he spurned them. The record shows that he did not compromise the high ideals he presented when he offered us his efforts in service of the higher vision. Today we begin to see the fruits of his efforts emerging. If he chooses to rest from his labor, why, it is well deserved, and bought and paid for manyfold. "If we see farther and more clearly, it is because we stand on the shoulders of giants."### Robert F.# Curley is such a man. .TEST PAGE 8 .SKIP 3 .CENTER ----- Uncut Gems from Your Leadership ----- Many of you ^&Multi-Tasker\& readers may not be aware that the DECUS leadership publishes its own newsletter. This newsletter is called ^&SUGgestions\&, and appears about monthly to bimonthly. There are lots of interesting things in ^&SUGgestions\&. Regrettably you never see most of them. The Editor culls some of what he considers the best from the June issue for this month's editorial. .SKIP .LM +2 .RM -2 Page 6. "A new mission statement was developed to read as: 'The mission of the Management Council is to oversee the management of the business, operations, and resources of the U.S. Chapter in support of the Chapter's strategic directions.'" [#Ed: The Board of Directors must be glad to have that load taken from their shoulders ...#] Page 26. "EDITORIAL POLICY: It was stated that editorials can be in the newsletters, as long as editorial 1 Are clearly identified as an editorial. 2 Include an appropriate disclaimer 3 Provide opportunity for timely rebuttal 4 Clearly identify author(s) of the editorial. (Final text of the editorial guidelines will be distributed via DCS.)## [#Ed: My cup runneth over ...#] .SKIP .LM -2 .RM -2 But don't take my word for it. After all, DECUS is your society. I showed these to a couple of SIG members - a fella name of Jeffrey Bostwick gave me a succinct response which I cannot better: "Ghaaaaaa!" .TEST PAGE 6 .SKIP 3 .CENTER ----- Submitting Articles to the Multi-Tasker ----- Please submit machine readable media. RX01/2, RX50 and 9 channel 800/1600 BPI magtape are preferred. Almost any medium I can't read can be converted. All RSX volume formats are acceptable, but please don't send VMS Backup or ODS-2 format media. You can also submit articles through the RSX bulletin board system at (612) 777-7664. The Editor loves you if you do so. Kermit the file in and send it via MAIL to username MULTITASKER. Or you can submit via BITNET. Send articles to CICHANOWSKI@MSUS1 and precede the article with "Please forward to WSU::WNIMHACKR". Submissions which aren't machine readable may take longer to get into print. If you format your submission in RUNOFF, please set page size 58,80; left margin 10; right margin 75; and, when changing margins, use incremental changes rather than absolute. The editor thanks you for the consideration. Send your articles and other submissions to the luxurious all-new Multi-Tasker offices: .SKIP .NO FILL .NO JUSTIFY Bruce R. Mitchell Machine Intelligence and Industrial Magic RR _#1, Box 216 Fountain City, MN###54629 .JUSTIFY .FILL .TEST PAGE 6 .SKIP 3 .CENTER ----- And That's The Way Things Are ----- _... this month in Pool Lowbegone, where the new leadership is strong, our IAS brothers are handsome, and the outlook for the future is above average. .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT Event Flags, Significant Events and V4.0 M-Plus .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .TEST PAGE 15 .SKIP 4 .CENTER Event Flags, Significant Events and V4.0 M-Plus .SKIP 2 .CENTER Bruce R.# Mitchell .CENTER Machine Intelligence and Industrial Magic .CENTER RR _#1, Box 216 .CENTER Fountain City, WI###54629 .SKIP [#Editor's note: The following is an extract from a forthcoming RSX programming textbook and is copyright (c) 1988, Bruce R. Mitchell and Denny J. Walthers. Used by permission.#] .SKIP Keep the following fact in your mind constantly when you use event flags for intertask synchronization and control: .SKIP FIDDLING WITH EVENT FLAGS DOES NOT CAUSE A SIGNIFICANT EVENT. .SKIP Now, we're going to repeat that to make sure you remember it, because it's very important and the majority of RSX programmers don't seem to know it. I tell you three times, and what I tell you is true: .SKIP SETTING AND CLEARING EVENT FLAGS DOES NOT, DOES *NOT*, DOES ABSOLUTELY *** NOT *** CAUSE A SIGNIFICANT EVENT. .SKIP This is very, very important to you as an RSX programmer. Don't ever forget it. Here is why it is important. There are only a few things in the RSX system that can cause a context switch from the current task to a new task. Setting and clearing event flags is not one of those things. By way of example: Task A sets global event flag 36 and then stops itself. Task B is waiting for global event flag 36. Task B may wait for hell to freeze over before continuing, if there is little or no I/O going on in the host system. I/O causes significant events, which cause the scheduler to reevaluate which tasks are eligible to run, which hopefully eventually causes task B to continue from its wait state. Simply setting the event flag does NOT cause the scheduler to run. In releases of RSX-11M-Plus and Micro/RSX prior to V4.0, this is not often a major problem due to the way the Exec round-robin algorithm works in those releases. The round-robin code causes a scheduler run at the expiration of every round-robin interval, so the longest a task can wait for a global event flag is one round-robin interval. This is not excellent response, but is often acceptable if the ultimate in response is not required. In V4.0 of RSX-11M-Plus and Micro/RSX, the round-robin algorithm is changed to improve system performance. The new round-robin code does not cause a scheduler run at the expiration of a round-robin interval if there is no contention for the CPU. In other words, if at least two tasks of the same priority within the round-robin priority limits are not competing, no scheduler run occurs at the expiration of the round-robin interval. Tasks waiting for global event flags can wait for minutes or hours in systems with low I/O activity. Contrary to some opinions, Digital did not deliberately "break" M-Plus. The problem exists ^&in the user code\& due to violation of RSX design rules. It was previously masked by the round-robin Exec code. One symptom typical of this problem in systems with accounting active is that the host system "breaks loose" every five minutes. This is caused by execution of accounting temporary file updates, which cause I/O, which in turn cause scheduler runs. Running RMD on the system to find the problem causes the problem to go away, of course. RMD updates its terminal screen once per second, ensuring that at least one scheduler run occurs each second. The solution to this problem is very simple. Remember it and you'll never be burned by response time due to event flag waits. .SKIP WHEN SETTING OR CLEARING AN EVENT FLAG WHICH MAY AFFECT ANOTHER TASK, USE DECL$ AFTER THE SETF$ / CLEF$ TO DECLARE A SIGNIFICANT EVENT AND FORCE A SCHEDULER RUN. .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT Fall 1987 DECUS Q_&A Update .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .TEST PAGE 18 .SKIP 4 .CENTER Fall 1987 DECUS Q_&A Update .SKIP 2 .CENTER Brian S.# McCarthy .CENTER Digital Equipment Corporation .SKIP There were a number of questions and requests from the Q&A session at Fall DECUS in Anaheim that we were unable to answer on the spot. Below is a list of these problems and suggestions along with the responses from the RSX Development group. .LM +4 .SKIP 2 .INDENT -4 Q:##A terminal is initially set up as full duplex. After a user logs in, it is set to half duplex. .SKIP .INDENT -4 A:##There are 2 situations in which a terminal is reset to half duplex. When a user logs out, BYE resets the terminal to half duplex, and it remains that way when the next user logs in. If a LAT terminal is set to full duplex when no one is logged on, the initialization for the LAT terminal also resets the terminal to half duplex. This is the expected and desired behavior in the general case. .SKIP 2 .INDENT -4 Q:##The documentation for the logical name directives in the ^&Executive Reference Manual\& is different from the documentation in the ^&Mini-Reference Guide\&. .SKIP .INDENT -4 A:##The documentation in the ^&Mini-Reference Guide\& contains a number of technical mistakes. Please refer to the Version 4.0 ^&RSX-11M-Plus and Micro/RSX Executive Reference Manual\& for the correct information. .SKIP 2 .INDENT -4 Q:##There are certain tasks on the M-Plus kit in [3,54] which are not documented such as MINUTL.TSK. There are other files which are unnecessary such as DCL.STB and F11MSG.STB. .SKIP .INDENT -4 A:##Certain tasks which are specific to Micro/RSX were shipped with the V4.0 RSX-11M-Plus kits. These tasks are removed from the RSX-11M-Plus V4.1 kit. Other unnecessary files are also removed. .SKIP 2 .INDENT -4 Q:##Is there any possibility that loadable crash drivers will be supported under RSX-11M-PLUS? If so, which devices will be allowed? .SKIP .INDENT -4 A:##Support for loadable crash drivers is included in RSX-11M-Plus V4.1. The devices supported are DU:, MU:, MS:, DL: and MM:. .SKIP 2 .INDENT -4 Q:##Why have the sources for Indirect been removed from the kits? .SKIP .INDENT -4 A:##We have traditionally distributed the sources for privileged components on the kit. All sources for non-privileged utilities were (and are) available only from the source kit, purchased separately. .SKIP During the V4.0 development cycle, we moved around certain components on our master packs so there wouldn't be so much overlap in certain directories. The sources for Indirect were moved from UFD [12,10]. .SKIP The reason they have been shipped in the past is simply because they resided in the same directory as MCR and the entire directory was copied from our master packs to the kit. These sources are now available with the rest of the non-privileged sources on the source kit. We will consider adding these back to the kit in a future release for your convenience. .SKIP 2 .INDENT -4 Q:##There are a number of new ELI switches which are undocumented. These are useful and provide an easier interface to error logging. Will these be documented for M-Plus? .SKIP .INDENT -4 A:##There were a number of enhancements made for Micro/RSX to allow use of the error logging system by non-technical users. to common sources, these changes also became a part of the RSX-11M-Plus V3.0 kits. .SKIP However, there are a number of limitations with this support under RSX-11M-PLUS. The only devices currently supported are those which are supported under Micro/RSX. Also, there is additional overhead in logging an error when the new options for Micro/RSX are used. For these reasons, the support was not documented for RSX-11M-Plus and was turned off in RSX-11M-Plus V4.0. We will consider expanding and incorporating this support into a future release of RSX-11M-PLUS. .SKIP 2 .INDENT -4 Q:##EDTRES bombs out with a small (30 line) initialization files or when too many buffers are opened. EDT and EDTFSL seem to work fine. Please either fix EDTRES or delete it from the kits. .SKIP .INDENT -4 A:##Using the resident library configuration of EDT (EDTRES.ODL) and having multiple DEFINE KEY commands (usually associated with an EDT initialization file) substantially reduces EDT's performance. In addition multiple DEFINE KEY commands and/or numerous open buffers may cause EDT to abort with a Memory Protect Violation error message. This restriction is documented on page A-5 of the ^&EDT Editor Manual\&. .SKIP Even with these limitations, the EDTRES configuration is still useful on limited memory systems. Therefore, it should continue to be made available. .SKIP The non-resident configuration overlay structures improve EDT's performance by enabling more DEFINE KEY commands to be used. We recommend that users with large EDT initialization files as mentioned above use a non-resident EDT configuration. This configuration may be installed as a separate EDT task. .SKIP 2 .INDENT -4 Q:##When building an RSX-11M-Plus Executive without support for external headers, the symbol $HEADR comes up undefined for DIR11M and DR211M. .SKIP .INDENT -4 A:##This problem is cosmetic only and does not affect the functioning of your system. It is corrected in V4.1 of RSX-11M-Plus. .SKIP 2 .INDENT -4 Q:##How about changing the default extension on batch command files from .CMD to .BAT? .SKIP .INDENT -4 A:##We believe that this is useful, and plan to implement this change in a future release. The new behavior will look for .BAT files first, and if not found, will default back to .CMD files. This ensures that applications that depend on the .CMD default continue to work. .SKIP 2 .INDENT -4 Q:##There should be no HELP allowed for non-logged in terminals. Or, a single help file should always be forced. .SKIP .INDENT -4 A:##We will look into a method for making HELP optionally disable a user at a non-logged in terminal from obtaining HELP text. .SKIP 2 .INDENT -4 Q:##You cannot specify a directory for the VFY command. .SKIP .INDENT -4 A:##We are unable to reproduce this problem. VFY does accept a device, directory and file specification for the output list file. If this problem still exists under V4.0, please send us an SPR with the appropriate command lines which will reproduce the problem. .LM -4 .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .TEST PAGE 15 .SKIP 4 .CENTER;More Programming Techniques for User Written Drivers .CENTER;(an addendum to "Timer Support for User Written Drivers") .BLANK 2 .CENTER;Lawrence M. Baker .CENTER;U. S. Geological Survey .CENTER;345 Middlefield Road##MS977 .CENTER;Menlo Park, CA##94025 .SKIP .; .; $ Runoff Drivers .; .PAGE SIZE 58,80 .LEFT MARGIN 10 .RIGHT MARGIN 75 .TAB STOPS 18,26,34,42,50,58,66,74 .STYLE HEADERS ,0 .FLAGS PERIOD .; .; .BLANK 2 I would like to add some comments to Jim Bostwick's excellent article in the April 1988 issue of the ^&Multi-Tasker\&, "Timer Support for User Written Drivers" [1]. It so happens that I am in the process of writing a communications device driver for RSX-11M/M-Plus which makes use of the clock queue services he describes. He mentions that one must not unload a driver which has a clock block in the clock queue. This is normally true. However, there are several ways to get around this problem, which are described in the sections below. .BLANK Additionally, Jim stated that the driver service routine must save and restore all registers. By my reading of the code (in module TDSCH), no register saves and restores are required. R4 is always refreshed from the clock queue listhead pointer, $CLKHD, and R5 is picked up from the "request type" field (C.RQT) in the clock block. Any other values used in TDSCH are calculated using these values. Furthermore, on a multi-processor RSX-11M-Plus system, if the clock block specifies a Unibus-Run Mask, TDSCH must conditionally fork to the correct processor, which ^&never\& saves anything but R4 and R5. To me, that's a dead giveaway that the rest of us don't have to worry either. .BLANK Finally, while I've got your attention, I thought I would describe another useful technique I have devised to protect an RSX-11M system when a driver is unloaded with device interrupts enabled. .BLANK I should warn you all up front, however, that I rarely have a chance to test my code on an RSX-11M system. Usually, I enable the code on an RSX-11M-Plus system and test it that way. I try to write all my drivers to be compatible with both RSX-11M and RSX-11M-Plus, but since we no longer have any RSX-11M systems under software maintenance, we no longer have a current RSX-11M distribution kit. I welcome your comments, either personally or through the ^&Multi-Tasker\&, on on these ideas. .BLANK 2 .CENTER;Disclaimer .BLANK No warranty, expressed or implied, is made by the United States Department of the Interior, Geological Survey, as to the accuracy and functioning of the program and related program material, nor shall the fact of distribution constitute any such warranty, and no responsibility is assumed by the Geological Survey in connection therewith. .; .SKIP 4 .CENTER;^&Unloading_ Drivers_ With_ Active_ Clock_ Queue_ Requests\& .; .HEADER LEVEL 1 RSX-11M-Plus Drivers .; If a driver only needs a single clock block to service all devices, e.g., for implementing I/O request timeouts in a driver that maintains its own internal queues, the RSX-11M-Plus Controller Table (CTB) may have an 8-word clock block* .FOOTNOTE .LEFT MARGIN 10 .RIGHT MARGIN 75 .LITERAL _______________ .END LITERAL .BLANK .LEFT MARGIN +2 .INDENT -2 *#The ClkDf$ macro defines the length of a clock block to be 9 words. However, since the last word is not used for a system-type request, it is safe to allocate only 8 words here. .LEFT MARGIN -2 .END FOOTNOTE prepended [3]. Setting LS.CLK ("clock block allocated") in the CTB status byte (L.STS) informs LOAd and UNLoad of its presence. When the driver is loaded, if LS.CLK is set, LS.CBL ("clock block linked into clock queue") is clear, and the request type in the clock block (C.RQT) is C.SYST ("internal system call"), LOAd will relocate the driver entry point $xxTMO (which must be global) and insert it at C.SUB in the clock block. When the driver is unloaded, if both LS.CLK and LS.CBL are set, and the entry point at C.SUB is located in the driver, then UNLoad will remove the entry from the clock queue. Thus, the driver need only concern itself with properly setting and clearing LS.CBL in L.STS to indicate the correct state of the clock block. .BLANK RSX-11M-Plus offers two other features that drivers may use to remove outstanding timer requests. If a clock block is associated with a particular controller or unit, then the driver can remove it in the controller or unit offline routines, xxKRB and xxUCB, respectively. For clock blocks not associated with a particular controller or unit, the driver can provide the $xxUNL entry point to gain control during the unloading process to remove them from the clock queue. (I have never tried the latter approach, however.)+ These routines are documented in the ^&RSX-11M-Plus_ Guide_ to_ Writing_ an_ I/O_ Driver\& [3], sections 4.5.9 (Controller Status Change Entry Point), 4.5.10 (Unit Status Change Entry Point), and 4.3.6 (Loadable Driver Entry Points for LOAD and UNLOAD). The UNLoad module UNLCTL contains the code for removing the clock block at label DOCTB, which may be used as a template for a driver routine. (Source code for MCR commands is found in UFD [12,10] on the distribution kit.) .; .HEADER LEVEL 1 RSX-11M Drivers .; Unfortunately, RSX-11M has no concept of taking a controller or a unit offline, nor is a driver informed when it is about to be unloaded [2]. Consequently, I have devised a "safe" clock queue transfer block, which is similar to the interrupt control block (ICB) used with loadable drivers. When the timer expires, the executive calls this small piece of code (residing in system pool) which is guaranteed to be there even if the driver has been unloaded. The "safe" entry point examines the Device Control Block (DCB) offset D.DSP ("address of driver dispatch table") to determine if the driver is still loaded. (D.DSP is non-zero only if the driver is still in memory -- the same test is applied in DRQIO.)+ If D.DSP is zero, control is returned immediately to the executive. If D.DSP is non-zero, then not only is the driver resident, but the driver has already been correctly mapped by the executive clock queue service routine (in executive module TDSCH) using the C.AR5 offset in the clock block. Therefore, it is safe to transfer control to the "real" entry point in the driver. .BLANK The clock block contains the address of it's service routine in C.SUB. Normally, this is where the "real" service routine address would be placed. However, since that must point instead to the "safe" entry point, some place is needed to store the "real" entry point for access by the "safe" service routine. Conveniently, the last word in the clock block is not used for the "system call"-type clock queue entry (C.SYST). (This is also true for RSX-11M-Plus.)+ Thus, the "real" timer service routine address can be safely placed there. A pleasant consequence is that a single "safe" service routine can then service any number of clock blocks, since the address of the clock block is included as an argument (in R4) when the executive clock queue service routine calls the driver service routine. .BLANK It is convenient to locate this code just after the DCB for easy access by the driver. A sample clock block and setup code is given below. The first case is the simplest and applies when the driver needs only a single clock block. It is similar to the CTB clock block scheme used by RSX-11M-Plus, described above. The second case includes an additional routine that allocates and initializes a clock block from system pool. .BLANK In general, this solution will ^¬\& work under RSX-11M-Plus (aha! something RSX-11M can do that RSX-11M-Plus can't do!). This is because it requires executable code in an area that is usually mapped for Data access only (assuming a separate I- and D-space executive). (That's why RSX-11M-Plus has a separate pool for interrupt control blocks -- it has the same problem dealing with the interrupt entry points to loadable drivers. The ICB pool ^&is\& mapped for both Instruction and Data access, so that one part of the executive can load an ICB -- which requires Data access -- and an interrupt process can execute it -- which requires Instruction access.)+ Of course, RSX-11M-Plus doesn't need these kludges either, as I have described above. .; .PAGE .; .HEADER LEVEL 1 RSX-11M-Plus Examples .; .HEADER LEVEL 2 Static Allocation .; If the driver needs a single clock block, allocate 8 words at the head of the CTB in the driver data base and notify LOAd of its presence by setting LS.CLK in L.STS. If the driver code contains the global entry point $xxTMO, LOAd will place the relocated address in C.SUB and no additional driver initialization is required. .BLANK .LITERAL .MCall ClkDf$ ClkDf$ ; Define Clock Block Offsets ; ; RSX-11M-Plus Controller Table (CTB) ; ; L.CLK 8-word clock block .Word 0 ; C.LNK Clock queue thread word .Byte C.SYST ; C.RQT Request type .Byte 0 ; C.EFN Event flag number .Word 0 ; C.TCB TCB addr/sys subr ident .Word 0,0 ; C.TIM Absolute expiration time .Word $xxTMO ; C.SUB Subroutine address .Word 0 ; C.AR5 Relocation base .Word 0 ; C.URM URM to execute routine .Word 0 ; L.ICB Link to first ICB .Word 0 ; L.LNK Link to next CTB .ASCII /xx/ ; L.NAM Device name .Word $xxDCB ; L.DCB Pointer to DCB .Byte x$$x11 ; L.NUM Number of KRB's .Byte LS.CLK ; L.STS Controller status $xxCTB::.Word xxAKRB ; L.KRB Table of KRB addresses : : .END LITERAL .; .HEADER LEVEL 2 Clock Queue Insertion Routine .; The code fragment below issues a one-shot request with a one second expiration. It assumes the address of the clock block to be inserted in the clock queue is in R0. .BLANK .LITERAL BITB #LS.CBL,L.STS-L.CLK(R0) ; Block already in queue? BNE 100$ ; If NE, yes CLR R1 ; High order delta time MOV $TKPS,R2 ; Low order delta time MOV #C.SYST,R4 ; System call, any CPU BISB #LS.CBL,L.STS-L.CLK(R0) ; Mark clock block in que CALL $CLINS ; Insert into clock queue 100$: ; Reference label .END LITERAL .; .HEADER LEVEL 1 RSX-11M Examples .; .HEADER LEVEL 2 Static Allocation .; To provide an equivalent feature for an RSX-11M driver to that described above for an RSX-11M-Plus driver, .BLANK .LEFT MARGIN +4 .INDENT -4 1.##Insert the following code in the data base, just after the DCB: .LEFT MARGIN -4 .BLANK .LITERAL ; ; RSX-11M Device Control Block (DCB) ; $xxDCB::.Word 0 ; D.LNK Link to next DCB : : ; ; RSX-11M periodic timer clock block (accessed off the DCB) ; .MCall ClkDf$ ClkDf$ ; Define Clock Block Offsets D.CLK==.-$xxDCB ; D.CLK Clock block .BlkB C.LGTH ; Clock entry really points here, which checks to see if the ; driver is still resident (M-Plus UNLoad does this for us) ; before attempting to enter driver. C.REAL==C.LGTH-2 ; C.REAL "Real" entry point addr D.CODE==.-$xxDCB ; D.CODE "Safe" entry point TST $XUDCB+D.DSP ; Driver resident? BNE 10$ ; If NE, yes RETURN ; Save us from crashing 10$: JMP @C.REAL(R4) ; Do it for real now .END LITERAL .BLANK .LEFT MARGIN +4 .INDENT -4 2.##To initialize the clock block, use the following code fragment in a powerfail recovery routine that has been entered as a result of a LOAd command (UC.PWF must be set in U.CTL in the UCB): .LEFT MARGIN -4 .BLANK .LITERAL MOV U.DCB(R5),R3 ; Get DCB address MOV R3,R0 ; Copy DCB address ADD #D.CLK,R0 ; Start of clock block TST C.SUB(R0) ; Already set up? BNE 20$ ; If NE, yes MOV R3,C.SUB(R0) ; Copy DCB address ADD #D.CODE,C.SUB(R0) ; "Safe" entry point addr MOV #$xxTMO,C.REAL(R0) ; "Real" entry point addr 20$: ; Reference label .END LITERAL .BLANK If multiple clock blocks are needed, and the number is always fixed, then more than one clock block can be allocated by surrounding the allocation with a repeat directive. .BLANK .LITERAL .Rept N$CLKB .BlkB C.LGTH .EndR ; N$CLKB .END LITERAL .BLANK Then the code above could be replaced by something like: .BLANK .LITERAL TMOTBL: .Word xxTMO1 ; Table of timeout entry points .Word xxTMO2 : : MOV U.DCB(R5),R3 ; Get DCB address MOV R3,R0 ; Copy DCB address ADD #D.CLK,R0 ; Addr of first clock blk MOV #N$CLKB,R1 ; Number of clock blocks MOV #TMOTBL,R2 ; Address of timeout tble 10$: TST C.SUB(R0) ; Already set up? BNE 20$ ; If NE, yes MOV R3,C.SUB(R0) ; Copy DCB address ADD #D.CODE,C.SUB(R0) ; "Safe" entry point addr MOV (R2),C.REAL(R0) ; "Real" entry point addr 20$: ADD #C.LGTH,R0 ; Addr of next clock blk TST (R2)+ ; Addr of next timeout SOB R1,10$ 30$: ; Reference label .END LITERAL .; .HEADER LEVEL 2 Dynamic Allocation .; .BLANK If the driver requires a variable number of clock blocks, they must be allocated from system pool. (This is also true for RSX-11M-Plus.)+ In that case, .BLANK .LEFT MARGIN +4 .INDENT -4 1.##The clock block allocation may be omitted from the device data base given above: .LEFT MARGIN -4 .BLANK .LITERAL D.CLK==.-$xxDCB ; D.CLK Clock block .BlkB C.LGTH .END LITERAL .BLANK .LEFT MARGIN +4 .INDENT -4 2.##The following routine is called to allocate and initialize each clock block. (The clock block addresses returned should be stored permanently in such a way that they can be accessed through the resident data base if the driver is reloaded. Otherwise, system pool will slowly disappear each time the driver is reloaded.) .LEFT MARGIN -4 .BLANK .LITERAL ;+ ; ALLCLK - Allocate and Initialize Clock Block from System Pool ; ; Inputs: R2 = Address of timer service routine ; ; Outputs: R0 = Address of clock block (if C=0) ; C.SUB = Address of clock queue transfer block ; C.REAL = Address of timer service routine ; C = 0 Clock block successfully allocated ; C = 1 Allocation failure (R0 invalid) ; ; Registers R1-R5 preserved. ;- ALLCLK: MOV R1,-(SP) ; Save R1 MOV #C.LGTH,R1 ; Length of clock block CALL $ALOCB ; Allocate clock block BCS 20$ ; Sorry MOV CLKCOD,C.SUB(R0) ; "Safe" transfer address MOV R2,C.REAL(R0) ; "Real" transfer address 20$: MOV (SP)+,R1 ; Restore R1 RETURN .END LITERAL .BLANK .LEFT MARGIN +4 .INDENT -4 3.##The following code fragment should be executed by the driver initialization routine, prior to any calls to ALLCLK: .LEFT MARGIN -4 .BLANK .LITERAL MOV U.DCB(R5),R0 ; Get DCB address ADD #D.CODE,R0 ; Address of "safe" code MOV R0,CLKCOD ; Save for ALLCLK .END LITERAL .; .HEADER LEVEL 2 Clock Queue Insertion Routine .; The code fragment below issues a one-shot request with a one second expiration. It assumes the address of the clock block to be inserted in the clock queue is in R0. It also uses the C.AR5 field as an "in-use" flag. $CLINS stores the driver APR 5 mapping there every time it is called, thereby marking the clock block "in-use". The "real" service routine must then clear C.AR5 upon entry to mark the clock block available again. .BLANK .LITERAL TST C.AR5(R0) ; Block already in queue? BNE 100$ ; If NE, yes CLR R1 ; High order delta time MOV $TKPS,R2 ; Low order delta time MOV #C.SYST,R4 ; System call CALL $CLINS ; Insert into clock queue 100$: ; Reference label .END LITERAL .; .PAGE .CENTER;^&Unloading_ Drivers_ With_ Device_ Interrupts_ Enabled\& .; .HEADER LEVEL 1 RSX-11M-Plus Drivers .; The same techniques described above for removing clock blocks apply here. Interrupts are always associated with a particular controller, so the controller online/offline entry point, xxKRB, is the appropriate mechanism to use. .; .HEADER LEVEL 1 RSX-11M Drivers .; The same priciples described above may be applied to protect an RSX-11M system from dangling interrupts. In this case, a "safe" interrupt transfer block (ITB) is appended to the Status Control Block (SCB) for each device to be protected. When entered, each ITB immediately transfers control to an ITB service routine which examines D.DSP in the DCB to determine if the driver is still loaded. If D.DSP is zero, further device interrupts are disabled and an RTI ("return from interrupt") is executed. (The executive's ICB never sees it.)+ If D.DSP is non-zero, then the saved contents of the original vector are placed on the stack, and an RTI is executed to pass control to the executuve's ICB -- as though it had never been intercepted. .BLANK A 4-word ITB is required: two words for a JSR R5,xxINT instruction, and two words for the saved vector contents. A single ITB service routine can thus service any number of controllers, since the transfer through the ITB loads the address of the vector save area into R5 as part of the subroutine linkage. (The JSR R5,xxINT in the ITB is not a true subroutine call, but a convenient shorthand for "save a register, load the address of the vector save area into the register, and branch to the ITB service routine", which can then obtain all the device-dependent information it needs by accessing locations relative to the address stored in the register.)+ This also frees R5 for use by the ITB service routine, which must restore it before executing the RTI instruction. .; .HEADER LEVEL 1 RSX-11M Examples .; To protect an RSX-11M system from interrupts to an unloaded driver, .; .BLANK .LEFT MARGIN +4 .INDENT -4 1.##Insert the following code in the data base, just after each SCB: .LEFT MARGIN -4 .BLANK .LITERAL ; SCB Extension i].IIf NDF S.ITB, S.ITB==.-xxcSCB ; S.ITB Interrupt Transfer Block JSR R5,xxINT ;;; Make R5 into arg list ;;; ptr, BR xxINT .IIf NDF I.VSAV, I.VSAV==.-xxcSCB-S.ITB .BlkW 2 ; I.VSAV Original vector contents .END LITERAL .BLANK .LEFT MARGIN +4 .INDENT -4 2.##Insert the following interrupt transfer block service routine in the data base, just after the DCB. The routine given below disables further interrupts by clearing the CSR -- substitute the appropriate method for your device. .LEFT MARGIN -4 .BLANK .LITERAL ; ; RSX-11M Interrupt Transfer Block Service Routine ; ; Interrupts transfer here using R5 as an argument list pointer ; to a three element argument list (original vector PS and PC, ; CSR address): ; ; | int PS | ; | int PC | |JSR R5,...| S.ITB ; SP -> | saved R5 | R5 -> | vec PS | I.VSAV ; | vec PC | ; ; The DCB is checked to see if the driver is still resident (on ; M-Plus, CON OFFLINE does this for us) before attempting to ; enter driver. xxINT: TST $xxDCB+D.DSP ;;; Driver resident? BNE 30$ ;;; If NE, yes CLR @(R5) ;;; Disable interrupts BR 40$ ;;; Join common code 30$: SUB #4,SP ;;; Make some stack space MOV 4(SP),(SP) ;;; Move saved R5 MOV (R5)+,4(SP) ;;; Put vec PS in place MOV (R5),2(SP) ;;; Put vec PC in place 40$: MOV (SP)+,R5 ;;; Restore R5 RTI ;;; Transfer to RSX ICB .END LITERAL .BLANK .LEFT MARGIN +4 .INDENT -4 3.##The following code fragment should be executed by the device initialization routine, prior to enabling device interrupts. It assumes the normal driver convention that R4 contains the SCB address. The strange order of the last three instructions is to prevent a device interrupt that occurs while the ITB is being set up from crashing the system (just in case). .LEFT MARGIN -4 .BLANK .LITERAL ; Set up interrupt transfer block that RTIs if driver not loaded MOV R4,R3 ; Copy SCB address ADD #S.ITB,R3 ; ITB address MOV S.VCT(R4),R0 ; Get interrupt vector/4 ASH #2,R0 ; Vector (base) address MOV R3,R1 ; Copy ITB address ADD #I.VSAV,R1 ; ITB vector save area MOV (R0)+,(R1)+ ; Get original vector PC MOV (R0),(R1) ; Get original vector PS MOV R3,-2(R0) ; Replace vector PC with ; ITB address .END LITERAL .; .BLANK 3 .CENTER;^&References\& .BLANK 2 .; .LEFT MARGIN +4 .INDENT -4 [1]#Bostwick, J., 1988, "Timer Support for User Written Drivers": ^&The_ RSX_ Multi-Tasker\&, in ^&DECUS_ U.S._ Chapter_ SIGs\& ^&Newsletters\&, v.#3, no.#8, pp.#RSX-11-RSX-16. .BLANK .INDENT -4 [2]#Digital Equipment Corp., 1981, ^&RSX-11M_ Guide_ to_ Writing_ an\& ^&I/O_ Driver\&: Order no.#AA-2600E-TC, Digital Equipment Corp., Maynard, MA. .BLANK .INDENT -4 [3]#Digital Equipment Corp., 1982, ^&RSX-11M-Plus_ Guide_ to_ Writing\& ^&an_ I/O_ Driver\&: Order no.#AA-H267B-TC, Digital Equipment Corp., Maynard, MA. .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .COMMENT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COMMENT .TEST PAGE 15 .SKIP 4 .CENTER;Adding Powerfail Detection to RSX Device Drivers .BLANK 2 .CENTER;Lawrence M. Baker .CENTER;U. S. Geological Survey .CENTER;345 Middlefield Road##MS977 .CENTER;Menlo Park, CA##94025 .SKIP .; .; $ Runoff PowerFail .; .PAGE SIZE 58,80 .LEFT MARGIN 10 .RIGHT MARGIN 75 .TAB STOPS 18,26,34,42,50,58,66,74 .STYLE HEADERS ,0 .FLAGS PERIOD .; .; .BLANK 2 On PDP-11 systems equipped with non-volatile memory (e.g., MOS memory with battery-backup or, on older PDP-11 systems, magnetic core memory), RSX will recover the machine state following a power failure. In fact, it does such a fine job that normally the only noticeable signs of an outage are an entry in the error log file and a lapse in the system clock equal to the duration of the outage. Both device drivers and user tasks (if requested) are informed of the occurrence when power is restored. .BLANK RSX powerfail recovery is implemented in Executive module POWER. Support for powerfail recovery is a SYSGEN option in RSX-11M systems; it is always included in RSX-11M-Plus systems. In the discussion which follows, I will assume the system contains the necessary hardware and Executive support for powerfail recovery. .BLANK The powerfail interrupt is one of the few non-maskable interrupts, or traps, on a PDP-11 [1]. (The powerfail interrupt is treated as a trap in the ^&PDP-11_ Architecture_ Handbook\& since it is generated by the CPU, even though it does not result from the execution of a machine instruction.)+ This means that the powerfail interrupt service routine inside RSX will gain control if power fails, regardless of the current processor priority. .BLANK When power fails, the powerfail interrupt service routine saves the volatile machine state in non-volatile memory and reconfigures the powerfail vector to point to the powerup interrupt service routine. When power is restored, the powerup interrupt service routine restores the machine state and increments a flag in the Executive common area ($PWRFL) to request Executive powerfail recovery. It then returns to the interrupted process after requesting a redispatching of the processor. When the Executive dispatcher is eventually entered, the Executive powerfail recovery routine is executed. (This is a distinct routine which cooperates with the powerup interrupt service routine described above to provide Executive powerfail recovery support. I apologize for any confusion my terminology may cause.) .BLANK The Executive powerfail recovery routine calls device drivers at their powerfail recovery entry point, XXPWF (where XX is the device name), for each unit with either active I/O or the "unconditional call on power failure" bit (UC.PWF) set in U.CTL. The interface to this routine is described in the appropriate RSX-11M or RSX-11M-Plus ^&Guide_ to_ Writing_ an_ I/O_ Driver\& [2,#3]. However, what is not explained is that the powerfail recovery entry point is not called until ^&after\& all outstanding driver fork requests are serviced and an interrupted Executive process completes (e.g., CALL $SWSTK in a privileged task or the Directive service routine handling an Executive request). This means that once a driver successfully dequeues an I/O packet (CALL $GTPKT) or converts itself from an interrupt process to a fork process (CALL $FORK), it will not be notified of a power failure until after it returns to RSX. .BLANK This can lead to the faulty initiation of a data transfer before the driver powerfail recovery routine has had a chance to reinitialize a device. (Even if the device does not require any reinitialization, the powerdown/powerup sequence will normally cause the device logic to reset -- clearing the contents of any registers that had previously been set up.)+ Imagine, for example, that a power failure occurs between the time the transfer address is loaded and the word count register is loaded. It is entirely likely that a transfer starting at location 0 will be initiated if the driver does not detect the power failure before setting the CSR GO bit. The most likely effect will be an immediate corruption of the interrupt vectors followed by a system crash or a HALT. .BLANK A driver can easily defend against this situation using a code sequence such as that given below (R2 contains the CSR address; GO, IE and RESET are typical device CSR command bits with obvious effect). It simply tests the powerfail recovery request flag within RSX to determine whether a power failure has occurred (i.e., Executive powerfail recovery is pending). If the flag is non-zero, the driver returns to RSX, deferring any cleanup to its powerfail recovery routine. (The code is similar to that recommended in ^&Writing_ a_ Device_ Driver_ for_ VAX/VMS\& [4].)+ Since the current I/O request has not completed, the device will continue to look busy, which will block the initiation of any further I/O requests. .; .BLANK 2 .LITERAL TST $PWRFL ; Powerfail recovery pending? BNE 20$ ; If NE, yes : : ; --- finish device setup --- BIS #GO!IE,(R2) ; Start the transfer RETURN ; Wait for interrupt ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ; Terminate xfers in progress; ; disable device interrupts RETURN .END LITERAL .BLANK 2 The current I/O request must be completed in either the driver powerfail recovery routine or in the driver timeout routine. The routine which completes the I/O request must exit by restarting the driver fork process (i.e., JMP XXINI) instead of returning to RSX. Otherwise, any I/O packets in the controller request queue will sit there until the next QIO to the device. .BLANK The following code fragment could be used in a driver unit-powerfail recovery routine (R4 contains the SCB address; R5 contains the UCB address): .BLANK 2 .LITERAL TSTB S.STS(R4) ; Was the driver/device busy? BEQ 10$ ; If EQ, no MOVB #IE.DNR&377,R0 ; Device not ready CALL $IOALT ; Finish w/ 0 bytes transferred 10$: JMP XXINI ; Restart driver process .END LITERAL .BLANK 2 RSX-11M-Plus drivers are also called at the same entry point for controller-powerfail recovery, which can usually be treated as a noop. If the driver completes the outstanding I/O in the powerfail recovery routine, it must distinguish between the two forms of entry (using the C-bit) to avoid multiple completion of the current I/O request. .BLANK Completion of the current I/O request in the driver timeout routine is even simpler, since there is no need to check for current driver/device activity (without activity, there can be no timeout) and RSX presets R0 to IE.DNR. The previous five lines of code reduce to: .BLANK 2 .LITERAL CALL $IOALT ; Finish w/ 0 bytes transferred JMP XXINI ; Restart driver process .END LITERAL .BLANK 2 That's the best a driver can do, given the current powerfail recovery support in RSX. There is still a chance of a power failure between the test of $PWRFL and the command to start the device (before and after the BNE instruction), but that is a much smaller window of vulnerability than is the case if the driver fails to detect power failures at all. .BLANK To shrink the window even smaller requires modifications to the Executive powerfail recovery module. This is more on the side of "blue sky," so you can quit reading now if you don't care about things that are not currently supported by RSX. .BLANK My first suggestion approximates the combination of BIT and BNE provided by the BBS ("Branch on Bit Set") instruction on a VAX. It uses two words in the per-CPU database to contain the driver address for continuation if no power failure has occurred, and the driver address for continuation following a power failure: .BLANK 2 .LITERAL $PWRAD::.Word 0 ; Branch target if no powerfail .Word 0 ; Branch target if power failure .END LITERAL .BLANK 2 Since these are shared global variables, the driver must enter a critical section (on the correct CPU) before manipulating them. When the device driver gains exclusive access to the processor, it sets up the target addresses for the power failure conditions, checks $PWRFL for a powerfail recovery already pending, and then JMPs indirectly through $PWRAD to start the transfer, followed by a lowering of the processor priority back to 0. This leaves a very small window of vulnerability between the JMP @$PWRAD and the target of the branch (one hole vs._ at least two holes in the current system). For example, .BLANK 2 .LITERAL ; Once we have entered the critical section, all maskable inter- ; rupts are blocked and we are guaranteed exclusive access to ; $PWRAD. Thus, the only possible way $PWRAD can be changed is ; by a non-maskable interrupt service routine, e.g., the powerup ; interrupt service routine. MFPS -(SP) ; Save processor priority MTPS #PR7 ; Enter critical section MOV #10$,$PWRAD ;;; Setup branch targets for MOV #20$,$PWRAD+2 ;;; the powerup ISR TST $PWRFL ;;; Powerfail recovery pending? BNE 20$ ;;; If NE, yes -- we lose already : : ;;; --- finish device setup --- JMP @$PWRAD ;;; Final test for powerfail 10$: BIS #GO!IE,(R2) ;;; Start the transfer MTPS (SP)+ ;;; End of critical section RETURN ; Wait for interrupt ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ;;; Terminate xfers in progress; ;;; disable device interrupts MTPS (SP)+ ;;; End of critical section RETURN ; Return to RSX .END LITERAL .BLANK 2 One line of code must be added to the powerup interrupt service routine to alter the branch target to indicate a power failure: .BLANK 2 .LITERAL MOV $PWRAD+2,$PWRAD ;;; Alter branch target to ;;; indicate power failure .END LITERAL .BLANK 2 Note that no logic is required in the Executive powerfail recovery routine to determine whether this feature is being used by the current process -- either way the code may safely be executed. It also turns out that this solution is general enough to be useful to any code that manipulates devices, whether or not it is in a driver (i.e., "connect-to-interrupt" code in a privileged task). .BLANK To completely remove the window of vulnerability requires the active participation of RSX. The powerup interrupt service routine in module POWER must be modified to replace the saved PC from the powerfail interrupt with the address of a powerfail condition handler just before the RTI instruction that returns control to the interrupted process. .BLANK 2 .LITERAL TST $ONPWF ;;; Powerfail condition handler? BEQ 40$ ;;; If EQ, no MOV $ONPWF,(SP) ;;; Alter return PC 40$: RTI ;;; Return from powerfail .END LITERAL .BLANK 2 $ONPWF contains the address of the driver powerfail condition handler (which ^&must\& be mapped by the current process), or zero, if the current (driver) process does not use one. As before, $ONPWF must be located in the per-CPU database. .BLANK 2 .LITERAL $ONPWF::.Word 0 ; Powerfail cond'n handler addr .END LITERAL .BLANK 2 Since $ONPWF is a shared global variable, the driver must enter a critical section (on the correct CPU) before setting up the powerfail condition handler address. .BLANK 2 .LITERAL MFPS -(SP) ; Save processor priority MTPS #PR7 ; Enter critical section MOV #20$,$ONPWF ;;; Set powerfail cond'n handler TST $PWRFL ;;; Powerfail recovery pending? BNE 20$ ;;; If NE, yes : : ;;; --- finish device setup --- BIS #GO!IE,(R2) ;;; Start the transfer BR 30$ ;;; Exit critical section ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ;;; Terminate xfers in progress; ;;; disable device interrupts ; Exit critical section protecting powerfail condition handler 30$: CLR $ONPWF ;;; No powerfail cond'n handler MTPS (SP)+ ;;; End of critical section RETURN ; Wait for inter'pt/return to RSX .END LITERAL .BLANK 2 This solution completely eliminates the window of vulnerability for detecting a power failure during device setup. The danger with this method is that the system is more susceptible to device driver coding errors, since the driver must correctly set and clear the powerfail condition handler address/flag. However, this is no different than the precautions a driver must take to avoid double forking or multiple completions of an I/O request. In addition, the driver must be prepared for the interruption of powerfail condition handler itself, should a rapid power fluctuation occur. .BLANK To reduce the risk of a driver coding error, the code to set and clear the powerfail condition handler could be incorporated into a macro defined in RSXMC.mac: .BLANK 2 .LITERAL ;+ ; **-ONPWF$-Set/Clear Driver Powerfail Condition Handler ; ; To establish ADDR as the powerfail condition handler, ; ; ONPWF$ ADDR ; Set powerfail condition handler ; ; The processor priority is raised to PR7 and execution either ; continues at the following statement, or, if powerfail recovery ; is already pending, branches immediately to ADDR (BNE ADDR). ; ; In either case, the powerfail condition handler must be cleared ; before returning to RSX, ; ; ONPWF$ ; Clear powerfail cond'n handler ; ; The processor priority is dropped to PR0 and execution ; continues at the following statement. ;- .MACRO ONPWF$ ADDR .IF NB ADDR MFPS -(SP) ; Save processor priority MTPS #PR7 ; Enter critical section MOV #ADDR,$ONPWF ;;; Set powerfail cond'n handler TST $PWRFL ;;; Powerfail recovery pending? BNE ADDR ;;; If NE, yes -- BR to handler .IFF ; NB ADDR CLR $ONPWF ;;; No powerfail cond'n handler MTPS (SP)+ ;;; End of critical section .ENDM ONPWF$ .END LITERAL .BLANK 2 Using this macro, the driver code simplifies to: .BLANK 2 .LITERAL ONPWF$ 20$ ; Set powerfail condition handler : : ;;; --- finish device setup --- BIS #GO!IE,(R2) ;;; Start the transfer BR 30$ ;;; Exit critical section ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ;;; Terminate xfers in progress; ;;; disable device interrupts ; Exit critical section protecting powerfail condition handler 30$: ONPWF$ ;;; Clr powerfail cond'n handler RETURN ; Wait for inter'pt/return to RSX .END LITERAL .BLANK 2 The driver must carefully manage any temporary storage on the stack to prevent corruption of the stack by the powerfail condition handler. This usually means that the stack pointer cannot be altered while the powerfail condition handler is armed. .BLANK For example, the following incorrect code will corrupt the stack if power fails between the time the device is started and the powerfail condition handler is disarmed (i.e., the return address is erroneously removed by the TST (SP)_+ instruction): .BLANK 2 .LITERAL MOV #READ,-(SP) ; Template CSR for READ function MOV (SP),(R2) ; Prepare the device : : ; --- finish device setup --- BIS #GO!IE,(SP) ; Enable interrupt and start xfer ONPWF$ 20$ ; Set powerfail condition handler MOV (SP)+,(R2) ;;; Start the transfer BR 30$ ;;; Exit critical section ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ;;; Terminate xfers in progress; ;;; disable device interrupts TST (SP)+ ;;; Cleanup stack ; Exit critical section protecting powerfail condition handler 30$: ONPWF$ ;;; Clr powerfail cond'n handler RETURN ; Wait for inter'pt/return to RSX .END LITERAL .BLANK 2 The correct method for managing the stack is to leave the template CSR on the stack until the powerfail condition handler is disarmed: .BLANK 2 .LITERAL MOV #READ,-(SP) ; Template CSR for READ function MOV (SP),(R2) ; Prepare the device : : ; --- finish device setup --- BIS #GO!IE,(SP) ; Enable interrupt and start xfer ONPWF$ 20$ ; Set powerfail condition handler MOV (SP),(R2) ;;; Start the transfer BR 30$ ;;; Exit critical section ; Power failed -- RETURN immediately so RSX can call XXPWF 20$: MOV #RESET,(R2) ;;; Terminate xfers in progress; ;;; disable device interrupts ; Exit critical section protecting powerfail condition handler 30$: ONPWF$ ;;; Clr powerfail cond'n handler TST (SP)+ ; Cleanup stack RETURN ; Wait for inter'pt/return to RSX .END LITERAL .BLANK 2 This device driver powerfail detection mechanism is superior to that available in either RSX ^&or\& VMS. I believe it is as airtight as is possible without the addition of specialized device hardware. It is reasonably simple to implement and requires no more programming discipline than that required to write a standard device driver. I encourage your comments and critiques, either personally or through the ^&Multi-Tasker\&. .BLANK 2 .CENTER;Disclaimer .BLANK No warranty, expressed or implied, is made by the United States Department of the Interior, Geological Survey, as to the accuracy and functioning of the program and related program material, nor shall the fact of distribution constitute any such warranty, and no responsibility is assumed by the Geological Survey in connection therewith. .BLANK 2 .CENTER;References .LEFT MARGIN +4 .BLANK .INDENT -4 [1]#Digital Equipment Corp., 1983, ^&PDP-11_ Architecture_ _ Handbook\&: Order no.#EB-23657-18, Digital Equipment Corp., Maynard, MA. .BLANK .INDENT -4 [2]#Digital Equipment Corp., 1981, ^&RSX-11M_ Guide_ _ to_ _ Writing_ _ an\& ^&I/O_ Driver\&: Order no.#AA-2600E-TC, Digital Equipment Corp., Maynard, MA. .BLANK .INDENT -4 [3]#Digital Equipment Corp., 1982, ^&RSX-11M-Plus_ Guide_ to_ _ Writing\& ^&an_ I/O_ Driver\&: Order no.#AA-H267B-TC, Digital Equipment Corp., Maynard, MA. .BLANK .INDENT -4 [4]#Digital Equipment Corp., 1984, ^&Writing_ a_ _ Device_ _ Driver_ _ for\& ^&VAX/VMS\&: Order no.#AA-Y511B-TE, Digital Equipment Corp., Maynard, MA.