
    $Id: NSD-Thoughts 1.4 1997/05/15 18:09:27 heinz Exp $


Thoughts & Consequences
=======================

This chapter may count as a set of annotations to NSD. It
should shed some light on certain decisions and the consequences
for users and implementors of NSD devices.

You may have noticed that there isn't a device type for SCSI or
narrator. This is intentional. There is no NSD narrator right now
and it is probably unwise to rely on the interface of the old
narrator. A scsi device is typically a logical superset of
trackdisk functionality and, for non disk devices relying only on
HD_SCSICMD, a subset of scsi.device, which in turn classifies as
trackdisk like. So in some way simple trackdisk functionality is
the common base. It is also expected that any user visible
difference between a SCSI like device and a trackdisk like device
will tend to disappear. So SCSI and trackdisk like device have been
put under the common label of NSDEVTYPE_TRACKDISK. The CD 32
cd.device is also a trackdisk like device within this meaning.

IOERR_NOCMD support is a design basis for NSD. Actually, support of
IOERR_NOCMD is _the_ design basis for NSD. There are very few very
broken devices out there which don't even support IOERR_NOCMD
correctly and simply crash on unknown commands. These are not
supported under NSD, and some kind of patch or "wrapper device" is
needed for them to avoid a crash with a NSD using application. This
was expected when NSD was designed, and based on the saying "the
needs of the many outweigh the needs of the few", it was accepted
that NSD cannot be safe for absolutely every single device in
existance.

Another design basis for NSD is mentioned in the RKM Libraries, 3rd
edtion on page 445:

    The philosophy behind the devices is that I/O operations should
    be consistent and uniform.

This means that many commands like CMD_WRITE have similar
functionality among very different types of devices. The
philosophy is reflected by the general reserved command area and
the general query command. This philosophy also extends to the
meaning of IOERR_NOCMD which is described in <exec/errors.h> and
referred to on page 924 of the RKM Libraries, 3rd edition.
IOERR_NOCMD should be returned consistently for unsupported, i.e.
unimplemented commands by the device. This means that it is not an
acceptable error value for commands that are in fact supported by
the device, but can't be executed correctly currently, because of
limitations of the currently set up underlying hardware or
configuration. It is only acceptable as error value if the
respective command will never ever at any time under any
circumstance be available.

A basic problem exists with old style SANA devices. They tweak the
OpenDevice() usage by passing in parameters via the request. The
RKM Libraries 3rd edition, page 447, says:

    In addition to establishing the link to the device,
    OpenDevice() also initializes fields in the I/O request.

Passing in configuration data via an "uninitialized" request on
OpenDevice() is therefore somewhat special and unusual. This is
considered a design flaw in the SANA specification as it breaks the
uniformness of device access. So SANA devices can put a monkey
wrench into the NSD system and this lead to the "safer assumptions"
kludge. NSD is based on the assumption that devices can be
"probed", so a general query on a SANA device may not return what
you expect. Unless absolutely required by the original device
specification, it is unwise to pass in configuration information on
OpenDevice() within the NSD framework. For a SANA-device you would
have to close it after the query and reopen it with the correct
configuration data to be able to use it, if you don't pass in the
configuration information right away. This leaves an access hole
that isn't there for other types of devices. 3rd party devices
needing this feature for 3rd party functionality should better use
a configuration command to set parameters. For device specific
usage of an NSD device, this isn't really a problem as you expect
to get the right device type on OpenDevice(), which should be OK
except for pathological cases. A query is mainly a verification of
the required feature set here, so the risk is minimal. In general,
it is an issue to think about, though.

The mn_Length check has been originally introduced into NSD to make
use of a device safer. The easiest check is for the minimum
required request size in OpenDevice(). This will catch basic
programming errors and, in the worst case, only make OpenDevice()
fail, rather than make the computer crash in unexpected ways.
Refusal to open is deemed better than definitely overwriting or
referencing garbage memory.

An exact check for mn_Length is very unwise and cannot be
recommended, as a user may decide to use an extended IORequest with
some additional user private fields. It would also be a fairly
simple improvement to add mn_Length checks to all individual
commands in the device. The overhead of a simple compare can
typically be neglected, and the device can make sure that the size
of the request is acceptable for the specific command. This would
be of additional help for devices which support different sizes of
IORequests for different commands.

Be aware that the minimum required request size on OpenDevice() may
be less than what the commands need. So design the mn_Length check
in OpenDevice() carefully to include the most error checking
possible right there without keeping the device from opening. Don't
forget that a general NSCMD_DEVICEQUERY must be possible, too, even
if the device itself does use completely different request sizes.
Note also that early NSD using software may use just a simple
struct IOStdReq for the general query. As you can see by now,
checking mn_Length for each command is not a bad idea, either.

Validating mn_Length is a very simple way to catch fundamental but
obscure errors to avoid a system crash. There will always be a
pathological case that cannot reasonably be caught like special
broken parameter settings, but simple validations like an mn_Length
check make device access a lot safer. Along these lines, other
fields, like io_Unit, of a request could be validated. If a device
can easily check for broken user SW, it should do so and return
decent error values instead of crashing the system.

*** EOT ***
