I will try to answer your question by taking a step back.
In most OS’s a driver consists of two parts, the OS interface code, and the hardware interface code. The hardware interface code is somewhat independent of the OS being used, but the OS interface code is specific to the OS.
In most OS’s a driver must be run as part of the kernel. The OS and processor protection features enforce this. So the only way to access the hardware is with a driver running as part of the kernel, and this is only available from an application by going through the OS interface.
Things are different with QNX. Drivers are not run as part of the kernel, but run as special applications. By special I mean that they must be run as super user and must also first ask the OS for permission to touch the hardware. The standard OS interface is implemented most easily by using the RM library. This interface can also be used for purposes other than a hardware driver for example a printer driver that converts text into PostScript or PCL.
There are other options. At the lowest level, the RM library consists of messages being passed to and from the driver. You can build your own interface using message passing, sending messages to your driver process and having it do the work for you. Again, this process must be run as super user and must ask the OS for permission to touch the hardware. This can be much simpler than the RM interface however there is not much point. The RM library needs a minimum of code to get started and there are examples available.
Another possibility if only one application process will access the hardware is to build the driver code into this application. You can still separate the driver code by isolating it into separate code modules. In this case, your application must run as super user.
There are a few other situations to consider. If you are writing a disk driver, you could implement an RM, but it would need to provide both hardware code as well as implementing a particular disk format. This is very inconvenient. What if you want the drive to have more than one disk format on it, QNX and DOS for example. The RM would have to handle all of this. Instead, QNX provides a special interface for disk drivers so that all you need to write is the disk interface code.
Another issue has to do with hardware that shares a common hardware interface. Examples are PCMCIA, Cardbus, and USB. QNX provides a generic RM for these interfaces, but additional driver code must be used for each different type of device. For this type of code there are special interfaces and a toolkit to support development.
The last example I’ll mention is network drivers. QNX provides a very flexible interface that allows the separate creation of hardware drivers, protocols, and misc. filters. This too requires a special interface and the related toolkit.