The Device Manager sends kInitializeCommand and kFinalizeCommand commands to a native driver as its first and last commands. The kInitializeCommand command gives the driver startup information; the kFinalizeCommand command informs the driver that the system would like to unload it.
A typical framework for a generic driver handler for Device Manager finalization and CFM initialization and termination commands is shown in Listing 8-3.
Listing 8-3 Initialization, finalization, and termination handlers
refNum gMyReferenceNumber;
RegEntryID gMyDeviceID;
OSErr DoInitializeCommand
( refNum myRefNum, regEntryIDPtr myDevice )
{
/* remember the refNum and Registry entry spec */
gMyReferenceNumber = myRefNum;
gMyDeviceID = *myDevice;
return noErr;
}
OSErr DoFinalizeCommand
( refNum myRefNum, RegEntryIDPtr myDevice )
{
#pragma unused ( myRefNum , myDevice )
return noErr;
}
CFMInitialize ()
{
return noErr;
}
CFMTerminate ()
{
return noErr;
}
The driver's initialization routine should perform the following functions:
Listing 8-4 Enabling PCI spaces
OSErr InitPCIMemorySpace (RegEntryIDPtr DeviceID,
LogicalAddress addr )
{
UInt16 cmdWord;
OSErr status;
status = ExpMgrConfigReadWord (DeviceID,addr,&cmdWord );
if ( status != noErr )
return status;
cmdWord |= cwCommandEnableMemorySpace |
cwCommandEnableIOSpace;
return ExpMgrConfigWriteWord (DeviceID,addr,cmdWord );
}
OSErr ProbePCIMemorySpace ( LogicalAddress addr )
{
UInt8 ctest3;
OSErr status;
status = DeviceProbe(
(void *) (((UInt32)addr) + CTEST3),
&ctest3,
k8BitAccess
);
if ( status != noErr )
return status;
}
The initialization code should also allocate any private storage the driver requires and place a pointer to it in its global variables. After allocating memory, the initialization routine should perform any other preparation required by the driver. If the handler fails to allocate memory for private storage, it should return an appropriate error code to notify the Device Manager that the driver did not initialize itself.
If the Open Firmware FCode in the device's expansion ROM does not furnish either a "driver,AAPL,MacOS,PowerPC" property or a unique name property, or if the driver's PCI vendor-id and device-id properties are generic, then the initialization routine must always check that the device is the correct one for the driver. If the driver has been incorrectly matched, the initialization routine must return an error code so the Device Manager can attempt to make a match. Driver matching is discussed in Matching Drivers With Devices. PCI vendor-id and device-id properties are discussed in Finding, Initializing, and Replacing Drivers
The driver's finalization routine must reverse the effects of the initialization routine by releasing any memory allocated by the driver, removing interrupt handlers, and canceling outstanding timers. If the finalization routine cannot complete the finalization request, it can return an error result code. In any event, however, the driver will be removed.
If the initialization routine needs to install an interrupt handler, see the discussion in Interrupt Management.
Initialization, finalization, and termination calls are always immediate.