[LMH]%IO instruction and Device Descriptors
Steve Krueger
stevelisp@grape-krueger.com
Sun Jul 27 13:35:02 2003
More on the MISCOP %IO.
%IO always returns NIL. Generally it is called D-IGNORE.
To start with, don't bother with simulating asych I/O, so the I/O will
run to completion during the execution of %IO. Later, when you want
more fidelity, you can use the OS asynch I/O functions to give a better
approximation of Explorer disk I/O.
The following describes the asynch behavior.
Each SCSI formatter (one per disk brick and one per tape drive, I
think), can only handle one command at a time. So the I/O queuing
involves figuring out which formatter (SCSI unit) is being addressed.
If that formatter is busy, insert this request into the queue in
priority order.
Priorities (from lroy-qdev.lsip):
(DefEnum IO-RQ-Priorities (Q-CORRESPONDING-VARIABLE-LISTS
System-Constant-Lists)
(%IO-RQ-Priority-Demand-Page
%IO-RQ-Priority-Local-File
%IO-RQ-Priority-Pre-Page
%IO-RQ-Priority-Remote-File
%IO-RQ-Priority-VM-Background)
)
So, the asynch IO magic occurs when the NuPI interrupts for a command
completion.
The NuPI completion interrupt doesn't indicate which unit (formatter)
completed a command. So, the interrupt handler needs to check the head
entry in each queue to see if it has completed. There is a bit vector
in the NuPI device descriptor block that contains a set bit for each
queue that has an active command. The RQB at the head of each active
queue is checked for the COMPLETE bit (%%nupi-status-high-complete
#o1601 ; complete bit). When a completed command is found, its
completion is processed as described below, and it is removed from the
queue. If the queue is not empty, the next command is started by
writing a physical address pointer to the RQB into the NuPI. If the
queue is empty, the active bit for the queue in the device descriptor is
cleared.
If the command being completed does not have the
%%IO-RQ-Suppress-Sequence-Break bit set, set the sequence break flag in
the Machine Control Register (MCR). This bit is sampled at certain
convenient moments when the state is clean enough that saving a process'
state into a stack group will fully capture the process. Generally, a
sequence break is can be taken between macroinstructions, but some long
running instructions (think MEMQ) check once per loop when a data item
is read. Without these additional tests, sequence breaks might be
inhibited for a very long time or forever (MEMQ on a circular list).
Generally, the process doing an explicit IO with %IO will wait for the
RQB to be marked done. RQB done bit is in the IO information word of
the RQB as %%IO-RQ-Done (#o0401 ; Ucode done status). Microcode sets
this bit and clears busy in the RQB to complete its processing.
If you don't even try to emulate the asynch IO, you can finish the IO
request before returning NIL and never bother with the queuing. You'll
need to clear busy and set done in the RQB before returning as the wait
code will check these.
Next up, NuPI.
-Steve