Leaked source code of windows server 2003
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.

1012 lines
36 KiB

  1. /*****************************************************************************
  2. @doc INT EXT
  3. ******************************************************************************
  4. * $ProjectName: $
  5. * $ProjectRevision: $
  6. *-----------------------------------------------------------------------------
  7. * $Source: z:/pr/cmbp0/sw/cmbp0.ms/rcs/cmbp0pnp.c $
  8. * $Revision: 1.4 $
  9. *-----------------------------------------------------------------------------
  10. * $Author: TBruendl $
  11. *-----------------------------------------------------------------------------
  12. * History: see EOF
  13. *-----------------------------------------------------------------------------
  14. *
  15. * Copyright 2000 OMNIKEY AG
  16. ******************************************************************************/
  17. #include <cmbp0wdm.h>
  18. #include <cmbp0pnp.h>
  19. #include <cmbp0scr.h>
  20. #include <cmbp0log.h>
  21. /*****************************************************************************
  22. Routine Description:
  23. ???
  24. Arguments:
  25. Return Value:
  26. ******************************************************************************/
  27. NTSTATUS CMMOB_AddDevice(
  28. IN PDRIVER_OBJECT DriverObject,
  29. IN PDEVICE_OBJECT PhysicalDeviceObject
  30. )
  31. {
  32. NTSTATUS NTStatus;
  33. PDEVICE_OBJECT DeviceObject = NULL;
  34. SmartcardDebug(DEBUG_TRACE,
  35. ("%s!AddDevice: Enter\n",DRIVER_NAME));
  36. try {
  37. PDEVICE_EXTENSION DeviceExtension;
  38. NTStatus = CMMOB_CreateDevice(DriverObject, PhysicalDeviceObject, &DeviceObject);
  39. if (NTStatus != STATUS_SUCCESS) {
  40. leave;
  41. }
  42. DeviceExtension = DeviceObject->DeviceExtension;
  43. DeviceExtension->AttachedDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject,
  44. PhysicalDeviceObject);
  45. if (DeviceExtension->AttachedDeviceObject == NULL) {
  46. NTStatus = STATUS_UNSUCCESSFUL;
  47. leave;
  48. }
  49. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  50. }
  51. finally {
  52. if (NTStatus != STATUS_SUCCESS) {
  53. CMMOB_UnloadDevice(DeviceObject);
  54. }
  55. }
  56. SmartcardDebug(DEBUG_TRACE,
  57. ("%s!AddDevice: Exit %x\n",DRIVER_NAME,NTStatus));
  58. return NTStatus;
  59. }
  60. /*****************************************************************************
  61. Routine Description:
  62. Send an Irp to the pcmcia driver and wait until the pcmcia driver has
  63. finished the request.
  64. To make sure that the pcmcia driver will not complete the Irp we first
  65. initialize an event and set our own completion routine for the Irp.
  66. When the pcmcia driver has processed the Irp the completion routine will
  67. set the event and tell the IO manager that more processing is required.
  68. By waiting for the event we make sure that we continue only if the pcmcia
  69. driver has processed the Irp completely.
  70. Arguments:
  71. DeviceObject context of call
  72. Irp Irp to send to the pcmcia driver
  73. Return Value:
  74. NTStatus returned by the pcmcia driver
  75. ******************************************************************************/
  76. NTSTATUS CMMOB_CallPcmciaDriver(
  77. IN PDEVICE_OBJECT AttachedDeviceObject,
  78. IN PIRP Irp
  79. )
  80. {
  81. NTSTATUS NTStatus = STATUS_SUCCESS;
  82. PIO_STACK_LOCATION IrpStack, IrpNextStack;
  83. KEVENT Event;
  84. /*
  85. SmartcardDebug(DEBUG_TRACE,
  86. ("%s!CMMOB_CallPcmciaDriver: Enter\n",DRIVER_NAME ));
  87. */
  88. //
  89. // Prepare everything to call the underlying driver
  90. //
  91. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  92. IrpNextStack = IoGetNextIrpStackLocation(Irp);
  93. //
  94. // Copy our stack to the next stack location.
  95. //
  96. *IrpNextStack = *IrpStack;
  97. //
  98. // initialize an event for process synchronization. the event is passed
  99. // to our completion routine and will be set if the pcmcia driver is done
  100. //
  101. KeInitializeEvent(&Event,
  102. NotificationEvent,
  103. FALSE);
  104. //
  105. // Our IoCompletionRoutine sets only our event
  106. //
  107. IoSetCompletionRoutine (Irp,
  108. CMMOB_PcmciaCallComplete,
  109. &Event,
  110. TRUE,
  111. TRUE,
  112. TRUE);
  113. //
  114. // Call the pcmcia driver
  115. //
  116. if (IrpStack->MajorFunction == IRP_MJ_POWER) {
  117. NTStatus = PoCallDriver(AttachedDeviceObject,Irp);
  118. } else {
  119. NTStatus = IoCallDriver(AttachedDeviceObject,Irp);
  120. }
  121. //
  122. // Wait until the pcmcia driver has processed the Irp
  123. //
  124. if (NTStatus == STATUS_PENDING) {
  125. NTStatus = KeWaitForSingleObject(&Event,
  126. Executive,
  127. KernelMode,
  128. FALSE,
  129. NULL);
  130. if (NTStatus == STATUS_SUCCESS) {
  131. NTStatus = Irp->IoStatus.Status;
  132. }
  133. }
  134. /*
  135. SmartcardDebug(DEBUG_TRACE,
  136. ("%s!CMMOB_CallPcmciaDriver: Exit %x\n",DRIVER_NAME,NTStatus));
  137. */
  138. return NTStatus;
  139. }
  140. /*****************************************************************************
  141. Routine Description:
  142. Completion routine for an Irp sent to the pcmcia driver. The event will
  143. be set to notify that the pcmcia driver is done. The routine will not
  144. 'complete' the Irp, so the caller of CMMOB_CallPcmciaDriver can continue.
  145. Arguments:
  146. DeviceObject context of call
  147. Irp Irp to complete
  148. Event Used by CMMOB_CallPcmciaDriver for process synchronization
  149. Return Value:
  150. STATUS_CANCELLED Irp was cancelled by the IO manager
  151. STATUS_MORE_PROCESSING_REQUIRED Irp will be finished by caller of
  152. CMMOB_CallPcmciaDriver
  153. ******************************************************************************/
  154. NTSTATUS CMMOB_PcmciaCallComplete (
  155. IN PDEVICE_OBJECT DeviceObject,
  156. IN PIRP Irp,
  157. IN PKEVENT Event
  158. )
  159. {
  160. UNREFERENCED_PARAMETER (DeviceObject);
  161. if (Irp->Cancel) {
  162. Irp->IoStatus.Status = STATUS_CANCELLED;
  163. }
  164. KeSetEvent (Event, 0, FALSE);
  165. return STATUS_MORE_PROCESSING_REQUIRED;
  166. }
  167. /*****************************************************************************
  168. Routine Description:
  169. driver callback for pnp manager
  170. Request: Action:
  171. IRP_MN_START_DEVICE Notify the pcmcia driver about the new device
  172. and start the device
  173. IRP_MN_STOP_DEVICE Free all resources used by the device and tell
  174. the pcmcia driver that the device was stopped
  175. IRP_MN_QUERY_REMOVE_DEVICE If the device is opened (i.e. in use) an error will
  176. be returned to prevent the PnP manager to stop
  177. the driver
  178. IRP_MN_CANCEL_REMOVE_DEVICE just notify that we can continue without any
  179. restrictions
  180. IRP_MN_REMOVE_DEVICE notify the pcmcia driver that the device was
  181. removed, stop & unload the device
  182. All other requests will be passed to the pcmcia driver to ensure correct processing.
  183. Arguments:
  184. Device Object context of call
  185. Irp irp from the PnP manager
  186. Return Value:
  187. STATUS_SUCCESS
  188. STATUS_UNSUCCESSFUL
  189. NTStatus returned by pcmcia driver
  190. ******************************************************************************/
  191. NTSTATUS CMMOB_PnPDeviceControl(
  192. IN PDEVICE_OBJECT DeviceObject,
  193. IN PIRP Irp
  194. )
  195. {
  196. NTSTATUS NTStatus = STATUS_SUCCESS;
  197. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  198. PIO_STACK_LOCATION IrpStack;
  199. PDEVICE_OBJECT AttachedDeviceObject;
  200. PDEVICE_CAPABILITIES DeviceCapabilities;
  201. KIRQL irql;
  202. LONG i;
  203. BOOLEAN irpSkipped = FALSE;
  204. BOOLEAN removed = FALSE;
  205. SmartcardDebug(DEBUG_TRACE,
  206. ("%s!PnPDeviceControl: Enter\n",DRIVER_NAME ));
  207. NTStatus = SmartcardAcquireRemoveLock(&DeviceExtension->SmartcardExtension);
  208. ASSERT(NTStatus == STATUS_SUCCESS);
  209. if (NTStatus != STATUS_SUCCESS) {
  210. Irp->IoStatus.Information = 0;
  211. Irp->IoStatus.Status = NTStatus;
  212. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  213. return NTStatus;
  214. }
  215. AttachedDeviceObject = DeviceExtension->AttachedDeviceObject;
  216. // Irp->IoStatus.Information = 0;
  217. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  218. //
  219. // Now look what the PnP manager wants...
  220. //
  221. #ifdef DBG
  222. if (IrpStack->MinorFunction <= IRP_PNP_MN_FUNC_MAX) {
  223. SmartcardDebug(DEBUG_DRIVER,
  224. ("%s!PnPDeviceControl: %s received\n",DRIVER_NAME,
  225. szPnpMnFuncDesc[IrpStack->MinorFunction] ));
  226. }
  227. #endif
  228. switch (IrpStack->MinorFunction) {
  229. case IRP_MN_START_DEVICE:
  230. //
  231. // We have to call the underlying driver first
  232. //
  233. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject,Irp);
  234. if (NT_SUCCESS(NTStatus)) {
  235. //
  236. // Now we should connect to our resources (Irql, Io etc.)
  237. //
  238. NTStatus = CMMOB_StartDevice(DeviceObject,
  239. &IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0]);
  240. }
  241. break;
  242. case IRP_MN_QUERY_STOP_DEVICE:
  243. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  244. if (DeviceExtension->lIoCount > 0) {
  245. // we refuse to stop if we have pending io
  246. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  247. NTStatus = STATUS_DEVICE_BUSY;
  248. } else {
  249. // stop processing requests
  250. KeClearEvent(&DeviceExtension->ReaderStarted);
  251. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  252. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  253. }
  254. break;
  255. case IRP_MN_CANCEL_STOP_DEVICE:
  256. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  257. ASSERT(NTStatus == STATUS_SUCCESS);
  258. // we can continue to process requests
  259. DeviceExtension->lIoCount = 0;
  260. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  261. break;
  262. case IRP_MN_STOP_DEVICE:
  263. //
  264. // Stop the device. Aka disconnect from our resources
  265. //
  266. CMMOB_StopDevice(DeviceObject);
  267. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  268. break;
  269. case IRP_MN_QUERY_REMOVE_DEVICE:
  270. //
  271. // Remove our device
  272. //
  273. if (DeviceExtension->lOpenCount > 0) {
  274. NTStatus = STATUS_UNSUCCESSFUL;
  275. } else {
  276. NTStatus = IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,
  277. FALSE);
  278. ASSERT(NTStatus == STATUS_SUCCESS);
  279. if (NTStatus != STATUS_SUCCESS) {
  280. break;
  281. }
  282. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  283. }
  284. break;
  285. case IRP_MN_CANCEL_REMOVE_DEVICE:
  286. //
  287. // Removal of device has been cancelled
  288. //
  289. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  290. if (NTStatus == STATUS_SUCCESS) {
  291. NTStatus = IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,
  292. TRUE);
  293. }
  294. ASSERT(NTStatus == STATUS_SUCCESS);
  295. break;
  296. case IRP_MN_REMOVE_DEVICE:
  297. //
  298. // Remove our device
  299. //
  300. CMMOB_StopDevice(DeviceObject);
  301. // Wait until we can safely unload the device
  302. SmartcardReleaseRemoveLockAndWait(&DeviceExtension->SmartcardExtension);
  303. CMMOB_UnloadDevice(DeviceObject);
  304. removed = TRUE;
  305. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  306. break;
  307. case IRP_MN_QUERY_CAPABILITIES:
  308. //
  309. // Query device capabilities
  310. //
  311. //
  312. // Get the packet.
  313. //
  314. DeviceCapabilities=IrpStack->Parameters.DeviceCapabilities.Capabilities;
  315. if (DeviceCapabilities->Version < 1 ||
  316. DeviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES)) {
  317. //
  318. // We don't support this version. Fail the requests
  319. //
  320. NTStatus = STATUS_UNSUCCESSFUL;
  321. break;
  322. }
  323. //
  324. // Set the capabilities.
  325. //
  326. // We cannot wake the system.
  327. DeviceCapabilities->SystemWake = PowerSystemUnspecified;
  328. DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  329. // We have no latencies
  330. DeviceCapabilities->D1Latency = 0;
  331. DeviceCapabilities->D2Latency = 0;
  332. DeviceCapabilities->D3Latency = 0;
  333. // No locking or ejection
  334. DeviceCapabilities->LockSupported = FALSE;
  335. DeviceCapabilities->EjectSupported = FALSE;
  336. // Device can be physically removed.
  337. DeviceCapabilities->Removable = TRUE;
  338. // No docking device
  339. DeviceCapabilities->DockDevice = FALSE;
  340. // Device can not be removed any time
  341. // it has a removable media
  342. DeviceCapabilities->SurpriseRemovalOK = FALSE;
  343. //
  344. // Call the next lower driver
  345. //
  346. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  347. //
  348. // Now look at the relation system state / device state
  349. //
  350. {
  351. SmartcardDebug( DEBUG_DRIVER,
  352. ("%s!PnPDeviceControl: systemstate to devicestate mapping\n",DRIVER_NAME ));
  353. for (i=1; i<PowerSystemMaximum; i++) {
  354. SmartcardDebug(DEBUG_DRIVER,
  355. ("%s!PnPDeviceControl: %s -> %s\n",DRIVER_NAME,
  356. szSystemPowerState[i],szDevicePowerState[DeviceCapabilities->DeviceState[i]] ));
  357. if (DeviceCapabilities->DeviceState[i] != PowerDeviceD3 &&
  358. (DeviceCapabilities->DeviceState[i] != PowerDeviceD0 ||
  359. i >= PowerSystemSleeping3)) {
  360. DeviceCapabilities->DeviceState[i]=PowerDeviceD3;
  361. SmartcardDebug(DEBUG_DRIVER,
  362. ("%s!PnPDeviceControl: altered to %s -> %s\n",DRIVER_NAME,
  363. szSystemPowerState[i],szDevicePowerState[DeviceCapabilities->DeviceState[i]] ));
  364. }
  365. }
  366. }
  367. // Store DeviceCapabilities in our DeviceExtension for later use
  368. RtlCopyMemory(&DeviceExtension->DeviceCapabilities,DeviceCapabilities,
  369. sizeof(DeviceExtension->DeviceCapabilities));
  370. break;
  371. case IRP_MN_QUERY_DEVICE_RELATIONS:
  372. //
  373. // Query device relations
  374. //
  375. SmartcardDebug(DEBUG_DRIVER,
  376. ("%s!PnPDeviceControl: Requested relation = %s\n",DRIVER_NAME,
  377. szDeviceRelation[IrpStack->Parameters.QueryDeviceRelations.Type] ));
  378. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  379. irpSkipped = TRUE;
  380. break;
  381. default:
  382. //
  383. // This might be an Irp that is only useful
  384. // for the underlying bus driver
  385. //
  386. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  387. irpSkipped = TRUE;
  388. break;
  389. }
  390. if (!irpSkipped) {
  391. Irp->IoStatus.Status = NTStatus;
  392. }
  393. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  394. if (removed == FALSE) {
  395. SmartcardReleaseRemoveLock(&DeviceExtension->SmartcardExtension);
  396. }
  397. SmartcardDebug(DEBUG_TRACE,
  398. ( "%s!PnPDeviceControl: Exit %x\n",DRIVER_NAME,NTStatus));
  399. return NTStatus;
  400. }
  401. /*****************************************************************************
  402. Routine Description:
  403. This function is called when the underlying stacks
  404. completed the power transition.
  405. ******************************************************************************/
  406. VOID CMMOB_SystemPowerCompletion(
  407. IN PDEVICE_OBJECT DeviceObject,
  408. IN UCHAR MinorFunction,
  409. IN POWER_STATE PowerState,
  410. IN PKEVENT Event,
  411. IN PIO_STATUS_BLOCK IoStatus
  412. )
  413. {
  414. UNREFERENCED_PARAMETER (DeviceObject);
  415. UNREFERENCED_PARAMETER (MinorFunction);
  416. UNREFERENCED_PARAMETER (PowerState);
  417. SmartcardDebug(DEBUG_TRACE,
  418. ("%s!SystemPowerCompletion: Enter\n",DRIVER_NAME));
  419. SmartcardDebug(DEBUG_DRIVER,
  420. ("%s!SystemPowerCompletion: Status of completed IRP = %x\n",DRIVER_NAME,IoStatus->Status));
  421. KeSetEvent(Event, 0, FALSE);
  422. SmartcardDebug(DEBUG_TRACE,
  423. ("%s!SystemPowerCompletion: Exit\n",DRIVER_NAME));
  424. }
  425. /*****************************************************************************
  426. Routine Description:
  427. This routine is called after the underlying stack powered
  428. UP the serial port, so it can be used again.
  429. ******************************************************************************/
  430. NTSTATUS CMMOB_DevicePowerCompletion (
  431. IN PDEVICE_OBJECT DeviceObject,
  432. IN PIRP Irp,
  433. IN PSMARTCARD_EXTENSION SmartcardExtension
  434. )
  435. {
  436. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  437. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  438. NTSTATUS NTStatus;
  439. UCHAR state;
  440. KIRQL irql;
  441. SmartcardDebug(DEBUG_TRACE,
  442. ("%s!DevicePowerCompletion: Enter\n",DRIVER_NAME));
  443. SmartcardDebug(DEBUG_DRIVER,
  444. ("%s!DevicePowerCompletion: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
  445. //
  446. // If a card was present before power down or now there is
  447. // a card in the reader, we complete any pending card monitor
  448. // request, since we do not really know what card is now in the
  449. // reader.
  450. //
  451. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
  452. &irql);
  453. if (SmartcardExtension->ReaderExtension->fCardPresent ||
  454. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT) {
  455. SmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN;
  456. SmartcardExtension->ReaderExtension->ulNewCardState = UNKNOWN;
  457. }
  458. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
  459. irql);
  460. KeSetEvent(&DeviceExtension->CanRunUpdateThread, 0, FALSE);
  461. // save the current power state of the reader
  462. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
  463. SmartcardReleaseRemoveLock(SmartcardExtension);
  464. // inform the power manager of our state.
  465. PoSetPowerState (DeviceObject,
  466. DevicePowerState,
  467. IrpStack->Parameters.Power.State);
  468. SmartcardDebug( DEBUG_DRIVER,
  469. ("%s!DevicePowerCompletion: called PoSetPowerState with %s\n",DRIVER_NAME,
  470. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  471. PoStartNextPowerIrp(Irp);
  472. // signal that we can process ioctls again
  473. DeviceExtension->lIoCount = 0;
  474. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  475. SmartcardDebug(DEBUG_TRACE,
  476. ("%s!DevicePowerCompletion: Exit\n",DRIVER_NAME));
  477. return STATUS_SUCCESS;
  478. }
  479. typedef enum _ACTION {
  480. Undefined = 0,
  481. SkipRequest,
  482. WaitForCompletion,
  483. CompleteRequest,
  484. MarkPending
  485. } ACTION;
  486. /*****************************************************************************
  487. Routine Description:
  488. The power dispatch routine.
  489. This driver is the power policy owner of the device stack,
  490. because this driver knows about the connected reader.
  491. Therefor this driver will translate system power states
  492. to device power states.
  493. Arguments:
  494. DeviceObject - pointer to a device object.
  495. Irp - pointer to an I/O Request Packet.
  496. Return Value:
  497. NT NTStatus code
  498. ******************************************************************************/
  499. NTSTATUS CMMOB_PowerDeviceControl (
  500. IN PDEVICE_OBJECT DeviceObject,
  501. IN PIRP Irp
  502. )
  503. {
  504. NTSTATUS NTStatus = STATUS_SUCCESS;
  505. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  506. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  507. PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
  508. POWER_STATE DesiredPowerState;
  509. KIRQL irql;
  510. ACTION action;
  511. KEVENT event;
  512. SmartcardDebug(DEBUG_TRACE,
  513. ( "%s!PowerDeviceControl: Enter\n",DRIVER_NAME));
  514. SmartcardDebug(DEBUG_DRIVER,
  515. ( "%s!PowerDeviceControl: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
  516. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  517. NTStatus = SmartcardAcquireRemoveLock(SmartcardExtension);
  518. ASSERT(NTStatus == STATUS_SUCCESS);
  519. if (NTStatus!=STATUS_SUCCESS) {
  520. Irp->IoStatus.Status = NTStatus;
  521. Irp->IoStatus.Information = 0;
  522. PoStartNextPowerIrp(Irp);
  523. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  524. return NTStatus;
  525. }
  526. ASSERT(SmartcardExtension->ReaderExtension->ReaderPowerState !=
  527. PowerReaderUnspecified);
  528. #ifdef DBG
  529. if (IrpStack->MinorFunction <= IRP_POWER_MN_FUNC_MAX) {
  530. SmartcardDebug(DEBUG_DRIVER,
  531. ("%s!PowerDeviceControl: %s received\n",DRIVER_NAME,
  532. szPowerMnFuncDesc[IrpStack->MinorFunction] ));
  533. }
  534. #endif
  535. switch (IrpStack->MinorFunction) {
  536. // ------------------
  537. // IRP_MN_QUERY_POWER
  538. // ------------------
  539. case IRP_MN_QUERY_POWER:
  540. //
  541. // A power policy manager sends this IRP to determine whether it can change
  542. // the system or device power state, typically to go to sleep.
  543. //
  544. switch (IrpStack->Parameters.Power.Type) {
  545. // +++++++++++++++++++
  546. // SystemPowerState
  547. // +++++++++++++++++++
  548. case SystemPowerState:
  549. SmartcardDebug( DEBUG_DRIVER,
  550. ("%s!PowerDeviceControl: SystemPowerState = %s\n",DRIVER_NAME,
  551. szSystemPowerState [IrpStack->Parameters.Power.State.SystemState] ));
  552. switch (IrpStack->Parameters.Power.State.SystemState) {
  553. case PowerSystemWorking:
  554. action = SkipRequest;
  555. break;
  556. case PowerSystemSleeping1:
  557. case PowerSystemSleeping2:
  558. case PowerSystemSleeping3:
  559. case PowerSystemHibernate:
  560. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  561. if (DeviceExtension->lIoCount == 0) {
  562. // Block any further ioctls
  563. KeClearEvent(&DeviceExtension->ReaderStarted);
  564. action = SkipRequest;
  565. } else {
  566. // can't go to sleep mode since the reader is busy.
  567. NTStatus = STATUS_DEVICE_BUSY;
  568. action = CompleteRequest;
  569. }
  570. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  571. break;
  572. case PowerSystemShutdown:
  573. action = SkipRequest;
  574. break;
  575. }
  576. break;
  577. // ++++++++++++++++++
  578. // DevicePowerState
  579. // ++++++++++++++++++
  580. case DevicePowerState:
  581. // For requests to D1, D2, or D3 ( sleep or off states ),
  582. // sets DeviceExtension->CurrentDevicePowerState to DeviceState immediately.
  583. // This enables any code checking state to consider us as sleeping or off
  584. // already, as this will imminently become our state.
  585. SmartcardDebug(DEBUG_DRIVER,
  586. ("%s!PowerDeviceControl: DevicePowerState = %s\n",DRIVER_NAME,
  587. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  588. action = SkipRequest;
  589. break;
  590. }
  591. break; /* IRP_MN_QUERY_POWER */
  592. // ------------------
  593. // IRP_MN_SET_POWER
  594. // ------------------
  595. case IRP_MN_SET_POWER:
  596. // The system power policy manager sends this IRP to set the system power state.
  597. // A device power policy manager sends this IRP to set the device power state for a device.
  598. // Set Irp->IoStatus.Status to STATUS_SUCCESS to indicate that the device
  599. // has entered the requested state. Drivers cannot fail this IRP.
  600. ASSERT(SmartcardExtension->ReaderExtension->ReaderPowerState != PowerReaderUnspecified);
  601. switch (IrpStack->Parameters.Power.Type) {
  602. // +++++++++++++++++++
  603. // SystemPowerState
  604. // +++++++++++++++++++
  605. case SystemPowerState:
  606. // Get input system power state
  607. SmartcardDebug( DEBUG_DRIVER,
  608. ("%s!PowerDeviceControl: SystemPowerState = %s\n",DRIVER_NAME,
  609. szSystemPowerState[IrpStack->Parameters.Power.State.SystemState] ));
  610. // determine desired device powerstate
  611. DesiredPowerState.DeviceState=DeviceExtension->DeviceCapabilities.DeviceState[IrpStack->Parameters.Power.State.SystemState];
  612. SmartcardDebug( DEBUG_DRIVER,
  613. ("%s!PowerDeviceControl: DesiredDevicePowerState = %s\n",DRIVER_NAME,
  614. szDevicePowerState[DesiredPowerState.DeviceState] ));
  615. switch (DesiredPowerState.DeviceState) {
  616. case PowerDeviceD0:
  617. if (SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderWorking) {
  618. // We're already in the right state
  619. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  620. action = SkipRequest;
  621. break;
  622. }
  623. // wake up the underlying stack...
  624. action = MarkPending;
  625. SmartcardDebug( DEBUG_DRIVER,
  626. ("%s!PowerDeviceControl: setting DevicePowerState = %s\n",DRIVER_NAME,
  627. szDevicePowerState[DesiredPowerState.DeviceState] ));
  628. break;
  629. case PowerDeviceD1:
  630. case PowerDeviceD2:
  631. case PowerDeviceD3:
  632. DesiredPowerState.DeviceState = PowerDeviceD3;
  633. if (SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderOff) {
  634. // We're already in the right state
  635. KeClearEvent(&DeviceExtension->ReaderStarted);
  636. action = SkipRequest;
  637. break;
  638. }
  639. action = MarkPending;
  640. SmartcardDebug( DEBUG_DRIVER,
  641. ("%s!PowerDeviceControl: setting DevicePowerState = %s\n",DRIVER_NAME,
  642. szDevicePowerState[DesiredPowerState.DeviceState] ));
  643. break;
  644. default:
  645. action = SkipRequest;
  646. break;
  647. }
  648. break;
  649. // ++++++++++++++++++
  650. // DevicePowerState
  651. // ++++++++++++++++++
  652. case DevicePowerState:
  653. SmartcardDebug(DEBUG_DRIVER,
  654. ("%s!PowerDeviceControl: DevicePowerState = %s\n",DRIVER_NAME,
  655. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  656. switch (IrpStack->Parameters.Power.State.DeviceState) {
  657. case PowerDeviceD0:
  658. // Turn on the reader
  659. SmartcardDebug(DEBUG_DRIVER,
  660. ("%s!PowerDeviceControl: PowerDevice D0\n",DRIVER_NAME));
  661. //
  662. // start update thread be signal that it should not run now
  663. // this thread should be started in completion rourine
  664. // but there we have a wrong IRQL for creating a thread
  665. //
  666. KeClearEvent(&DeviceExtension->CanRunUpdateThread);
  667. NTStatus = CMMOB_StartCardTracking(DeviceObject);
  668. if (NTStatus != STATUS_SUCCESS) {
  669. SmartcardDebug(DEBUG_ERROR,
  670. ("%s!StartCardTracking failed ! %lx\n",DRIVER_NAME,NTStatus));
  671. }
  672. //
  673. // First, we send down the request to the bus, in order
  674. // to power on the port. When the request completes,
  675. // we turn on the reader
  676. //
  677. IoCopyCurrentIrpStackLocationToNext(Irp);
  678. IoSetCompletionRoutine (Irp,
  679. CMMOB_DevicePowerCompletion,
  680. SmartcardExtension,
  681. TRUE,
  682. TRUE,
  683. TRUE);
  684. action = WaitForCompletion;
  685. break;
  686. case PowerDeviceD1:
  687. case PowerDeviceD2:
  688. case PowerDeviceD3:
  689. // Turn off the reader
  690. SmartcardDebug(DEBUG_DRIVER,
  691. ("%s!PowerDeviceControl: PowerDevice D3\n",DRIVER_NAME));
  692. PoSetPowerState (DeviceObject,
  693. DevicePowerState,
  694. IrpStack->Parameters.Power.State);
  695. // Block any further ioctls
  696. KeClearEvent(&DeviceExtension->ReaderStarted);
  697. // stop the update thread
  698. CMMOB_StopCardTracking(DeviceObject);
  699. // save the current card state
  700. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
  701. &irql);
  702. SmartcardExtension->ReaderExtension->fCardPresent =
  703. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  704. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
  705. irql);
  706. if (SmartcardExtension->ReaderExtension->fCardPresent) {
  707. SmartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  708. NTStatus = CMMOB_PowerOffCard(SmartcardExtension);
  709. ASSERT(NTStatus == STATUS_SUCCESS);
  710. }
  711. // save the current power state of the reader
  712. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderOff;
  713. action = SkipRequest;
  714. break;
  715. default:
  716. action = SkipRequest;
  717. break;
  718. }
  719. break;
  720. } /* case irpStack->Parameters.Power.Type */
  721. break; /* IRP_MN_SET_POWER */
  722. default:
  723. SmartcardDebug(DEBUG_DRIVER,
  724. ("%s!PowerDeviceControl: unhandled POWER IRP received\n",DRIVER_NAME));
  725. //
  726. // All unhandled power messages are passed on to the PDO
  727. //
  728. action = SkipRequest;
  729. break;
  730. } /* irpStack->MinorFunction */
  731. switch (action) {
  732. case CompleteRequest:
  733. SmartcardReleaseRemoveLock(SmartcardExtension);
  734. PoStartNextPowerIrp(Irp);
  735. Irp->IoStatus.Status = NTStatus;
  736. Irp->IoStatus.Information = 0;
  737. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  738. break;
  739. case MarkPending:
  740. // initialize the event we need in the completion function
  741. KeInitializeEvent(&event,
  742. NotificationEvent,
  743. FALSE);
  744. // request the device power irp
  745. NTStatus = PoRequestPowerIrp (DeviceObject,
  746. IRP_MN_SET_POWER,
  747. DesiredPowerState,
  748. CMMOB_SystemPowerCompletion,
  749. &event,
  750. NULL);
  751. SmartcardDebug( DEBUG_DRIVER,
  752. ("%s!PowerDeviceControl: called PoRequestPowerIrp with %s\n",DRIVER_NAME,
  753. szDevicePowerState[DesiredPowerState.DeviceState] ));
  754. ASSERT(NTStatus == STATUS_PENDING);
  755. if (NTStatus == STATUS_PENDING) {
  756. // wait until the device power irp completed
  757. NTStatus = KeWaitForSingleObject(&event,
  758. Executive,
  759. KernelMode,
  760. FALSE,
  761. NULL);
  762. }
  763. if (NTStatus == STATUS_SUCCESS) {
  764. SmartcardReleaseRemoveLock(SmartcardExtension);
  765. PoStartNextPowerIrp(Irp);
  766. IoSkipCurrentIrpStackLocation(Irp);
  767. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  768. } else {
  769. SmartcardReleaseRemoveLock(SmartcardExtension);
  770. PoStartNextPowerIrp(Irp);
  771. Irp->IoStatus.Status = NTStatus;
  772. Irp->IoStatus.Information = 0;
  773. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  774. }
  775. break;
  776. case SkipRequest:
  777. SmartcardReleaseRemoveLock(SmartcardExtension);
  778. PoStartNextPowerIrp(Irp);
  779. IoSkipCurrentIrpStackLocation(Irp);
  780. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  781. break;
  782. case WaitForCompletion:
  783. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  784. break;
  785. default:
  786. SmartcardReleaseRemoveLock(SmartcardExtension);
  787. PoStartNextPowerIrp(Irp);
  788. IoSkipCurrentIrpStackLocation(Irp);
  789. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  790. break;
  791. }
  792. SmartcardDebug(DEBUG_TRACE,
  793. ("%s!PowerDeviceControl: Exit %lx\n",DRIVER_NAME,NTStatus));
  794. return NTStatus;
  795. }
  796. /*****************************************************************************
  797. * History:
  798. * $Log: cmbp0pnp.c $
  799. * Revision 1.4 2000/08/24 09:05:12 TBruendl
  800. * No comment given
  801. *
  802. * Revision 1.3 2000/07/27 13:53:01 WFrischauf
  803. * No comment given
  804. *
  805. *
  806. ******************************************************************************/