From: goathunter@goatley.com Sent: Thursday, July 05, 2001 10:18 AM To: Info-VAX@Mvb.Saic.Com Subject: Re: Writing to OPA0: from a device driver On 5 Jul 2001 09:21:52 -0500, koehler@encompasserve.org (Bob Koehler) wrote: >In article , Simon Clubley writes: >> >> What are the various methods used by VMS device drivers to write (for example, >> debugging text) to the system console and which method do people prefer ? > >Generally they don't. It's somewhat difficult in any device driver to >write to any device other than the one being controlled. > >I've got device drivers that use the OPCOM mailbox, they haven't >successfully sent out a message in years. I haven't bothered debugging >this because the messages they did send out are useless. > If you want a real way to write to the actual console and not just to OPCOM, there are (I think still undocumented) routines that will do just that. They can be called from device IPL and they write directly to the console device. I wrote about this in the January 1995 issue of DIGITAL SYSTEMS JOURNAL as part of my series (co-authored with Ed Heinrich) on writing kernel mode code. In the assumption that others might find it useful, here's the section of the article discussing these routines. (I also have some MACRO macros that make using these routines even simpler; if you'd like to see those, drop me a line and I'll e-mail them to you.) =============================================================================== 1.4 Writing Messages to the Console Invoking XDELTA while debugging systems code works very well, but there are cases when it is not practical to use XDELTA. One such case is a device driver that interacts with an external peripheral device. If the device driver starts some operation on the peripheral and then invokes XDELTA, the system will stop, but the peripheral may not. By the time the system is allowed to continue, the peripheral may or may not still be in the desired state, which can skew testing with the peripheral. In cases like this, messages to the system error log may be useful, but they cannot be examined in "real-time"; the error log buffers must be flushed to disk before they can be examined. A time-honored method of debugging is the writing of informational messages to a video or hardcopy terminal. Such messages could indicate which subroutine is executing or the status of certain operations. For example, it is not uncommon when writing applications code to write a routine like the following: -------------------- . . int do_the_work (int x) { int i; printf("Inside do_the_work()\n"); for (i = 0; i < x; i++) printf("%d\n", i); printf("Leaving do_the_work()\n"); return 1; } -------------------- When the program calling this routine is run, the informational messages "Inside do_the_work()" and "Leaving do_the_work()" will be written to the current output device. This can speed the debugging process---if the second message is never printed, there must be a problem inside the loop that keeps it from exiting. Obviously, any method that uses RMS to do the output is of limited-use in privileged code, since a kernel-mode routine cannot call the executive-mode RMS services. $QIO system service calls would work for process-context code that is not executing at elevated IPL. But what about real systems code, that may not have any process context and executes at elevated IPL? These code threads can write output directly to the system console using some little-known executive routines. 1.4.1 The Console I/O Routines OpenVMS module [SYS]CONSOLIO.LIS contains I/O routines for the console terminal. On a VAX, the routines all expect the address of a terminal device's CSR (Control Status Register) to be passed in general register R11. If R11 has the value 0, the system console device is used by calling CPU-specific routines named beginning with CON$. Under OpenVMS AXP, the CSR address is ignored by the EXE$ console I/O routines. The system console device is used for all I/O operations. Also, the OpenVMS AXP source module [OPDRIVER] contains the source code for OPDRIVER, the console device driver. The characters are written and read from the physical device registers, bypassing the normal device drivers for the device. The console I/O routines should be called from device IPL or higher, with any spinlock held. This makes them ideal for use in device drivers and other elevated-IPL code. The routines will work for non-elevated IPL as long as the system console is not being used for other purposes at that time. Table 1-2 describes the EXE$ routines for writing to the console terminal. However, before the routines can be called, interrupts must be disabled on the console and then re-enabled. This is accomplished by calling two CON$ routines: CON$SAVE_CTY to save the current settings, and CON$RESTORE_CTY to restore the saved settings. These routines are defined in OPDRIVER (found in [SYSLOA] in the VAX listings and [OPDRIVER] in the AXP listings). CON$SAVE_ CTY returns the current console state in R0 and R1; CON$RESTORE_ CTY expects the console state to be passed in R0 and R1. Table_1-2:__EXE$_Console_I/O_Routines_____________________________ Routine_______________Description_________________________________ EXE$OUTBYTE Convert and output hex byte (value passed in R1) EXE$OUTHEX Convert and output hex longword (value passed in R1) EXE$OUTBLANK Output blank character EXE$OUTCHAR Output character (character passed in R0) EXE$OUTCRLF Output carriage return/line feed pair EXE$OUTCSTRING Output counted string (address passed in R1) EXE$OUTZSTRING Output zero terminated string (address ______________________passed_in_R1)_______________________________ Example 1-5 shows a VAX MACRO-32 module that defines two subroutines, PUT_CONSOLE_ASCIC and PUT_CONSOLE_HEX. These routines save the current console state, perform the specified output with some additional linefeeds and carriage returns, then restore the saved console state. The following fragment shows how these routines would be called: -------------------- MSG: .ASCIC /This is a test console message/ . . MOVAQ MSG,R0 ; Get address of ASCIC message JSB PUT_CONSOLE_ASCIC ; Write it to the console . . MOVL #^XDEAD00ED,R0 ; Move the value to R0 JSB PUT_CONSOLE_HEX ; Write it to the console . . -------------------- Example 1-5: PUT_CONSOLE Subroutines _____________________________________________________________________ .TITLE PUT_CONSOLE - Write messages to console .IDENT /01-000/ ;+ ; ; File: PUT_CONSOLE.MAR ; ; Author: Hunter Goatley ; ; Date: November 10, 1992 ; ; Description: ; ; The module contains two routines for performing device I/O ; to the system console: PUT_CONSOLE_ASCIC and PUT_CONSOLE_HEX. ; ; Modified by: ; ; 01-000 Hunter Goatley 10-NOV-1992 13:09 ; Genesis. ; ;- .DSABL GLOBAL .EXTRN CON$RESTORE_CTY ;* Restore console state .EXTRN CON$SAVE_CTY ;* Save console state .EXTRN EXE$OUTCHAR ;* Print a character .EXTRN EXE$OUTCRLF ;* Print .EXTRN EXE$OUTCSTRING ;* Print ASCIC string .EXTRN EXE$OUTHEX ;* Dump a HEX string ;+ ; ; PUT_CONSOLE_ASCIC Expects ASCIC address in R0, preserves all regs ; ;- PUT_CONSOLE_ASCIC:: PUSHR #^M ; Save registers CLRL R11 ; Show I/O to console PUSHL R0 ; Save address of string JSB G^CON$SAVE_CTY ; Save console state MOVQ R0, ; Save the data MOVL #10, ; Move a to R0 JSB G^EXE$OUTCHAR ; Send the POPL R1 ; Restore address of string JSB G^EXE$OUTCSTRING ; Write it out MOVL #13, ; Move a to R0 JSB G^EXE$OUTCHAR ; Send the MOVQ R3, ; Restore console state data JSB G^CON$RESTORE_CTY ; Restore console state POPR #^M ; Save registers RSB ; Return to caller ;+ ; ; PUT_CONSOLE_HEX Expects hex value address in R0, preserves all regs ; ;- PUT_CONSOLE_HEX:: PUSHR #^M ; Save registers CLRL R11 ; Show I/O to console PUSHL R0 ; Save address of string JSB G^CON$SAVE_CTY ; Save console state MOVQ R0,R3 ; Save the data JSB G^EXE$OUTCRLF ; Follow with a MOVL #10,R0 ; Move a to R0 JSB G^EXE$OUTCHAR ; Send the POPL R1 ; Restore hex value JSB G^EXE$OUTHEX ; Write it out MOVL #13,R0 ; Move a to R0 JSB G^EXE$OUTCHAR ; Send the MOVQ R3,R0 ; Restore console state data JSB G^CON$RESTORE_CTY ; Restore console state POPR #^M ; Save registers RSB ; Return to caller .END _____________________________________________________________________ 1.4.2 Using the $SNDOPR System Service Non-privileged code can send messages to the operator console by calling the $SNDOPR system service to queue a message to OPCOM, the operations communication manager. Messages received by OPCOM are sent to appropriate operator terminals, including the console, and are recorded in the system operator log (OPERATOR.LOG in SYS$MANAGER). Unfortunately, $SNDOPR cannot be called from kernel mode because it initially executes in executive mode. $SNDOPR uses the executive mode stack for temporary storage space for the message text, then changes mode to kernel to actually write the message to the OPCOM mailbox, whose address is stored in SYS$AR_ OPRMBX. The system routine EXE$SNDOPR actually writes the message to the OPCOM mailbox by calling the system routine EXE$SNDMSG. This routine ensures that the memory holding the message text is faulted in and calls EXE$WRTMAILBOX to write the message to the OPCOM mailbox. In order to ensure that all the necessary pages have been faulted into memory, the address of the message text is rounded down to the previous page boundary. If the message is small and near the top of the executive stack, this can cause an overrun into the kernel stack, which works because the routine is executing in kernel mode. If the message were allowed to reside on the kernel stack, the rounding down of the address could result in the access of the page preceding the kernel stack, which is not a valid page. The system would then generate an access violation exception. Still, $SNDOPR can be useful in non-privileged portions of systems code as a means of notifying the system manager of a particular event. Even at the driver-level, if a code thread needs to produce an alarm associated with a particular process, it may be able to queue an executive-mode AST to that process (to be discussed in a future article); the executive-mode AST could then call the $SNDOPR system service. ========================================================================= Hunter ------ Hunter Goatley, Process Software, http://www.process.com/ goathunter@goatley.com http://www.goatley.com/hunter/