[ Next ] [ Previous ] | Chapter 8 | [ Contents ] [ Chapter 7: Exception Handling ] [ Chapter 9: Introduction to Windows ]

### 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:

1. Serialization / synchronization controls are built into the driver.
2. All OS/2 device drivers are interrupt driven.
3. It provides a well-defined interface for upward OS/2 migration.
4. 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.

[ Next ] [ Previous ] | Chapter 8 | [ Contents ] [ Chapter 7: Exception Handling ] [ Chapter 9: Introduction to Windows ]