Hi Martin,
my gut feeling is that you actually want to do more than just compiling a driver. My feeling is that you want to enable others to actually write a device driver, maybe you are thinking about people capable of writing a device driver for Windows but who have no clue about OS/2.
That said, I'd go with Roderick's hint. Have a look at David's driver library (for 16-bit and also for 32-bit).
Don't use the DDK for these purposes:
1) the DDK is a mess. It is unstructured, things are difficult to find.
2) the DDK mostly relies on the old 16-bit Microsoft C compiler and/or masm.exe, an extremly old Microsoft assembler that can only deal with nothing better than an 386 CPU.
2) I do not recommend to take any of the DDK code as being correct or suitable for SMP systems. Fact is, many of the DDK drivers are VERY old. You cannot rely on that code to work on any modern system, SMP systems in particular.
The only thing that is really necessary from the DDK are the header files as they basically define all of the internal interfaces/structures (as far as things have been made public to begin with).
Unfortunately, even with this info there are things about OS/2 that are really special:
1) a 16-bit driver is, well, 16-bit. For example, if you want to read a 32-bit HW register there is usually a HW requirement to read it as full 32-bits. That will require a minimum of assembler code because you will need to use memory instructions that will move a full 32-bit of data. A 16-bit compiler won't generate these instructions. There are more of these issues.
2) You will need to fumble around with virtual addresses: a selector and an offset. That is what most programmers nowadays will have forgotten about. Then there is the additional difficulty to hop back and forth between virtual addresses, linear addresses (a 32-bit offset in a flat 4 GB address space) and physical addresses. The reason for this most likely will be that virtual addresses can only address a "chunk" of memory <= 64 kBytes. More often than not this is not sufficient. For example, USBEHCD.SYS needs to address 128 kBytes of internal management data structures to make isochronous transfers work (something that you need to make USBAUDIO.SYS work, for example).
Lars