Serial Software Functional Specification
Distribution: COMPANY CONFIDENTIAL
Project: NC1
Issue: 0.08
Author(s): Rich Buckley
Date: 25-Oct-96
Last Issue: 0.07
Contents.
0.01 23-Apr-96 First created
0.02 30-Apr-96 Modified following changes to FileSwitch
0.03 03-May-96 Extended with ioctl reason codes
0.04 10-May-96 Changed ioctl calling convention since we only have one register to play with.
0.05 13-May-96 Added new ioctl for setting fifo trigger level.
0.06 15-May-96 Changed information provided on *SerialInfo.
0.07 14-Jun-96 Updated section on asynchronous events.
0.08 25-Oct-96 Added ioctls to enumerate supported baud rates.
- Allocation of upcall number
- Modification of DeviceFS to issue upcalls
The Network Computer contains a combo chip supporting two serial ports, the interrupts from each of these serial ports are wired-ORed together to form a shared interrupt. If the combo chip is IrDA capable, the second serial port can be configured to operate in an IrDA compliant mode.
We have three potential uses for the two serial ports supplied with the NC.
- connection to external devices
- infrared communications (serial port 2 only)
- connection to smart card interface hardware
It has been suggested that the smart card interface use serial port 1. Serial port two would then be used for either IrDA communications or traditional communications as per build option or application.
Traditionally RiscOS has only supported one serial port. The serial device driver would require significant alteration to support multiple ports and on a RiscPC, the interrupt from the second serial port is not connected to anything so nothing useful can be done with the port.
Overview
In order to successfully use the second serial port on the Network Computer platform, the existing serial driver would require modification. The OS_SerialOp swi interface could be extended to allow a port number to be specified (using higher byte in reason code register) but the internals of the SerialDeviceDriver and SerialDeviceSupport would require major changes. For example the use of workspace to record current state information.
Send/receive data interface
There are too many different ways of sending and receiving data to/from the serial port. For example
- open file on devices:$.Serial and use file transfers
- use buffer manager calls to insert/remove byte/block directly to/from the serial buffers
- use swi
OS_SerialOp
(reason code 3 and 4) to send/read a byte
Having so many ways of doing the same thing requires work to be done behind the scenes to ensure all the buffer thresholding and handshaking works correctly for all cases. It also confuses developers who are unsure of the most efficient method of doing things.
Configuration interface
The swi interface to allow baud rates, data formats and handshaking to be configured is non-linear and at times completely confusing. (Jon says crap, and Ant says fundamentally flawed). There is no logical way of extending the swi interface to support multiple ports without the interface feeling cluttered.
Backwards compatability
Old style OS_Byte serial port operations are currently provided for backwards compatability with very early versions of RiscOS or even the BBC OS. These are no longer required on the NC.
Efficiency
The efficiency of the serial port interrupt handling code could be improved to reduce the number of swis called on every interrupt. Currently the swi OS_CallAVector is called once for every byte that is taken from the serial port. This could be improved by reading a block of bytes from the port into RAM and then performing a single swi to do a block write of this data into the buffer.
It is proposed that a new module provide an interface to both serial ports on the combo chip. This module would arbitrate between both ports using the shared interrupt. The interface for configuration of these ports is documented in sections below.
A single data input/output interface will be provided to access the serial ports. This will be through the DeviceFS interface with data transfers analogous to file read/writes.
The new wizzo buffer manager internal calls will be used to insert/remove data to/from the buffers. This removes the overhead of calling swis and vectors for every byte of data transfered.
The modules FileSwitch and DeviceFS have been altered to support IOCtl's. This allows a device driver to receive a control command from an application based on either an open file handle or a directory path in DeviceFS. The following modifications have taken place.
A new OS_Arg
reason code has been allocated OSArgs_IOCtl
this has the following arguments.
On entry
r0 = 9 (reason code)
r1 = file handle
r2 -> ioctl parameter block
On exit
r0 preserved
r1 preserved
r2 preserved
A new bit has been allocated in the extra filing system information word (PRM 2-523) as follows
Bit Meaning if set
3 Filing system supports OS_Arg IOCtl
.
Filing systems should set this bit if they intend to support OS_Arg IOCtl
. Existing filing systems will have this bit clear so will never be asked to handle this call.
If the registered filing system supports the IOCtl OS_Arg
swi, the call will be dispatched using the normal entry point and reason code. It is up to the underlying filing system to impose a meaning on the registers r2-r7.
DeviceFS now sets bit 3 in the extra filing system information word to indicate that it wants to handle OS_Arg IOCtl
.
A new DeviceFS_CallDevice
reason code has been allocated DeviceCall_IOCtl
this has the following arguments when received.
DeviceDriver_Entry 14
IOCtl
On entry
r0 = 14 (reason code)
r1 = file handle
r2 = stream handle
r3 -> ioctl parameter block as passed in r2 of OS_Args call
On exit
r0 preserved
r1 preserved
r2 preserved
r3 preserved
This call is dispatched to the underlying device driver whenever the OS_Arg IOCtl
swi is called or the swi DeviceFS_CallDevice (14)
is called.
The following calling convention should be adopted when using this ioctl interface. Fields have been taken from the unix ioctl implementation as shown below.
On entry
r2 -> ioctl parameter block
On exit
r2 preserved
where ioctl control block is a pointer to the following structure
typedef struct {
unsigned int reason : 16; /* ioctl reason code */
unsigned int group : 8; /* ioctl group code */
unsigned int reserved : 6; /* should be zero */
unsigned int read : 1; /* read flag */
unsigned int write : 1; /* write flag */
unsigned int data; /* actual data */
} ioctl_t;
In the case of a ioctl called with both read and write flags set, the returned value will be the new or latest value of the parameter being accessed.
*SerialInfo
A *command will be provided to display internal serial driver statistics such as current configuration of each port.
serial1
Baud (bps) : <baud>
Data format : <length>.<start/stop>.<n|e|o>
Handshake : <none|rts/cts|rtr/dsr|xon/xoff>
serial2
Baud (bps) : <baud>
Data format : <length>.<start/stop>.<n|e|o>
Handshake : <none|rts/cts|rtr/dsr|xon/xoff>
More information such as buffer sizes, stream handles, etc will be provided if the module is compiled with the debug
flag set to true
.
The programmer interface to the serial ports will be via DeviceFS and file access. DeviceFS provides a standardised interface to device drivers within RiscOS. Some analogies can be made between DeviceFS files and unix special files. Currently the only devices to use the DeviceFS interface are the serial and parallel device drivers.
Input and/or output to DeviceFS streams should be made on the file path : devices:$.<stream name>
DeviceFS also establishes an environment variable to allow simpler access to this path. This would be constructed as : <stream name>:
The new device driver will register a number of streams (files) within then DeviceFS filing system. Any application wishing to see what ports are available would enumerate the contents of the directory devices:$
. The following streams would be present for the proposed hardware combination on NCD1.
-
serial1
- serial port 1 on the combo chip
-
serial2
- serial port 2 on the combo chip (IrDa capable depending upon device)
The existing serial port configuration requires the calling of a number of swis to set baud rate, data format etc. These swis have interesting parameters which require the programmer to reference the PRMs every time they wish to use them.
The proposed driver works by having a configuration string passed to DeviceFS when the stream is opened for input/output. The position of this configuration string is demonstrated below :
devices#<configuration options>:$.serial1
Where <configuration options>
can be made up of any of the following entries in order. Some fields may be omitted and this will leave the option unchanged. Currently due to a problem with DeviceFS, the options should be given in order. A semicolon ';' is used to separate option fields.
-
baud<n>
- baud rate in bps
-
data<n>
- data length in bits
-
stop<n>
- number of start/stop bits
-
[noparity|even|odd]
- type of parity required
-
[nohandshake|rts|xon|dtr]
- type of handshaking required
-
size<n>
- size of buffer
-
thres<n>
- buffer threshold point
For example '#baud19200;data8;stop1;noparity;size1024;thres32;rts
'. In fact this is the default state of the driver on initialisation. Except the tx buffer will default to 512 bytes.
If any of the parameters are invalid, for example baud rate not supported, the request to open the stream is refused.
Direct control of the serial port control lines can be achieved using the IOCtl interface described before. This will have the following reason codes.
- set/read baud rate :
- 50, 75, 110, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 56000 or 115200
- set/read data format :
- bits 0-7 : data length (5,6,7 or 8)
- bits 8-15 : number of start/stop bits (1 or 2)
- bits 16-23 : parity encoded as
- 0 - no parity
- 1 - even parity
- 2 - odd parity
- bits 24-31 : reserved (should be 0)
- set/read handshaking :
- 0 - no handshake
- 1 - rts/cts handshaking
- 2 - xon/xoff handshaking
- 3 - dtr/dsr handshaking
- set/read buffer size :
- Size of buffer in bytes used for rx/tx (depending upon stream). If the buffer has already been created, this call will fail by returning the actual buffer size.
- set/read rx/tx buffer threshold point :
- rx buffer, sets the point at which handshaking will be invoked.
- tx buffer, sets the point at which upcall notification is sent to higher level modules/applications to indicate tx space available.
- set/read control lines :
- bits 0-15 read/writable bits
- bit 0 : DTR (1 = /DTR active, i.e. low)
- bit 1 : RTS (1 = /RTS active, i.e. low)
- bits 16-31 read only flags
- bit 16 : CTS (1 = /CTS active, i.e. low)
- bit 17 : DSR (1 = /DSR active, i.e. low)
- bit 18 : RI (1 = /RI active, i.e. low)
- bit 19 : DCD (1 = /DCD active, i.e. low)
- bit 20 : fifos enabled
- set/read fifo trigger level :
- This sets the number of bytes that need to be present in the 16 byte fifo in order for an interrupt to be generated. Valid options for this are 1, 4, 8 or 14.
- read number of supported baud rates :
- This returns the number of baud rates supported by the driver. It should be used in conjunction with the ioctl below to enumerate baud rates.
- read baud rate associated with index :
- This will return the baud rate associated with index . is an index between 0 and number of supported baud rates-1.
Once the DeviceFS stream has been chosen, data input/output is carried out using standard file access on the stream path name. For example :
-
type devices:$.serial1
- echo's to the screen any characters received on serial port 1.
-
copy <filename> devices:$.serial1
- copies the data in file <filename>
to serial port 1.
- swi interface
-
OS_Find
to open a stream for tx/rx
-
OS_GBPB 2,4
to perform block read/writes from/to the stream
-
OS_BPut
to transmit a character
-
OS_BGet
to fetch a character
-
OS_Args 2
to obtain the amount of data in rx stream buffer and amount of free space in tx stream buffer
It should be noted that a single DeviceFS stream cannot be opened for read/write access. Two streams should be opened and maintained. If the second stream is opened with different line characteristics for example a different baud rate, the initial settings will be overwritten in preference of the latest.
To obtain the functionality of swi OS_Args 2
required a change to DeviceFS to allow this information to be returned. You therefore require version 0.31 of DeviceFS in order to implement this functionality.
A scheme is required whereby modules and applications using the serial ports can receive notification of asynchronous events. Such notification would remove the need for constant polling of the streams when waiting to transmit/receive data. The following events are of concern to higher level programmer.
Data present
An upcall is dispatched whenever data enters a previously empty input buffer.
On entry
r0 = 15 (upcall code Upcall_DeviceRxDataPresent)
r1 = stream handle
Threshold above
An upcall is dispatched whenever the amount of data in a stream exceeds the threshold value.
On entry
r0 = 16 (upcall code UpCall_DeviceThresAbove)
r1 = stream handle
Threshold below
An upcall is dispatched whenever the amount of data in a stream falls below the threshold value.
On entry
r0 = 17 (upcall code UpCall_DeviceThresBelow)
r1 = stream handle
Serial errors and line status changes
An event is generated whenever DSR or DCD change or when a line error (parity, framing, overrun) occurs.
On entry
r0 = 7 (event code Event_RS423Error)
r1 = flags
SerialEvent_Parity bit 5
SerialEvent_Overrun bit 4
SerialEvent_Framing bit 3
SerialEvent_DSR bit 2
SerialEvent_DCD bit 1
r2 = input stream handle
RS232 hardware handshaking using rts/cts, dtr/dsr lines and software handshaking using xon/xoff characters depending on configuration options.
There are no data interchange formats defined by this project.
There are not data formats defined by this project.
NC hardware platform.
Serial data transfer independantly through each serial port on the NC will be at least as good as, if not better than if the existing serial device drivers were to be used.
Using available hardware (NC1, RiscPC, STB2, serial expansion card).
Standard RiscOS module written in ARM assembler. Module will be built as part of the Omega build tree for inclusion in main ROM.
Integration of modem driver functionality as serial port 3 ?
- BSD unix ioctl man pages
- MS Visual C/C++ Win32s API