RISCOS.com

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

 

Parallel and serial device drivers


Introduction and Overview

This chapter outlines changes made in RISC OS 3.5 to the Buffer Manager, DeviceFS, and the serial and parallel device drivers in order to improve the performance of these ports.

Buffer Manager

The buffer manager has been extended to provide facilities for insertion and removal of buffered data without using SWI calls, hence avoiding all the related overheads. This is done by directly calling the buffer manager service routine, which uses a reason code to specify its action. The service routine provides all of the functionality of vectors InsV, RemV and CnpV, and has been based on the existing handlers in the buffer manager but optimised as much as possible. For full details of the various reason codes, see The buffer manager service routine.

Device drivers wishing to use this service routine first have to call a new SWI - Buffer_InternalInfo. This provides the information that is required to use the service routine with a particular buffer.

The existing vector interface is still supported, but takes the form of an extra layer on top of the new code.

DeviceFS module

The DeviceFS module has been modified to call the buffer manager service routine in all situations where InsV, RemV or CnpV were previously used; for example the calls DeviceFS_ReceivedCharacter and DeviceFS_TransmitCharacter in the filing system interface.

Parallel device driver

The parallel device driver has been modified to use the buffer manager service routine, hence greatly improving performance.

The parallel device can be opened either for input or output but not for both. When an input or output stream is created, the parallel device driver calls Buffer_InternalInfo to obtain the internal buffer ID for the relevant buffer and the address of the buffer manager service routine. All calls to InsV, RemV or CnpV have been replaced with calls to the buffer manager service routine.

Fast Centronics mode

The new I/O chips provide a fast Centronics mode where bytes written to the FIFO are automatically sent by the hardware at a very high transfer rate using STROBE and BUSY signals as the handshake. The parallel device driver accesses this mode using a new device called 'fastparallel:'. To work with this device driver, technically speaking the printer must assert BUSY within 500ns of receiving STROBE; in practice, it should explicitly state it supports fast Centronics

The 'parallel:' device is still available as the default, since some printers cannot cope with the fast transfer rate of the new device.

Serial device driver

The serial device driver does not use the new buffer manager interface; this is to retain maximum compatibility with existing applications that use the serial interface.

However, its performance has been considerably improved, and it can now support a maximum serial port rate of 115200 baud. Other improvements have resulted in the elimination of most interrupt problems affecting serial input. At the maximum serial port rate of 115200 baud, the input FIFO will allow 1ms of interrupt latency before overrun occurs. This should be ample under most circumstances. The allowed latency increases as the baud rate is lowered.

OS_SerialOp has been extended with the addition of new baud rate codes and reason codes; see OS_SerialOp.

Technical Details

The buffer manager service routine

The buffer manager service routine provides direct access to buffers without the overheads of calling SWIs.

A device driver wishing to use the service routine should first create or register its buffers with the buffer manager. It must then call the SWI Buffer_InternalInfo for each buffer. This returns the address of the service routine and a pointer to its workspace (which are the same for all buffers), and an internal buffer ID specific to that buffer.

Calling the buffer manager service routine

The service routine provides various functions, specified by a reason code. It can be called in IRQ or SVC mode, interrupts may be enabled or disabled. Entry conditions are:


R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
Other registers depend on reason code

Current reason codes are as follows:

R0 Action
0 Insert byte
1 Insert block
2 Remove byte
3 Remove block
4 Examine byte
5 Examine block
6 Return used space
7 Return free space
8 Purge buffer
9 Next filled block

The service routine can use the internal buffer ID to go straight to the appropriate buffer record in the buffer manager's workspace, rather than having to perform a linear search on a buffer handle.

On exit from the service routine, registers are normally preserved, save for those used to return results.

If the device driver removes or deregisters a buffer, it must ensure it no longer quotes that buffer's internal ID when calling the buffer manager service routine.

Insert byte
On entry

R0 = 0 (reason code)
R1 = internal buffer ID
R2 = byte to insert
R12 = R2 value from Buffer_InternalInfo call

On exit

All registers preserved

C = 1 => failed to insert

Use

This reason code inserts a byte into the specified buffer.

Insert block
On entry

R0 = 1 (reason code)
R1 = internal buffer ID
R2 = pointer to data to insert
R3 = number of bytes to insert
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = pointer to first byte not inserted
R3 = number of bytes not inserted
All other registers preserved

C = 1 => UNABLE TO TRANSFER ALL DATA (IE. R3[NOT EQUAL]0)

Use

This reason code inserts a block of data into the specified buffer. The pointer and length are adjusted to reflect how much data was actually inserted. If the data has already been written directly into the buffer (ie. R2 = pointer to buffer insertion point), then no data is copied and the buffer indices are simply updated.

Remove byte
On entry

R0 = 2 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = byte removed
All other registers preserved

C = 1 => unable to remove byte

Use

This reason code removes a byte from the specified buffer.

Remove block
On entry

R0 = 3 (reason code)
R1 = internal buffer ID
R2 = pointer to destination area
R3 = number of bytes to remove
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = pointer to first free byte in destination area
R3 = number of bytes not removed
All other registers preserved

C = 1 => UNABLE TO REMOVE ALL DATA (IE. R3[NOT EQUAL]0)

Use

This reason code removes a block from the specified buffer. The pointer and length are adjusted to reflect how much data was actually removed.

Examine byte
On entry

R0 = 4 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = next byte to be removed
All other registers preserved

C = 1 => unable to get byte

Use

This reason code reads the next byte to be removed from the specified buffer, without actually removing it.

Examine block
On entry

R0 = 5 (reason code)
R1 = internal buffer ID
R2 = pointer to destination area
R3 = number of bytes to examine
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = pointer to first free byte in destination area
R3 = number of bytes not transferred
All other registers preserved

C = 1 => UNABLE TO TRANSFER ALL DATA (IE. R3[NOT EQUAL]0)

Use

This reason code reads a block of data from the specified buffer, without actually removing it. The pointer and length are adjusted to reflect the data transferred.

Return used space
On entry

R0 = 6 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = number of used bytes in buffer
All other registers preserved

Use

This reason code returns the number of bytes in the specified buffer.

Return free space
On entry

R0 = 7 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = number of free bytes in buffer
All other registers preserved

Use

This reason code returns the number of free bytes in the specified buffer.

Purge buffer
On entry

R0 = 8 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call

On exit

All registers preserved

Use

This reason code purges all data from the specified buffer.

Next filled block
On entry

R0 = 9 (reason code)
R1 = internal buffer ID
R3 = number of bytes read since last call
R12 = R2 value from Buffer_InternalInfo call

On exit

R2 = pointer to first byte in next block to be removed
R3 = number of bytes in next block
All other registers preserved

C = 1 => buffer empty

Use

This reason code can be used to remove buffered data directly, rather than copying it from the buffer using reason code 3. Initially, the call should be made with R3 = 0 so that no bytes are purged. The call returns a pointer to the next byte to be removed from the buffer, and the number of bytes which can be removed from that address onwards. In the next call R3 should equal the number of bytes read since the last call, at which point the buffer indices will be updated to purge the data, and the next filled block will be returned.

A device driver which uses this call must be the only application which removes data from the buffer.

Changes to existing SWIs

OS_ReadSysInfo

This call has been extended to provide information on the new hardware supported by RISC OS 3.5.

  • Extra values are now returned by reason code 2 (read presence of chips and unique machine ID) to allow support of new hardware features. This is described below.
  • The values returned by reason code 3 (read features mask) differ for the new hardware, although the call itself has not changed, Again, this is described below.

Furthermore, two new reason codes (4 and 5) have been added. However, these are for internal use only, and you must not use them in your own code.

OS_ReadSysInfo 2

This reason code has been extended in a backward-compatible manner to return information on the new hardware supported by RISC OS 3.5. This has been done by splitting into fields the values returned in R0 - R2 on exit:

R0 = hardware configuration word 0:

bits 0 - 7 = special functions chip type:
0 => NONE_ 1 => IOEB ASIC
bits 8 - 15 = I/O control chip type:
0 => IOC_ 1 => IOMD
bits 16 - 23 = memory control chip:
0 => MEMC1/MEMC1A_ 1 => IOMD
bits 24 - 31 = video control chip type:
0 => VIDC1A_ 1 => VIDC20

R1 = hardware configuration word 1:

bits 0 - 7 = I/O chip type:
0 => ABSENT_ 1 => 82C710/711 OR SMC '665 or similar
bits 8 - 31 reserved (set to 0)

R2 = hardware configuration word 2:

bits 0 - 7 = LCD controller type:
0 => ABSENT_ 1 => present (type 1)
bits 8 - 31 reserved (set to 0)

The unique machine ID is still returned in R3 and R4, if available.

OS_ReadSysInfo 3

This reason code has not been altered in functionality. However the values returned in R0 and R1 have altered, because RISC OS 3.5 machines do not use the 710/711 family of chips, but instead use the broadly compatible SMC '665 family. Values returned in R0 are:

R0 bits sub-unit SMC '665
0 - 3 IDE hard disc interface 1
4 - 7 floppy disc interface 1
8 - 11 parallel port 1
12 - 15 1st serial port 1
16 - 19 2nd serial port 1
20 - 23 chip configuration 3
24- 31 reserved 0

The only difference is the chip configuration, since the sub-units described still have the same basic functionality. The SMC '665 has extra functionality: you can use a fast parallel mode (with FIFO and hardware handshake), and use the serial FIFOs provided. Hence the extra features mask returned in R1 differs to reflect this:

R1 bits sub-unit SMC '665
0 - 3 IDE hard disc interface 0
4 - 7 floppy disc interface 0
8 - 11 parallel port 1
12 - 15 1st serial port 1
16 - 19 2nd serial port 1
20 - 23 chip configuration 0
24- 31 reserved 0
OS_SerialOp
New flag bit

OS_SerialOp 0 accepts a new flag bit to enable or disable the serial FIFOs (if present):

Bit Read/Write or Read only Value Meaning
8 R/W 0 Disable the serial FIFOs, if present
1 Enable the serial FIFOs, if present
New baud rates

OS_SerialOp 5 and OS_SerialOp 6 accept new baud rate codes to support the higher baud rates possible under RISC OS 3.5. These are:

Value of R1 Baud rate
16 38400
17 57600
18 115200
New reason code

This call has also been extended by the addition of a new reason code, described later in this chapter:

OS_Byte 7 and OS_Byte 8

These calls have been updated to support the new reason codes used by OS_SerialOp 5 and 6 (see above). However, as in RISC OS 3, you should use the OS_SerialOp calls in preference.

SWI calls


OS_SerialOp 9
(SWI &57)

Enumerates the available serial port speeds

On entry

R0 = 9 (reason code)

On exit

R0 preserved
R1 = pointer to table of supported baud rates
R2 = number of entries in table

Interrupts

Interrupt status is undefined
Fast interrupts are enabled

Processor Mode

Processor is in SVC mode

Re-entrancy

SWI is not re-entrant

Use

This call enumerates the available serial port speeds, returning them as a table. The table is word aligned; each word in the table specifies a baud rate in units of 0.5 bit/sec. (This is to support rates such as 134.5 baud.)

The index into the table (starting at 1) can be used in OS_SerialOp 5 and 6 calls to set the corresponding baud rate.

This call is available from RISC OS 3.5 onwards.

Related SWIs

None

Related vectors

SerialV


Buffer_InternalInfo
(SWI &42949)

Converts a buffer handle to a buffer manager internal buffer ID

On entry

R0 = buffer handle

On exit

R0 = internal buffer ID
R1 = address of buffer manager service routine
R2 = value to pass to service routine in R12

Interrupts

Interrupt status is not altered
Fast interrupts are not altered

Processor mode

Processor is in SVC mode.

Re-entrancy

SWI is not re-entrant

Use

This call converts the buffer handle passed in R0 to a buffer manager internal buffer ID, which is specific to that buffer. It also returns the address of the buffer manager service routine, and the value to quote in R12 when calling the service routine; these are the same for all buffers.

If the buffer handle is invalid an error is returned, but can be ignored; the service routine address and R12 value will still be returned.

This call is available from RISC OS 3.5 onwards.

Related SWIs

None

Related vectors

None

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