A Paranoia intro document intended for application developers who wish
to get started using Paranoia in their own applications as well as new
developers who with to contribute to the Paranoia project itself.

* Paranoia Project Introduction *************************************

The Paranoia IV library simplifies portable packet command based
device programming across platforms and across device interfaces on
the same platform; the idea is to make ATAPI/SCSI programming uniform
regardless of the platform (Linux, Solaris, NetBSD, FreeBSD, etc) and
regardless of the kernel interface on a specific platform (Linux SG,
Linux PG, *BSD SCSI ioctl(), etc).  The abstraction layers in Paranoia
IV are also arranged to allow adding other packet command interfaces
(USB will probably be the first) with minimal pain.

Secondly, Paranoia then builds specialized interfaces (eg, CDROM CDDA)
on top of these packet interfaces. 

Other other libraries also provide this infrastructure; paranoia has
several additional goals that necessitated a somewhat different
abstraction structure from, eg, libscg:

1) automatic hardware, kernel and device identification and handling;
   no compile-time system settings.
2) built in extensive and intelligent progress and error reporting 
3) complete error correction capabilites offered through high-level
   functionality-based interfaces

(Note to Paranoia developers; libscg is a great place to look at
existing, stable SCSI code for other platforms, albeit with a slightly
different design bent. Note to application developers: if you're
looking for a simpler, single-layer SCSI transport library, libscg is
a good choice)

* Paranoia functionality summary ************************************

1) provide a portable, packet command interface to SCSI and ATAPI devices
   that is uniform across platforms and devices.  Programming to a
   Parallel port ATAPI CDROM under Linux should be no different than
   coding for a SCSI drive under Solaris or Rhapsody.  This point is
   the same as libscg.

2) provide specialized interfaces to device types that both simplify
   accessing device functionality and add robust error handling and
   correction to inherently unreliable function (eg, digital audio
   extraction from audio CDROM drives).  

3) provide a uniform method across platforms of identifying and
   addressing device types and specific named devices.

4) provide detailed and intelligent reporting of system capability,
   software status and error situations.

* Paranoia layer overview *******************************************

Paranoia is split up into several layers, each building on preceeding
layers to construct higher-level interfaces.  The layers are entirely
seperable. The best way to understand the structure of the library is
probably to start with the simple and familiar (the transport layer,
which provides raw functionality and not much else).
                                                                
                                                     /\      /\ 
  __________________________________________________/  \____/  \__
 |                                                          |  |  |
 | IV  COMMAND layer  (management and implementation of     |  |  |
 |                     high-level specialized interfaces)   |  |  |
 |                                                   /\     |  |  |
 |__________________________________________________/  \____|  |__|
  __________________________________________________|  |____|  |__
 |                                                  |  |    |  |  |
 | III AUTO layer (search and detection of system   |  |    |  |  |
 |                 devices and hardware)            |  |    |  |  |
 |__________________________________________________|  |____|  |__|
  __________________________________________________|  |  __|  |__ 
 |                                                    _|_|   II   |
 |  I  TRANSPORT layer (packet command based         /     REPORT |
 |                      communication with hardware) \___  layer  |
 |_____________________________________________________| |________|


I]  Transport:

  I.a) Basic use
	
The transport layer looks a like a simpler version of libscg and other
transport packages.  One allocates a transport device using an open
function and an fd already opened and attached* to a given packet
command device.

*(Some systems, like Linux, provide /dev/sg entries that map
one-to-one with actual hardware on the SCSI bus[ses].  When an
application opens, for example, /dev/sga, that fs already directly
corresponds to the first target on the first SCSI chain.  Other
systems, such as FreeBSD and Solaris, provide generic SCSI devices
that may refer to *any* actual piece of SCSI hardware in the system.
The device is first opened, then associated with a specific hardware
item.)

Allocation returns a transport_device structure that contains state
information, as well as function pointers to provide the rest of the
transport library's functions.  Currently, the pointers returned are
for the functions 'reset', 'command', 'special' and 'close'.
"command" is used to send raw packet commands to the device in
question (packed into a packet_command struct) and returns the result
of the command.  "reset" is used to try to reset the device to a known
state if command processing goes awry.  "close" is used to close and
destroy the transport_device when it is no longer needed. "special" is
an abstraction hack that will be explained in the section on
implementation of the command layer.  Detailed programming
instructions and requirements for the transport layer are described
later in this document (under programming).

  I.b) Using callbacks:

At this level (transport), use of Paranoia is very simple.  Open,
submit commands, get results, then close.  The simplest form of error
reporting is to not use the callback mechanism built into each
command.  Pass NULL as the callback argument, and any fatal errors
simply return an error result and set errno to one of the errors
listed in paranoia_errors.h.  Function calls will always run
uninterrupted to completion or return an error.

Callbacks provide a way to get additional detailed error information
about what caused a failure or get detailed progress information from
a command before it finishes.  All the functions in each layer of
Paranoia provide a callbacks argument to the function call.

A callback is a function passed as an argument a Paranoia call that
will be called immediately at the point of an error, non-fatal warning
or progress information point.  The callback is called with the
error/warning/progress number, the current working state at the point
the error occurred, and an argument that identifies the type of the
passed state.  The callback mechanism is described in detail in the
programming section later.  Application developers may write their own
callback function from scratch, or make use of some or all of
Paranoia's built-in callback mechanism, described next.

II] Built in callbacks [Report layer]

Developer's applications can construct their own callbacks.  To
minimize work (and provide an example of how to use callbacks),
Paranoia provides a built in set of callback building blocks.  The
built in callbacks consist of a message database and state lookup
mechanism; the state passed to the callback is matched to the message
database, and a detailed message returned in text form.  The message
database is not hardwired, and may be modified or supplemented by
applications.

The callback building blocks extend through all of the layers of
Paranoia, not just the transport layer.  The building blocks are
mutable and need not be used at all; the application can construct its
own callbacks (Paranoia can be compiled without any of the callback
code), use callbacks only occasionally, or ignore the callback
mechanism entirely.  Use of the callback mechanisms is covered later.

III] The device scanning/location layer [Auto layer]

The role of the auto layer is to automate the process of returning a
useful transport_device struct matching a desired piece of physical
hardware into a single step.  Search criteria could be any or several
of device name (the trivial case), device type, interface type,
vendor, or location in a device sequence.

The auto layer can be fairly complex on platforms with multiple
possible interfaces for a given device family.  In this case, the auto
layer is not only responsible for locating hardware, but also being
aware of multiple interface families and matching a request to the
right device and low-level transport.  Further tasks that fall upon
the auto layer include mapping specialized devices to generic devices
(eg, mapping /dev/sr0 to /dev/sgb or the like) and associating a
specialized device to a specific target on system that allow a generic
packet command device to address any physical hardware device on that
interface.

In summary, the auto layer is given a search criteria and does all the
work necessary to hand an open and ready filedescriptor to the
transport layer for transport_device allocation.  Auto then returns
that transport_device to the application (note that the auto layer
wraps the transport_device inside an auto_device which also contains
additional information about the device, such as the path of the
device entry).

IV] The COMMAND layer

The command layer takes a transport_device and returns a high-level
command interface for that device.  An example is taking a
transport_device representing the raw packet interface to a CDROM and
requesting a high-level interface with function calls to control
playback or extraction of audio disks.  

* Programming with Paranoia *****************************************

This section discusses details and examples of programming with
Paranoia using the various layer interfaces.  It is not an exhaustive
reference but does intend to cover all details of programming.
Paranoia developers are encouraged to read and internalize this
section.  It's just as important as the implementation section to
follow; after all, Paranoia is a goal-driven exercise, and the goals
are a) the simple interface and b) the most reliable, consistent
possible behavior.

I] Programming to the TRANSPORT layer
   I.a) "Open()ing" a transport_device

Interaction with the transport layer begins with allocating a
transport_device using one of the transport layer's 'open' calls.
Each interface family on a machine has its own open function*.  For
example, to allocate a transport_device for an fd belonging to a Linux
generic scsi device, one would call linuxsg_open(fd, callback).  Note
that only the open() naming is different among interfaces and
platforms; all open calls are identical except for the exact name of
the function called. The various interfaces and open calls available
for given platforms are listed in Appendix A.

*(The transport layer contains a few inelegancies that expose minor
platform differences; the naming of the xxxxx_open() functions is one
of these.  This naming approach was taken for two reasons: 1) it keeps
the transport layer simple; transport is not designed to make
determinations about appropriate device interface.  That is the job of
the auto layer or user application. 2) Depending on circumstance, more
than one device interface might be usable for a given fd on some
platforms.  In this case being overly clever about hiding the actual
interface type behind a naming scheme would be more trouble to the
implementor and the developer than elegance is worth.)

The xxxxxx_open prototypes follow:

transport-device *xxxxxxx_open(int fd, void (*callback)(int,int,void))

For the moment, use of the callback mechanism isn't explained in
detail; the construction and use of callbacks and the built in
Paranoia callback building blocks is described in "Programming
Callbacks".  When not using callbacks, pass 'NULL' as the callback
argument.

Call xxxxxx_open() with a valid, attached fd; that is, on systems that
may associate a generic interface entry with any actual hardware
target (eg, on FreeBSD, a generic SCSI device can be associated with
any SCSI target).  On systems like Linux and NetBSD, this is not an
issue as a generic device is associated directly with a specific
target.

A failed call to xxxxxx_open() returns NULL and sets errno
appropriately.  Note that Paranoia defines its own error numbers in
order that numbers for a failure are consistent across platforms.
This document does not yet include an exhaustive list of possible
errors for a command as they may vary from platform to platform.
However, Appendix B lists all currently possible Paranoia IV error,
warning and progress numbers.







* Appendix A ********************************************************

Currently supported platforms and interfaces by platform as of March
11, 1999.

LINUX:   generic scsi (sg, including ide-scsi hostadapter emulation):
		linuxsg_open()
	 generic paride (pg)
		linuxpg_open()
	 atapi ioctl() cooked (hd)
		linuxioctl_open()

* Appendix B ********************************************************

List of all Paranoia IV error, warning and progress number codes with
their definitions, as of March 11, 1999.
