Jump to content

OS/2 Device Driver Frequently Asked Questions: Difference between revisions

From EDM2
Line 88: Line 88:
If you really want to perform I/O on regions greater than 64K, then you should use an IOCTL command to pass in the address of a 32 bit memory item.
If you really want to perform I/O on regions greater than 64K, then you should use an IOCTL command to pass in the address of a 32 bit memory item.


==compiling and building your OS/2 device driver==
==Compiling and building your OS/2 device driver==


===Using the Microsoft C compiler===
===Using the Microsoft C compiler===
Line 142: Line 142:


===Will IBM fix CSet so that it can generate OS/2 device drivers===
===Will IBM fix CSet so that it can generate OS/2 device drivers===
'''Question''':  Will IBM fix CSet so that it can generate OS/2 device drivers
'''Answer''': No, the stated policy on CSet is that it will NOT and NEVER will generate 16 bit code. The reason IBM's CSet people give for this drastic decision, is that there already exist many, many 16 bit 'C' compiler products.
In fact this will all change when OS/2 for Power hits the streets. OS/2 for Power uses a 32 bit driver model so it will be possible to use CSet for drivers in the future.
===Using the CSet compiler to generate 32 bit driver code===
===Using the CSet compiler to generate 32 bit driver code===
'''Question''': How do I use the CSet compiler to generate 32 bit code for linking into a 16 bit device driver.
'''Answer''': This can be done. The security kernel consists of 16 bit assembler code which is linked with 32 bit code emitted by CSet.
There is an example device driver that does this however it is not for the faint hearted. In order to get the code to work you must first supply a (complete) replacement run-time library. The body of the driver is pure 16 bit assembler and the CSet code is bolted onto this.
The way this code is implemented is very specific to the security kernel, however the message is it can be done
===Using Steve Mastriannis example 'C' code.===
===Using Steve Mastriannis example 'C' code.===
'''Question''': I am about to write a device driver for a simple network now. Before starting this I am reading the book "Writing OS/2 2.1 device drivers in C" by Steven J. Mastriani. In this book they write about a C callable 2.0 Devhlp library and a toolkit. About this I have a few questions. I don't have this C callable Devhlp library so I will have to call this function from an assembler routine. My problem is that I can not find any "prototype" of this function anywhere. I suppose these are different for all Devhlp functions. Where do I find this?
'''Answer''': Steve supplies these helper libraries as seperate products. I think the retail price is 129 USD.
There are a number of alternative helper libraries. These can be found in the Devcon DDK product.
It is unfortunate that IBM was not able to standardise on a single library of helper functions. The result is everyone tends to create their own.
===Problem using Microsoft library===
===Problem using Microsoft library===
'''Question''': In S.J.Mastrianni's book (second edition page 498 3rd line from the end and in manyother places) he uses the library "llibcep.lib" from the Microsoft Compiler LIB directory. I did a full instalation of the compiler (Version 6.0A) and I can not find the librery.
'''Answer''': The files installed & their names will vary depending on the installation options you typed in when you ran the MS setup program.
The name
llibcep
  l = represents large memory model
  s = represents small memory model
  e = represents floating point emulation
  7 = represents floating point in 8087 hardware
  p = represents protected mode
  r = represents real mode
One of the installation options asks "use default naming convention" in which case your llibcep.lib file is renamed llibce.lib
To fix it either rename or copy the file to llibcep or modify your link parameters so it uses the "correct" default name of llibce.lib.
===Where are the 16 bit DOS library functions===
===Where are the 16 bit DOS library functions===
'''Question''': I wrote a driver under OS/2 1.3, but now under Warp the linker cannot find the DOS library functions, DosOpen, DosRead etc., where are these functions ?
'''Answer''': These functions used to be in the file DOSCALLS.LIB, this file is no longer shipped with the Warp Toolkit, instead you should use the library OS2286.LIB.
Alternatively you could copy your version of DOSCALLS.LIB from the earlier release to your current development system.


==Initialising the driver for the first time==
==Initialising the driver for the first time==

Revision as of 16:53, 17 June 2012

By Tim Snape

This article contains a selection of frequently asked questions and is intended to be used by anyone who is writing or planning to write OS/2 device drivers.


Support Categories

Situations when it is (un)necessary to write an OS/2 device driver

Is a driver necessary to use IRQs

Question: I have a requirement to intercept hardware interrupts from an adapter. Do I need to write a device driver.

Answer: Yes, a device driver is absolutely the only way to interact with hardware generated interrupts.

Is a driver necessary to access I/O ports

Question: I have a requirement to read and write to I/O ports. Is it necessary for me to write an OS/2 driver.

Answer: No, it is not.

Under OS/2 there are four levels of privilege (referred to as rings)

  • Ring 3 - Least privilege, this is where applications normally reside
  • Ring 2 - Next highest privilege. Code which is running at Ring 2 may access I/O ports under OS/2. For this reason this privilege is often referred to as I/O privilege level or IOPL.
  • Ring 1 - Is not used under OS/2
  • Ring 0 - Is the highest privilege level and is used by device drivers & the operating system.

In order to access an I/O port (and also to disable/enable the interrupt flag) a program MUST be running at ring 2. The way this is done is to specify in the programs definition file that a particular segment will have IOPL (IO privilege).

Next comes the clever bit. The compiler/ling will generate an executable that contains a special (IOPL) code segment. When the program is loaded, the loader will see that there is an IOPL segment & it will create a special mechanism that will allow that segment to run at ring 2.

For the technically knowledgable the loader creates a ring 2 call gate.

When the IOPL segment (containing the I/O access code) is called, privilege is changed to ring 2, and I/O access can be performed.

N.B. There is an overhead in this transition so if you plan to implement a polling loop on an I/O port (or something equally horrible) then be warned.

For some example code that accesses I/O ports go to the file download area.

Is a driver necessary to access memory on an adapter card

Question: I have a requirement to read and write to specific areas in memory in the range D000:0 to D800:0. This is to interface with a special function option card.

There is no time criticality or interrupts to deal with, so writing an OS/2 device driver does seem rather over-the-top.

In DOS, no problem. With MS-Windows, there are Global Selectors pre-defined ( _D000 etc. ).

How can this be done using OS/2.

Answer: At some point you will HAVE to use a driver to access the RAM directly. However it is not necessary to write a driver from scratch. Instead use one of OS/2's drivers to do the job for you.

Failing that, there are a number of drivers written by third parties that will provide you with this function.

I have placed some code in the anonymous ftp area that can be used to access memory directly. Download the Technical Developers Toolkit. The interesting file in the .zip is parallel.c, this contains code that reads the Bios data area used to hold the parallel port addresses.

Accessing Video Ram

Question: I need to access the memory mapped video ram do I need a driver

Answer: There is already support for obtaining addressability in the way you require. I suspect you don't need a device driver. You can access the frame buffer directly, use memory-mapped and port IO from the app level.

A note on the physical memory address space. Your graphics adapter memory can live anywhere above the end of physical memory (RAM) up to the 4Gb limit (0FFFFFFFFh). To see the memory, try as Tim suggested, using the KDB to dump physical memory, %%address.

There is an IOCTl supported by the SCREEN$ device driver for this purpose. You'll need to know the physical address and the aperture size, ie. how much memory the adapter has. See the include file bsedev.h and the definitions for SCREENDD_GETLINEARACCESS. The IOCTl will create and return a linear address which maps to the physical for you to use.

The flags field in the call is critical and one reason I asked what you're writing. They allow you to choose where in OS/2s linear address space the mapping occurs 1) in the current process address space 2) in the shared arena 3) in global space. BTW the flags map directly to those for VMAlloc except the ATTACH bit which causes a DevHlp_ProcessToGlobal.


Application Issues

Accessing IO ports at application level

Question: I have a requirement to access I/O ports from a 32 bit application. I know all about IOPL privilege BUT the only way to create a ring 2 IOPL segment seems to be to use a 16 bit DLL, is this right ?

Answer: Unfortunately yes, there is a more complete explanation of IOPL and accessing I/O ports in the Is a driver necessary section, so I will not repeat it here.

Basically though ring 2 IOPL segments can only be 16 bit, there are however several approaches to solving your problem.

  • Use another driver, one that already exists. The TESTCFG driver contains code that allows you to access I/O port addresses higher than hex 100.
  • Package up your 16 bit IOPL segment into a DLL and call that from your 32 bit code segment.
  • Write a driver from scratch and get the driver to perform the I/O on behalf of the application.
  • Write a driver from scratch and get the driver to set the IOPL bits in the EFLAGS register to 3. This will allow the calling thread to perform I/O at ring 3.

The last (rather neat) suggestion was supplied by Holger Veit. It should be noted that patching the EFLAGS register will only allow the calling thread to access I/O ports.

Read buffers greater than 64K

Question: When performing Read/Write operations can I use data buffers larger than 64K.

Answer: No you cannot. The Read/Write device driver commands have a length field which is a 16 bit word, this implies that the largest I/O operation is 64K.

If you really want to perform I/O on regions greater than 64K, then you should use an IOCTL command to pass in the address of a 32 bit memory item.

Compiling and building your OS/2 device driver

Using the Microsoft C compiler

Question: Should I use the Microsoft C6 compiler & if yes, where can I buy it.

Answer: Back in the old days when IBM & Microsoft were talking to each other, all device drivers were written using Microsoft C compilers. Usually Version 6.00a.

Unhappily following the rift between the two companies Microsoft withdrew support for the C6 product & brought out new versions. These versions were incompatible with OS/2.

Many people today still use the C6 compiler, many examples exist based on the C6 compiler & many companies still recommend using the C6 compiler - but you cannot buy it.

So if you want an easy life use the C6 compiler, how you acquire the tool is the real question. But that cannot be answered here.

If you elect to purchase an alternative C compiler to generate your driver look at the other QA's in this category.


Using the Borland C compiler

Question: How do I use the Borland compiler

Answer: You should refer to Borlands web site for support questions.

Using the Watcom C compiler

Question: How do I use the Watcom compiler version 10.5

Answer: Watcom is a recommended supplier of 'C' compilers for OS/2 device driver developers. IBM development are now widely using the product. The Watcom 'C' compiler comes with sample OS/2 device drivers plus a number of useful utilities. For detailed support information on using the Watcom product you should refer to Watcoms web site.

When using Watcom for the first time you may experience compatibility problems linking to libraries compiled using other products. The following comments assume you are using the dhcalls.lib helper library found in the Devcon DDK

  1. Instead of _acrtused, the Watcom C runtime library looks for cstart_. This should be declared as public in the .asm file.
  2. Watcom provides a special pragma, cdecl, for specifying the calling convention used by MSC. They also provide a _Cdecl keyword, as in 'int _Cdecl main(...);'.
  3. The Watcom naming convention is to append an underscore to function & variable names. Under Microsoft 'C' the convention is to prefix the names with underscore :
 Watcom function name  = name_
 MSC     function name = _name

Therefore all references to Watcom 'C' names from assembler code should assume a trailing underscore. All references to Microsoft 'C' names from assembler code should assume leading underscores. The reverse should be assumed when referencing assembler names from Watcom or MS 'C' code.

  1. The compiler flag -Zu must be used.
  2. The "_Seg16" keyword is not legal when compiling with WCC(Watcom 16bit), therefore in all declarations "_Seg16" must be replaced with "_far". Because of this some of the toolkit headers like OS2DEF.H must be changed.
  3. The "PASCAL" keyword must be changed to "pascal".
  4. There is a library of device driver helper functions, that is callable from Watcom 'C'. This library can be found on the DDK BBS.
  5. The symbol files generated by Watcoms linker are incompatible with the Kernel debugger. If you use Watcom .sym files and the kernel debugger then the system will crash at boot time, with the error message :
 Internal symbol error: SegDefLinkUp

There is a utility for translating Watcom .sym files to the correct format. This utility is called WAT2MAP.EXE and can be found on the DUDE BBS.

  1. The Watcom 'C' compiler is more rigorous in its compliance with the ANSI 'C' standard. This may cause minor problems when porting from other 'C' compilers.

There was an article on porting OS/2 device drivers to Watcom 'C' in the Devcon 7 newsletter.

Please note that according to Watcom technical support, there are some problems with using NMAKE with the Watcom compilers/linkers.

Using the CSet compiler

Question: How do I use the CSet compiler

Answer: You should not. CSet generates 32-bit code this is incompatible with the the 16 bit architecture of OS/2's device drivers.

Will IBM fix CSet so that it can generate OS/2 device drivers

Question: Will IBM fix CSet so that it can generate OS/2 device drivers

Answer: No, the stated policy on CSet is that it will NOT and NEVER will generate 16 bit code. The reason IBM's CSet people give for this drastic decision, is that there already exist many, many 16 bit 'C' compiler products.

In fact this will all change when OS/2 for Power hits the streets. OS/2 for Power uses a 32 bit driver model so it will be possible to use CSet for drivers in the future.

Using the CSet compiler to generate 32 bit driver code

Question: How do I use the CSet compiler to generate 32 bit code for linking into a 16 bit device driver.

Answer: This can be done. The security kernel consists of 16 bit assembler code which is linked with 32 bit code emitted by CSet.

There is an example device driver that does this however it is not for the faint hearted. In order to get the code to work you must first supply a (complete) replacement run-time library. The body of the driver is pure 16 bit assembler and the CSet code is bolted onto this.

The way this code is implemented is very specific to the security kernel, however the message is it can be done

Using Steve Mastriannis example 'C' code.

Question: I am about to write a device driver for a simple network now. Before starting this I am reading the book "Writing OS/2 2.1 device drivers in C" by Steven J. Mastriani. In this book they write about a C callable 2.0 Devhlp library and a toolkit. About this I have a few questions. I don't have this C callable Devhlp library so I will have to call this function from an assembler routine. My problem is that I can not find any "prototype" of this function anywhere. I suppose these are different for all Devhlp functions. Where do I find this?

Answer: Steve supplies these helper libraries as seperate products. I think the retail price is 129 USD.

There are a number of alternative helper libraries. These can be found in the Devcon DDK product.

It is unfortunate that IBM was not able to standardise on a single library of helper functions. The result is everyone tends to create their own.

Problem using Microsoft library

Question: In S.J.Mastrianni's book (second edition page 498 3rd line from the end and in manyother places) he uses the library "llibcep.lib" from the Microsoft Compiler LIB directory. I did a full instalation of the compiler (Version 6.0A) and I can not find the librery.

Answer: The files installed & their names will vary depending on the installation options you typed in when you ran the MS setup program.

The name

llibcep
  l = represents large memory model
  s = represents small memory model
  e = represents floating point emulation
  7 = represents floating point in 8087 hardware
  p = represents protected mode
  r = represents real mode

One of the installation options asks "use default naming convention" in which case your llibcep.lib file is renamed llibce.lib

To fix it either rename or copy the file to llibcep or modify your link parameters so it uses the "correct" default name of llibce.lib.

Where are the 16 bit DOS library functions

Question: I wrote a driver under OS/2 1.3, but now under Warp the linker cannot find the DOS library functions, DosOpen, DosRead etc., where are these functions ?

Answer: These functions used to be in the file DOSCALLS.LIB, this file is no longer shipped with the Warp Toolkit, instead you should use the library OS2286.LIB.

Alternatively you could copy your version of DOSCALLS.LIB from the earlier release to your current development system.

Initialising the driver for the first time

Start of operations

Using Request Packets

A collection of commonly asked questions about the IOCTL interface

Defining and Using Semaphores

How the stack works

Using DMA

Defining and Using memory

32 Bit issues compiling/linking/running

How time works

Using interrupts

Shutting down OS/2 gracefully

What differences are there between the versions of OS/2

Debugging tips, tricks and treats

A collection of tools & information on tools for device driver authors

General useful information and support

Other sources of information and support

Download