Interfacing with OS/2 Devices
The current OS/2 architecture supports three types of device drivers:
-
Virtual device drivers (VDD)
-
Physical device drivers (PDD)
-
Presentation drivers (PD)
VDDs are used primarily by the legacy DOS and Windows applications. The
virtualization of the physical devices provides OS/2 with the ability to
control the access to these devices through the Virtual Device Driver.
An example of a VDD is a VMOUSE.SYS or a VCDROM.SYS. The first one provides
the virtual support for the mouse pointer requirements, while the latter
one makes sure the CD ROM interfaces for the DOS and Windows applications
are supported correctly.
The PD concerns itself mainly with 0S/2's Presentation Manager support.
PDs usually run at Ring 2 or Ring 3. and enable the Presentation Manager
(PM) APIs to perform all of the necessary video functions. These include
all aspects of the PM windowing, messaging, and controlling requirements.
The PDDs provide the OS/2 user with the actual access to the standard
I/0 devices. A PDD usually has a corresponding VDD, which allows the same
functionality for the DOS and Windows legacy applications. The PDDs and
VDDs are loaded at system startup and remain loaded for the entire duration
of an 0S/2 session. PDD architecture also provides OS/2 the flexibility
to add non-standard device support just by loading the appropriate device
driver at startup time. There are two kinds of PDDs: block device driven
and character device drivers.
A SCSI (Small Computer Systems Interface) driver is a type of block
device driver. This driver manipulates the data in blocks of a certain
size, and is referred to by the system via a drive letter. A good
example of a PDD is the serial I/O device driver. But many character and
block device drivers make up the device driver suite for OS/2.
This chapter offers two examples of how to talk to the serial devices
under 0S/2's control. The first example utilizes the preferred device driver
interface DosDevIOCtl(), while the second shows how to get to I/O ports
without having to talk to the device driver.
There are obvious advantages for using the device driver interface:
-
Serialization / synchronization controls are built into the driver.
-
All OS/2 device drivers are interrupt driven.
-
It provides a well-defined interface for upward OS/2 migration.
-
Devices can be shared by multiple users.
Generally, the OS/2 applications gain access to the devices through the
IOCTL interface, while the DOS applications can perform the same I/O functions
that are allowed under real DOS (not VDM). Only 16-bit OS/2 code can run
at Ring 2 privilege level, which allows the code direct I/0 access (IOPL
- means I/O Privilege Level). Occasionally
it is advantageous to use the IOPL code to perform a quick read or a write
from or to a particular I/O port, but it is not the preferred OS/2 method.
For example, if an application is monitoring room temperature and displays
it on the screen, writing a full-blown device driver to access a particular
I/O port on some adapter just to read two bytes of data may not make sense.
In this case it is easier to utilize a 16-bit I/0 code segment to perform
an IN (Input from Port) instruction and read the temperature data. Synchronization
and serialization do not have to be worried about. On the other hand ,
if the program reads the temperature and then decides to adjust the environmental
conditions, a device driver must provide serialization and locking controls.
Serial Interface Example Using DosDevIOCtl
The first of the two serial I/O examples deals with reading the data from
the keyboard and transmitting all of the keystrokes to the Ox3F8 I/O port
(COM 1).
In order to gain access to the COM1, DEVICE=COM.SYS must be executed
correctly at system startup and COM.SYS must be loaded, Next, a DosOpen
call is issued to the device driver with "$COM1" as the filename. The system
is smart enough to recognize the fact that the user is looking to gain
access to the COM1 I/O port; if no other program is using the device,
the file handle for the COM1 device is granted. Using this file handle
the process can now issue any DosDevIOCtl call with the appropriate
asynchronous parameters to gain access to the control functions of the
NS 8250/16450/16550 UARTs. Issuing DosRead and DosWrite
requests to the system using the same file handle results in the data being
transferred between the application buffers and the hardware UART.
The program uses the main thread to perform all of the keyboard read
functions. The characters read are transmitted immediately to the COM1
I/O port via DosWrite function. However, a separate
thread is used to read the data from COM1 and display it on the screen.
Since the device driver is capable of processing both the read and the
write requests simultaneously, a better-designed communications program
will dedicate a thread for each major function, such as read or write.
32_TERM.C
32_TERM.MAK
32_TERM.DEF
The COM.SYS expects the following to be true:
COM1 |
Must reside at 0x3F8 and use the interrupt level 4. |
COM2 |
Must reside at 0x2F8 and use the interrupt level 3. |
The COM.SYS driver provides support for the UART control functions and
the RS232C interface only. No specific devices are supported directly by
the COM.SYS driver. It is left up to the applications to create subsystems
or standalone programs to support the RS232C devices (modems and the like).
The COM.SYS is a fully interrupt driven driver and has support for extended
hardware buffering that is offered by the NS 16550 UARTs.
The PDD utilizes a memory buffer between the operating system and the
UARTs, and data is copied in and out of the buffer from and to the UART
transmit/receive registers. Once the user has obtained the file handle
for a particular I/O port (COM1, COM2, etc.), he or she can use this handle
to issue DosRead and DosWrite requests
to move the data between an application and an I/O port. Currently, the
system maintains a 1,024-byte receive and a 128-byte transmit buffer for
the COM1-COM4 I/O ports when the driver is in the non-DMA mode. When the
driver is in the enhanced DMA mode, there are two 1,024 receive queues
and one 255-byte transmit queue. OS/2 does not guarantee that the sizes
will remain constant with each version of the operating system, and thus
the sizes are subject to change. The operating system also does not guarantee
packet delivery to the device drivers in the same order that they were
issued by the application due to the multitasking nature of OS/2.
Serial Interface Example Using inp
The second example is much simpler than the first. As was mentioned before,
only 16-bit code is allowed to execute with IOPL flag enabled. Taking this
into consideration we can create a very handy 16-bit DLL like 16BITIO.DLL
that exports the inp(), inpw(), outp(), and outpw()
calls. Any 32-bit application can link with the import 16BITIO.LIB library
and allow direct I/O functionality. This particular example uses a very
simple algorithm to check for the presence of an NS l6550 UART by issuing
a series of inp() and outp() calls
to the particular COM1 and COM2 I/O port ranges.
CHK16550.C
CHK16550.H
CHK16550.MAK
CHK16550.DEF
16BITIO.C
16BITIO.MAK
16BITIO.DEF
The. ASYNC PDD is covered in much greater detail in the IBM Physical
Device Driver Reference manual (10G6266), which is
part of the OS/2 Toolkit Technical Library.