Device Manager

The QNX Device Manager (Dev) is the interface between processes and terminal devices. These terminal devices are located in the I/O namespace with names starting with /dev. For example, a console device on QNX would have a name such as: /dev/con1.

QNX programs access terminal devices using the standard read(), write(), open(), and close() functions. A terminal device is presented to a QNX process as a bidirectional stream of bytes that can be read or written by the process. The Device Manager regulates the flow of data between an application and the device. Some processing of this data is performed by Dev according to parameters in a terminal control structure (called termios), which exists for each device. Users can query and/or change parameters by using the stty utility; programs can use the tcgetattr() and tcsetattr() functions. The termios parameters control low-level fuctionality such as:

Some auxiliary services provided by the Device Manager:

Edited input mode

The most significant mode ofdevice processing is controlled by the ICANON bit in the termios control structure. If this control bit is set, the Device Manager performs line-editing functions on received characters. Thus, only when line is entered (typically when a carriage return is received) will the processed data be made available to applications. This mode of operation is referred to as edited, canonical, or cooked mode. Line editing characters vary from terminal to terminal. The QNX console always starts out with a full set of editing keys defined.

If a terminal is connected to QNX via a serial channel, it is necessary to define the editing characters that apply to that particular terminal. T do this, you can use stty utility.

Raw input mode

When ICANON is not set, the device is said to be in raw mode. In this mode, no input editing is performed, and any received data is made immediately available to QNX processes. When reading from a raw device, the application is capable of specifying underwhat conditions an input is to be satisfied. The criteria used for accepting raw input data are based on two members of the termios control structure: MIN and TIME. The application can specify a further qualifier of accepting input data when it issues its read request via dev_read(). This qualifier, TIMEOUT, is useful when writing protocols or realtime applications. TIMEOUT is always 0 for read(). When a QNX process issues a read request for n bytes of data, these three paraeters define when that read request is to be satisfied:

MIN TIME TIMEOUT Description
0
0
0
Return immediately with as many bytes as are currently available (up to n bytes).
M
0
0
Return with up to n bytes only, when at least M bytes are available.
0
T
0
Return with up to n bytes when at least one byte is available, or Tx0.1 second has expired.
M
T
0
Return with up to n bytes when either M bytes are available or at least one byte has been received and the interbyte time between any subsequently received characters exceeds Tx0.1 second.
0
0
t
Reserved.
M
0
t
Return with up to n bytes when tx0.1 second has expired, or M bytes are available.
0
T
t
Reserved.
M
T
t
Return with up to n bytes when M bytes are available, or tx0.1 second has expired and no characters are received, or at least one byte has been received and the interbyte time between any subsequently received characters exceeds Tx0.1 second.

Device drivers

A Typical QNX device subsystem:

The hardware interface is managed by individual driver processes. Data flows between Dev and its drivers through a set of shared memory queues for each terminal device. Because shared memory queues are used, it is necessary that Dev and all of its drivers reside on the same physical CPU. Three queues are used for each device. Each queue is implemented using a first-in, first-out mechanism. A control structure is also associated with each queue.

Received data is placed into the raw input queue by the driver and is consumed by Dev only when application process request data. Interrupt handlers within drivers typically call a trusted library routine within Dev to add data to this queue. Dev places output data into the output queue; the data is consumed by the driver as characters are physically transmitted to the device. Dev calls a trusted routine within the driver process each time new data is added so it can "kick" the driver into operation. Since output queues are used, Dev implements full write-behind for all terminal devices. Only when the output buffers are full will Dev cause a process to block while writing.

The canonical queue is managed by Dev and is used while processing input data in edited mode. The size of this queue determines the maximum edited input line that can be processes for a particular device. The sizes of all these queues are configurable; the only restriction is that the sum of all three queues can not exceed 64K.

Device drivers simply add received data to the raw input queue or consume and transmit data from the output queue. Dev decides when and if output transmission is to be suspended, how and if received data is echoed, etc. Low-level device control is implemented with a far call into an ioctl entry point within each driver. A common set of ioctl commands are supported by most drivers used directly by Dev. Device-specific ioctl commands can also be sent through Dev to the drivers by QNX processes (via the qnx_ioctl() C function).

The QNX console

System consoles are managed by the Dev.con driver process. The display adapter and the screen, plus the system keyboard, are collectively referred to as the console. The console driver provides a set of cosole-specific functions that let application processes communicate via messages directly to a console driver process. Communication is established with the console_open() C function. Once a communication is established, a QNX process can

Serial devices

Serial communication channels are managed by the Dev.ser driver process. This driver can manage more than one physical channel; it provides terminal devices with names such as /dev/ser1, /dev/ser2, etc. Dev.ser is an example of a purely interrupt-driven I/O server. After initializing the hardware, the process itself goes to slepp. Received interrupts place input data directly into the input queue. The first output character on an idle channel is transmitted to the hardware when Dev issues the first kick call into the driver. Subsequent characters are transmitted by the appropriate interrupt being received.

Parallel devices

Parallel printer ports are managed by the Dev.par driver process. When you start Dev.par, you specify a command-line argument that determines which parallel port is installed. Dev.par is an output-only driver, so it has no input or canonical input queues. Dev.par is a typical example of a completely non-interrupt I/O server. The parallel printer process normally remains RECEIVE-blocked, waiting for data to appear in its output queue and a kick from Dev. When data is available to print, Dev.par runs in a busy-wait loop (at relatively low adaptive priority), while waiting for the printer hardware to accept characters.