Commit 1d464cee authored by Neil Turton's avatar Neil Turton
Browse files

Import from cleaned 360 CD

hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
**/s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
*,ffb gitlab-language=bbcbasic linguist-language=bbcbasic linguist-detectable=true
> Calls
Title: Device Calls
Authors: David De Vorchik, Tim Dobson
Last updated: 29-Jul-91
15-Apr-91 DDV Created.
15-Apr-91 DDV Added note about special field staying intact.
16-Apr-91 DDV Added stream created reason, issued when fs_open exits.
29-May-91 TMD Corrected some typos.
29-Jul-91 TMD Updated with Mark Taunton's comments
01-Aug-91 TMD Updated StreamCreated call
This document explains the device call interface between devices and the
DeviceFS device manager. The device when registering with DeviceFS passes a
vector to the manager which is called with an array of reason codes. All
reason codes with bit 31 clear are reserved for use by Acorn. With bit 31
set these are reserved for specific drivers, these do not need to be
registered within Acorn, although it is suggested that some consistency is
maintained between devices.
Calls from DeviceFS to devices
These calls are made at specific points when files are being opened and
closed, streams halted etc..
In all cases the following applies. On return from any device call V should
reflect the error state with r0 -> error block if an error occurs, else
r0, r1 should be preserved along with any other undocumented registers.
r0 = reason code
0: Initialise
1: Finalise
2: Wake up for TX
3: Wake up for RX
4: Sleep RX
5: EnumDir
6: Create buffer for TX
7: Create buffer for RX
8: Halt
9: Resume
10: End of data
11: Stream created
r1 = reserved (contains meaningless data)
r2...r7 = parameters for call
r8 = private word (specified when device registered)
wp -> workspace for call
So here goes an explanation of the currently used reason codes.
0: Initialise
in: r0 = reason code (0)
r2 = external handle used for call
bit 0 clear => stream opened for RX
bit 0 set => stream opened for TX
all others bits should be ignored.
r3 = flags for opening the stream
r6 -> special field control block
out: r2 = internal handle for stream.
This call is passed as a stream is being opened onto the device by DeviceFS,
the call is passed an external handle and returns the internal handle. The
external handle is used by the outside world to communicate with DeviceFS,
this includes the actual device driver calling to get or pass on characters
back to the system.
The internal handle returned should NOT be zero, this is a reserved value
and passing this back will cause some strange effects.
The device is also passed a pointer to the special field string, this is
described in the documentation about special fields.
It can be assumed that the special field block will remain intact until the
stream has been closed.
1: Finalise
in: r0 = reason code (1)
r2 = internal handle / =0 for all
This call is made to the device when a stream is being closed. The device
is assumed to tidy up and ensure that all vectors have been released. This
call is also made when a device is being removed, although in this case r0
is set to contain 0 indicating that all devices should be closed.
2: Wake up for TX
in: r0 = reason code (2)
r2 = internal handle
out: r0 = 0 => device wishes to remain dormant
r0 preserved => device wishes to become active
This call is made when data is ready to be transmitted, the device should
then start passing data to the device, calling DeviceFS_TransmitCharacter
to obtain data to be transmitted.
3: Wake up for RX
in: r0 = reason code (3)
r2 = internal handle
This call is made when data is being requested from the device, it is really
issued to wake up any dormant devices, although you will always receive it
when data is going to be read.
The device should then return data using the DeviceFS_ReceivedCharacter SWI,
this will unblock any task waiting on data being returned.
4: Sleep RX
in: r0 = reason code (4)
r2 = internal handle
To save bandwidth when DeviceFS has finished removing characters from the
device it will issue this as a call to the manager, this is so that the
device can stop receiving characters and no longer call
DeviceFS_ReceivedCharacter, and wait to be woken up again using the 'Wake up
for RX' event.
This call is not applicable to all devices, most buffered devices would wait
for a halt and resume sequence to be triggered on their buffers.
5: EnumDir
in: r0 = reason code (5)
r2 -> path being enumerated
This call is made as a broadcast to all devices when the directory structure
for DeviceFS is about to be read. This allows them to add and remove
non-permanent devices (such as net connections) as required.
The path supplied will be full, ie. $.<foo>.<poo> and null terminated.
6: Create buffer for TX
7: Create buffer for RX
in: r0 = reason code (6 or 7)
r2 = internal handle
r3 = suggested flags for buffer being created
r4 = suggested size for buffer
r5 = suggested buffer handle (-1 for unique generated one)
r6 = suggested threshold for buffer
out: r3, r4, r5 and r6 modified as the device requires.
This call is made just before the buffer for a stream is going to be
created, it allows the device to modify the parameters as required.
r3 contains the flags as specified when the device was registered, see the
buffer manager documentation for further details. r4 contains the suggested
buffer size, this should be non-zero.
r5 contains a suggested buffer handle, this is by default set to -1, this
indicates that the buffer manager must attempt to generate a free handle.
If the buffer already exists then it will be used and not removed when
finished with. This is used by the kernel devices which specify that they
want to link upto buffers 1,2 or 3 (for compatibility)
r6 contains the threshold at which a halt event is received, this usually
only applies to receive streams which want to halt the receive process,
although it can be supplied on either. This value may be changed by calling
8: Halt
in: r0 = reason code (8)
r2 = internal handle
When this is received then the free space has dropped below the specified
threshold (on creation or by DeviceFS_Threshold). The device should only
resume receiving data when the next event has been received:-
9: Resume
in: r0 = reason code (9)
r2 = internal handle
This is the opposite to the halt reason, the free space is now greater than
the specified threshold so data receiving can continue.
10: End of data
in: r0 = reason code
r2 = internal handle
r3 = -1
out: r3 = 0 (more data coming eventually)
= -1 (no more data coming)
This call is made to enquire with the device about the end of data from this
stream. In most cases devices will ignore this and return r3 =-1
(unchanged) to indicate that the end of data has been received, but there
will be some cases where this is suitable so the process goes something like
Is the stream buffered?
Yes:- Does the buffer still contain data?
Yes:- don't return end of data
No :- call end of data and check flag, return state.
No :- Is the RX/TX word empty?
Yes:- don't return end of data
No:- call end of data and check flag, return state.
11: Stream created
in: r0 = reason code (11)
r2 = internal handle
r3 = buffer handle (-1 if none)
This is broadcast after the stream has finally been generated, this allows
any devices that have important interrupt handling to be performed can set
themselves up and start receiving.
(Aside: This call may be extended in the future to supply entry points to
DeviceFS for speed, this is a matter for debate though!)
Changes implemented in DeviceFS by JSR:
* Optimise CallBuffMan to call with LDMIA
* Fix bug in create buffer for TX to quote internal handle, not external one.
* Fix bug is fs_get where 2nd time round loop would try args_eof with a duff file handle.
* fs_get calls MonitorRX if goes round loop more than once.
* fs_put calls MonitorTX if goes round loop more than once.
* Fix bug in gbpb_get to not ignore checkescape.
* Add MonitorTX to gbpb_put and MonitorRX to gbpb_get.
* Fix bug in gbpb_put to not ignore checkescape.
* Add MonitorEOF flag to fs_get and fs_gbpb read.
* Fix bug in gbpb_put where escape got swallowed by purgebuffer.
* Ignore rather than return error on Args_SetEXT. This is to ensure
compatibility with C file I/O.
To the interface:
Added flag:
ParentFlag_MonitorTransfers bit 2
When this flag is set DeviceFS monitors transfers using the new reason codes
MonitorTX (12) and MonitorRX (13). r2 = internal handle. Return an error if
a transfer is in difficulties.
Added flag:
ParentFlag_MonitorEOF bit 3
When this flag is set then DeviceFS will monitor EOF during a read
operation. For example Serial and Parallel input don't want this set (hang,
waiting for input), but Tape input does want it set (file mark reached).
> DeviceFS
Title: DeviceFS
Author: David De Vorchik
27-Apr-91 DDV Created.
NB: This document forms part of a set of documents describing DeviceFS, its
SWIs and service calls.
DeviceFS provides a standardised interface to devices within the RISC OS
environment. Device drivers are declared within the system and they 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
A device driver is simply a set of routines that handle the input or output
of data. The device can specifiy 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 be used for controlling a scanner or what ever.
DeviceFS currently only supports stream devices, block devices have yet to
be implemented.
The kernel based device drivers have now been exported to use the DeviceFS
interface, this includes serial and parallel. These devices are replaceable
modules within the RISC OS ROM set and provide working examples of how
device drivers should be developed.
Most filing system operations can be performed on objects, it is not
possible to create objects within the directory structure which are not
devices, nor is it possible to delete objects. Data transfer operations
are supported though.
> SWIs
Title: SWI interface to DeviceFS
Authors: David De Vorchik, Tim Dobson
27-Apr-91 DDV Created.
29-May-91 TMD Corrected some typos.
31-May-91 TMD Corrected another typo.
30-Jul-91 TMD Added some of Mark Taunton's comments.
SWI interface
This document describes the SWI interface to DeviceFS.
NB: All reserved/unused fields should be 0 for future expansion.
42740 DeviceFS_Register
in: r0 = global flags for device
bit 0 clear => character device
bit 0 set => block device
bit 1 clear => device is not full duplex
bit 1 set => device is full duplex
bit 2 clear => device TX/RX monitoring not necessary
bit 2 set => MontorTX/RX can be used
r1 -> list of devices to be installed
+0 = self-relative offset to device name / =0 no more devices
+4 = flags specific to this incarnation of the device
bit 0 clear => device not buffered
bit 0 set => device is buffered
bit 1 clear => don't set a path variable for device
bit 1 set => set a path variable for device
+8 = default flags for the RX buffer of the device
+12 = default size of RX buffers
+16 = default flags for the TX buffer of the device
+20 = default size of TX buffers
+24 = reserved for future expansion (must be zero)
.... repeating until first word =0.
r2 -> device entry point
r3 = private word
r4 = workspace pointer
r5 -> validation string / =0 none (pass through to caller)
r6 = maximum number of RX streams / =0 for none / =-1 unlimited
r7 = maximum number of TX streams / =0 for none / =-1 unlimited
out: V clear => r0 = device handle
V set => r0 -> error block
This SWI registers the parent and its associated devices to DeviceFS. The
parent is the actual interfacing code with the hardware and the device acts
as a port into the parent. A device driver may have many devices within it,
for instance you may have a device which supports both buffered and
unbuffered transfer.
The SWI accepts r0 as a global flags word which describes what the device
actually does and how it works. It contains the following bit fields:
Bit 0 is used to indicate if the device is a character or block device, an
example of a block device is a floppy driver where data is transferred in
blocks (sectors) to the caller. A character device could be a parallel
port or serial port. All devices within RISC OS 2.50 are character devices,
block devices are not currently supported under the RISC OS 2.50
implementation of DeviceFS.
Bit 1 this is used to indicate if the device is full duplex or not, ie.
can handle both input and output streams at the same time.
R1 on entry contains a pointer to the list of devices to be associated with
this parent record being created. The list is terminated by a null word,
and the list on entry to this SWI need not actually define any devices at
all and they could be registered later.
Assuming that a device is being registered then the first word of the
list contains a self relative offset to the device name, this is used for
creating options variables and is used in the DeviceFS directory structure.
We suggest that device names be registered with Acorn to avoid conflicts.
The next word is a set of flags describing the characteristics of this
particular implementation of the device:
Bit 0 indicates if the device is buffered or not. Bit 1 is used to
say if the device would like a path variable so that it can be
access as a pseudo filing system, ie. parallel: is achieved via setting up a
variable called 'Parallel$Path' which points to the DeviceFS entry for this
The next four words in the control block contain information and sizes for
buffers to be created for the device when a stream is opened onto it. These
words should be zero if not used, see the Buffer Manager documentation of
the flags).
The control block then repeats n times until a null entry is found. If for
any reason a device should fail to register than all devices specified will
be removed.
r2 on entry to the SWI contains the pointer to the device entry point, this
is called with various reason codes both from DeviceFS and the outside
world. This is the suggested interface between devices and external
r3 and r4 contains parameters which are to be passed in on device calls. r3
contains a private word passed to the device, this can be used for what ever
the device wants, usually to indicate which hardware platform is being used.
r4 is used as a workspace pointer and is passed to the device in r12.
On entry r5 contains the pointer to a validation string used to decode
special fields within the device. 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 there will be ones used by DeviceFS present.
r6 and r7 contains the counters for the maximum number of output streams on
a device. If a register is zero then the device does not support that
operation, if a value is -1 then the device has unlimited support for that
type of transfer and will be called to open streams.
DeviceFS range checks the number of streams being opened using these values
so that device driver need not worry about what is happening around it, it
can assume (unless unlimited) that it will only receive x open requests.
When registering a device DeviceFS checks to see if a system variable is
set called 'DeviceFS$<device name>$Options', if it does not exist then it
will attempt to create it with a null entry. This is used for storing
device setup options. It is concatenated with the special field strings
when streams are opened.
42741 DeviceFS_Deregister
in: r0 = device handle
out: V clear => device deregistered (all preserved)
V set => r0 -> error block.
This call will deregister all devices and their parent from DeviceFS. This
causes all streams to be closed and the system variables setup for the
device to be unset. The exception to this is the 'DeviceFS$<device
name>$Options' variable which will be left intact so that when the device is
reloaded it can assume the original setup.
42742 DeviceFS_RegisterObject
in: r0 = device handle
r1 -> list of devices to be registed with device (see Register call)
out: V clear => all devices registered.
V set => devices not registered (none will have been registered)
This call registers a list of devices with a parent of the device. This is
an extension to the DeviceFS register SWI which itself allows devices to be
registered when the parent record is made.
42743 DeviceFS_DeregisterObject
in: r0 = device handle
r1 -> device name of the object to remove
out: V clear => device has been deregistered.
V set => device could not be deregistered.
This call will deregister a device related to a particular parent, tidying up
as required.
42744 DeviceFS_CallDevice
in: r0 = reason code
r1 -> parent record (device handle), or
-> path (can include "$."), or
= 0 broadcast to all devices
r2..r7 = parameters passed to device
wp -> workspace
out: V clear, registers setup as defined by call
V set, r0 -> error block.
This call is used to talk to the actual device, the call is made and then
the device is called with the specified register set. A call can be
directed at a specific device or all devices. When directing a call at a
specific device you can specifiy this by either its parent handle or its
filename within the directory structure.
The following SWIs are used by devices to communicate with DeviceFS when transferring
or handling data.
42745 DeviceFS_Threshold
in: r1 = external handle (from DeviceFS on open)
r2 = threshold value to be used / -1 to read
out: V set, r0 -> error block
V clear, preserved.
This call is used to set the threshold value used on buffered devices, this
SWI will give an error if the device is not buffered. Otherwise a set
of halt and resume reason codes will be passed to the device when the
buffer levels get close to the specified threshold.
42746 DeviceFS_ReceivedCharacter
in: r0 = byte recieved
r1 -> external handle (from DeviceFS on open)
out: C set, if byte not transferred, else C clear.
This call is made by the device 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.
The C flag is set to indicate if the transfer was successful.
42747 DeviceFS_TransmitCharacter
in: r1 = external handle
out: C clear:
r0 = character to transmit (8 bits)
C set:
unable to read character to be transmitted
V set, r0 -> error block!
This call is used when the device wants to transmit a character. DeviceFS will
attempt to obtain the character to be sent either by extracting from
the buffer or reading it from a waiting stream.
NB: For speed TransmitCharacter and CharacterReceived do not validate
the external handle passed so be warned some strange effects can
occur by passing in duffo handles matey!
> Services
Title: DeviceFS Service calls
Authors: David De Vorchik, Tim Dobson
19-Apr-91 DDV Created.
20-Apr-91 DDV Improved information on Service_DeviceDead (r3).
29-May-91 TMD Corrected some typos.
DeviceFS will issue several service calls during its time, it issues them to
inform the device drivers when it has been installed, it is about to die and
when a particular device has been killed.
The following can be generated:
Service_DeviceFSStarting (&70)
Service_DeviceFSDying (&71)
Service_DeviceDead (&79)
in: r1 = Service_DeviceFSStarting
out: -
This code is issued when the module wants the device drivers to re-register
with DeviceFS, the call 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.
in: r0 = 0
r1 = Service_DeviceFSDying
out: -
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.