Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
5.1 KiB

  1. Questions:
  2. If we send an inrush IRP to A (which is inrush) and A sends it on
  3. to B, which is not (so we'll process it normally), does anything weird happen?
  4. Driver Rules:
  5. 1. Must call PoCallDriver for IRP_MJ_POWER regardless
  6. of the minor code.
  7. 3. When a driver has received a power irp, and wishes to pass it
  8. on to other drivers, the following rules apply.
  9. a. The SystemContext field must be copied into the next stack location.
  10. b. if a driver passes a given irp on to multiple parallel drivers
  11. (for example, an FT driver that calls multiple disk drivers with
  12. a single request) then the driver must pass the power irp on to
  13. each driver one at a time. it could pass on multiple copies in
  14. parallel, but if and only if they are not INRUSH.
  15. 4. If a single irp's stack of functions contains both Power functions and
  16. non-power functions, the SystemContext field must be propogated accross
  17. the non-power functions.
  18. Example:
  19. driver A gets MJ_PNP_POWER, MN_SET_POWER, incoming SystemContext = s0
  20. A calls B with MJ_IOCTL, MN..., to get B to do some side function
  21. associated with powering down (flushing a hardware cache, say)
  22. B calls C with MJ_POWER, MN_SET_POWER, ...
  23. Then A must pass SystemContext on to B, which must pass it on to C
  24. (via a call to PoCallDriver) PoCallDriver may modify the SystemContext
  25. that was passed in, so that C gets a different one.
  26. If this is not done, when the power IRP is passed to C, PoCallDriver won't
  27. know it's a continuation of a previous IRP, and therefore may do the wrong
  28. thing.
  29. (For example, if A and C have INRUSH set, and B doesn't pass on the
  30. SystemContext value passed into A, then when B does PoCallDriver(C, irp)
  31. it will be enqueued forever because PoCallDriver thinks it is
  32. another, different, inrush irp.)
  33. 5. Any code that fills in a stack location with the first Power function
  34. of that IRP's stack must set SystemContext to 0.
  35. @@ inrush will lead to deadlocks if two inrush DOs are ever in the same
  36. stack
  37. !!> special context rules allow an irp to flow up and down a stack,
  38. need to be sure this is well doc'd.
  39. if a driver has D0_INRUSH set, and an INRUSH irp arrives, that irp
  40. might get held up waiting for some other irp to clear in that driver.
  41. (e.g. some other driver power state irp that didn't set power TO D0
  42. might hold up all inrush irps in the system)
  43. if DO is marked inrush, we will always call it at DPC level, just
  44. to avoid confusion over what is pageable and what is not.
  45. inrush applies only to device irps, or to device irps and system irps?
  46. if the later, then an inrush DO can only ever see one irp at time regardless
  47. of type!!!
  48. !!> driver can receive a SystemPowerState irp even while INRUSH is locked.
  49. !!> when calling any driver that does not set PAGE or INRUSH, we must call
  50. it from a worker thread at IRQL 0, regardless of where PoCallDriver was called.
  51. if it is an INPAGE device, we must call it from DPC at IRQL 2.
  52. not sure about INRUSH, I think it's at DPC too.
  53. ?? how will MN_POWER_SEQUENCE and MN_WAIT_WAKE fit into all this?
  54. DOE content
  55. The contents of the DOE are 100% private. There is a special
  56. declaration that allows the PoSetDeviceBusy() call to be a macro.
  57. (Actually, best if PoSetDeviceBusy() takes a system returned pointer,
  58. then there are no longer any fixed offsets to worry about.)
  59. The idea is that any value not needed by every DO is stored in a
  60. power control block (POB). Any operation that might allocate this
  61. object must allow for failure of the allocation!!!
  62. SPEC NOTES:
  63. Any operation that might allocate a POB must allow for failure to allocate.
  64. None of the DOE data is public.
  65. Power irp rules. Allowed one DevicePowerState and one SystemPowerState
  66. irp at a time.
  67. Context Values:
  68. If low order bit of the context field is 1, it is a flag.
  69. If 0, it is a pointer.
  70. If the whole thing is null, then no value.
  71. So:
  72. if (SystemContext == 0)
  73. no context set
  74. else if (SystemContext & 1)
  75. test for flag values
  76. else
  77. it's a pointer to some structure
  78. (need to change some code to match this.)
  79. IRP Queues:
  80. Use a single global holding queue. When a DO is busy, the IRP is
  81. enqueued on the tail of this queue. Whenever a power IRP completes
  82. AND the "pending" bit is set, run the entire list looking for an
  83. IRP of that type for that DO, and dispatch it to the DO if we find it.
  84. This means that each DOE has only 2 bits to mark S and D active,
  85. and 2 bits to mark S and D pending.
  86. If we search the entire list and do not find any Irps for that DO,
  87. then the pending bit is cleared along with the active one.
  88. Power IRPs, Inrush, and copying
  89. Globally, only one IRP is allowed to be active on any INRUSH DO in
  90. the system at any time.
  91. Active and Pending bits have different meanings for INRUSH DevObj
  92. than for normal devobj.