windows-nt/Source/XPSP1/NT/drivers/wdm/usb/driver/selsusp/selsusp.htm
2020-09-26 16:20:57 +08:00

195 lines
9.9 KiB
HTML

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-
1252">
<META NAME="Generator" CONTENT="Microsoft FrontPage 5.0">
<TITLE>Selective Suspend</TITLE>
</HEAD>
<BODY LINK="#0000ff">
<p><b><font face="Times New Roman">The Selective Suspend driver</font></b></p>
<ul>
<li><font face="Times New Roman">The selective suspend driver is a generic function driver based on the
Windows Driver Model (WDM).</font></li>
<li><font face="Times New Roman">Supports Plug and Play(PnP), Power
Management(PM), Windows Management Instrumentation (WMI) and the Selective
Suspend (SS) features.</font></li>
<li><font face="Times New Roman">The support for PnP, PM and the WMI feature
is essential for any driver based on the WDM model.</font></li>
<li><font face="Times New Roman">The SS feature, described in detail later, is
a new feature in the core USB stack.</font></li>
</ul>
<p><font face="Times New Roman"><b>Plug and Play</b></font></p>
<ul>
<li><font face="Times New Roman">The Plug and Play system allows for dynamic
recognition of installed hardware and configuration of resources.</font></li>
<li><font face="Times New Roman">The selective suspend driver (function
driver) registers a dispatch routine to receive and process PnP requests
from the PnP manager.</font></li>
<li><font face="Times New Roman">In the dispatch routine, the driver examines
the minor function of the PnP requests and delegates them for further
processing. <br>
Please refer the Windows XP DDK docs and the Toaster sample in the DDK to
understand the kernel-driver responsibilities and handling of PnP requests.</font></li>
<li><font face="Times New Roman">The selective suspend driver has the
following delegate-routines to process the PnP requests.</font></li>
</ul>
<table border="1" width="65%">
<tr>
<td width="46%"><font face="Courier New">IRP_MN_START_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleStartDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_QUERY_STOP_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleQueryStopDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_CANCEL_STOP_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleCancelStopDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_STOP_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleStopDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_QUERY_REMOVE_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleQueryRemoveDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_CANCEL_REMOVE_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleCancelRemoveDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_SURPRISE_REMOVAL</font></td>
<td width="54%"><font face="Courier New">HandleSurpriseRemoval()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_REMOVE_DEVICE</font></td>
<td width="54%"><font face="Courier New">HandleRemoveDevice()</font></td>
</tr>
<tr>
<td width="46%"><font face="Courier New">IRP_MN_QUERY_CAPABILITIES</font></td>
<td width="54%"><font face="Courier New">HandleQueryCapabilities()</font></td>
</tr>
</table>
<p><font face="Times New Roman"><b>Power Management</b></font></p>
<ul>
<li>The power manager is the global power-policy owner for the system and the
devices.</li>
<li>The selective suspend driver registers a dispatch routine to receive and
process power requests.</li>
<li>In the dispatch routine, the driver examines the minor function of the
power requests and delegates them for further processing.</li>
<li>Please refer the Windows XP DDK docs and the Toaster sample in the DDK to
understand the kernel-driver responsibilities and handling of power requests.</li>
</ul>
<table border="1" width="64%">
<tr>
<td width="50%"><font face="Courier New">IRP_MN_QUERY_POWER(SystemPowerState)</font></td>
<td width="50%"><font face="Courier New">HandleSystemQueryPower()</font></td>
</tr>
<tr>
<td width="50%"><font face="Courier New">IRP_MN_QUERY_POWER(DevicePowerState)</font></td>
<td width="50%"><font face="Courier New">HandleDeviceQueryPower()</font></td>
</tr>
<tr>
<td width="50%"><font face="Courier New">IRP_MN_SET_POWER (DevicePowerState)</font></td>
<td width="50%"><font face="Courier New">HandleDeviceSetPower()</font></td>
</tr>
<tr>
<td width="50%"><font face="Courier New">IRP_MN_SET_POWER (SystemPowerState)</font></td>
<td width="50%"><font face="Courier New">HandleSystemSetPower()</font></td>
</tr>
</table>
<p><b>Remote Wakeup capability</b></p>
<p>The selective suspend driver supports the remote wakeup capability. The
routines which implement this capability are:<br>
<font face="Courier New">IssueWaitWake()<br>
WaitWakeCallback()<br>
WaitWakeCompletionRoutine()</font></p>
<ul>
<li>After the device is configured and is in a D0 power state, the selective
suspend driver requests an <font face="Courier New">IRP_MN_WAIT_WAKE</font>
request for the device - <font face="Courier New">IssueWaitWake</font>. </li>
<li>A pointer to the callback function in the driver, <font face="Courier New">WaitWakeCallback</font><font face="Times New Roman">,</font>
is passed along this request. </li>
<li>The wait-wake request is sent to the PDO for the driver. </li>
<li>When this request is received by the selective
suspend driver , the dispatch routine sets a completion routine, <font face="Courier New">WaitWakeCompletionRoutine</font><font face="Times New Roman">,
for this request.</font></li>
<li>The request is then passed down the stack.</li>
<li>The request remains pending with the hub driver until completed by the hub
driver.</li>
<li>On resume signaling, the wait wake request is completed and the callback
function is invoked. <br>
The <font face="Courier New">WaitWakeCallback</font> routine powers up the
device and issues a new wait-wake request for the device.</li>
<li>The wait wake request should not be sent when the device is in a low power
state.</li>
</ul>
<p><b>Selective Suspend feature</b></p>
<p>The USB core stack supports a new feature called the selective suspend
feature. This feature allows the driver to power down the device while the
system remains in the S0 power state. </p>
<ul>
<li>The device driver &quot;observes&quot; that the device is idle and sends
an idle request down the stack&nbsp; - <font face="Courier New">SubmitIdleRequestIrp.<br>
</font> <font face="Times New Roman">The exact notion of the device in idle
state is
described in the selective suspend model section.</font></li>
<li>A pointer to the callback function in the driver, <font face="Courier New">IdleNotificationCallback,</font>
is passed along with it.</li>
<li>The driver also sets a completion routine, <font face="Courier New">IdleNotificationRequestComplete
</font><font face="Times New Roman">for this request</font>. </li>
<li>The hub driver pends this idle request for the device.</li>
<li>When the hub &quot;deems it appropriate&quot; to selectively suspend the
device, the callback function <font face="Courier New">IdleNotificationCallback</font>
is invoked.<br>
This function powers down the device.&nbsp; The device is powered down to
the <font face="Courier New">DeviceWake</font>
state (initialized while handling the <font face="Courier New">IRP_MN_QUERY_CAPABILITIES</font>).
<br>
If the <font face="Courier New">DeviceWake</font> state is not known, then
the device should power down to the D2 power state.</li>
</ul>
<p>Notes</p>
<ul>
<li>Since the hub invokes the callback function, <font face="Courier New">IdleNotificationCallback</font>,
only when it deems appropriate, the function driver should never assume that
the device will power down as soon as the idle request is sent down the
stack. </li>
<li>Since it is not appropriate to send requests down the stack when the
device is in low power state,
the function driver should send an idle request only when the device is in D0
power state. </li>
<li>As soon as the device is &quot;not idle&quot;, the driver should cancel
the idle request - <font face="Courier New">CancelSelectSuspend</font>.</li>
<li>No assumptions should be made on the completion of idle request. If the
driver needs to pass requests (reads/writes/ioctls) down the stack, then the
driver should wait for the idle request to complete before proceeding to
submit one.</li>
<li>If the idle request completes in error, the <font face="Courier New">IdleNotificationRequestComplete
</font><font face="Times New Roman">powers
up the device.</font></li>
<li>Only one idle request can be pending for the device at any time.</li>
</ul>
<p>Selective Suspend model</p>
<ul>
<li>The selective suspend driver interprets the device as idle when<br>
a) there are no open handles to the device and<br>
b) no PnP requests are being processed. <br>
This is a mere suggestion. A function driver may have a different
interpretation of the idle state.<br>
As an example, an open handle need not violate the idle state of the device
if this does not cause any request to be sent down the stack.</li>
<li>The selective suspend driver initializes a timer to fire at fixed
intervals. </li>
<li>The DPC associated with the timer checks the idle state of the device and
queues a work item to submit an idle request for the device. </li>
<li>The timer is cancelled when the idle request is passed down the stack. </li>
<li>The timer is re-initialized when the idle request completes.</li>
</ul>
<p>Please refer the inline comments in the selSusp sample for implementation of
the above suggestions.</p>
</BODY>
</HTML>