Environment
RTAS provides an interface definition between the OS and the firmware
provided by the platform. This chapter defines the calling conventions used
by both the OS and the platform’s RTAS firmware.
RTAS runs with instruction and data relocate as well as processing
exceptions disabled. To not interfere with the OS, RTAS may not cause any
exceptions, nor can it depend on any particular virtual memory
mappings.
All RTAS functions are invoked from the OS by calling the
rtas-call function. The address of this
function is obtained from OF when
RTAS is instantiated. See Requirement
for more details. RTAS determines
what function to invoke based on the data passed into the
rtas-call function. This section describes the
mechanisms used to invoke the rtas-call function,
the machine state, register usage, resource
allocation, and the invocation requirements.
If the LPAR option is enabled, multiple partitions may exist, each
with its own OS instance. This requires some changes to the RTAS
environment. These changes are discussed in
.
Machine State
When RTAS functions are invoked, the calling processor shall have
address translations, floating point, and most other exceptions disabled
and it shall be running in privileged state.
R1--1.
RTAS must be called in “real
mode,” that is, all address translation must be disabled. Bits MSRIR and
MSRDR of the MSR register must be zero.
R1--2.
RTAS must be called in privileged mode, and
the MSRPR bit must be set to 0.
R1--3.
RTAS must be called with external
interrupts disabled, and the MSREE bit must be set to 0.
R1--4.
RTAS must be called with trace disabled,
and the MSRSE and
MSRBE bits must be set to 0.
R1--5.
RTAS must be
called with floating point disabled, and the
MSRFE0,
MSRFE1, and
MSRFP bits must be set to 0.
R1--6.
RTAS must be called with the MSRSF,
(MSRISF, and ASRV
bits if applicable on the specific processor) set
to match the mode used to instantiate RTAS (0 for
instantiate-rtas or 1 for
instantiate-rtas-64) and the
LE bit set to 0.
R1--7.
With the exception of the MSRDR and
MSRRI bits, RTAS must not change the state of the
machine by modifying the MSR.
R1--8.
rtas-call is entered
in a non-recoverable mode, indicated by having the
MSRRI bit set equal to 0, then RTAS must not enter a
recoverable mode by setting the MSRRI bit to 1.
R1--9.
If called with MSRRI equal to 1,
then RTAS must protect its own
critical regions from recursion by setting the MSRRI
bit to 0 when in the critical regions.
Software Implementation Notes:
If the MSRME bit is left enabled, the OS’s exception
handler must be aware that RTAS might have been running and that various
processor registers might not be in the expected state for an interrupted
OS, which precludes recoverability but permit logging machine
checks.
There are some provisions for recursive calls to RTAS error
handling functions. Therefore, RTAS should set the MSRRI
bit to 0 if SRR0/SRR1 or any other RTAS resource
is in a state where information could be lost and prohibit
recovery.
Requirement
implies that RTAS must be able
to be instantiated in 64-bit mode on platforms that can support 64-bit
execution.
Register Usage
R1--1.
Except as
required by a specific function, registers SPRG2, R0, R3 through R12,
CTR, XER, LR, and fields CR2-CR4 of the CR, RTAS must preserve all OS
visible register state.
R1--2.
RTAS must not modify the DEC and registers SPRG0, SPRG1, and SPRG3.
Software Implementation Notes:
RTAS is entered in real mode
(with address translation turned off). In this mode, all data accesses
are assumed to be cached in copy back mode with memory coherence
required. Since these settings may not be appropriate for all accesses,
RTAS is free to transparently use the processor specific facilities
required to access platform hardware resources. The OS machine check
handler can only depend on those registers that are required to be
unchanged (see Requirement
).
RTAS must not change the preserved registers, or must first save
them and restore the original contents before returning to the OS.
The SRR0-SRR1, LR, CTR, XER registers, as well as any
reservations made via the load and reserve instructions, need not be
preserved.
RTAS Critical Regions
The OS, when using RTAS, is responsible for protecting RTAS and
devices used by RTAS from any simultaneous accesses that could corrupt
memory or device registers. Such corruption could be caused by
simultaneous execution of RTAS code, or by a device driver accessing a
control register that is also modified by RTAS. In a single processor
system, since the MSREE bit is 0 when entering RTAS, a call to RTAS while
it is in execution is prevented except for the machine check handler.
This handler may need to call various RTAS services such as
check-exception or
system-reboot even if the error was detected while in
an RTAS service
.
The OS and RTAS must co-exist on the same platform. RTAS must not
change device registers that are used by the OS, nor may the OS change
device registers on devices used by RTAS. With the advent of more and
more integration into common super parts, some of these registers may
physically reside on the same component. In this section, device implies
the collection of common registers that together perform a function. Each
device must be represented in the OF device tree.
R1--1.
Except as noted in Requirement
and
, the OS must ensure that RTAS
is not called while RTAS is in execution and that RTAS is not
simultaneously called from different processors in a multi-processor
system.
R1--2.
Any RTAS access to device or I/O registers
specified in this document must be made in such a way as to be
transparent to the OS.
R1--3.
Any device that
is used to implement the RTAS abstracted services must have the property
“used-by-rtas” in the OF device tree.
However, if the device is only used by the
power-off, and
system-reboot calls, the property should not be set.
The
rtas-display-device must be marked with the property
“used-by-rtas” if it is a specialized
device only to be accessed via the RTAS
display-character call and not otherwise shared with
the OS
Software Implementation Note:
clarifies when a device should
be marked with the
“used-by-rtas” property, based on whether
it has any interaction with RTAS and/or the OS (with the exception of the
calls listed in Requirement
).
Use of
“used-by-rtas”
Normal Device (1)
rtas-display-device
Only used by OS
not marked
N/A (2)
Only used by RTAS
marked
marked
OS and RTAS shared
marked (3)
not marked (4)
Virtual
N/A
N/A
A device which is not normally to be used by the OS must meet
one of the following rules.
It must not be included in the OF device tree.
It must be defined as a “reserved” device
node.
It must be marked with the
“used-by-rtas” property in the OF device
tree.
It is assumed that an
rtas-display-device is used by RTAS.
It is assumed that there are no devices other than the
rtas-display-device which are used by both RTAS and
an “unaware” OS. To allow an aware OS to share a device with
RTAS, the device should be marked.
It is assumed that the
rtas-display-device is used by both RTAS and the OS
(as coordinated by the OS via display-character) unless it is marked. See
also Requirement
.
R1--4.
Platforms must be designed such that
accesses to devices that are marked
“used-by-rtas”
have no side effects on other registers in the system.
R1--5.
Any OS access to devices specified as
“used-by-rtas”
must be made in such a way as to be transparent to RTAS.
R1--6.
RTAS must not generate any exceptions (for
example, no alignment exceptions, page table walk exceptions,
etc.).
R1--7.
The OS machine check and soft reset handlers must be
able to call the RTAS services:
nvram-fetch
nvram-store
check-exception
display-character
system-reboot
set-power-level(0,0)
power-off
ibm,set-eeh-option
ibm,set-slot-reset
ibm,read-slot-reset-state2
R1--8.
The stop-self
service need only be serialized with calls to the
stop-self,
start-cpu, and
set-power-level services. The OS must be able to call
RTAS services on other processors while a processor is stopped or being
stopped.
Software Implementation Notes:
While RTAS must not generate any exceptions, it is still
possible that a machine check interrupt may occur during the execution of
an RTAS function. In this case, the machine check handler may be entered
prior to the normal termination of the RTAS function.
It is permissible for the OS exception handler to make an RTAS
call as long as Requirements
and
are met. In particular, it is
expected that the RTAS
check-exception is called from the OS exception
handler.
Resource Allocation and Use
During execution, RTAS requires memory for both code and data. This
memory may be in RAM, in a private memory area only known by the system
firmware, or in memory allocated by the OS for RTAS use. RTAS should use
this memory for its stack and any state savings. This memory is
subsequently called the “RTAS private data area.”
R1--1.
The OS must allocate
“rtas-size”
bytes of contiguous real memory as RTAS
private
data area. This memory must be aligned on a 4096 byte boundary and may
not cross a 256 MB boundary.
R1--2.
The RTAS private data area must not be accessed by the OS.
R1--3.
Except for the RTAS private data area, the
argument buffer, System Memory pointed to by any reference parameter in
the argument buffer, and any other System Memory areas explicitly
permitted in this chapter, RTAS must not modify any System Memory. RTAS
may, however, modify System Memory during error recovery provided that
such modifications are transparent to the OS.
R1--4.
RTAS calls may
not sleep in any fashion nor busy wait for more than a very short period
of time, except for
power-off, ibm,power-off-ups, set-power-level (0,0),
system-reboot, ibm,update-flash-64-and-reboot, and
ibm,os-term.
Software
Implementation Note: An RTAS call should take the same amount of time to
perform a service that it would take the OS to perform the same function.
A specific goal is that RTAS primitives should take less than a few tens
of microseconds.
R1--5.
For RTAS calls which do not allow the
Status of -2 (Busy), there may be “rare”
instances where an anomaly may occur and the call may take longer than a
“very short period of time.” In these cases, the call must
complete within 250 microseconds. Otherwise, a hardware error response
must be given.
Instantiating RTAS
RTAS is instantiated by an explicit client interface service call
into OF. The OF device tree contains a property
(“rtas-size”, under
the
/rtas node) which defines how much real memory RTAS
requires from the OS. The OS allocates
“rtas-size”
bytes of real memory, and
then invokes the
instantiate-rtas or
instantiate-rtas-64 method of the
/rtas node, passing the real address of the private
data area (or zero, if
“rtas-size” is zero) as the
rtas-base-address input argument. Firmware binds RTAS
to that address, binds the addresses of devices that RTAS uses, performs
any RTAS initialization, and returns the address of the
rtas-call
function
that is appropriate.
R1--1.
The instantiate-rtas or
instantiate-rtas-64
OF method
must have the arguments specified in
.
instantiate-rtas
instantiate-rtas-64
Argument Call Buffer
Parameter Type
Name
Values
In
rtas-base-address
Real Address of RTAS area or zero, if
“rtas-size” is zero
Out
rtas-call
Real address used to invoke RTAS functions
R1--2.
The RTAS code bound and initialized by the
instantiate-rtas method on a 64-bit capable platform,
must be able to handle platform resources that are accessed using 64-bit
addresses.
RTAS Device Tree Properties
The OF device tree contains a
/rtas device node that describes the implemented RTAS
features and the output device supported by RTAS. Within this device node
are properties that describe the RTAS functions implemented by the
firmware. For every implemented RTAS function, the
/rtas node contains an OF property whose name is the
same as the RTAS function. The value of this property is the token
argument passed into the
rtas-call
function
when making that specific RTAS call. Note that some
RTAS functions are optional and some are required. This is defined in
.
R1--1.
The OF device tree must contain a device
node named
/rtas which describes the RTAS implementation.
R1--2.
The /rtas device node must have a property for each
implemented RTAS function in
. The value of this property is
a token that is passed into the
rtas-call
function to
indicate which RTAS function to invoke.
RTAS Tokens for Functions
RTAS property/function
Required?
Notes
“nvram-fetch”
Required
Execution time proportional to amount of data
“nvram-store”
Required
Execution time proportional to amount of data
“get-time-of-day”
Required
“set-time-of-day”
Required
“set-time-for-power-on”
“event-scan”
Required
“check-exception”
Required
“rtas-last-error”
Required
“ibm,platform-dump”
If the Platform Dump option is implemented
“ibm,read-pci-config”
Required
“ibm,write-pci-config”
“display-character”
“set-indicator”
Required
Some specific indicators are required, and some are
optional
“get-sensor-state”
“ibm,set-system-parameter”
“ibm,get-system-parameter”
“set-power-level”
Required for DR operations (see
)
“get-power-level”
“power-off”
Provided for platforms with software controlled power off
capability
“ibm,power-off-ups”
If there may be a platform controlled UPS.
For power off control in a platform which may have power
backed up with an Uninterruptible Power Supply (UPS).
“system-reboot”
Required
“ibm,update-flash-64-and-reboot”
“ibm,manage-flash-image”
“ibm,validate-flash-image”
“ibm,activate-firmware”
“stop-self”
See Note
“start-cpu”
“query-cpu-stopped-state”
“ibm,os-term”
“ibm,exti2c”
“ibm,get-xive”
Required for the PowerPC External Interrupt option
“ibm,set-xive”
“ibm,int-off”
“ibm,int-on”
“ibm,configure-connector”
Required for all DR options
See
.
“ibm,set-eeh-option”
Required for EEH option
“ibm,set-slot-reset”
“ibm,read-slot-reset-state”
Being replaced by
ibm,read-slot-reset-state2
See
.
“ibm,read-slot-reset-state2”
Required for all platforms
“ibm,get-config-addr-info2”
Required on all platforms
“ibm,slot-error-detail”
Required for the EEH option
“ibm,open-errinjct”
Required for ERRINJCT option
“ibm,errinjct”
“ibm,close-errinjct”
“ibm,nmi-register”
Required for FWNMI option
“ibm,nmi-interlock”
“ibm,configure-bridge”
Required for the EEH option
“ibm,configure-pe”
Required for the EEH option
“ibm,get-indices”
Sometimes (see
)
“ibm,get-vpd”
Required for the Dynamic VPD option
“ibm,manage-storage-preservation”
Required for the Storage Preservation option
“ibm,get-dynamic-sensor-state”
See Requirement
.
“ibm,set-dynamic-indicator”
See Requirement
.
“ibm,change-msi”
Required for the MSI option. Required if any PCI Express
HB in the platform.
“ibm,suspend-me”
Required for the Partition Suspension option
“ibm,update-nodes”
Required for the Update OF Tree option
“ibm,update-properties”
Required for the Update OF Tree option
“ibm,configure-kernel-dump”
Required for the Configure Platform Assisted Kernel Dump
option
“ibm,query-pe-dma-window”
Required for the Dynamic DMA Window (DDW) option
“ibm,create-pe-dma-window”
“ibm,remove-pe-dma-window”
“ibm,reset-pe-dma-windows”
Required for the LoPAR version l of the Dynamic DMA
Window (DDW) option
Note: These commands are required in SMP platforms if
dynamic reconfiguration is required of the processors. Similarly, a
degraded mode may need these, or similar commands in the case of
detection of excessive errors. In the case of a processor deconfigured by
dynamic reconfiguration or due to excessive errors, the returned
CPU_status from the
query-cpu-stopped-state RTAS call is 2 (The processor
thread is not in the RTAS stopped state) since the deconfigured processor
cannot be started.
R1--3.
The OF properties listed in
must be in the
/rtas device tree node prior to booting the
OS.
OF Device Tree Properties
name
value
“rtas-size”
integer size of RTAS private data area or zero if
allocation is not required
“rtas-version”
An integer encoding of the RTAS interface version. This
document describes version 1.
“rtas-event-scan-rate”
The rate, in calls per minute, at which rtas-event-scan
should be called by the OS. See
.
“rtas-display-device”
The
phandle of the device node used by the RTAS
call,
display-character.
“rtas-error-log-max”
The maximum size of an extended error log.
R1--4.
All RTAS functions listed as
“Required” in
must be implemented in
RTAS.
R1--5.
For the Symmetric Multiprocessor option: The
functions listed as “Required in SMP Platforms” in
must be implemented in
RTAS.
Software Implementation Notes:
It is permitted for RTAS not to implement those optional
functions that are not appropriate or not needed on a particular
platform.
Vendors may introduce private RTAS calls of their own. If they
do, the property names should be of the form
“vendor,property” where
vendor is a company name string as defined by OF.
Future versions of this architecture will not choose RTAS property names
that include a comma.
RTAS Device Tree Properties for Indicators and
Sensors
Indicators and sensors may be static or dynamic. Each indicator or
sensor type is identified by its token; a number which is associated with
the functionality of the indicator or sensor. A specific indicator token
is static in a particular platform if the number of indicators of that
type do not change with Dynamic Reconfiguration (DR) operations, and
dynamic otherwise. Certain sensors and indicators associated with DR
DR indicators include isolation-state (9001), DR indicator
(9002), and allocation-state (9003). DR sensors include dr-entity-sense
(9003). DR indicators and sensors are required to be there based on the
DR entity being supported. Their indices are specified by the DR index
for the DR entity. See
and
for more information.
are static since they represent the base hardware, others are
dynamic coming and going with extensions to the base hardware. Indices
for DR indicators and sensors are obtained from the DRC index for the DRC
connector. Information about static non-DR indicators and sensors (like
indices and location codes) are specified in the OF device tree at boot
time and do not change. Information about non-DR dynamic indicators and
sensors, needs to be gathered via the
ibm,get-indices RTAS call (see
), and sensors, instead of
being represented in the device tree.
Indicators and sensors within a platform generally have location
codes associated with them. Location code information for static
indicators and sensors, except DR indicators and sensors, are placed in
the
“<vendor>,indicator-<token>” and
“<vendor>,sensor-<token>”
properties, respectively, in the
/rtas node, where “<vendor>” is
defined in the column marked “<vendor>” in
and
, respectively. Location code
information for dynamic indicators and sensors, except DR indicators and
sensors, for the most part come in via the
ibm,get-indices call.
Information (index, location code) about a particular indicator or
sensor token, except DR indicators and sensors, are in the
/rtas node properties or are available via the
ibm,get-indices call, but not both. When indices are
provided via the
“rtas-sensors” or
“rtas-indicators” properties, it is
expected that there exists a sensor/indicator for each index between 0
and
maxindex. When indices are provided via the
ibm,get-indices call, the indices may not be
contiguous, and any of the indices between 0 and
maxindex may be missing.
The formats for location codes are defined in
. For indicators and sensors,
these location codes are for the location of the device being manipulated
or measured, not the location of the specific controller or sensor. The
location code for an abstracted indicator or sensor is a NULL
string.
Indicators
For static indicators, except DR indicators, OF provides for paired
integers (
token maxindex) for each indicator token under the
property
“rtas-indicators”
in the
/rtas node. With this information, the OS can
determine which types of indicators, and the maximum number (
maxindex) of each type, that the platform
provides.
For static indicators, except DR indicators, the extension
property,
“<vendor>,indicator-<token>”
(see ), provides an array of strings
containing the FRU location codes associated with each indicator. See
. Here, “
<vendor>” corresponds to the
“<vendor>” column of
and “
<token>” corresponds to the token of the
“rtas-indicators”
type.
The index of a specific indicator token is used to index into the array
up to
maxindex.
Indices and location codes for dynamic indicators are obtained via
the
ibm,get-indices RTAS call and do not appear in the
static properties in the
/rtas node.
Indices for DR indicators 9001, 9002, and 9003 are obtained from
the DRC index for the DRC connector. See Requirement
.
R1--1.
For all static
indicators, except DR indicators 9001, 9002, and 9003, OF must provide
the extension property,
“<vendor>,indicator-<token>”,
in the
/rtas node, unless the indicator is part of an
extension which has its own set of appropriate properties for the
indicator, where “
<vendor>” must be as defined in the
column labeled “<vendor>” in
for the specific indicator
token value.
R1--2.
For all static indicators for which
there is an associated
“<vendor>,indicator-<token>”
property and for which there is not a
physical realization, the location code string must be NULL.
R1--3.
Indices and location codes for any
indicator token, except DR indicators 9001, 9002, and 9003, for which the
number of such indicators in the platform may change dynamically, must be
obtained via the
ibm,get-indices RTAS call and the indicator token
must not appear in the
“<vendor>,indicator-<token>”
or “rtas-indicators” in the
/rtas node.
R1--4.
The indicator token of 4 must not exist
in a platform when a Error Log (token 9006) is implemented.
Sensors
For static sensors, except DR sensors, OF currently provides for
paired integers (
token maxindex) for each sensor token under the
property
“rtas-sensors”
in the
/rtas node. With this information, the OS can
determine which types of sensors, and how many of each type, that the
platform provides.
For static sensors, except DR sensors, the extension property,
“<vendor>,sensor-<token>”
(see ), provides an array of strings
containing the FRU location codes associated with each sensor. See
. Here, “
<vendor>” corresponds to the
“<vendor>” column of
and “
<token>” corresponds to the token in the
“rtas-sensors” property. The index of a
specific sensor is used to index into the array up to
maxindex.
Indices and location codes for dynamic sensors, except DR sensors,
are obtained via the
ibm,get-indices RTAS call and do not appear in the
static properties in the
/rtas node.
Indices for DR sensors 9003 are obtained from the DRC index for the
DRC connector. See Requirement
.
R1--1.
For all static
sensors, except DR sensor 9003, OF must provide the extension property,
“<vendor>,sensor-<token>”, in the
/rtas node, unless the sensor is part of an extension
which has its own set of appropriate properties for the sensor, where
“
<vendor>” must be as defined in the
column labeled “<vendor>” in
for the specific sensor token
value.
R1--2.
For all static sensors for which there
is an associated
“<vendor>,sensor-<token>”
property and for which there is not a
physical realization, the location code string must be NULL.
R1--3.
Indices and location codes for any
sensor token, except DR sensor 9003, for which the number of such sensors
in the platform may change dynamically, must be obtained via the
ibm,get-indices RTAS call and the sensor token must
not appear in the
“<vendor>,sensor-<token>”
or “rtas-sensors” in the
/rtas node.
R1--4.
The following sensor tokens must not be
implemented if the number of them may be changed by a DR operation (that
is, they can only be used when static): 3, 9001, and 9002.
Calling Mechanism and Conventions
RTAS is
called through a mechanism similar to the OF client interface service. An
argument buffer is constructed which describes the desired RTAS call.
This description includes an indication of the RTAS call that is being
invoked, the number and value of the input parameters, the number of
result values, and space for each of the result values.
R1--1.
In order to make an RTAS call, the OS must
construct an argument call buffer aligned on an eight byte boundary in
physically contiguous real memory as described by
.
RTAS Argument Call Buffer
Cell Number
Use
1
Token Specifying which RTAS Call
2
Number of Input Parameters
3
Number of Output Parameters
4
First Input Parameter
...
Other Input Parameters
4 + Number of Inputs -1
Last Input Parameter
4 + Number of Inputs
First Output Parameter
...
Other Output Parameters
4 + Number of Inputs
+ Number of Outputs -1
Last Output Parameter
R1--2.
If the system is
a 32-bit system, or if RTAS was instantiated by
instantiate-rtas, then all
cells in
the RTAS argument buffer must be 32-bit sign extended values that are
aligned to 4 byte boundaries.
R1--3.
If the system is
a 64 bit system and if RTAS was instantiated by
instantiate-rtas-64, then all
cells in the RTAS argument buffer must be 64-bit sign extended values
that are aligned to 8 byte boundaries.
R1--4.
RTAS functions must be invoked by branching
to the
rtas-call address which is returned by the
instantiate-rtas
or
instantiate-rtas-64
OF method (see
).
R1--5.
Register R3 must contain the argument
buffer’s real address when
rtas-call is invoked.
R1--6.
Register R4 must contain the real address
of the RTAS private data area when
rtas-call is invoked (see Requirement
).
R1--7.
The Link Register must contain the return
address when
rtas-call is invoked.
Software Implementation Notes:
RTAS is not required to perform sanity checking of its input
parameters. Using invalid values for any parameter in an RTAS argument
buffer gives undefined results. However, when such checks are made, the
appropriate return code for invalid parameters is -3.
The token that specifies the RTAS call is obtained by looking up
the desired call from the
/rtas node of the OF device tree.
The OS must be aware that the effective address range for RTAS
is 4 GB when instantiated in 32-bit mode and the OS should not pass RTAS
addresses or blocks of data which might fall outside of this
range.
Return Codes
R1--1.
The first output
value of all the RTAS functions must be a
Status word which denotes the result of the call. The
Status word takes on one of the values in
. Non-negative values indicate
success.
RTAS
Status Word Values
Values
Status Word Meanings
0
RTAS function call succeeded.
-1
RTAS function call encountered a hardware error.
-2
A necessary hardware device was busy, and the requested
function could not be performed. The operation should be
retried at a later time.
-3
Parameter Error.
In some cases, specific parameter errors are enumerated.
However, other parameter errors may be reported using this
return code in addition to those enumerated.
-7
Unexpected state change.
9000-9899
Reserved for vendor specific success codes.
990x
Extended delay - where x is a number in the range of
0-5
-9000
Multi-level isolation error (see
).
-9004 - (-9999)
Reserved for vendor specific error codes.
Additional Negative Numbers
An error was encountered. The meaning of this error is
specific to the RTAS function that was invoked.
Additional Positive Numbers
The function succeeded. The meaning of the
Status word is specific to the RTAS
function that was invoked.
indicates a summation of all
possible
Status word values. A given RTAS function cannot
yield all of the possible
Status words. For the specific
Status words which apply to a specific RTAS function,
see the semantics for that function.
Software Implementation Notes:
A return code of -2 or 990x may either mean that the operation
was initiated but not completed, or may mean that the operation was not
initiated at all.
When the extended delay (990x) is returned, it is suggested that
software delay for 10 raised to the x milliseconds, where x is the last
digit of the 990x return code, before calling the function again.