RISCOS.com

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

 

Writing a device driver


Adding your own device driver to DeviceFS

DeviceFS does not know how to communicate directly with the hardware that your device driver uses. Your module must provide these facilities, and declare the entry points to DeviceFS.

This section describes how to add a device driver to DeviceFS. You should also see the chapter entitled Modules for more information on how to write a module.

Registering your device driver

When your module initialises, it must register itself and its devices with DeviceFS. You must call DeviceFS_Register (see DeviceFS_Register) to register your device driver and any associated devices. Note that modules can hold more than one driver; in such cases you must call DeviceFS_Register for each one.

When you register your device driver with DeviceFS you pass it the location of an entry point to your driver's low level routines that interface with the hardware. A reason code is used to determine which of your driver's routines has been called.

  • Reason codes with bit 31 clear are reserved for use by Acorn.
  • Reason codes with bit 31 set are reserved for specific drivers. You do not need to register these with Acorn, although we suggest that you maintain some consistency between devices.
Registering and deregistering additional devices

You may later register additional devices by calling DeviceFS_RegisterObject (see DeviceFS_RegisterObjects). This is most commonly needed for devices on a network.

You may deregister devices by calling DeviceFS_DeregisterObject (see DeviceFS_DeregisterObjects).

Deregistering your device driver

The finalise entry of your module must deregister all registered drivers and devices by calling DeviceFS_Deregister (see DeviceFS_Deregister). It must make this call for each device driver it registered.

Device driver interfaces

Calling conventions

The principal part of a device driver is the set of low-level routines that control the device's hardware. There are certain conventions that apply to them.

Private word

R8 on entry to the device driver is set to the value of R3 it passed to DeviceFS when registering by calling DeviceFS_Register. Conventionally, this is used as a private word to indicate which hardware platform is being used.

Workspace

R12 on entry to the device driver is set to the value of R4 it passed to DeviceFS when registering by calling DeviceFS_Register. Conventionally, this is used as a pointer to its workspace.

Returning errors

If a routine wishes to return an error, it should return to DeviceFS with V set and R0 pointing to a standard format error block.

Other conventions

Device driver routines must preserve R0, R1, and all other undocumented registers.

Interfaces

These are the interfaces that your device driver must provide. The entry point must be declared to DeviceFS by calling DeviceFS_Register when your device driver module is initialised.

DeviceDriver_Entry

Various calls are made by DeviceFS through this entry point when files are being opened and closed, streams halted etc. The actions are specified by R0 as follows:

DeviceDriver_Entry 0

Initialise
On entry

R0 = 0
R2 = DeviceFS stream handle
R3 = flags for opening the stream:

bit 0 clear => STREAM OPENED FOR RX_ SET => stream opened for TX
all others bits reserved, and should be ignored
R6 = pointer to special field control block

On exit

R2 = device driver stream handle

Details

This entry point is called as a stream is being opened onto the device driver by DeviceFS. The stream handle passed in must be stored, as you need to quote it when calling DeviceFS SWIs such as DeviceFS_Threshold, DeviceFS_ReceivedCharacter, and DeviceFS_TransmitCharacter.

The stream handle returned will be passed by DeviceFS when calling the device driver's other entry routines. It must not be zero, which is a reserved value.

The device driver is also passed a pointer to the special field string: see the chapter entitled Special fields.

You can be assumed that the special field block will remain intact until the stream has been closed.

DeviceDriver_Entry 1

Finalise
On entry

R0 = 1
R2 = device driver stream handle, or 0 for all streams

On exit

--

Details

This entry point is called when a stream is being closed. Your device driver must tidy up and ensure that all vectors have been released. This entry point is also called when a device driver is being removed, although in this case R2 is set to contain 0 indicating that all streams should be closed.

DeviceDriver_Entry 2

Wake up for TX
On entry

R0 = 2
R2 = device driver stream handle

On exit

R0 = 0 if the device driver wishes to remain dormant, else preserved

Details

This entry point is called when data is ready to be transmitted. Your device driver should set R0 to 0 if it wishes to remain dormant, or else start passing data to the physical device, calling DeviceFS_TransmitCharacter to obtain the data to be transmitted.

DeviceDriver_Entry 3

Wake up for RX
On entry

R0 = 3
R2 = device driver stream handle

On exit

--

Details

This entry point is called when data is being requested from the device driver. It is really issued to wake up any dormant device drivers, although you will always receive it when data is going to be read.

The device driver should return any data it receives from the physical device by calling DeviceFS_ReceivedCharacter. This will unblock any task waiting on data being returned.

This call is not applicable to all device drivers; most interrupt-driven buffered device drivers would be ready to receive data at any time.

DeviceDriver_Entry 4

Sleep RX
On entry

R0 = 4
R2 = device driver stream handle

On exit

--

Details

This entry point is called when data is no longer being requested from the device driver. If appropriate, the device driver can then wait to be woken up again using the 'Wake up for RX' entry point.

This call is not applicable to all device drivers; most interrupt-driven buffered device drivers would continue to receive and buffer data even after this call.

DeviceDriver_Entry 5

EnumDir
On entry

R0 = 5
R2 = pointer to path being enumerated

On exit

--

Details

This entry point is called as a broadcast to all device drivers 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 (eg $.foo.poo) and null terminated.

DeviceDriver_Entry 6 and 7

Create buffer for TX (6), and Create buffer for RX (7)
On entry

R0 = 6 or 7
R2 = device driver stream 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

On exit

R3 - R6 modified as the device driver requires

Details

This entry point is called just before the buffer for a stream is going to be created; it allows the device driver to modify the parameters as required.

  • R3 contains the buffer flags as specified when the device was registered; see the chapter entitled The Buffer Manager.
  • R4 contains the suggested buffer size; this should be non-zero.
  • R5 contains a suggested buffer handle. This is by default set to -1, which indicates that the buffer manager must attempt to generate a free handle.

If you specify the handle of an existing buffer, then it will be used and not removed when finished with. For compatibility, the kernel devices use this feature to link up to buffers 1,2 or 3.

  • 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. You may change this value by calling DeviceFS_Threshold.

DeviceDriver_Entry 8

Halt
On entry

R0 = 8
R2 = device driver stream handle

On exit

--

Details

This entry point is called when the free space has dropped below the specified threshold (set on creation, or by DeviceFS_Threshold). It is called so the device driver can - if necessary - try to stop its device from receiving more data (eg a serial device driver might perform handshaking by sending an XOff character, or asserting the RTS line) until the Resume entry point is called.

DeviceDriver_Entry 9

Resume
On entry

R0 = 9
R2 = device driver stream handle

On exit

--

Details

This entry point is called when the free space has risen above the specified threshold (set on creation, or by DeviceFS_Threshold). It is called so the device driver can - if necessary - try to resume its device receiving more data (eg a serial device driver might perform handshaking by sending an XOn character, or de-asserting the RTS line) until the Halt entry point is again called.

DeviceDriver_Entry 10

End of data
On entry

R0 = 10
R2 = device driver stream handle
R3 = -1

On exit

R3 = 0 if more data coming eventually, else -1 (ie no more data coming)

Details

This entry point is called as a result of FileSwitch calling DeviceFS to check on EOF, and DeviceFS believing that there is no more data to come. In more detail:

DeviceFS informs FileSwitch that more data is coming eventually - without calling this entry point - if:

  • the stream is buffered, and its buffer still holds data
  • the stream is unbuffered, and its RX/TX word is not empty

Otherwise it calls this entry point. In most cases a device driver should ignore this, and return with all registers preserved (so R3 = -1, thus there is no more data coming). In some cases, such as a scanner, you may be able to give an accurate return.

DeviceDriver_Entry 11

Stream created
On entry

R0 = 11
R2 = device driver stream handle
R3 = buffer handle (-1 if none)

On exit

--

Details

This entry point is called after a stream has finally been generated. Your device driver can then perform any important interrupt handling, set itself up and start receiving or transmitting.

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