|
|
|
|
|
BlockDriver Module Specification
|
|
|
Version 0.11 - updated 21 December 2017
|
This page explains the use of the BlockDriver Module that is part of
the current distribution of the BlockDrivers. Its intention is to make
writing a BlockDriver much easier.
In fact, when your device is known by DeviceFS, the module can do most
of the work for you.
The module is located
inside !SerialDev and will be loaded into memory when it is first
seen by the filer. !SerialDev is usually installed in !Boot.Resources.
The use of the Module is not mandatory, but is strongly advised.
If your interface software is implemented as a DeviceFS device,
and is visible in Resources:$, the BlockDriver Module knows how to
address it, which makes the implementation of a BlockDriver a lot
easier.
But even if it does not support DeviceFS, the module provides
some useful utilities that can help to improve your work. If you have
written your own driver, which is not available through DeviceFS, you
are advised to register it as a fake device with the BlockDriver
Module, so that it can keep track of it. This allows a monitoring
application, such as !Serial, to show its status.
|
The BlockDriver Module provides an Application Programmers Interface (API)
for developers of a BlockDriver. The main interface is through a
series of SWI calls that are explained in more detail below.
In addition there are several *-commands that can be accessed from
the command line.
For each port that is handled or monitored, the module allocates a
Channel. When registering a port, a pointer to the channel's
workspace is returned, which should be quoted in all further calls.
|
All SWI calls have a (registered) offset of 0x56F00.
This offset has been omitted in the tables below,
in order to improve readability.
The SWIs can also be called by their names.
|
In addition, the following *-commands are available:
|
All errors have a (registered) offset of 0x56F00.
This offset has been omitted in the tables below,
in order to improve readability.
|
0
|
|
Address in r6 is out of bounds
|
1
|
|
Channel not in use
|
2
|
|
File already closed
|
3
|
|
Can't open stream,
|
4
|
|
Too many open channels
|
|
BlockDriver_Register
0x56F00
|
|
|
This call is used to register a BlockDriver with the BlockDriver Module.
Although registering is not mandatory, it is strongly advised.
It claims the port for the current application and will reject any
further clients.
BlockDrivers should only register themselves, when they are actually going to be
used by the parent application, which is when they are called through
Device_Initialise
with a valid port number in r1.
When the parent application calls Device_Initialise
with r1 = -1 (pre-initialise),
the driver should not register itself with the module.
Entry
|
r0
|
|
Error (0 if successful, otherwise → to error block)
|
r1
|
|
→ Channel block 1
|
r2
|
|
RX file handle
|
r3
|
|
TX file handle
|
r4
|
|
RX buffer handle
|
r5
|
|
TX buffer handle
|
Initialisation flags (r2 on entry)
|
0
|
|
Shared device
|
1
|
|
Fake device 2
|
2
|
|
Statistics
|
3
|
|
NoBuffer
|
4
|
|
Removable
|
5
|
|
Location
|
6
|
|
Serno
|
7-31
|
|
Reserved for future expansion
|
3
|
|
Can't open stream,
|
4
|
|
Too many open channels
|
-
Channel block is a pointer to an internal structure that is
used by the module, to keep track of each allocated
channel. Your driver should remember this pointer and specify
it in all further calls to the module.
-
A device should register itself as a Fake device, if it does
not provide an interface through DeviceFS. This means that the
BlockDriver module can not handle the device on your behalf.
In such cases you should fully implement your own driver, and
call the module only to keep it informed of any status changes.
|
|
BlockDriver_Deregister
0x56F01
|
|
|
You driver should call this entry when the interface is not longer
needed by the parent application. Although registering is not
mandatory, once the driver has been registered, it must
be deregistered when it is no longer needed, as otherwise the port
will not be available to any future clients.
The module will close any open files/streams on your behalf.
Entry
|
r0
|
|
Close flags (see below)
|
r6
|
|
→ Channel block
|
r0
|
|
Error (0 if successful, otherwise → to error block)
|
Close flag bits (r0 on entry)
|
0
|
|
Address in r6 is out of bounds
|
1
|
|
Channel not in use
|
2
|
|
File already closed
|
|
BlockDriver_PutByte
0x56F02
|
|
|
This can can be used to send a single byte to the output file (i.e. the
selected port). The entry Driver_PutByte of your BlockDriver
can call this SWI directly. Even if you are handling the device yourself
(which means you have registered it as a fake device), you should
call this entry, to allow the module to keep track of its activity.
This activity is reflected in the !Serial application.
Entry
|
r2
|
|
Byte to send
|
r6
|
|
→ Channel block
|
r0
|
|
Result (0 when successful, or -1 when not)
|
|
BlockDriver_GetByte
0x56F03
|
|
|
This can can be used to get a single byte from the input file (i.e. the
selected port). The entry Driver_GetByte of your BlockDriver
can call this SWI directly. Even if you are handling the device yourself
(which means you have registered it as a fake device), you should
call this entry, to allow the module to keep track of its activity.
This activity is reflected in the !Serial application.
Entry
|
r0
|
|
Received byte (or -1 if no byte available)
|
|
BlockDriver_ExamineByte
0x56F04
|
|
|
This call is similar to the one above, but does not removed the
by from the input buffer. It can be used to inspect the next byte
before actually using it.
Entry
|
r0
|
|
Received byte (or -1 if no byte available)
|
|
BlockDriver_PutBlock
0x56F05
|
|
|
Send a block of data (bytes) to the output file. There is no
guarantee that all bytes will be transferred, so your driver
should check the returned number of successfully inserted
bytes and call the SWI again later if there are still bytes
pending.
Entry
|
r2
|
|
→ Data block
|
r3
|
|
Number of bytes to transfer
|
r6
|
|
→ Channel block
|
r0
|
|
Number of bytes successfully transferred
|
|
BlockDriver_GetBlock
0x56F06
|
|
|
Read a block of data (bytes) from the input file.
There is no guarantee that all requested bytes are transferred,
so your driver should check the returned value.
Entry
|
r2
|
|
→ Data block
|
r3
|
|
Maximum number of bytes to be transferred
|
r6
|
|
→ Channel block
|
r0
|
|
Number of bytes successfully transferred
|
|
BlockDriver_CheckTXBuffer
0x56F07
|
|
|
This call returns the number of free bytes in the output (TX)
buffer. The parent application can use this to determine if
and when to send more data.
Entry
|
r0
|
|
Number of bytes free in TX buffer
|
|
BlockDriver_CheckRXBuffer
0x56F08
|
|
|
This call returns the number of free bytes in the input (RX)
buffer. The parent application can use this to determine if
and when it should collect data.
Entry
|
r0
|
|
Number of bytes used in RX buffer (or -1 if channel is invalid)
|
|
BlockDriver_FlushTXBuffer
0x56F09
|
|
|
Clear the output (TX) buffer.
Entry
|
|
BlockDriver_FlushTXBuffer
0x56F0A
|
|
|
Clear the input (RX) buffer.
Entry
|
|
BlockDriver_ControlLines
0x56F0B
|
|
|
This can be used to read or write the status of the modem
control lines of the device, in any of three different formats.
The first one (DeviceFS format) provides the most flexible options.
The other formats are provided for legacy reasons.
Entry
|
r0
|
|
Format (see below)
|
r2
|
|
Control lines (bitmask), or -1 to read
|
r6
|
|
→ Channel block
|
r0
|
|
Control lines status (in requested format)
|
0
|
|
DeviceFS format
|
1
|
|
BlockDriver (8) format
|
2
|
|
BlockDriver (9) format
|
Control lines bits - DeviceFS format (0)
|
0
|
|
DTR
|
1
|
|
RTS
|
16
|
|
CTS
|
17
|
|
DSR
|
18
|
|
RI
|
19
|
|
DCD
|
20
|
|
FIFO
|
Control lines bits - BlockDriver (8) format (1)
|
Control lines bits - BlockDriver (9) format (2)
|
|
BlockDriver_ReadRXErrors
0x56F0C
|
|
|
Currently not implemented
This call reads the error flags of a selected device.
It is currently not implemented for DeviceFS devices,
and always returns '0' in r0.
Entry
|
Error state bits (r0 on exit)
|
0
|
|
Overrun error
|
1
|
|
Parity error
|
2
|
|
Framing error
|
3
|
|
Break received
|
|
BlockDriver_SendBreak
0x56F0D
|
|
|
Currently not implemented
This call issues a break on the selected interface/port.
Is is currently not implemented for DeviceFS devices.
Entry
|
r2
|
|
Time [cs]
|
r6
|
|
→ Channel block
|
|
BlockDriver_BaudRateTX
0x56F0E
|
|
|
Set the transmission speed, also known as the baudrate
of the outgoing (TX) channel of the selected port. If the device does
not support split baudrates (check bit 1 of the
driver flags), the call also updates the
RX baudrate. On exit of the call, r0 contains the actual speed
as reported by the device. This may be different from the
requested speed.
Entry
|
r2
|
|
Speed [baud], or -1 to read the current speed
|
r6
|
|
→ Channel block
|
|
BlockDriver_BaudRateRX
0x56F0F
|
|
|
Set the reception speed, also known as the baudrate
of the incoming (RX) channel of the selected port. If the device does
not support split baudrates (check bit 1 of the
driver flags), the call also updates the
TX baudrate. On exit of the call, r0 contains the actual speed
as reported by the device. This may be different from the
requested speed.
Entry
|
r2
|
|
Speed [baud], or -1 to read the current speed
|
r6
|
|
→ Channel block
|
|
BlockDriver_DataFormat
0x56F10
|
|
|
This call sets or reads the bit format of a single data word,
also known as the word format, consisting of the number
of start bits, the number of data bits and the number of stop bits.
It also defines any parity error checking.
Entry
|
r2
|
|
Data format (see below), or -1 to read
|
r6
|
|
→ Channel block
|
0-1
|
|
Data length (0 = 8 bits, 1 = 7 bits, 2 = 6 bits, 3 = 5 bits)
|
2
|
|
Stop bits (0 = 1 stop bit, 1 = 2 stop bits)
|
3
|
|
Use parity (0 = no parity, 1 = parity on)
|
4
|
|
Even parity (0 = odd parity, 1 = even parity)
|
|
BlockDriver_Handshaking
0x56F11
|
|
|
Define what type of handshaking is used. Also known as flow control.
Note that not all serial ports support all types of handshaking. In most
cases, the computer's primary serial port is fully implemented and has all
modem control lines. Additional ports may be less complete. Also note that
DTR/DSR handshaking is not supported by most modern ports.
Entry
|
r2
|
|
Handshaking type (see below), or -1 to read
|
r6
|
|
→ Channel block
|
0
|
|
No flow control
|
1
|
|
RTS/CTS
|
2
|
|
XON/XOFF
|
3
|
|
DTR/DSR
|
|
BlockDriver_EnumerateBaudRates
0x56F12
|
|
|
This call returns a pointer to a NULL-terminated list of baudrates
that are supported by the device. Each baudrate is represented by
a single 32-bit word. It can be used by your BlockDriver to dynamically
build a list of valid baudrates in the driver's header.
Entry
|
r0
|
|
→ Buffer to hold the results
|
r6
|
|
→ Channel block
|
r0
|
|
→ Buffer to hold the results (preserved)
|
|
BlockDriver_GetInfo
0x56F13
|
|
|
Read global information about the BlockDriver module,
or read information about a specific channel. A channel
is a block of workspace, allocated to an active port,
or a port that has previously been active.
Entry
|
r0
|
|
Reason code
|
r1
|
|
Channel number from 0 onwards (only when r0 > 1)
|
r6
|
|
→ Channel block (only when r0 > 1)
|
0
|
|
Read global information
|
1
|
|
Read channel-specific information
|
r0
|
|
Number of active channels
|
r1
|
|
Maximum number of channels allowed
|
r2
|
|
Stamp 1
|
r3
|
|
Highest channel currently in use
|
r4
|
|
DeviceFS stamp 2
|
r5-r7
|
|
Reserved
|
r0
|
|
→ Device name
|
r1
|
|
→ Description string
|
r2
|
|
Current baud rate
|
r3
|
|
Current data format
|
r4
|
|
Current handshake setting
|
r5
|
|
Status of the control lines
|
r6
|
|
→ Channel block (structure)
|
r7
|
|
Length of data structure in r6
|
-
The value of Stamp is incremented on each change. A monitoring
application polling the module, can use it to determine if anything
has changed since the last poll.
-
DeviceFS stamp is changed whenever a new device appears or an existing
one disappears through DeviceFS. This can be useful when handling
removable devices, such as USB-to-Serial adapters.
|
|
BlockDriver_SetInfo
0x56F14
|
|
|
Overwrite specific parameters of a given channel.
This only works for fake channels. When called for
a device that is supported by the DeviceFS interface, it
will be ignored.
Entry
|
r0
|
|
Reason code
|
r1
|
|
Value
|
r6
|
|
→ Channel block (only when r0 > 1)
|
0
|
|
Reserved
|
1
|
|
Set RX file handle
|
2
|
|
Set TX file handle
|
3
|
|
Set RX buffer handle
|
4
|
|
Set TX buffer handle
|
|
BlockDriver_Platform
0x56F15
|
|
|
This call tries to work out what hardware platform the software
is running on. It can be useful when determining which features
and ports are available on a given platform. As there is no way
in RISC OS to determine the hardware platform, the call inspects
the fixed part of the computer's unique ID and reports this back
in r0.
Entry
|
r0
|
|
Reason code (should be 0 for now)
|
r0
|
|
Vendor ID (see below)
|
r1
|
|
→ Platform name (string)
|
r2
|
|
IDL (lower 32-bits of unique ID)
|
r3
|
|
IDH (upper 32 bits of unique ID)
|
r4
|
|
Reserved
|
0x0000
|
|
Unknown
|
0x17FB
|
|
Freescale iMX6 hardware
|
0x0995
|
|
IYONIX PC
|
0xD063B4
|
|
CuBox iMX6
|
|
BlockDriver_Devices
0x56F16
|
|
|
This call can be used to find the actual DeviceFS names
under which the interfaces of a given sub-system are known
by the OS. It can also be used to count the number of ports
available on a given sub-system, by specifying r0 = -1
on entry to the call.
Entry
|
r0
|
|
Port 1 , or -1 to read number of ports
|
r1
|
|
→ Prefix 2
|
r0
|
|
Number of ports found 3
|
r0
|
|
→ DeviceFS name for this port 3
|
-
The ports of a given sub-system are numbered from 0 onwards.
-
The Prefix should specify the name of the sub-system (e.g. 'Serial'
or 'USBSerial').
-
The EQ flag is set if no ports are found.
|
|
|
Any links shown in red are currently unavailable.
© X-Ample Technology BV. Created: Wednesday 26 April 2017. Last changed: Thursday, 28 September 2023 - 14:12 CET.
|
|
|
|
|