I/O operations on these systems are initiated by issuing a QIO call to the kernel. There are two types of QIO - Queue I/O, and Queue I/O and Wait.
For QIO without wait, the call returns immediately. If the request is successfully enqueued, the actual operation occurs asynchronously. On completion, status is returned in the QIO status doubleword. The QIO request may also specify that completion set an event flag or issue an Asynchronous System Trap (AST).
The call may also be issued as QIOW (Queue I/O and Wait for completion), allowing synchronous I/O. In this case, the wait-for-event-flag operation is combined so the call does not return until the I/O operation completes or fails.
The following operating systems implemented QIO(W):
QIO arguments in VMS
Under VMS, the arguments to the QIO call are:
- The event flag to set when the operation completes. It isn't possible to not specify an event flag; flag 0 is valid. It is perfectly permissible to have multiple simultaneous operations that set the same event flag on completion. It is then up to the application to sort out any confusion this might cause, or just ignore that event flag.
- The channel, a small integer previously associated with the device. At this level, all operations on disk files and directories (filename parsing, directory lookup, file opening/closing) are done by appropriate QIO requests.
- The function code to be performed. 6 bits are assigned to the basic code (such as read, write), with a further 10 bits for "modifiers" whose meaning depend on the basic code.
- The optional I/O status block (IOSB), which is cleared by the QIO call, and filled in on completion of the I/O operation. The first two bytes hold the completion status (success, end of file reached, timeout, I/O error, etc.), while the next two bytes normally return the number of bytes read or written in the operation. The meaning, if any, of the last four bytes is operation-dependent.
- The optional AST routine to invoke when the operation completes.
- An additional parameter (whose meaning is up to the caller) to be passed to the AST routine.
- A partially standardized list of up to six parameters known as P1 through P6. The first two parameters typically specify the I/O buffer starting address (P1), and the I/O byte count (P2). The remaining parameters vary with the operation, and the particular device. For example, for a computer terminal, P3 might be the time to allow for the read to complete whereas, for a disk drive, it might be the starting block number of the transfer.
There are three different ways to sense when the queued I/O operation has completed:
- When the event flag becomes set.
- When the first two bytes of the IOSB become nonzero.
- When the AST routine executes.
Unusual QIOs that require complex processing
Simple QIOs, such as read or write requests, are either serviced by the kernel itself or by device drivers. Certain more complicated requests, specifically those involving tape drives and file-level operations, were originally executed by an Ancillary Control Processor (ACP) (a special purpose task with its own address mapping).
The Files-11 ODS-1 file system on RSX-11 was implemented by a subroutine library that communicated with a task named F11ACP using a special set of QIOs called the "ACP QIOs." The equivalent functionality for controlling magnetic tape devices was provided by a task named MTAACP.
Originally, the Files-11 ODS-2 file system was provided by F11BACP on VMS, but the functionality of F11BACP was later incorporated into the VMS kernel to save the overhead of process context switches, and is now called an XQP (eXtended Qio Processor).
Probably the most complex single QIO request possible is the VMS terminal driver's IO$_READPROMPT call with the IO$M_TIMED modifier; this QIO requires all six additional parameters:
- P1 is the address of the buffer into which the input characters are received
- P2 is the length of the buffer, limiting the maximum number of characters to read. If the buffer is filled, the read will complete successfully, even if the user does not type a line-terminator character. Zero is allowed, in which case the read will terminate successfully with zero characters read.
- P3 is the maximum number of seconds to wait for more input. This is only used if the IO$M_TIMED modifier is present, and a value of zero means zero seconds: the read will terminate immediately, so the only possible input will be whatever had been "typed ahead" by the user.
- P4 is the address of the optional "terminator mask", specifying which ASCII characters terminate the read. If omitted, this defaults to the usual VMS line delimiters including carriage-return (but not line-feed). It is possible to specify a mask with no line terminators, in which case the read will only complete when the buffer is full, or the timeout has elapsed.
- P5 is the address of a prompt string to be displayed to the user before accepting input. The advantage of providing this prompt, instead of as a prior write operation, is automatic redisplay in any situation requiring a refresh of the input line while the read is in progress (such as after an operator message has been broadcast to the terminal, or the user hits CTRL/R to redisplay the line).
- P6 is the length of the prompt string.
By appropriate choices of the above parameters, it is possible to do both terminal input and output with the one call, there is no need to use the regular IO$_WRITEVBLK call for terminal output at all.