6.13 Shutdown

A session begins when a miniport successfully completes an OID_TAPI_PROVIDER_INITIALIZE request. Within a session, one or more lines can be opened with an OID_TAPI_OPEN request, and on a line, one or more calls can be established by OID_TAPI_MAKE_CALL, OID_TAPI_DIAL, or OID_TAPI_ANSWER requests. During the time a line is up, many calls can be established and then closed or dropped. During a session, one or more lines can go through transitions from open to closed many times. How a miniport handles such transitions is described here.

Closing a Call

An in-process call can be closed either by the local node or by the remote node. The call can be closed on the local node, either because the last application with a handle to the call has closed the handle, or perhaps because the miniport driver’s MiniportHalt or MiniportReset has been called. If the remote node hangs up an in-process call, the miniport must indicate this status change to upper layers.

If an application on the local node closes the call, MiniportSetInformation will be called either with an OID_TAPI_DROP request followed by an OID_TAPI_CLOSE_CALL, or it will simply be called with an OID_TAPI_CLOSE_CALL.

If the miniport receives an OID_TAPI_DROP request, it must do the following:

  1. Drop the call.

  2. Change the status of the call to LINECALLSTATE_IDLE and report the state change by calling NdisMIndicateStatus.

The handles for the dropped call, htCall and hdCall remain valid. The miniport must not deallocate, reuse, or otherwise modify the state associated with the hdCall that it created for the call instance, since the miniport can receive queries related to the call, for instance a request for statistics related to the call. If MiniportHalt or MiniportReset is called, the miniport should disconnect the call but retain the state maintained for the call instance until the miniport receives an OID_TAPI_CLOSE_CALL request.

MiniportSetInformation can also receive an OID_TAPI_CLOSE_CALL request when the last application with an open handle to the call instance closes the handle. The miniport cannot fail this close call request. After MiniportSetInformation returns after processing this request, htCall is no longer valid.

A miniport must be prepared to handle timing issues involving such occurrences as getting an OID_TAPI_CLOSE_CALL before getting an OID_TAPI_DROP. If the miniport gets an OID_TAPI_CLOSE_CALL without a preceding OID_TAPI_DROP, it should behave as if it had received both a drop and a close call request. If the miniport receives a drop after a close call request has already closed the referenced call, the call handle is no longer valid and the miniport should return an appropriate error message.

If the miniport detects that the remote node has dropped the call, the miniport should change the call state to LINECALLSTATE_DISCONNECTED and indicate the change by calling NdisMIndicateStatus passing the htCall for this call instance. After the state change is propagated to the connected application on the local node, the miniport will receive an OID_TAPI_DROP followed by an OID_TAPI_CLOSE_CALL, or perhaps just the OID_TAPI_CLOSE_CALL request. The miniport should handle the drop and close call requests as described earlier.

Closing a Line

A line is closed when the last application with an open handle to the line has closed the handle. When the miniport subsequently receives an OID_TAPI_CLOSE, it should tear down the line instance, that is, any state related to the line maintained by the miniport can be reused or deallocated because the information is no longer valid.

An OID_TAPI_CLOSE call must succeed if the line handle, htLine, passed in the call exists and is still valid. A miniport will never receive an OID_TAPI_CLOSE request for a line if there are calls on the line. All existing calls on a line will be closed with an OID_TAPI_CLOSE_CALL request before the line-close request is made.

Existing calls must be closed when a line is closed; the miniport should drop those calls and clean up their state. The miniport should also change the state of the line to idle. Any handle the miniport has for the line is no longer valid. If the miniport receives any requests which pass the htLine handle or any htCall after the close request is received, such request(s) must be failed with an appropriate status.

Closing a Session

Session termination can be initiated by either the upper layers or a WAN miniport NIC driver. When the last client process has detached from the higher-level Telephony module, the NDISTAPI driver will be informed that it needs to terminate its session with each of the registered adapters. The NDISTAPI driver does this by calling NdisRequest specifying OID_TAPI_PROVIDER_SHUTDOWN. Upon receiving this request, NDISWAN will call the miniport NIC driver’s MiniportSetInformation function, which should terminate any related activities it has in progress on the specified adapter and release any relevant resources.

Driver-initiated session termination can occur when the miniport NIC driver is being unloaded in its MiniportHalt function. Typically, the miniport NIC driver would complete any outstanding NDISTAPI driver requests and notify the NDISWAN that its line devices are going off-line by calling NdisMIndicateStatus. NDISWAN would, in turn, call the NDISTAPI driver to deregister the adapter. If the miniport NIC driver were reloaded again later, it would go through the same initialization process described previously.

The miniport NIC driver might also initiate session termination if it underwent some dynamic reconfiguration that necessitated a complete reinitialization of all clients and drivers. For example, if an adapter’s line-device modeling (for example, the number of line devices supported) was changed on the fly, the miniport would call NdisMIndicateStatus with a LINE_LINEDEVSTATE event and the LINEDEVSTATE_REINIT flag set.