www.riscos.com Technical Support: |
|
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.
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.
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.
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.
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.
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.
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.
R0 = 0 (reason code)
R1 = internal buffer ID
R2 = byte to insert
R12 = R2 value from Buffer_InternalInfo call
All registers preserved
C = 1 failed to insert
This reason code inserts a byte into the specified buffer.
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
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. R30)
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.
R0 = 2 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
R2 = byte removed
All other registers preserved
C = 1 unable to remove byte
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
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. R30)
This reason code removes a block from the specified buffer. The pointer and length are adjusted to reflect how much data was actually removed.
R0 = 4 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
R2 = next byte to be removed
All other registers preserved
C = 1 unable to get byte
This reason code reads the next byte to be removed from the specified buffer, without actually removing it.
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
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. R30)
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.
R0 = 6 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
R2 = number of used bytes in buffer
All other registers preserved
This reason code returns the number of bytes in the specified buffer.
R0 = 7 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
R2 = number of free bytes in buffer
All other registers preserved
This reason code returns the number of free bytes in the specified buffer.
R0 = 8 (reason code)
R1 = internal buffer ID
R12 = R2 value from Buffer_InternalInfo call
All registers preserved
This reason code purges all data from the specified buffer.
R0 = 9 (reason code)
R1 = internal buffer ID
R3 = number of bytes read since last call
R12 = R2 value from Buffer_InternalInfo call
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
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.
This call has been extended to provide information on the new hardware supported by RISC OS 3.5.
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.
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:
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:
The unique machine ID is still returned in R3 and R4, if available.
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:
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 |
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 |
This call has also been extended by the addition of a new reason code, described later in this chapter:
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.
R0 = 9 (reason code)
R0 preserved
R1 = pointer to table of supported baud rates
R2 = number of entries in table
Interrupt status is undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant
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.
None
Converts a buffer handle to a buffer manager internal buffer ID
R0 = buffer handle
R0 = internal buffer ID
R1 = address of buffer manager service routine
R2 = value to pass to service routine in R12
Interrupt status is not altered
Fast interrupts are not altered
Processor is in SVC mode.
SWI is not re-entrant
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.
None
None