The information in this section describes a HAM's major functional procedures and their main flow of events. The information provided in this section helps to add functionality to a HAM program shell and covers the following topics:
The following figure outlines the HAM registration process:
Figure 3-1 HAM Initialization
Loading of the HAM can be initiated in multiple ways:
Figure 3-1 shows the sequence of events for initializing and registering a HAM at load-time.
When a HAM is loaded, the OS calls the HAM's HAM_Load entry point passing it loadHandle, screenID, and commandLine as input parameters. HAM_Load is responsible to perform the following (see Figure 3-1):
The HAM registers its module by calling NPA_Register_HAM_Module. This API sets up the general environment necessary for the HAM to become operational and makes it possible for the HAM to allocate and register any resources it may need.
Within the context of NPA_Register_HAM_Module, HAM's npaHandle is assigned a value, and that the following HAM entry points get registered with NWPA:
NOTE:If the HAM supports multiple adapters, it should call NPA_Register_HAM_Module for each instance it supports. This API accepts a HAM-generated instance number as an input parameter. This instance number should correspond to the adapter card instance being supported by the HAM. A separate instance number is necessary to register different hardware options for each adapter.
The HAM can check the host bus type by calling NPA_Return_Bus_Type. The HAM can then verify that the bus type is compatible with the type it supports.
If the HAM is NBI-aware and is supporting an adapter designed for a bus architecture that provides configuration information on a per-slot basis, (such as EISA, MCA, PCI, PnPISA), do the following:
Repeat Steps b and c for each product ID whose hardware exists in your system.
During the context of NPA_Parse_Options, HAM_Check_Option is repeatedly called (for each product ID), passing it the option structure with output parameters as follows:
For each adapter instance found, HAM_Check_Option stores the return information in a configuration table for use later. The Product_ID option doesn't need to be registered. Parsing of this option is done only to obtain the slot value for the next step.
i. Build a Slot Option (type 0x0005) structure.
ii. Add the Slot Option using NPA_Add_Option
iii. Parse the option using NPA_Parse_Options.
NPA_Parse_Options calls the HAM's HAM_Check_Option function. During the context of this HAM function, NWPA passes the slot that was selected by the user in the NPAOptionStruct structure.
iv. Register the slot option using NPA_Register_Options.
The slot that was specified during the proceeding Step iii is then registered (if HAM_Check_Option returned 0) during this function.
If a SLOT= option matching one of the elements in the HAM's configuration table is present on the command line, the HAM calls NPAB_Get_Card_Config_Info passing it the bus tag and unique ID given during the parse of the Product ID option. This routine returns the bus-specific configuration information associated with the target adapter. Use these to create the list of desired options.
HIN awareness is required for PCI, EISA, PnPISA, MCA, and PCMCIA adapters.
iv. Register the Slot Option by calling NPA_Register_Options.
Options are command line keywords that set operational states, or specify hardware resources such as interrupts, DMA channels, ports, memory decoding, and custom parameters.
For each of these applicable resources, the HAM creates a select-list by filling out an instance of an NPAOptionStruct with flags set to USE_THIS_OPTION and parameter2 = busTag (if NBI aware) and calling NPA_Add_Option.
During the context of NPA_Add_Option, the NPA copies the option information and constructs a "select-list" of valid options for the HAM and adapter.
To completely build the option list, the HAM should iteratively fill out the NPAOptionStruct instance and call NPA_Add_Option for each option type it desires. Since NWPA maintains its own copy of option information in constructing the select-list, the HAM can reuse the same NPAOptionStruct instance for each call to NPA_Add_Option.
For hardware resource options, if NPA_Add_Option returns a non-zero value, it indicates that the option is already reserved and NWPA does not add the option to the HAM's select-list.
The HAM calls NPA_Parse_Options to cause NWPA to match options specified on the command line with those in the HAM's select-list. In turn, NPA_Parse_Options iteratively calls the HAM's HAM_Check_Option entry point for each match it finds. HAM_Check_Option either accepts or rejects the selected option. Each time HAM_Check_Option accepts an option, NWPA places it on a use-list.
If there is an option on the command line that does not match anything in the HAM's select-list, it is ignored. However, if after parsing the command line NWPA finds residual options in the HAM's select-list, it either prompts the user for the options or discards them depending on the bits set in the flags field of each option's NPAOptionStruct.
Hardware options are not physically registered during the context of NPA_Parse_Options. Therefore, the HAM should not try to physically access a resource when its HAM_Check_Option entry point is called during this context.
The HAM registers the parsed options (options specified in its use-list) by calling NPA_Register_Options. This API accepts the instance number introduced in the note after step 1. NPA_Register_Options uses this number to associate the group of options being registered with a particular instance of an adapter managed by the HAM.
NPA_Register_Options physically registers the hardware resources in the use-list, making them available to the HAM. Also, similar to the parse phase in step 4, NPA_Register_Options iteratively calls the HAM's HAM_Check_Option entry point for each registered option, this time allowing the HAM to physically verify the resource or set internal flags to set an operational mode.
Another reason why HAM_Check_Option gets called during option registration is to provide the HAM with return information pertinent to the option. For example, the memory decode option (type 0x0004) that pages in memory-mapped I/O space to the system returns a logical address to the HAM. This type of return information is given to the HAM through HAM_Check_Option when it is called under the context of NPA_Register_Options. The actual information is found in the parameter2 field of the NPAOptionStruct pointed at by the entry point's option input parameter.
NOTE:Steps 2 - 5 describe the general paradigm for registering hardware and configuration options. For more detailed information and actual registration examples, refer to NPAOptionStruct
The HAM allocates any memory buffers it may need by calling NPA_Allocate_Memory.
The HAM schedules its timeout routine, HAM_Timeout, by calling NPA_Spawn_Thread. The HAM will use this routine to recover from a hung-device condition. HAM_Timeout monitors the elapsed time of a HACB request as specified in the HACB's timeoutAmount field.
NPA_Spawn_Thread creates a thread that is executed once. If the thread is to be executed again, as in a timeout, it must be spawned again within the routine by calling NPA_Spawn_Thread.
The HAM must ensure that it is operational and ready to accept HACB requests before going to step 10.
The HAM calls HAI_Activate_Bus to activate an instance of a host bus. This API requires an exchange of handles that identify the bus instance. The HAM passes a unique handle (hamBusHandle) it generates to identify the bus instance as an input parameter. Then, NWPA returns its own unique handle (npaBusHandle) it will use to identify the bus instance as an output parameter. The HAM must call HAI_Activate_Bus for each bus instance it will manage.
If the HAM loaded successfully, HAM_Load should return zero. If the load was unsuccessful, it should do the following:
WARNING:NPA_Unregister_Module will unregister all instances of this module and abort all pending I/O for this HAM. If other instances are to remain active, do not make this call. Use Instance Unload to unload a single instance (see Section 5.2, Unloading a Specific Instance of a HAM).
If at any time during initialization and registration an uncorrectable error occurs, the HAM must return its resources and back out from the point it reached. For example, if the bus type returned in 2 is not compatible with what the HAM supports, the HAM only needs to call NPA_Unregister_Module to error out. If the HAM progressed as far as step 6 in the sequence, then the HAM would need to return memory, unregister options, and then unregister the module.
After the HAM is loaded and registered with the OS, it must be ready to receive the following sequence of hacbType = 0 requests:
The first request, HAM_Return_Bus_Info (Function 0x00), is initiated by NWPA so that it can get HAM-specific information and add the HAM to its object database.
The second request, HAM_Scan_For_Devices (Function 0x01), is either initiated from NWPA and OS or by the systems operator at the console. This HAM function spawns a blocking thread, using NPA_Spawn_Thread, that performs a host bus scan for attached devices. The spawned thread builds the HAM's device list, creates a unique deviceHandle for each device, and fills out an instance of a DeviceInfoStruct for each device.
The third request, HAM_Return_Device_Info (Function 0x02), is initiated by NWPA so that it can get device-specific information and add an object for each device to its database. NWPA initiates a find-first-find-next sequence of these requests until information about each device is returned. The return information for each request is in a form defined by the DeviceInfoStruct.
The HAM receives the above sequence of requests for each bus instance it registered at load-time using HAI_Activate_Bus.
The following figure outlines the process for HACB I/O requests:
Figure 3-2 HACB I/O Request Flow
HAM_Execute_HACB is the HAM's entry point for receiving and executing HACB I/O requests, and it has non-blocking context except for HAM_Instance_Unload (Function 0x09)). This entry point is registered with NWPA during NPA_Register_HAM_Module. The following steps show the sequence of events for processing a HACB I/O request:
The HAM identifies the target bus instance based on the value contained in the hamBusHandle input parameter. The HAM originally generated this hamBusHandle value and registered it for the bus instance using HAI_Activate_Bus at load-time.
If the HAM is managing only one host bus, the value in the hamBusHandle input parameter is the same for all requests.
If the HAM is managing multiple buses (when the adapter supports more than one bus or the HAM is managing multiple buses spanned over multiple adapters), the hamBusHandle value is unique to each bus instance.
The HAM identifies the target device based on the value contained in the deviceHandle field of the HACBStruct instance pointed at by the HACB input parameter.
The HAM originally generated this deviceHandle value during the scan thread scheduled by HAM_Scan_For_Devices (Function 0x01) and reported it to NWPA during HAM_Return_Device_Info (Function 0x02).
If the adapter can immediately accept the request, the HAM should translate the HACB request information into a protocol-specific command block, issue the request to the adapter, and then return to the calling process.
NWPA expects the HAM to provide a queue for each device it manages.
If a request cannot be immediately issued to the adapter during the context of HAM_Execute_HACB, the HAM must place the request in the target device's queue and return to the calling process. The HAM must pull requests from the queue and execute them at another time during another thread.
For a detailed specification on device queue behavior and how it affects HAM_Execute_HACB, see Queue State.
The HAM must provide the logic to determine which of the adapters it is managing caused the interrupt.
If the HAM's adapter does DMA or bus-mastering, the ISR is not concerned with physical data transfer because the transfer buffer was specified when the request was issued to the adapter. However, for host buses that rely on programmed I/O, the ISR needs to perform the transfer. The HACB provides both the virtual (logical) and physical (absolute) addresses of the request's I/O buffer. These addresses are found in the HACB's vDataBufferPtr and pDataBufferPtr fields, respectively.
After the request is complete, HAM_ISR must post the HACB's completion status to its hacbCompletion field. Valid completion status values are listed in Section 11.1, HACB Completion Codes under the description of the hacbCompletion field. These status codes can reflect successful completion of the request, or they can reflect HACB and/or device errors. For processor-independence reasons, this field must be processed as a LONG. Manipulation of its contents can be done arithmetically using macros such as SET_STATUS. The HAM can post HACB completion using the SET_STATUS macro, defined below:
#define SET_STATUS(UpperWord, LowerWord)((UpperWord)<< 16) | ((LowerWord)& 0xFFFF))
|
|
|
The device's queue must remain frozen until either the HAM receives a HAM_Unfreeze_Queue (Function 0x03) for that device, or it receives a priority HACB request for that device. Additionally, the low-order 31 bits of the hacbCompletion field must remain intact to the value set in the third bullet in step d above. This value indicates the type of error that occurred.
HAM_ISR has other responsibilities regarding the device queue. For a detailed specification on device queue behavior and how it affects HAM_ISR, see Queue State.
The following figure outlines the process of HACB abort requests:
Figure 3-3 Aborting a HACB Request
HAM_Abort_HACB is the HAM's entry point for aborting I/O requests, and it has non-blocking context. This entry point is registered with NWPA during NPA_Register_HAM_Module. The following shows the sequence of events for aborting a HACB request.
NWPA calls HAM_Abort_HACB passing it hamBusHandle, a pointer to a HACB, and flag as input parameters.
HAM_Abort_HACB does the following:
The HAM identifies the target bus instance based on the value contained in the hamBusHandle input parameter. The HAM originally generated this hamBusHandle value and registered it for the bus instance using HAI_Activate_Bus at load-time. From this hamBusHandle, the HAM should be able to access its device list for the target bus instance.
NWPA passes a pointer to the HACB that is to be aborted, which the HAM uses to locate the associated request.
HAM_Abort_HACB has three possible actions depending on the value of the flag input parameter passed by NWPA.
If the HACB is still in the device queue (clean abort case):
|
If the HACB is currently being processed by the device (dirty abort case):
|
If the HACB is still in the device queue (clean abort): |
|
If the HACB has already been sent to the device, returns -1 to notify NWPA that the HACB could not be cleanly aborted. The device queue continues to operate normally. |
The results of step 4 will abend the server. The HAM must keep track of HACB requests it receives.
The following figure shows the process for deregistering at unload time:
Figure 3-4 Deregistering Unload-Time
Unloading of the HAM is initiated by the systems operator at the server console. The following steps show the sequence of events at unload-time.
HAM_Unload_Check calls NPA_Unload_Module_Check, which checks NWPA's database and returns the status of each device attached to the adapter. HAM_Unload_Check returns the use-status from NPA_Unload_Module_Check.
NPA_Unload_Module_Check issues a warning message to the console for each device that is locked. Current I/O to these devices will halt if the HAM is unloaded, and the devices will be deactivated.
A return value of zero indicates that none of the HAM's devices are in use. A return value greater than zero indicates that one or more of the HAM's devices are in use.
The OS calls the HAM's HAM_Unload entry point with blocking context, and it does the following:
HAM_Unload terminates I/O to the HAM by calling HAI_Deactivate_Bus immediately upon entry. It is during the context of this API that the NLM application is notified that its link to the device is about to be severed. Therefore, the HAM must remain operational and process requests until HAI_Deactivate_Bus returns control. Once this happens, the HAM is guaranteed not to receive any more HACB requests for that bus instance. HAM_Unload must call HAI_Deactivate_Bus for each bus instance being managed by the HAM.
Verifies that all outstanding HACBs, if any exist, are canceled with the appropriate completion code described in Section 11.1, HACB Completion Codes. This action is really a preventative measure. All of these outstanding HACBs have been aborted during the context of HAI_Deactivate_Bus. |
Cancels all asynchronous events, such as timeout handlers, timers, etc., by calling NPA_Cancel_Thread on each event. |
Returns memory to the system pool by calling NPA_Return_Memory. Do not call NPA_Unregister_Options at unload time. NWPA resolves hardware unregistration issues within the call NPA_Unregister_Module. If called during unload, resources are unregistered even in a software hot replace condition. The driver then fails. |
Unregisters the module using NPA_Unregister_Module. |