Home
Developer Resources
QNX RTOS v4
QNX RTOS v4 Knowledge Base

QNX RTOS v4 Knowledge Base

Foundry27
Foundry27
QNX RTOS v4 project
Resources

QNX RTOS v4 Knowledge Base

Title Fsys changes from QNX 4.1x/4.22 to 4.25
Ref. No. QNX.000010352
Category(ies) Filesystem, Development
Issue We are porting a Fsys driver from an older version of QNX to QNX 4.25.  We are having problems however with the commands and the changes made to the Fsys module.  What are the changes that have been made to the module that is preventing us from porting our driver?
Solution
                          32-bit Fsys/Driver Interface
                      Differences from 16-bit Interface
                                August 23, 1995

This document is a preliminary document, intended for experienced Fsys driver
authors.  It is not a complete description of the Fsys/driver interface.
Instead it is intended to document the differences between the 16-bit and the
32-bit interface.

<sys/_dskdrvr.h> header file:

If you examine this file you will notice a number of differences.  One is that
the 32-bit Fsys attaches a different name: "qnx/fsys32" instead of "qnx/fsys".
However to minimize changes for existing drivers, the macro _FSYS_NAME is given
the appropriate value depending on the compiler model.

To allow for possible future extensions, the 32-bit interface allows for 20
entry points instead of just 16 entry points.  However at this time no new
entry points have been defined.

One key difference which will impact existing 16-bit drivers which will be
ported is that the _block structure has been radically changed.  Instead of the
driver being given a being a linked list of struct _block for read and write
operations, it now is given an array.  This eliminates the pointer member.  In
reality, the linked list which 16-bit drivers have been passed is actually a
list through an array and has been for some time -- originally (4.0x) this was
not true.

Another change to this structure is the elimination of the block number; since
all I/O is sequential, this is passed at the start of an I/O operation (as
documented below).

Finally, the 16-bit __far pointer has been replaced with both a 32-bit pointer
(b_virt) and a physical address (b_phys) useful for drivers which can DMA
directly to/from the Fsys cache.

A note about the Fsys cache is in order at this point: in the 16-bit Fsys, the
cache was "DMA safe" -- that is the cache was all below the 16M point and no
block crossed a segment boundary.  This effectively limited the cache size to
about 14M in a typical system.  In the 32-bit Fsys the cache is no longer
restricted to any particular portion of memory.  The only guarentee which Fsys
makes about the cache placement is that no block will cross a page boundary
(4K).  If your hardware cannot DMA anywhere in memory (such as PCI bus
mastering controllers can do) then it is up to you to supply your own DMA safe
intermediate buffer.  For a read, it is still acceptable to leave the data in
the DMA buffer and have Fsys copy it out by setting the d_dma_seg field in
struct _disk.

In struct _disk, you'll notice that little has changed except the fields have
been rearranged.  The only exception to this is the addition of the
'd_attention' field.  It is anticipated that this field will be used by a
driver to asynchronously gain the attention of Fsys (i.e. when there are no I/O
operations occurring) to inform Fsys, for example, that a removable drive has
been removed (as a signal for Fsys to flush its cache perhaps).  However at the
time of writing this, the field is not yet used and the full details of how it
will be used have yet to be resolved.

The 4.3 Fsys supports some new unit status bits.  This bit flags are assigned
to a 'd_stat' field in struct _disk.  This field is examined after every read,
write and ioctl (both synchronous and asynchronous).  The new fields are:

#define _DRVR_LOCKED_MEDIA  0x0004  /*  Removable media locked in drive    */
                                    /*  will be treated like a hard disk.  */
                                    /*  If removable is not locked, it will */
                                    /*  be treated like a floppy and the    */
                                    /*  cache timed out after 2 seconds    */
                                    /*  of inactivity. (v4.3+)              */
#define _DRVR_ASYNCH_WRITE  0x0008  /*  Regardless of Fsys flags,          */
                                    /*  all system (metadata) writes will  */
                                    /*  be asynchronouns.  Synchronous data */
                                    /*  writes are unaffected. (v4.3+)      */

One possible use for this is an ioctl which locks and unlocks the drive door
for a removable cartridge disk, with the Fsys cache being invalidated (or at
least beginning a timeout) when it is unlocked.

Driver entry points:

In defining the 32-bit interface, two sometimes conflicting goals were used: to
minimize the changes and to rationalize the interface for a 32-bit system.

_DRIVER_INITIALIZE:
Instead of the number of cache segments and a pointer to an array of segments
being passed to the driver, the 32-bit Fsys passes the number of cache blocks
and a pointer to the start of the cache.  With a 32-bit Fsys, all the cache can
fit in the one data segment.

_DRIVER_TERMINATE:
Called after all the block special files which were created by Fsys have been
unlinked by an appropriately priviliged user.  (Finally, a controlled way to
terminate a driver!)

_DRIVER_UNIT_INIT:
No change.

_DRIVER_UNIT_TERM:
Not used.

_DRIVER_IO:
As mentioned, for reading and writing the driver is now passed the starting
block number (instead of it being in the struct _block entries) and a pointer
to an array of type struct _block (instead of a pointer to a linked list).

_DRIVER_CONTROL:
The ioctl interface has some significant changes: instead of being passed a
16-bit request type and a pointer to a 512-byte data buffer, the driver is now
passed a 32-bit ioctl request (as defined in <sys/ioctl.h>) and a pointer to an
array of type struct _block allowing ioctls of up to 8191 bytes.  The ioctl
request follows the BSD conventions and encodes whether the ioctl has no
parameters (IOC_VOID), or whether it copies parameters in (IOC_IN), out
(IOC_OUT) or both (IOC_INOUT).  The ioctl request also encodes the size of the
parameters (see the IOCPARM_LEN() macro).  Since that information is in the
ioctl request type, Fsys does not pass the size or the number of blocks for the
ioctl to the driver -- the driver can trivially obtain that information for
itself.

_DRIVER_CONTROL_MASK:
Changes as above:

_DRIVER_UNIT_OPEN:
No change.

_DRIVER_UNIT_CLOSE:
No change.

_DRIVER_ABORT_CMD:
No change.