Home
RISC OS
Contact
Links
Crypto
Enigma-E
MediX
Logo (click for homepage)
Extended BlockDriver specification
Version 2.10 - updated 25 April 2017
 
Driver layout
The first 384 bytes of the driver has a fixed format. It allows an application to check its features, even before actually installing and using it. It also provides the main entry point through which the functions of the blockdriver should be called. The driver code should start at offset 0x0180 (384) and may have any length. The parent application should check its size before loading it.
 
Offset Length Description
0x0000 0x80 Main entry point to call routines (see below)
0x0080 32 Driver information string (31 characters max., NULL terminated)
0x00A0 32 Manufacturer information string (31 characters max. NULL terminated)
0x00C0 4 Version number (top 16 bits major, bottom 16 bits minor)
0x00C4 4 Driver flags (see below)
0x00C8 4 Driver number (see below)
0x00CC to 0xFF Reserved
0x0100 0x80 Speed table (see below)
0x0180 ... Driver code

 
BlockDriver module
In version 2.00 of the BlockDriver speicification, a relocatable module (RM) has been introduced to make writing a BlockDriver a lot easier. Although the use of the BlockDriver module is not mandatory and you are free to write your own routines, it is highly recommended to register with the module as a bare minimum, and keep it informated about any statistics. It allows the monitoring application !Serial to give a relibably view of the status of your serial ports.

If your serial port driver is properly implemented, it should be accessible through DeviceFS, which means that the BlockDriver Module can call most of the functions on your behalf. This means that the actual BlockDriver should be no more than a simple venier to the calls of the BlockDriver Module. In addition, the BlockDriver Module provides some useful calls to check the current hardware and find the correct device names under which your interface is known by the OS.

 BlockDriver Module specification

 
Main entry point   0x0000 (128 bytes)
This is the main entry point for calling the functions supplied by the BlockDriver. The entry point can be called in usermode or in supervisor mode. Registers r0-r3 are used to pass parameters to the routines. The routines may corrupt r0-r3, but should preserve r4-r12 and used r14 for the return address.

Entry
 
r0   Function code
r1   Port number
r2   Parameter 1
r3   Parameter 2

Exit
 
r0   Return code

The code to despatch the function should be placed in the first 0x80 bytes of the driver code. In assembler, it might look like this:

  .entry
      STMFD    R13!,R14
      CMP      R0,#((table_end - table_start)/4)
      ADDCC    PC,PC,R0,LSL#2
      LDMFD    R13!,PC
 
   .table_start
      B        func_0
      B        func_1
  ...
   .table_end

 
Driver flags   0x00C4 (4 bytes)
32-bit value of which the top byte specifies the highest port number (pp) available. As the ports are internally numbered from zero onwards, the higest port number is the number_of_ports-1. The remaining 24 bits are used for the driver flags. The flag bits have the following meaning:
 
0   More than one port available
1   Supports split baudrates
2   Has more than one byte FIFO
3   Can use Driver_ControlLines to generate a break
4   Requires polling (function 19)
5   Won't empty (is a shared buffer)
6   Supports block get/put operations
7   Prefer not to overlap serial IO and disk IO
8   Supports inquiry initialise
9   Supports return of RISC OS TX and RX buffers (function 20 and 21)
10-15   reserved for future expansion
16   Code is 32-bit compliant (bit 16 set)
17   Code is NOT 26-bit compatible (bit 17 set)
18   Allows flags in the top 24 bits of the port number in r1 on entry to 'Driver_Initialise'
19   Code is ARMv7 compliant
20-23   reserved
24-31   Highest port number supported

 
Driver number   0x00C8 (4 bytes)
Unique 32-bit value that identifies the driver, allocated by us. The lowest byte is always zero, so that it can be used to specify the port on a particular interface, as part of the Device_Claim call. For example, if you want to claim port 5 on an II Dual Serial expansion card (0x00000100), you would use 0x00000105. The primary internal port of the computer uses driver 0 and port 0.

Currently allocated drivers numbers (bits 8-31):
 
0   Internal serial port(s), e.g. Internal, InternalPC, Internal32
1   II Dual Serial podule
2   Serial Port dual serial podule
3   Internal serial (with PC-style cable wiring)
4   Brainsoft Multipod
5   Acorn telnet interface
6   Serial Port dual serial podule (with PC-style cable wiring)

25   ModemCard
50   MultiPort serial card

100   Remote econet driver
128   Virtual pipe (end A)
129   Virtual pipe (end B)

255   Dummy

 
Speed table   0x0100 (128 bytes)
Table with supported baudrates. One word per speed, terminated with a NULL word.

Note that some drivers will only build this table after a pre-initialisation call. Check bit 8 (supports inquiry initialise) of the driver flags to see if this is the case. If the flag is set, you should call Driver_Initialise with r1 = -1, before reading the baudrate table.
 
Function codes
The following function codes can be called from the parent application, through the main entry point at address 0x0000:
 
0   Driver_PutByte
1   Driver_GetByte
2   Driver_PutBlock
3   Driver_GetBlock
4   Driver_CheckTXBuffer
5   Driver_CheckRXBuffer
6   Driver_FlushTXBuffer
7   Driver_FlushRXBuffer
8   Driver_ControlLines
9   Driver_ReadControlLines
10   Driver_ReadRXErrors
11   Driver_SendBreak
12   Driver_ExamineByte
13   Driver_BaudRateTX
14   Driver_BaudRateRX
15   Driver_DataFormat
16   Driver_Handshaking
17   Driver_Initialise
18   Driver_CloseDown
19   Driver_Poll
20   Driver_GetTXBuffer 1
21   Driver_GetRXBuffer 1

  1. Added in version 2.00. Check bit 9 of the driver flags before calling this entry.

 
Driver_PutByte   0
Send a byte to the serial port. Returns with r0 if the byte was successfully inserted into the TX buffer, or -1 if it was not.

Entry
 
r0   0
r1   Port number
r2   Byte to send

Exit
 
r0   Result code (0 = ok, -1 = error)

 
Driver_GetByte   1
Get a byte from the serial port. Returns with the byte in r0 when successful, or -1 if it was not.

Entry
 
r0   1
r1   Port number

Exit
 
r0   Byte (or -1 if no byte available)

 
Driver_PutBlock   2
Send a block of data to the serial port. The call returns with the number of bytes that have been transferred successfully. There is no guarantee that all bytes are sent in a single call. You should call this entry with updated parameters repeatedly, until all bytes are sent.

Entry
 
r0   2
r1   Port number
r2   Pointer to block
r3   Number of bytes to send

Exit
 
r0   Number of bytes transferred

 
Driver_GetBlock   3
Get a block of data from the serial port and put them into the input buffer. There is no guarantee that the number of bytes requested have actually been transferred, so you should inspect the value returned in r0 on exit.

Entry
 
r0   3
r1   Port number
r2   Pointer to block
r3   Maximum number of bytes to read

Exit
 
r0   Number of bytes transferred

 
Driver_CheckTXBuffer   4
Check how much space is left in the output buffer.

Entry
 
r0   4
r1   Port number

Exit
 
r0   Number of bytes free in TX buffer

 
Driver_CheckRXBuffer   5
Check how much space is left in the input buffer.

Entry
 
r0   5
r1   Port number

Exit
 
r0   Number of bytes free in RX buffer

 
Driver_FlushTXBuffer   6
Clear the output buffer.

Entry
 
r0   6
r1   Port number

 
Driver_FlushRXBuffer   7
Clear the input buffer.

Entry
 
r0   7
r1   Port number

 
Driver_ControlLines   8
Set the state of the modem control lines of the RS232 port.

Entry
 
r0   8
r1   Port number
r2   New settings or -1 to read

Bit flags (r2)
 
0   DTR
1   RTS
2   TX data active (when set), i.e. break state

 
Driver_ReadControlLines   9
Read the state of the modem control lines of the RS232 port.

Entry
 
r0   9
r1   Port number

Exit
 
r0   Status

Status bits (r0)
 
0   CTS
1   DSR
2   RI
3   DCD

 
Driver_ReadRXErrors   10
Returns a bitmask of errors seen since last call to this entry. The bitmask is reset, each time this entry is called.

Entry
 
r0   10
r1   Port number

Exit
 
r0   Error flags

Error flag bits (r0)
 
0   Overrun error
1   Parity error
2   Framing error
3   Break received

 
Driver_SendBreak   11
Send a so-called break. Note that this call blocks until the break has been sent. Although some serial ports might be able to multitask when sending a break, the internal serial port can't. Check the driver flags to see of you can use a multitasking break before using this call. The break time (r2) should be specified in centiseconds.

Entry
 
r0   11
r1   Port number
r2   Break time [cs]

 
Driver_ExamineByte   12
This call is similar to Driver_GetByte, but leaves the byte in the buffer.

Entry
 
r0   12
r1   Port number

exit
 
r0   Byte (or -1 if no byte available)

 
Driver_BaudRateTX   13
This call allows the speed of the serial port's transmitter to be set to a particular baudrate. Note that most serial ports do not support a split baudrate (i.e. a differentb audrate for RX and TX). Inspect the driver flags to see if it does. If split baudrates are not supported, setting either the TX or the RX baudrate, will set both. Note that the returned speed might be (slightly) different from the requested speed, as some interfaces return the actual calculated speed of the device.

Entry
 
r0   13
r1   Port number
r2   Speed (or -1 to read)

Exit
 
r0   Speed

 
Driver_BaudRateRX   14
This call allows the speed of the serial port's receiver to be set to a particular baudrate. Note that most serial ports do not support a split baudrate (i.e. a differentb audrate for RX and TX). Inspect the driver flags to see if it does. If split baudrates are not supported, setting either the TX or the RX baudrate, will set both. Note that the returned speed might be (slightly) different from the requested speed, as some interfaces return the actual calculated speed of the device.

Entry
 
r0   14
r1   Port number
r2   Speed (or -1 to read)

Exit
 
r0   Speed

 
Driver_DataFormat   15
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
 
r0   15
r1   Port number
r2   Data format (or -1 to read)

Exit
 
r0   Data format

Data format bits (r0)
 
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)

 
Driver_Handshaking   16
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
 
r0   16
r1   Port number
r2   Handshaking type (or -1 to read)

Exit
 
r0   Handshaking type

Handshaking types
 
0   No flow control
1   RTS/CTS
2   XON/XOFF
3   DTR/DSR 1

  1. Traditionally, this value was used to set both (i.e. hardware and software handshaking), In version 2.00 of the BlockDriver specification this has been changed to DTR/DSR hardware handshaking, which is supported by the OS. Note that most hardware does not support this type of handshaking though.

 
Driver_Initialise   17
This call serves two purposes. It should be called at least once with a value of -1 in r1, before calling any of the other functions, to allow the driver to adjust itself to the available hardware, count ports, baudrates, etc. When called this way, the driver will not touch any hardware. Bit 8 of the driver flags will tell you whether this function is supported. Do not read the baudrate tables or any of the other driver flags, until after this call.

The second purpose of this call is to initialise a driver and claim the port for the host application. This is done by specifying the port number in r1. Once claimed, the port can generally not be used by another application, until Driver_CloseDown is called.

Entry
 
r0   17
r1   Port number and flags 1 (or -1 for pre-initialise call)
r2   Pointer to parameter string (optional)
r3   Reserved (should be 0 for now)

Port number and flags 1 (r1)
 
0-7   Port number
8   Device is shared (i.e. may have multiple users)
9-31   Reserved for future expansion

Exit
 
r0   0 when successful (or pointer to error string if not)

  1. Before specifying flags in this register, you should check the driver flags to see if this feature is supported.

 
Driver_CloseDown   18
This entry should be called when the application no longer needs the serial port. It is typically called when closing the application, or before claiming another port. Once the port has been released, it will be available to other applications.

Entry
 
r0   18
r1   Port number

 
Driver_Poll   19
This entry should be called regularly for the driver to perform polling tasks. This was needed in the past, for example, by the Econet drivers to check internal buffers and poll any Econet Protocol tasks. This entry should typically be called from the main polling loop of the parent task, and may be as infrequent as three to four time a second. If the driver needs more frequent polling, it should install a module and use callbacks.

Entry
 
r0   19
r1   Port number

 
Driver_GetTXBuffer   20
This call can be used to read the handle of the current TX buffer. Note that this call has first been specified in version 2.00 of the BlockDriver specification. Check bit 9 of the driver flags before calling this entry.

Entry
 
r0   20
r1   Port number

Exit
 
r0   Handle (or -1 when not available)

 
Driver_GetRXBuffer   21
This call can be used to read the handle of the current RX buffer. Note that this call has first been specified in version 2.00 of the BlockDriver specification. Check bit 9 of the driver flags before calling this entry.

Entry
 
r0   21
r1   Port number

Exit
 
r0   Handle (or -1 when not available)

 

 
Further information

Any links shown in red are currently unavailable. X-Ample Technology BV.
Last changed: Wednesday, 26 April 2017 - 10:12 CET.
Click for homepage