When a service requires the use of your driver, Open Transport will automatically load it and install it into the STREAMS module tables. In order to do this, your module must export a function named either GetOTInstallInfo or GetOT xxxxx InstallInfo (where xxxxx is the name of the module or driver).
install_info* GetOTInstallInfo(void);
This function returns the installation information that Open Transport needs to install the driver into the STREAMS tables, using the following data structure:
structure install_info
{
structure streamtab* install_str;
UInt32 install_flags;
UInt32 install_sqlvl;
char* install_buddy;
void* ref_load;
UInt32 ref_count;
};
Whenever Open Transport loads your module or driver, and the ref_count field of the install_info structure is 0, Open Transport will call an optional initialization function exported by the module. This function must be named either InitStreamModule or Init xxxxx StreamModule (where xxxxx is the name of the module or driver).
Boolean InitStreamModule (void* systemDependent);
If InitStreamModule returns false to Open Transport, then the loading of the module will be aborted and an ENXIO error will be returned to the client. Otherwise, the module will be loaded and installed into a stream.
The systemDependent parameter is a pointer to the cookie value used when registering the port. For drivers loaded using the System registry, its value is RegEntryIDPtr.
If the PCI device supports changing power levels, the InitStreamModule function should set the power level for normal operation.
Whenever Open Transport removes the last instance of a module or driver from the system, it calls an optional termination function exported by the module. This function must be named either TerminateStreamModule or Terminate xxxxx StreamModule (where xxxxx is the name of the module or driver).
void TerminateStreamModule (void);
If the PCI device supports changing power levels, the TerminateStreamModule function should set the power level to low power or no power, as appropriate.
Of course, modules and drivers may also use the initialization and termination features of their DLL technology. Both CFM and ASLM allow initialization and termination routines. However, only a call to InitStreamModule implies that the module is about to be loaded into a stream. Open Transport often loads a module just to call the GetOTInstallInfo information.
All memory allocations that do not use the Open Transport allocation routines ( OTAllocMem and OTFreeMem ) or any interrupt-safe allocators supplied by the interrupt subsystem must be performed from within the initialization and termination routines--that is, PoolAllocateResident and PoolDeallocate may be called only from them.
Once your port driver has been loaded, all communication with it will be through STREAMS messages and the entry points in the streamtab.
Native drivers usually require a DoDriverIO export. Drivers that only support Open Transport do not need this export, and all references to it in the driver documentation may be safely ignored.