> &.docs.NewIdeas

Description; DeviceFS III - this time its war
Authors; David De Vorchik, Ran Mokady
History;
        12-Mar-91 Created
        13-Mar-91 Altered


Questions
=========

1. Kernel printing via buffer 3 x
2. Kernel serial printing via buffer 3,2 x
3. Kernel serial input.
4. Printer:



1. Kernel printing via buffer 3
-------------------------------

Kernel without device drivers goes via "<PrinterType$x>", x being the current
printer destination FX 5.   Within the system variable is specified a buffer
handle, this is a special field keyword.

ie.             device#buffer3:$.foo

This works for parallel (me too!)



2. Serial printing via buffer 3 and 2
-------------------------------------

This can be solved by specifing two buffers on the special field keyword.  It
has been decided that this should become a feature of DeviceFS, esp. when we
move to the new DeviceFS_GetCharacter + DeviceFS_TransmitCharacter SWIs.

Devices instead of calling InsV and RemV will issue the SWIs to DeviceFS and
specifiy a stream handle.

The buffer keyword within the special field will allow multiple buffers to be specified and DeviceFS will cycle around attempting to use each one, ie. the first fails so we will try the next, ie:

ie.             device#buffer3,4,5:$.foo

If buffer 3 fails, then buffer 4 and finally buffer 5 before giving up.



3. Kernel Serial input
----------------------

When the buffer manager is installed the kernel will register the  serial
input and output buffers.  The serial device when enabled for input will
attempt to call DeviceFS_ByteRecieved, if this fails then it will call InsV
directly to insert into buffer 2.

When a stream is created for input the device will force the buffer handle to
be two (via the pre create RX IOCTL) call, this retains compatibilty. 
Therefore any removal of characters from this buffer will then be correct and
no loss of data should occur.


4. Printer:
-----------

This is handled by the comments in 1.




New interface to Devices
========================

1. DeviceFS -> Device
2. Device -> DeviceFs
3. User -> DeviceFS


DeviceFS provides a flexible ever changing interface to devices under RISC OS
2.xx (see current FuncSpec for correct defination (you'd better hurray 'cos
its constantly changing)).

And now for something completely different....

DeviceFS is the RISC OS filing system providing file/stream access to
character based devices.  Devices are mapped to the DeviceFS filename space,
thus providing a virtual interface to any device within the operating system.

Devices when registered with DeviceFS provide a list of objects to be created
in the directory structure.  File operations can be performed on these
objects to create input or output streams.  A device driver module may
contain more than one object relating to a itself.

When a device registers it can specifiy complete path.  Each section except
the last element is created as a directory, the last object is given a file
type of 'Device' and its access rights are setup to reflect the capabilities
ie. R for a Input device, W for an output device.

A device can specify that it would like a path variable defining to point a
particular entry in the structure, this is used to provide pseudo filing
systems such as serial and parallel.


* DeviceFS$<name>$Options
* Gerernal waffel about IOCTL
* Description of how it all really works, buffered, non buffered
* Reserved keywords.


Interface
=========

DeviceFS_Register
-----------------

  in: r0  = device driver specific flags
                bit 0 clear => character device
                  bit 0 set => block device
           bits 1..31 clear => reserved must be zero.

        [ bit 0 set is not supported at the moment so all this bit
          must remain zero at all times ]

      r1 -> list of devices to be installed:
                +0  = offset to device name to register (null terminated)
                    = 0 end of list of devices.

                +4  = flags relating to installed device
                        bit 0 clear => device not buffered
                          bit 0 set => device buffered
                        bit 1 clear => don't define fs alias for device
                          bit 1 set => setup filing system alias.
                    bit 2..31 clear => reserved must be zero.

                +8  = default flags for TX buffer (=0 if not buffered)
               +12  = default size of TX buffer (=0 if not buffered)
               +16  = default flags for RX buffer (=0 if not buffered)
               +20  = default size of RX buffer (=0 if not buffered)

      r2 -> IOCTL routine
      r3  = private word
      r4 -> Workspace
      r5 -> validation string used to parse special fields, 
          = 0, don't parse simply pass onto device in 'raw' format
         = -1, don't allow special fields on this device.

      r6  = Maximum number of inputs / =0 for none / =-1 unlimited
      r7  = Maximum number of outputs / =0 for none / =-1 unlimited

 out: V clear => r0  = device handle
      V set => r0 -> error and device not registered.

This call is made to register a device with DeviceFS, once registered its
entries appear within the DeviceFS directory operations to open and close can
be performed onto it.

On entry in r0 are device specific flags, these relate the device driver as a
whole entity and are not related to any specific incarnation of the driver.

bit 0 clear  => input / output is performed on a character basis.
      set    => not supported yet - should not be used..

other bits of r0 are reserved and should be zero for future expansion.

R1 contains the pointer to a list of devices to be register within the
directory structure, the data within these records describe the actual
incarnations of the device.  This list is terminated by a null word in the
first location.

The +0 within each description within the list contains the offset from that
entry to the null terminated device name, this name is case insensitive, no
copy is made of the string.

+4 within the block is a flags word, this describes the characteristics of this device, ie. should it buffered or not and should a filing system alias be setup.

bit 0 clear  => device is not buffered, DeviceFS will poll for single bytes
                when required.

      set    => device is buffered and data should be inserted into buffers
                controlled by the buffer manager.

bit 1 clear  => don't setup a "<devicename>$Path>" variable as a pseudo
                filing system.

      set    => do setup a "<devicename>$Path>" variable as a pseudo
                filing system.

The next four words describe the buffers that should be used, these words
should be zero if the the device is not buffered, else they should reflect
the default state of the buffers created.

This list continues repeating itself until a null offset to the name is 
specified.

r2 contains the address of the IOCTL entry within the device driver, this is
used by DeviceFS to communicate with the device driver (see above).

r3, r4 contain the private word and workspace pointers.  r3 is passed on
entry to the device in r8 and r4 is passed in r12.

r5 contains a validation string used for parsing the keywords within the 
special field string.  If this is 0 then the string is not processed it is
simply passed through, if it is -1 then DeviceFS will error complaining that
special fields are not supported by this device.

r6, r7 contain the maximum number of input and output streams allowed, these
are used to range check the open before the device driver is informed.  If
the value is -1 then the type of open is unlimited (- probably a bad way to
describe it ed?)




DeviceFS_Deregister
-------------------

  in: r0  = handle of device
 
 out: V clear => all preserved, device deregistered.
      V set => r0 -> error block, device not registered.

This call will dereigster a device, tidying and closing any streams opened
onto it.

[ ASIDE: Should buffered input devices flush and close, or should DeviceFS
         attempt to close the stream when the last byte is removed? ]



DeviceFS_ByteRecieved
---------------------

  in: r0  = character
      r1  = external handle

  
 out: V clear => character transfered to DeviceFS
      V set => r0 -> error block character not transfered

This call is used to transfer a character from the device driver to DeviceFS.

DeviceFS inturn will handle insertion of the character into a buffer or
passing back to the client as required.




DeviceFS_RequestByte
--------------------

  in: r1  = external handle

 out: r0  = byte if obtained, or -1 if unable to obtain a character.
    
This call should be made when the device is ready to recieve the next
character, if on exit r0 contains -1 (no character) then it must then 
go to sleep and it will be woken up when it is time to transmit the next
byte.




DeviceFS_Threshold
------------------

  in: r0  = threshold / -1 to read
      r1  = external handle, or
         -> device name
 
 out: V clear => r0  = old value of threshold
      V  set => r0 -> errror block


This call can be used to modify the handshaking thresholds used by a buffered
device.  When the free space is less than the specified threshold then a
device recieves an event via the IOCTL entry.  When there is enough free
space then the device is woken up again to handle more RX. 


  

DeviceFS_RegisterObjects
------------------------

  in: r0  = device handle 
      r1 -> list of objects to be registered

 out: usual stuff about V.

This call is used to register further objects to a specified device, the list
of objects is the same as the one specified on DeviceFS_Register.




DeviceFS_DeregisterObjects
--------------------------

  in: r0  = device handle
      r1 -> list objects to be removed from structure.

 
 out: usual stuff about V.

This call removes the specified list of null terminated objects from the
directory structure, removing all objects relating to a device does not
remove the device.




DeviceFS_CallDevice
-------------------

   in: r0  = reason code (bit 31 set)
       r1  = external handle, or
          -> device name string (null terminated)
    r2-r7  = reason code specific to reason code.

  out: V   set => r0 -> error block
       V clear => no error

This SWI allows the client to call the device_IOCTL entry.  r0 on entry
contains a reason code to be passed, only reason codes with bit 31 set are
allowed through, others are faulted.  r1 contains the external handle or 0 if
this is a general purpose call, the handling of which is determined by the
device.

When the device recieves the call the handle passed in r1 will have been
converted from its external form into an internal copy.  Registers r2-r7 are
defined for device use and all registers on exit are passed back.  Errors can
be generated in the normal way by setting the V flag and returning r0 ->
error block.



DeviceFS -> Device interface
----------------------------

A device will supply one entry point (device_IOCTL, sounds a bit UNIX to
me?!), through this are passed various reason codes.  Some are reserved for
DeviceFS use and an external way of calling this entry is provided for device
specific operations.



device_IOCTL
------------

in: r0  = reason code
           0 : initialise
           1 : wake up TX
           2 : wake up RX
           3 : RX sleep
           4 : finalise
           5 : halt RX
           6 : resume RX
           7 : directory being enumerated
           8 : pre buffer create for TX
           9 : pre buffer create for RX
            

reason 0: intialise
-------------------

  in: r0  = 0
      r1  = external stream handle 
      r2  = flags
                bit 0 set => TX
                bit 1 set => RX
            bit 2..31 clear => reserved for future extension

      r3 -> full path (eg. "$.foo") used to open stream
      r4 -> parsed special field string

 out:   V set => r0 -> error block, all other registers ignored
      V clear => r0 preserved
                 r1   = internal handle
                 r2 preserved

This call is made when a stream is opened, it will never be called more than
the specified limits of the device.


reason 1: wake up TX
--------------------

  in: r0  = 1
      r1  = internal handle 

 out: all preserved, including PSR.

This call is made when data is ready for transmission, the device should call
DeviceFS_TransmitByte to obtain the data to be transfered.


reason 2: wake up RX
--------------------

  in: r0  = 2
      r1  = internal handle 

 out: all preserved, including PSR.

This call is made to enable reception, ie. when the DeviceFS is expecting
characters from the device, these characters should be passed back using the
DeviceFS_ByteRecieved SWI.



reason 3: RX sleep
------------------

   in: r0  = 3
       r1  = internal handle

  out: all preserved, including PSR.

This call is made after all characters have been recieved that are needed
from the non-buffered device.  Upon reciept the device should stop issuing
DeviceFS_ByteRecieved SWIs.



reason 4: finalise
------------------

  in: r0  = 4
      r1  = internal handle 

 out:   V set => r0 -> error block, stream cannot be closed.
      V clear => all preserved.

This is called when the stream is being closed, any errors returned result in
the stream being left active and the error is reported back to the client.


All reason codes with bit 31 set are device specific and are defined by the device itself, access to these is provided by the SWI DeviceFS_CallDevice.


reason 5: halt RX
-----------------

  in: r0  = 5
      r1  = internal handle

 out: -

This call is made from DeviceFS to the device when the buffer that the device
is streaming into has less free space that the defined threshold.  Once
recieved the device should perform whatever handshaking is required.



reason 6: resume RX
-------------------
 
  in: r0  = 6
      r1  = internal handle

This call is made from DeviceFS when it is safe to resume recieving
characters into the buffer that you are streaming to, ie. the free space is
greater than the specified threshold.



reason 7: directory being enumerated
------------------------------------

  in: r0  = 7
      r1 -> pathname
     
 out: -

This call is made when a part of the directory structure is being enumerated
that relates to the device, ie. if a directory owned by the device driver is
being examined therefore allowing device to update its contents.



reason 8: pre-buffer create for TX
----------------------------------

  in: r0  = 8
      r1  = flags for buffer
      r2  = size of buffer
      r3  = buffer handle to use, -1 for default

 out: r1-r3 modified as required

This call provides a way for devices to modify the parameters passed to the
buffer manager to create a buffer, if the buffer handle in r3 exists prior to
attaching then the device will simply be linked to the device.

*** THIS CALL IS PROVIDED FOR COMPATILBITY ***



reason 9: pre-buffer create for RX
----------------------------------

  in: r0  = 9
      r1  = flags for buffer
      r2  = size of buffer
      r3  = buffer handle to use, -1 for default

 out: r1-r3 modified as required

This call provides a way for devices to modify the parameters passed to the
buffer manager to create a buffer, if the buffer handle in r3 exists prior to
attaching then the device will simply be linked to the device.

*** THIS CALL IS PROVIDED FOR COMPATILBITY ***


