RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

DeviceFS


Introduction and Overview

DeviceFS provides a standardised interface to device drivers within the RISC OS environment. Devices are declared within the system, and are seen as objects within the 'devices:' filing system.

Streams can be opened for input or output (as supported) onto these objects within the directory structure. A device is given the device file type of &FCC. A device adopts the access rights relevant to its input or output capabilities.

A device driver is simply a set of routines that handle the input or output of data. The device can specify if it would like to be buffered, but it will never know if this is the case. Devices have access to the special field passed on opening a stream, this can be used to pass extra information about opening streams and configuration required, for instance a serial device may contain its setup within the special field string.

DeviceFS provides a way of calling devices (DeviceFS_CallDevice) with a reason code and control registers. All devices have to support a set of system specific calls, but have a range of reason codes available for their own use. This could, for example, be used for controlling a scanner.

DeviceFS currently only supports character devices; block devices have yet to be implemented.

Most filing system operations can be performed on objects: for example data transfer operations. However, it is not possible to create objects within the directory structure which are not devices, nor is it possible to delete objects.

DeviceFS is not available in RISC OS 2.

Technical Details

Special fields

Special fields within DeviceFS are commonly used to specify parameters to the device, ie what buffers to be used, if the device should be flushing when a stream is closed and so on.

The device can specify a validation string which is used to parse the special field when the stream is being opened. If this is present then DeviceFS will parse the string and return a block of data relating to the strings contents. This data will remain intact until the stream is closed. If no validation string is specified then it is up to the device to take and manage a copy, also to filter out any unwanted information.

The syntax for validation strings is very simple:

keyword[,keyword]/escape_seq[/escape_seq]...

Keywords are used to associate each command with an escape sequence, there can be more than one keyword associated with a particular escape field, this is provided for two reasons, the first is when a different word has the same meaning, eg. Colour or Color. And secondly when defining the various states for a switch.

The escape sequence describes how the preceding data should be treated and also that to do with the rest of the special field string (up to the next separator).

The following characters are valid in escape sequences:

/N - number
/S - switch

Within the special field string each parameter is separated by a comma or a character which is out of place, ie a non-numeric in a numerical field. Each keyword within the special field string is separated by a semi-colon.

The buffer passed to the device contains 1 word per escape character, set to &DEADDEAD if the corresponding keyword is not present in the special field string.

Numbers are simply stored into the word; they are decoded using OS_ReadUnsigned and stored away. Switches store the state of the keywords placed, ie:

mike,dennis/S

This yields 0 if 'mike' is present within the string, 1 if 'dennis' is present within the string.

The order of commands within the validation string and the special field string need not match; the commands within the validation string control how the values are returned back to the caller.

Service Calls


Service_DeviceFSStarting
(Service Call &70)

DeviceFS is starting

On entry

R1 = &70 (reason code)

On exit

All registers preserved

Use

This call is issued when the module wants the device drivers to re-register with DeviceFS; it is issued during the module initialisation. In this case it is actually issued on a callback to ensure that the module has been correctly linked into the module chain.


Service_DeviceFSDying
(Service Call &71)

DeviceFS is dying

On entry

R0 = 0
R1 = &71 (reason code)

On exit

All registers preserved

Use

This is issued when DeviceFS is about to be killed, the device driver will already have had all of its streams closed and will have received the DeviceFS_DeviceDead service.


Service_DeviceDead
(Service Call &79)

Device has been killed by DeviceFS

On entry

R0 = 0
R1 = &79 (reason code)
R2 = handle of device driver
R3 = pointer to device name (if an individual device is being deregistered),
or 0 (if the device driver as a whole is being deregistered)

On exit

All registers must be preserved

Use

This is issued to inform a device driver that a specified device has been killed. This is usually caused by another device of the same name being registered, when the original one is therefore killed to stop duplicates.

If a device driver is being deregistered, this service call is issued once for each device using that driver (with R3 pointing to the device name), and is then issued a last time with R3 set to 0.


Service_DeviceFSCloseRequest
(Service Call &81)

Opening a device which already has the maximum number of streams open

On entry

R1 = &81 (reason code)
R2 = file handle of an open stream on that device

On exit

R1 = 0 if the file was closed; otherwise all registers preserved

Use

This service call is issued whenever an attempt is made to open a device for input or output and one of the following applies:

  • the device already has the maximum number of streams open for input or output respectively; one such stream must be closed before the new one can be opened
  • the device is not full duplex, and already has one or more streams open for output or input respectively; all such streams must be closed before the new one can be opened.

The service call is offered in the hope that one or more 'blocking' streams need no longer be kept open and can be closed, allowing the new stream to be opened.

If your application opened the stream specified by R2, and you no longer need to keep it open, you should close it and then claim the service call to inform DeviceFS that you have done so. Otherwise you should pass on the service call with all registers preserved.

The kernel responds to this service call, because it implicitly opens streams such as the printer and the serial device, which need only be open when actually sending data.

DeviceFS issues this service call for each blocking stream, stopping if sufficient blocking streams have been closed for it to open the new stream, or if this is clearly impossible (eg the service call is not claimed for an output stream that is blocking input to a half-duplex device).

SWI Calls


DeviceFS_Register
(SWI &42740)

Registers a device driver and its associated devices with DeviceFS

On entry

R0 = global flags for devices:

bit 0 clear => CHARACTER DEVICE_ SET => block device
bit 1 clear => DEVICE IS NOT FULL DUPLEX_ SET => device is full duplex
all other bits reserved (must be zero)
R1 = pointer to list of devices to be installed
R2 = pointer to device driver entry point
R3 = private word
R4 = workspace pointer
R5 = pointer to validation string for special fields (0 => none)
R6 = maximum number of RX devices (0 => NONE_ -1 => unlimited)
R7 = maximum number of TX devices (0 => NONE_ -1 => unlimited)

On exit

R0 = device driver's handle

Use

This call registers a device driver and its associated devices with DeviceFS. The device driver is the actual interfacing code with the hardware, and the device acts as a port into the driver. A device driver may have many devices within it; for instance you may have devices to support both buffered and unbuffered transfer.

Flags word

R0 contains a global flags word which describes all the driver's devices. It contains the following bit fields:

  • Bit 0 is used to indicate if the devices are character or block devices.

    An example of a block device is a floppy disc drive, where data is transferred in blocks (sectors) to the caller. Examples of character devices are a parallel port or serial port.

    Block devices are not supported under the RISC OS 3 implementation of DeviceFS.

  • Bit 1 is used to indicate if the device is full duplex or not

    A full duplex device can handle both input and output streams at the same time.

List of devices

R1 contains a pointer to a list of devices to be associated with this device driver. The list is terminated by a null word, and can be empty as you can use the SWI DeviceFS_RegisterObjects to register devices later. The format of each entry in the list is as follows:

Offset Meaning
0 offset to device name
4 flags:
bit 0 set => device is buffered
bit 1 set => create path variable for use as pseudo filing system
8 default flags for the device's RX buffer
12 default size of RX buffers
16 default flags for the device's TX buffer
20 default size of TX buffers
24 reserved (must be zero)

Device names should be registered with Acorn; see Appendix H: Registering names. They are used for several things:

  • The device name is used in the DeviceFS directory structure.
  • The device name is used to create an option variable (initially null) named DeviceFS$Device$Options, so long as one does not already exist.

    This is used for storing device setup options, and is concatenated with the special field strings when streams are opened.

    If the options variable already exists, it is preserved, thus preserving the last setup used for the same device.

  • The device name is used to create - if specified in the flags word - a path variable named Device$Path which points to the driver's entry point. The device can then be accessed via the pseudo filing system device:.

The device's buffers are not created until a stream is opened onto it. The flags are passed to the buffer manager; see Buffer_Create.

If for any reason a device in the list should fail to register than all devices specified will be removed.

Device driver entry point

R2 contains the pointer to the device driver entry point, which is called with various reason codes to access the routines available in the driver. See the chapter entitled Writing a device driver.

Parameters passed to driver: private word, and workspace pointer

R3 and R4 contain parameters which are passed to the device driver whenever its entry point is called. The parameter in R3 is passed to the device driver in R8, and might be used as a private word to indicate which hardware platform is being used; the parameter in R4 is used as a workspace pointer and is passed to the device in R12.

Validation string

On entry R5 contains the pointer to a validation string used to decode special fields within the device. For a full explanation, see the chapter entitled Special fields.

This value can be 0 which means that the string will be passed to the device unparsed; in these cases any unknown keywords should be ignored, as some keywords used by DeviceFS will still be present.

Number of output streams

R6 and R7 contain the maximum number of input and output streams on a device. If a register is zero then the device does not support that operation; if a register is -1 then the device has unlimited support for that type of transfer, and will be called to open streams.

DeviceFS uses these values to range check the number of streams being opened, so the device driver need not worry about this.

Device driver's handle

You will need to use the returned handle of the device driver to refer to it in any further SWI calls you make to DeviceFS.

Related SWIs

DeviceFS_Deregister, DeviceFS_RegisterObjects

Related vectors

None


DeviceFS_Deregister
(SWI &42741)

Deregisters all devices and their device driver from DeviceFS

On entry

R0 = device driver's handle

On exit

R0 preserved

Use

This call deregisters all devices and their device driver from DeviceFS. This causes all streams to be closed and any system variables set up for the device to be unset. The exception to this is the DeviceFS$Device$Options variable, which is left intact so that when the device is reloaded it can assume its original setup.

Related SWIs

DeviceFS_Register, DeviceFS_DeregisterObjects

Related vectors

None


DeviceFS_RegisterObjects
(SWI &42742)

Registers a list of additional devices with a device driver

On entry

R0 = device driver's handle
R1 = pointer to list of devices to be registered with device driver

On exit

--

Use

This call registers a list of additional devices with a device driver. This is an extension to the DeviceFS_Register SWI which itself allows devices to be registered at the same time as their device driver.

The list of devices pointed to by R1 has the same format as that used in DeviceFS_Register (see DeviceFS_Register).

Related SWIs

DeviceFS_DeregisterObjects

Related vectors

None


DeviceFS_DeregisterObjects
(SWI &42743)

Deregisters a device related to a particular device driver

On entry

R0 = device driver's handle
R1 = pointer to device name of the device to remove

On exit

--

Use

This call deregisters a device related to a particular device driver, tidying up as required.

Related SWIs

DeviceFS_RegisterObjects

Related vectors

None


DeviceFS_CallDevice
(SWI &42744)

Makes a call to a device with a specified register set

On entry

R0 = reason code
R1 = device driver's handle, or pointer to path, or 0 to broadcast to all devices
R2 - R7 = parameters passed to device driver
R12 = pointer to workspace

On exit

Register values returned by device (ie device/call-dependent)

Use

This call is used to make a call to a device with the specified register set. You can direct the call at a specific device or at all devices. When directing a call at a specific device you can specify this either by its device driver's handle, or by its filename within the directory structure (which can include '$').

Related SWIs

None

Related vectors

None


DeviceFS_Threshold
(SWI &42745)

Informs DeviceFS of the threshold value to use on buffered devices

On entry

R1 = DeviceFS stream handle, as passed to device driver on initialisation
R2 = threshold value to be used, or -1 to read

On exit

R1, R2 preserved

Use

This call is made by a device driver to set the threshold value used on buffered devices. DeviceFS will call the device drivers 'Halt' and 'Resume' entry points appropriately when the buffer levels cross the specified threshold.

An error is generated if the device is not buffered.

Related SWIs

None

Related vectors

None


DeviceFS_ReceivedCharacter
(SWI &42746)

Informs DeviceFS that a device driver has received a character

On entry

R0 = byte received
R1 = DeviceFS stream handle, as passed to device driver on initialisation

On exit

C set => byte not transferred, else C clear

Use

This call is made by a device driver when it receives a character. DeviceFS then attempts to process the character as required, unblocking any streams that may be waiting for the character or simply inserting it into a buffer.

For speed, DeviceFS_TransmitCharacter and DeviceFS_ReceivedCharacter do not validate the external handle passed; be warned that some strange effects can occur by passing in bad handles.

The C flag is cleared if the transfer was successful.

Related SWIs

DeviceFS_TransmitCharacter

Related vectors

None


DeviceFS_TransmitCharacter
(SWI &42747)

Informs DeviceFS that a device driver wants to transmit a character

On entry

R1 = DeviceFS stream handle, as passed to device driver on initialisation

On exit

R0 = character to transmit (8 bits) if C clear

C set => unable to read character to be transmitted

Use

This call is made by a device driver when it wants to transmit a character. DeviceFS then attempts to obtain the character to be sent, either by extracting from a buffer or reading it from a waiting stream.

For speed, DeviceFS_TransmitCharacter and DeviceFS_ReceivedCharacter do not validate the external handle passed; be warned that some strange effects can occur by passing in bad handles.

The C flag is cleared if the transfer was successful.

Related SWIs

DeviceFS_ReceivedCharacter

Related vectors

None

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015