Portability


An OS/2 MIDI Device Driver

Carl M. Benda


Mr. Benda is a programmer in the Charlotte Lab of the Services Sector Division of IBM. He holds an MS in computer science from the University of North Carolina - Charlotte, and an MS in materials engineering from Worcester Polytechnic Institute.

The market currently offers many excellent software packages that include device drivers for the MPU-401, the standard PC Musical Instrument Digital Interface (MIDI). Almost all of the packages, however, run under MS-DOS, while almost none runs under OS/2. No commercial driver interface at the time of this writing is available for OS/2 2.0. (The 32-bit version of OS/2 currently in beta-test.) This article partially fills the gap by describing a simple device driver written mostly in C for handling interrupt-driven I/O to and from the Roland MPU-401.

Writing Device Drivers For OS/2

There are several reasons why so few commercial MIDI device drivers exist for OS/2. First, OS/2 drivers are more complex than their MS-DOS counterparts. To understand OS/2 device drivers, it is necessary to look at the structure of the operating system and see where the device driver fits into the operating system (Figure 1) .

In MS-DOS, any program can read and write to any portion of the RAM, whereas in OS/2, device drivers are required to handle hardware addresses and interrupt handling. OS/2 device drivers exist in a multitasking environment and so must handle requests from multiple processes and threads of execution within a single process. Before the driver can complete a request from one process, it may have to handle additional requests from a different process.

OS/2 device drivers also have the special responsibility of being well behaved in terms of not disrupting other portions of the system. Since drivers run at the RING 0 execution level, they have ultimate access to all of the system's memory and resources. If an OS/2 device driver does not have a proper initialization routine, the system will crash at boot time.

OS/2 device drivers in most implementations consist of two segments. The first segment is for data, and the second is for code. This scheme presents two problems when writing the code for the device driver entirely in C.

First, the C compiler for OS/2 puts the code segment first in the program and the data segment last. An OS/2 device driver, however, must have the data segment first in the program. In this data segment, the first item must be the device header. The device header contains startup information that is critical to how the operating system treats that device driver. Second, it is necessary to prevent the C compiler from inserting the C startup code before the device header. I accomplish this by linking in a small assembly language function.

Implementing The Device Driver

This article presents all the necessary pieces for generating a MIDI device driver. This OS/2 device driver handles interrupts from the Roland MPU-IMC, which is a PS/2 Micro Channel adapter card that generates interrupts using IRQ 9. When the card generates an interrupt, the device driver gathers the information from the adapter's addresses: 0x331h for the commands and status, and 0x330h for any data bytes coming from other MIDI devices. From these addresses the device driver places the data into a shared memory buffer that may be accessed by an application program.

The assembly code in Listing 1 serves as the startup code to replace the C compiler's normal startup code. The remaining portions for a minimal MIDI OS/2 device driver appear in Listing 2, Listing 3, Listing 4, and Listing 5.

The OS/2 device driver must be linked with a definitions file which has the name of the MIDI library as the entry point into the device driver. For this device driver, a definitions file would contain the lines

LIBRARY MIDI
PROTMODE
The OS/2 config.sys file must reference the subdirectory and filename of the device driver so that at boot time, the OS/2 kernel can load the device driver and run the Init routine.

OS/2 is much like DOS in the way it handles interrupts. When the hardware generates a level 9 interrupt, the operating system immediately runs the code entry point named by the SetIRQ routine. Thus OS/2 responds to the hardware in more of a real-time fashion.

Conclusion

The next logical step from this device driver would be to write an application that uses its interface.

Sidebar: "MIDI Data Management"