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.

2405 lines
60 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
  3. Module Name:
  4. PscrNT.c
  5. Abstract:
  6. Main Driver Module - NT Version
  7. Author:
  8. Andreas Straub
  9. Revision History:
  10. Andreas Straub 1.00 8/18/1997 Initial Version
  11. Klaus Schuetz 1.01 9/20/1997 Timing changed
  12. Andreas Straub 1.02 9/24/1997 Low Level error handling,
  13. minor bugfixes, clanup
  14. Andreas Straub 1.03 10/8/1997 Timing changed, generic SCM
  15. interface changed
  16. Andreas Straub 1.04 10/18/1997 Interrupt handling changed
  17. Andreas Straub 1.05 10/19/1997 Generic IOCTL's added
  18. Andreas Straub 1.06 10/25/1997 Timeout limit for FW update variable
  19. Andreas Straub 1.07 11/7/1997 Version information added
  20. Klaus Schuetz 1.08 11/10/1997 PnP capabilities added
  21. Klaus Schuetz Cleanup added
  22. --*/
  23. #include <PscrNT.h>
  24. #include <PscrCmd.h>
  25. #include <PscrCB.h>
  26. #include <PscrLog.h>
  27. #include <PscrVers.h>
  28. #pragma alloc_text(INIT, DriverEntry)
  29. #pragma alloc_text(PAGEABLE, PscrAddDevice)
  30. #pragma alloc_text(PAGEABLE, PscrCreateAndStartDevice)
  31. #pragma alloc_text(PAGEABLE, PscrCreateDevice)
  32. #pragma alloc_text(PAGEABLE, PscrStartDevice)
  33. #pragma alloc_text(PAGEABLE, PscrUnloadDriver)
  34. #pragma alloc_text(PAGEABLE, PscrCreateClose)
  35. BOOLEAN DeviceSlot[PSCR_MAX_DEVICE];
  36. NTSTATUS
  37. DriverEntry(
  38. PDRIVER_OBJECT DriverObject,
  39. PUNICODE_STRING RegistryPath
  40. )
  41. /*++
  42. DriverEntry:
  43. entry function of the driver. setup the callbacks for the OS and try to
  44. initialize a device object for every device in the system
  45. Arguments:
  46. DriverObject context of the driver
  47. RegistryPath path to the registry entry for the driver
  48. Return Value:
  49. STATUS_SUCCESS
  50. STATUS_UNSUCCESSFUL
  51. --*/
  52. {
  53. NTSTATUS NTStatus = STATUS_SUCCESS;
  54. ULONG Device;
  55. SmartcardDebug(
  56. DEBUG_TRACE,
  57. ( "PSCR!DriverEntry: Enter\n" )
  58. );
  59. // tell the system our entry points
  60. DriverObject->MajorFunction[IRP_MJ_CREATE] =
  61. DriverObject->MajorFunction[IRP_MJ_CLOSE] = PscrCreateClose;
  62. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PscrDeviceIoControl;
  63. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PscrSystemControl;
  64. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PscrCleanup;
  65. DriverObject->MajorFunction[IRP_MJ_PNP] = PscrPnP;
  66. DriverObject->MajorFunction[IRP_MJ_POWER] = PscrPower;
  67. DriverObject->DriverExtension->AddDevice = PscrAddDevice;
  68. DriverObject->DriverUnload = PscrUnloadDriver;
  69. SmartcardDebug(
  70. DEBUG_TRACE,
  71. ("PSCR!DriverEntry: Exit %x\n",
  72. NTStatus)
  73. );
  74. return NTStatus;
  75. }
  76. NTSTATUS
  77. PscrAddDevice(
  78. IN PDRIVER_OBJECT DriverObject,
  79. IN PDEVICE_OBJECT PhysicalDeviceObject
  80. )
  81. /*++
  82. Routine Description:
  83. This function is called by the pnp manager. This is used to create
  84. a new device instance.
  85. --*/
  86. {
  87. NTSTATUS status;
  88. UNICODE_STRING vendorNameU, ifdTypeU;
  89. ANSI_STRING vendorNameA, ifdTypeA;
  90. HANDLE regKey = NULL;
  91. PDEVICE_OBJECT DeviceObject = NULL;
  92. SmartcardDebug(
  93. DEBUG_TRACE,
  94. ( "PSCR!PscrAddDevice: Enter\n" )
  95. );
  96. try {
  97. ULONG DeviceInstance;
  98. UNICODE_STRING DriverID;
  99. PDEVICE_EXTENSION DeviceExtension;
  100. PREADER_EXTENSION ReaderExtension;
  101. PSMARTCARD_EXTENSION SmartcardExtension;
  102. RTL_QUERY_REGISTRY_TABLE parameters[3];
  103. RtlZeroMemory(parameters, sizeof(parameters));
  104. RtlZeroMemory(&vendorNameU, sizeof(vendorNameU));
  105. RtlZeroMemory(&ifdTypeU, sizeof(ifdTypeU));
  106. RtlZeroMemory(&vendorNameA, sizeof(vendorNameA));
  107. RtlZeroMemory(&ifdTypeA, sizeof(ifdTypeA));
  108. for( DeviceInstance = 0; DeviceInstance < PSCR_MAX_DEVICE; DeviceInstance++ )
  109. {
  110. if (DeviceSlot[DeviceInstance] == FALSE) {
  111. DeviceSlot[DeviceInstance] = TRUE;
  112. break;
  113. }
  114. }
  115. if (DeviceInstance == PSCR_MAX_DEVICE) {
  116. status = STATUS_INSUFFICIENT_RESOURCES;
  117. leave;
  118. }
  119. // Create the device object
  120. status = IoCreateDevice(
  121. DriverObject,
  122. sizeof(DEVICE_EXTENSION),
  123. NULL,
  124. FILE_DEVICE_SMARTCARD,
  125. 0,
  126. TRUE,
  127. &DeviceObject
  128. );
  129. if (status != STATUS_SUCCESS) {
  130. SmartcardLogError(
  131. DriverObject,
  132. PSCR_INSUFFICIENT_RESOURCES,
  133. NULL,
  134. 0
  135. );
  136. leave;
  137. }
  138. // set up the device extension.
  139. DeviceExtension = DeviceObject->DeviceExtension;
  140. SmartcardExtension = &DeviceExtension->SmartcardExtension;
  141. // initialize the DPC routine
  142. KeInitializeDpc(
  143. &DeviceExtension->DpcObject,
  144. PscrDpcRoutine,
  145. DeviceObject
  146. );
  147. KeInitializeSpinLock(&DeviceExtension->SpinLock);
  148. // Used for device removal notification
  149. KeInitializeEvent(
  150. &DeviceExtension->ReaderRemoved,
  151. NotificationEvent,
  152. FALSE
  153. );
  154. // Used for stop / start notification
  155. KeInitializeEvent(
  156. &DeviceExtension->ReaderStarted,
  157. NotificationEvent,
  158. FALSE
  159. );
  160. // allocate the reader extension
  161. ReaderExtension = ExAllocatePool(
  162. NonPagedPool,
  163. sizeof( READER_EXTENSION )
  164. );
  165. if( ReaderExtension == NULL ) {
  166. SmartcardLogError(
  167. DriverObject,
  168. PSCR_INSUFFICIENT_RESOURCES,
  169. NULL,
  170. 0
  171. );
  172. status = STATUS_INSUFFICIENT_RESOURCES;
  173. leave;
  174. }
  175. RtlZeroMemory( ReaderExtension, sizeof( READER_EXTENSION ));
  176. SmartcardExtension->ReaderExtension = ReaderExtension;
  177. // setup smartcard extension - callback's
  178. SmartcardExtension->ReaderFunction[RDF_CARD_POWER] = CBCardPower;
  179. SmartcardExtension->ReaderFunction[RDF_TRANSMIT] = CBTransmit;
  180. SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = CBCardTracking;
  181. SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = CBSetProtocol;
  182. SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = PscrGenericIOCTL;
  183. // setup smartcard extension - vendor attribute
  184. RtlCopyMemory(
  185. SmartcardExtension->VendorAttr.VendorName.Buffer,
  186. PSCR_VENDOR_NAME,
  187. sizeof( PSCR_VENDOR_NAME )
  188. );
  189. SmartcardExtension->VendorAttr.VendorName.Length =
  190. sizeof( PSCR_VENDOR_NAME );
  191. RtlCopyMemory(
  192. SmartcardExtension->VendorAttr.IfdType.Buffer,
  193. PSCR_IFD_TYPE,
  194. sizeof( PSCR_IFD_TYPE )
  195. );
  196. SmartcardExtension->VendorAttr.IfdType.Length =
  197. sizeof( PSCR_IFD_TYPE );
  198. SmartcardExtension->VendorAttr.UnitNo =
  199. DeviceInstance;
  200. SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = 0;
  201. // store firmware revision in ifd version
  202. SmartcardExtension->VendorAttr.IfdVersion.VersionMajor =
  203. ReaderExtension->FirmwareMajor;
  204. SmartcardExtension->VendorAttr.IfdVersion.VersionMinor =
  205. ReaderExtension->FirmwareMinor;
  206. SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0;
  207. // setup smartcard extension - reader capabilities
  208. SmartcardExtension->ReaderCapabilities.SupportedProtocols =
  209. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
  210. SmartcardExtension->ReaderCapabilities.ReaderType =
  211. SCARD_READER_TYPE_PCMCIA;
  212. SmartcardExtension->ReaderCapabilities.MechProperties = 0;
  213. SmartcardExtension->ReaderCapabilities.Channel = 0;
  214. SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 4000;
  215. SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 4000;
  216. SmartcardExtension->ReaderCapabilities.DataRate.Default = 10750;
  217. SmartcardExtension->ReaderCapabilities.DataRate.Max = 10750;
  218. // enter correct version of the lib
  219. SmartcardExtension->Version = SMCLIB_VERSION;
  220. SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
  221. SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
  222. SmartcardExtension->ReaderExtension->ReaderPowerState =
  223. PowerReaderWorking;
  224. status = SmartcardInitialize(SmartcardExtension);
  225. if (status != STATUS_SUCCESS) {
  226. SmartcardLogError(
  227. DriverObject,
  228. PSCR_INSUFFICIENT_RESOURCES,
  229. NULL,
  230. 0
  231. );
  232. leave;
  233. }
  234. // tell the lib our device object
  235. SmartcardExtension->OsData->DeviceObject = DeviceObject;
  236. DeviceExtension->AttachedPDO = IoAttachDeviceToDeviceStack(
  237. DeviceObject,
  238. PhysicalDeviceObject
  239. );
  240. if (DeviceExtension->AttachedPDO == NULL) {
  241. status = STATUS_UNSUCCESSFUL;
  242. leave;
  243. }
  244. // register our new device
  245. status = IoRegisterDeviceInterface(
  246. PhysicalDeviceObject,
  247. &SmartCardReaderGuid,
  248. NULL,
  249. &DeviceExtension->DeviceName
  250. );
  251. ASSERT(status == STATUS_SUCCESS);
  252. DeviceObject->Flags |= DO_BUFFERED_IO;
  253. DeviceObject->Flags |= DO_POWER_PAGABLE;
  254. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  255. //
  256. // try to read the reader name from the registry
  257. // if that does not work, we will use the default
  258. // (hardcoded) name
  259. //
  260. if (IoOpenDeviceRegistryKey(
  261. PhysicalDeviceObject,
  262. PLUGPLAY_REGKEY_DEVICE,
  263. KEY_READ,
  264. &regKey
  265. ) != STATUS_SUCCESS) {
  266. leave;
  267. }
  268. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  269. parameters[0].Name = L"VendorName";
  270. parameters[0].EntryContext = &vendorNameU;
  271. parameters[0].DefaultType = REG_SZ;
  272. parameters[0].DefaultData = &vendorNameU;
  273. parameters[0].DefaultLength = 0;
  274. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  275. parameters[1].Name = L"IfdType";
  276. parameters[1].EntryContext = &ifdTypeU;
  277. parameters[1].DefaultType = REG_SZ;
  278. parameters[1].DefaultData = &ifdTypeU;
  279. parameters[1].DefaultLength = 0;
  280. if (RtlQueryRegistryValues(
  281. RTL_REGISTRY_HANDLE,
  282. (PWSTR) regKey,
  283. parameters,
  284. NULL,
  285. NULL
  286. ) != STATUS_SUCCESS) {
  287. leave;
  288. }
  289. if (RtlUnicodeStringToAnsiString(
  290. &vendorNameA,
  291. &vendorNameU,
  292. TRUE
  293. ) != STATUS_SUCCESS) {
  294. leave;
  295. }
  296. if (RtlUnicodeStringToAnsiString(
  297. &ifdTypeA,
  298. &ifdTypeU,
  299. TRUE
  300. ) != STATUS_SUCCESS) {
  301. leave;
  302. }
  303. if (vendorNameA.Length == 0 ||
  304. vendorNameA.Length > MAXIMUM_ATTR_STRING_LENGTH ||
  305. ifdTypeA.Length == 0 ||
  306. ifdTypeA.Length > MAXIMUM_ATTR_STRING_LENGTH) {
  307. leave;
  308. }
  309. RtlCopyMemory(
  310. SmartcardExtension->VendorAttr.VendorName.Buffer,
  311. vendorNameA.Buffer,
  312. vendorNameA.Length
  313. );
  314. SmartcardExtension->VendorAttr.VendorName.Length =
  315. vendorNameA.Length;
  316. RtlCopyMemory(
  317. SmartcardExtension->VendorAttr.IfdType.Buffer,
  318. ifdTypeA.Buffer,
  319. ifdTypeA.Length
  320. );
  321. SmartcardExtension->VendorAttr.IfdType.Length =
  322. ifdTypeA.Length;
  323. }
  324. finally {
  325. if (vendorNameU.Buffer) {
  326. RtlFreeUnicodeString(&vendorNameU);
  327. }
  328. if (ifdTypeU.Buffer) {
  329. RtlFreeUnicodeString(&ifdTypeU);
  330. }
  331. if (vendorNameA.Buffer) {
  332. RtlFreeAnsiString(&vendorNameA);
  333. }
  334. if (ifdTypeA.Buffer) {
  335. RtlFreeAnsiString(&ifdTypeA);
  336. }
  337. if (regKey != NULL) {
  338. ZwClose(regKey);
  339. }
  340. if (status != STATUS_SUCCESS) {
  341. PscrUnloadDevice(DeviceObject);
  342. }
  343. SmartcardDebug(
  344. DEBUG_TRACE,
  345. ( "PSCR!PscrAddDevice: Exit %x\n",
  346. status)
  347. );
  348. }
  349. return status;
  350. }
  351. NTSTATUS
  352. PscrCallPcmciaDriver(
  353. IN PDEVICE_OBJECT AttachedPDO,
  354. IN PIRP Irp
  355. )
  356. /*++
  357. Routine Description:
  358. Send an Irp to the pcmcia driver and wait until the pcmcia driver has
  359. finished the request.
  360. To make sure that the pcmcia driver will not complete the Irp we first
  361. initialize an event and set our own completion routine for the Irp.
  362. When the pcmcia driver has processed the Irp the completion routine will
  363. set the event and tell the IO manager that more processing is required.
  364. By waiting for the event we make sure that we continue only if the pcmcia
  365. driver has processed the Irp completely.
  366. Return Value:
  367. status returned by the pcmcia driver
  368. --*/
  369. {
  370. NTSTATUS status = STATUS_SUCCESS;
  371. KEVENT Event;
  372. // Copy our stack location to the next.
  373. IoCopyCurrentIrpStackLocationToNext(Irp);
  374. //
  375. // initialize an event for process synchronization. the event is passed
  376. // to our completion routine and will be set if the pcmcia driver is done
  377. //
  378. KeInitializeEvent(
  379. &Event,
  380. NotificationEvent,
  381. FALSE
  382. );
  383. // Our IoCompletionRoutine sets only our event
  384. IoSetCompletionRoutine (
  385. Irp,
  386. PscrPcmciaCallComplete,
  387. &Event,
  388. TRUE,
  389. TRUE,
  390. TRUE
  391. );
  392. if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER) {
  393. status = PoCallDriver(AttachedPDO, Irp);
  394. } else {
  395. // Call the serial driver
  396. status = IoCallDriver(AttachedPDO, Irp);
  397. }
  398. // Wait until the pcmcia driver has processed the Irp
  399. if (status == STATUS_PENDING) {
  400. status = KeWaitForSingleObject(
  401. &Event,
  402. Executive,
  403. KernelMode,
  404. FALSE,
  405. NULL
  406. );
  407. if (status == STATUS_SUCCESS) {
  408. status = Irp->IoStatus.Status;
  409. }
  410. }
  411. return status;
  412. }
  413. NTSTATUS
  414. PscrPcmciaCallComplete (
  415. IN PDEVICE_OBJECT DeviceObject,
  416. IN PIRP Irp,
  417. IN PKEVENT Event
  418. )
  419. /*++
  420. Routine Description:
  421. Completion routine for an Irp sent to the pcmcia driver. The event will
  422. be set to notify that the pcmcia driver is done. The routine will not
  423. 'complete' the Irp, so the caller of PscrCallPcmciaDriver can continue.
  424. --*/
  425. {
  426. UNREFERENCED_PARAMETER (DeviceObject);
  427. if (Irp->Cancel) {
  428. Irp->IoStatus.Status = STATUS_CANCELLED;
  429. }
  430. KeSetEvent (Event, 0, FALSE);
  431. return STATUS_MORE_PROCESSING_REQUIRED;
  432. }
  433. NTSTATUS
  434. PscrPnP(
  435. IN PDEVICE_OBJECT DeviceObject,
  436. IN PIRP Irp
  437. )
  438. /*++
  439. Routine Description:
  440. driver callback for pnp manager
  441. All other requests will be passed to the pcmcia driver to ensure correct processing.
  442. --*/
  443. {
  444. NTSTATUS status = STATUS_SUCCESS;
  445. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  446. PIO_STACK_LOCATION IrpStack;
  447. PDEVICE_OBJECT AttachedPDO;
  448. BOOLEAN deviceRemoved = FALSE, irpSkipped = FALSE;
  449. KIRQL irql;
  450. LARGE_INTEGER timeout;
  451. SmartcardDebug(
  452. DEBUG_TRACE,
  453. ( "PSCR!PscrPnPDeviceControl: Enter\n" )
  454. );
  455. status = SmartcardAcquireRemoveLock(&DeviceExtension->SmartcardExtension);
  456. ASSERT(status == STATUS_SUCCESS);
  457. if (status != STATUS_SUCCESS) {
  458. Irp->IoStatus.Information = 0;
  459. Irp->IoStatus.Status = status;
  460. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  461. return status;
  462. }
  463. AttachedPDO = DeviceExtension->AttachedPDO;
  464. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  465. // Now look what the PnP manager wants...
  466. switch(IrpStack->MinorFunction)
  467. {
  468. case IRP_MN_START_DEVICE:
  469. // Now we should connect to our resources (Irql, Io etc.)
  470. SmartcardDebug(
  471. DEBUG_DRIVER,
  472. ("PSCR!PscrPnPDeviceControl: IRP_MN_START_DEVICE\n")
  473. );
  474. // We have to call the underlying driver first
  475. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  476. if (NT_SUCCESS(status)) {
  477. status = PscrStartDevice(
  478. DeviceObject,
  479. &IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0]
  480. );
  481. ASSERT(NT_SUCCESS(status));
  482. }
  483. break;
  484. case IRP_MN_QUERY_STOP_DEVICE:
  485. SmartcardDebug(
  486. DEBUG_DRIVER,
  487. ("PSCR!PscrPnPDeviceControl: IRP_MN_QUERY_STOP_DEVICE\n")
  488. );
  489. KeAcquireSpinLock(&DeviceExtension->SpinLock, &irql);
  490. if (DeviceExtension->IoCount > 0) {
  491. // we refuse to stop if we have pending io
  492. KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);
  493. status = STATUS_DEVICE_BUSY;
  494. } else {
  495. // stop processing requests
  496. KeClearEvent(&DeviceExtension->ReaderStarted);
  497. KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);
  498. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  499. }
  500. break;
  501. case IRP_MN_CANCEL_STOP_DEVICE:
  502. SmartcardDebug(
  503. DEBUG_DRIVER,
  504. ("PSCR!PscrPnPDeviceControl: IRP_MN_CANCEL_STOP_DEVICE\n")
  505. );
  506. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  507. ASSERT(status == STATUS_SUCCESS);
  508. // we can continue to process requests
  509. DeviceExtension->IoCount = 0;
  510. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  511. break;
  512. case IRP_MN_STOP_DEVICE:
  513. // Stop the device. Aka disconnect from our resources
  514. SmartcardDebug(
  515. DEBUG_DRIVER,
  516. ("PSCR!PscrPnPDeviceControl: IRP_MN_STOP_DEVICE\n")
  517. );
  518. PscrStopDevice(DeviceObject);
  519. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  520. break;
  521. case IRP_MN_QUERY_REMOVE_DEVICE:
  522. // Remove our device
  523. SmartcardDebug(
  524. DEBUG_DRIVER,
  525. ("PSCR!PscrPnPDeviceControl: IRP_MN_QUERY_REMOVE_DEVICE\n")
  526. );
  527. // disable the reader
  528. status = IoSetDeviceInterfaceState(
  529. &DeviceExtension->DeviceName,
  530. FALSE
  531. );
  532. ASSERT(status == STATUS_SUCCESS);
  533. if (status != STATUS_SUCCESS) {
  534. break;
  535. }
  536. //
  537. // check if the reader has been opened
  538. //
  539. if (DeviceExtension->ReaderOpen) {
  540. // someone is connected, enable the reader and fail the call
  541. IoSetDeviceInterfaceState(
  542. &DeviceExtension->DeviceName,
  543. TRUE
  544. );
  545. status = STATUS_UNSUCCESSFUL;
  546. break;
  547. }
  548. // pass the call to the next driver in the stack
  549. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  550. break;
  551. case IRP_MN_CANCEL_REMOVE_DEVICE:
  552. // Removal of device has been cancelled
  553. SmartcardDebug(
  554. DEBUG_DRIVER,
  555. ("PSCR!PscrPnPDeviceControl: IRP_MN_CANCEL_REMOVE_DEVICE\n")
  556. );
  557. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  558. if (status == STATUS_SUCCESS) {
  559. status = IoSetDeviceInterfaceState(
  560. &DeviceExtension->DeviceName,
  561. TRUE
  562. );
  563. }
  564. break;
  565. case IRP_MN_REMOVE_DEVICE:
  566. // Remove our device
  567. SmartcardDebug(
  568. DEBUG_DRIVER,
  569. ("PSCR!PscrPnPDeviceControl: IRP_MN_REMOVE_DEVICE\n")
  570. );
  571. KeSetEvent(&DeviceExtension->ReaderRemoved, 0, FALSE);
  572. PscrStopDevice(DeviceObject);
  573. PscrUnloadDevice(DeviceObject);
  574. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  575. deviceRemoved = TRUE;
  576. break;
  577. default:
  578. // This is an Irp that is only useful for underlying drivers
  579. status = PscrCallPcmciaDriver(AttachedPDO, Irp);
  580. irpSkipped = TRUE;
  581. break;
  582. }
  583. if (irpSkipped == FALSE) {
  584. // Don't touch the status field of irps we don't process
  585. Irp->IoStatus.Status = status;
  586. }
  587. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  588. if (deviceRemoved == FALSE) {
  589. SmartcardReleaseRemoveLock(&DeviceExtension->SmartcardExtension);
  590. }
  591. SmartcardDebug(
  592. DEBUG_TRACE,
  593. ( "PSCR!PscrPnPDeviceControl: Exit %x\n",
  594. status)
  595. );
  596. return status;
  597. }
  598. VOID
  599. PscrSystemPowerCompletion(
  600. IN PDEVICE_OBJECT DeviceObject,
  601. IN UCHAR MinorFunction,
  602. IN POWER_STATE PowerState,
  603. IN PKEVENT Event,
  604. IN PIO_STATUS_BLOCK IoStatus
  605. )
  606. /*++
  607. Routine Description:
  608. This function is called when the underlying stacks
  609. completed the power transition.
  610. --*/
  611. {
  612. UNREFERENCED_PARAMETER (DeviceObject);
  613. UNREFERENCED_PARAMETER (MinorFunction);
  614. UNREFERENCED_PARAMETER (PowerState);
  615. UNREFERENCED_PARAMETER (IoStatus);
  616. KeSetEvent(Event, 0, FALSE);
  617. }
  618. NTSTATUS
  619. PscrDevicePowerCompletion (
  620. IN PDEVICE_OBJECT DeviceObject,
  621. IN PIRP Irp,
  622. IN PSMARTCARD_EXTENSION SmartcardExtension
  623. )
  624. /*++
  625. Routine Description:
  626. This routine is called after the underlying stack powered
  627. UP the serial port, so it can be used again.
  628. --*/
  629. {
  630. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  631. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  632. NTSTATUS status;
  633. UCHAR state;
  634. if(Irp->PendingReturned) {
  635. IoMarkIrpPending(Irp);
  636. }
  637. status = CmdResetInterface(SmartcardExtension->ReaderExtension);
  638. ASSERT(status == STATUS_SUCCESS);
  639. SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
  640. state = CBGetCardState(SmartcardExtension);
  641. CBUpdateCardState(SmartcardExtension, state, TRUE);
  642. // save the current power state of the reader
  643. SmartcardExtension->ReaderExtension->ReaderPowerState =
  644. PowerReaderWorking;
  645. SmartcardReleaseRemoveLock(SmartcardExtension);
  646. // inform the power manager of our state.
  647. PoSetPowerState (
  648. DeviceObject,
  649. DevicePowerState,
  650. irpStack->Parameters.Power.State
  651. );
  652. PoStartNextPowerIrp(Irp);
  653. // signal that we can process ioctls again
  654. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  655. return STATUS_SUCCESS;
  656. }
  657. typedef enum _ACTION {
  658. Undefined = 0,
  659. SkipRequest,
  660. WaitForCompletion,
  661. CompleteRequest,
  662. MarkPending
  663. } ACTION;
  664. NTSTATUS
  665. PscrPower (
  666. IN PDEVICE_OBJECT DeviceObject,
  667. IN PIRP Irp
  668. )
  669. /*++
  670. Routine Description:
  671. The power dispatch routine.
  672. This driver is the power policy owner of the device stack,
  673. because this driver knows about the connected reader.
  674. Therefor this driver will translate system power states
  675. to device power states.
  676. Arguments:
  677. DeviceObject - pointer to a device object.
  678. Irp - pointer to an I/O Request Packet.
  679. Return Value:
  680. NT status code
  681. --*/
  682. {
  683. NTSTATUS status = STATUS_SUCCESS;
  684. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  685. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  686. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  687. POWER_STATE powerState;
  688. ACTION action = SkipRequest;
  689. KEVENT event;
  690. SmartcardDebug(
  691. DEBUG_DRIVER,
  692. ("PSCR!PscrPower: Enter\n")
  693. );
  694. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  695. //
  696. // Prefix initialization
  697. //
  698. powerState.DeviceState = PowerDeviceUnspecified;
  699. status = SmartcardAcquireRemoveLock(smartcardExtension);
  700. ASSERT(NT_SUCCESS(status));
  701. if (!NT_SUCCESS(status)) {
  702. PoStartNextPowerIrp(Irp);
  703. Irp->IoStatus.Status = status;
  704. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  705. return status;
  706. }
  707. if (irpStack->Parameters.Power.Type == DevicePowerState &&
  708. irpStack->MinorFunction == IRP_MN_SET_POWER) {
  709. switch (irpStack->Parameters.Power.State.DeviceState) {
  710. case PowerDeviceD0:
  711. // Turn on the reader
  712. SmartcardDebug(
  713. DEBUG_DRIVER,
  714. ("PSCR!PscrPower: PowerDevice D0\n")
  715. );
  716. //
  717. // First, we send down the request to the bus, in order
  718. // to power on the port. When the request completes,
  719. // we turn on the reader
  720. //
  721. IoCopyCurrentIrpStackLocationToNext(Irp);
  722. IoSetCompletionRoutine (
  723. Irp,
  724. PscrDevicePowerCompletion,
  725. smartcardExtension,
  726. TRUE,
  727. TRUE,
  728. TRUE
  729. );
  730. action = WaitForCompletion;
  731. break;
  732. case PowerDeviceD3:
  733. // Turn off the reader
  734. SmartcardDebug(
  735. DEBUG_DRIVER,
  736. ("PSCR!PscrPower: PowerDevice D3\n")
  737. );
  738. PoSetPowerState (
  739. DeviceObject,
  740. DevicePowerState,
  741. irpStack->Parameters.Power.State
  742. );
  743. // save the current card state
  744. smartcardExtension->ReaderExtension->CardPresent =
  745. smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  746. if (smartcardExtension->ReaderExtension->CardPresent) {
  747. smartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  748. status = CBCardPower(smartcardExtension);
  749. ASSERT(NT_SUCCESS(status));
  750. }
  751. // save the current power state of the reader
  752. smartcardExtension->ReaderExtension->ReaderPowerState =
  753. PowerReaderOff;
  754. action = SkipRequest;
  755. break;
  756. default:
  757. action = SkipRequest;
  758. break;
  759. }
  760. }
  761. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  762. //
  763. // The system wants to change the power state.
  764. // We need to translate the system power state to
  765. // a corresponding device power state.
  766. //
  767. POWER_STATE_TYPE powerType = DevicePowerState;
  768. ASSERT(smartcardExtension->ReaderExtension->ReaderPowerState !=
  769. PowerReaderUnspecified);
  770. switch(irpStack->MinorFunction) {
  771. KIRQL irql;
  772. case IRP_MN_QUERY_POWER:
  773. SmartcardDebug(
  774. DEBUG_DRIVER,
  775. ("PSCR!PscrPower: Query Power\n")
  776. );
  777. //
  778. // By default we succeed and pass down
  779. //
  780. action = SkipRequest;
  781. Irp->IoStatus.Status = STATUS_SUCCESS;
  782. switch (irpStack->Parameters.Power.State.SystemState) {
  783. case PowerSystemMaximum:
  784. case PowerSystemWorking:
  785. case PowerSystemSleeping1:
  786. case PowerSystemSleeping2:
  787. break;
  788. case PowerSystemSleeping3:
  789. case PowerSystemHibernate:
  790. case PowerSystemShutdown:
  791. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  792. if (deviceExtension->IoCount == 0) {
  793. // Block any further ioctls
  794. KeClearEvent(&deviceExtension->ReaderStarted);
  795. } else {
  796. // can't go to sleep mode since the reader is busy.
  797. status = STATUS_DEVICE_BUSY;
  798. action = CompleteRequest;
  799. }
  800. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  801. break;
  802. }
  803. break;
  804. case IRP_MN_SET_POWER:
  805. SmartcardDebug(
  806. DEBUG_DRIVER,
  807. ("PSCR!PscrPower: PowerSystem S%d\n",
  808. irpStack->Parameters.Power.State.SystemState - 1)
  809. );
  810. switch (irpStack->Parameters.Power.State.SystemState) {
  811. case PowerSystemMaximum:
  812. case PowerSystemWorking:
  813. case PowerSystemSleeping1:
  814. case PowerSystemSleeping2:
  815. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  816. PowerReaderWorking) {
  817. // We're already in the right state
  818. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  819. action = SkipRequest;
  820. break;
  821. }
  822. powerState.DeviceState = PowerDeviceD0;
  823. // wake up the underlying stack...
  824. action = MarkPending;
  825. break;
  826. case PowerSystemSleeping3:
  827. case PowerSystemHibernate:
  828. case PowerSystemShutdown:
  829. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  830. PowerReaderOff) {
  831. // We're already in the right state
  832. action = SkipRequest;
  833. break;
  834. }
  835. powerState.DeviceState = PowerDeviceD3;
  836. // first, inform the power manager of our new state.
  837. PoSetPowerState (
  838. DeviceObject,
  839. SystemPowerState,
  840. powerState
  841. );
  842. action = MarkPending;
  843. break;
  844. default:
  845. action = SkipRequest;
  846. break;
  847. }
  848. }
  849. }
  850. switch (action) {
  851. case CompleteRequest:
  852. Irp->IoStatus.Status = status;
  853. Irp->IoStatus.Information = 0;
  854. SmartcardReleaseRemoveLock(smartcardExtension);
  855. PoStartNextPowerIrp(Irp);
  856. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  857. break;
  858. case MarkPending:
  859. // initialize the event we need in the completion function
  860. KeInitializeEvent(
  861. &event,
  862. NotificationEvent,
  863. FALSE
  864. );
  865. // request the device power irp
  866. status = PoRequestPowerIrp (
  867. DeviceObject,
  868. IRP_MN_SET_POWER,
  869. powerState,
  870. PscrSystemPowerCompletion,
  871. &event,
  872. NULL
  873. );
  874. ASSERT(status == STATUS_PENDING);
  875. if (status == STATUS_PENDING) {
  876. // wait until the device power irp completed
  877. status = KeWaitForSingleObject(
  878. &event,
  879. Executive,
  880. KernelMode,
  881. FALSE,
  882. NULL
  883. );
  884. SmartcardReleaseRemoveLock(smartcardExtension);
  885. if (powerState.SystemState == PowerSystemWorking) {
  886. PoSetPowerState (
  887. DeviceObject,
  888. SystemPowerState,
  889. powerState
  890. );
  891. }
  892. PoStartNextPowerIrp(Irp);
  893. IoSkipCurrentIrpStackLocation(Irp);
  894. status = PoCallDriver(deviceExtension->AttachedPDO, Irp);
  895. } else {
  896. SmartcardReleaseRemoveLock(smartcardExtension);
  897. Irp->IoStatus.Status = status;
  898. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  899. }
  900. break;
  901. case SkipRequest:
  902. SmartcardReleaseRemoveLock(smartcardExtension);
  903. PoStartNextPowerIrp(Irp);
  904. IoSkipCurrentIrpStackLocation(Irp);
  905. status = PoCallDriver(deviceExtension->AttachedPDO, Irp);
  906. break;
  907. case WaitForCompletion:
  908. status = PoCallDriver(deviceExtension->AttachedPDO, Irp);
  909. break;
  910. default:
  911. ASSERT(FALSE);
  912. break;
  913. }
  914. SmartcardDebug(
  915. DEBUG_DRIVER,
  916. ("PSCR!PscrPower: Exit %lx\n",
  917. status)
  918. );
  919. return status;
  920. }
  921. NTSTATUS
  922. PscrStartDevice(
  923. PDEVICE_OBJECT DeviceObject,
  924. PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
  925. )
  926. /*++
  927. Routine Description:
  928. get the actual configuration from the passed FullResourceDescriptor
  929. and initializes the reader hardware
  930. Note:
  931. for an NT 4.00 build the resources must be translated by the HAL
  932. Arguments:
  933. DeviceObject context of call
  934. FullResourceDescriptor actual configuration of the reader
  935. Return Value:
  936. STATUS_SUCCESS
  937. status returned from the HAL (NT 4.00 only )
  938. status returned by LowLevel routines
  939. --*/
  940. {
  941. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
  942. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  943. PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
  944. PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
  945. NTSTATUS status;
  946. ULONG Count;
  947. SmartcardDebug(
  948. DEBUG_TRACE,
  949. ("PSCR!PscrStartDevice: Enter\n")
  950. );
  951. // Get the number of resources we need
  952. Count = FullResourceDescriptor->PartialResourceList.Count;
  953. PartialDescriptor = FullResourceDescriptor->PartialResourceList.PartialDescriptors;
  954. // parse all partial descriptors
  955. while(Count--)
  956. {
  957. switch(PartialDescriptor->Type)
  958. {
  959. case CmResourceTypePort: {
  960. // 0 - memory, 1 - IO
  961. ULONG AddressSpace = 1;
  962. BOOLEAN Translated;
  963. PHYSICAL_ADDRESS PhysicalAddress;
  964. ReaderExtension->IOBase =
  965. (PPSCR_REGISTERS) UlongToPtr(PartialDescriptor->u.Port.Start.LowPart);
  966. ASSERT(PartialDescriptor->u.Port.Length >= 4);
  967. SmartcardDebug(
  968. DEBUG_TRACE,
  969. ("PSCR!PscrStartDevice: IoBase = %lxh\n",
  970. ReaderExtension->IOBase)
  971. );
  972. break;
  973. }
  974. case CmResourceTypeInterrupt: {
  975. KINTERRUPT_MODE Mode;
  976. BOOLEAN Shared;
  977. KIRQL Irql;
  978. KAFFINITY Affinity;
  979. ULONG Vector;
  980. Mode = (
  981. PartialDescriptor->Flags &
  982. CM_RESOURCE_INTERRUPT_LATCHED ?
  983. Latched : LevelSensitive
  984. );
  985. Shared = (
  986. PartialDescriptor->ShareDisposition ==
  987. CmResourceShareShared
  988. );
  989. Vector = PartialDescriptor->u.Interrupt.Vector;
  990. Affinity = PartialDescriptor->u.Interrupt.Affinity;
  991. Irql = (KIRQL) PartialDescriptor->u.Interrupt.Level;
  992. // store IRQ to allow query configuration
  993. ReaderExtension->CurrentIRQ =
  994. PartialDescriptor->u.Interrupt.Vector;
  995. SmartcardDebug(
  996. DEBUG_TRACE,
  997. ("PSCR!PscrStartDevice: Irql: %d\n",
  998. PartialDescriptor->u.Interrupt.Level)
  999. );
  1000. // connect the driver's isr
  1001. status = IoConnectInterrupt(
  1002. &DeviceExtension->InterruptObject,
  1003. PscrIrqServiceRoutine,
  1004. (PVOID) DeviceExtension,
  1005. NULL,
  1006. Vector,
  1007. Irql,
  1008. Irql,
  1009. Mode,
  1010. Shared,
  1011. Affinity,
  1012. FALSE
  1013. );
  1014. break;
  1015. }
  1016. case CmResourceTypeDevicePrivate:
  1017. break;
  1018. default:
  1019. ASSERT(FALSE);
  1020. status = STATUS_UNSUCCESSFUL;
  1021. break;
  1022. }
  1023. PartialDescriptor++;
  1024. }
  1025. try {
  1026. HANDLE handle;
  1027. UCHAR CardState;
  1028. // IOBase initialized ?
  1029. if( ReaderExtension->IOBase == NULL ) {
  1030. //
  1031. // under NT 4.0 the failure of this fct for the second reader
  1032. // means there is only one device
  1033. //
  1034. SmartcardLogError(
  1035. DeviceObject,
  1036. PSCR_ERROR_IO_PORT,
  1037. NULL,
  1038. 0
  1039. );
  1040. status = STATUS_INSUFFICIENT_RESOURCES;
  1041. leave;
  1042. }
  1043. // irq connected ?
  1044. if( DeviceExtension->InterruptObject == NULL ) {
  1045. SmartcardLogError(
  1046. DeviceObject,
  1047. PSCR_ERROR_INTERRUPT,
  1048. NULL,
  1049. 0
  1050. );
  1051. status = STATUS_INSUFFICIENT_RESOURCES;
  1052. leave;
  1053. }
  1054. ReaderExtension->Device = DEVICE_ICC1;
  1055. ReaderExtension->MaxRetries = PSCR_MAX_RETRIES;
  1056. status = CmdResetInterface( ReaderExtension );
  1057. SmartcardExtension->ReaderCapabilities.MaxIFSD =
  1058. ReaderExtension->MaxIFSD;
  1059. if (status != STATUS_SUCCESS) {
  1060. SmartcardLogError(
  1061. DeviceObject,
  1062. PSCR_CANT_INITIALIZE_READER,
  1063. NULL,
  1064. 0
  1065. );
  1066. leave;
  1067. }
  1068. status = CmdReset(
  1069. ReaderExtension,
  1070. 0x00, // reader
  1071. FALSE, // cold reset
  1072. NULL, // no atr
  1073. NULL
  1074. );
  1075. if (status != STATUS_SUCCESS) {
  1076. SmartcardLogError(
  1077. DeviceObject,
  1078. PSCR_CANT_INITIALIZE_READER,
  1079. NULL,
  1080. 0
  1081. );
  1082. leave;
  1083. }
  1084. PscrFlushInterface(DeviceExtension->SmartcardExtension.ReaderExtension);
  1085. CmdGetFirmwareRevision(
  1086. DeviceExtension->SmartcardExtension.ReaderExtension
  1087. );
  1088. // If you change the min. firmware version here, please update
  1089. // the .mc file for the correct error message, too
  1090. if (SmartcardExtension->ReaderExtension->FirmwareMajor < 2 ||
  1091. SmartcardExtension->ReaderExtension->FirmwareMajor == 2 &&
  1092. SmartcardExtension->ReaderExtension->FirmwareMinor < 0x30) {
  1093. SmartcardLogError(
  1094. DeviceObject,
  1095. PSCR_WRONG_FIRMWARE,
  1096. NULL,
  1097. 0
  1098. );
  1099. }
  1100. //
  1101. // make sure the ICC1 status file in the reader file system will
  1102. // be selected
  1103. //
  1104. ReaderExtension->StatusFileSelected = FALSE;
  1105. CardState = CBGetCardState(&DeviceExtension->SmartcardExtension);
  1106. CBUpdateCardState(&DeviceExtension->SmartcardExtension, CardState, FALSE);
  1107. // signal that the reader has been started (again)
  1108. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  1109. status = IoSetDeviceInterfaceState(
  1110. &DeviceExtension->DeviceName,
  1111. TRUE
  1112. );
  1113. if (status == STATUS_OBJECT_NAME_EXISTS) {
  1114. // We tried to re-enable the device which is ok
  1115. // This can happen after a stop - start sequence
  1116. status = STATUS_SUCCESS;
  1117. }
  1118. ASSERT(status == STATUS_SUCCESS);
  1119. }
  1120. finally {
  1121. if (status != STATUS_SUCCESS) {
  1122. PscrStopDevice(DeviceObject);
  1123. }
  1124. SmartcardDebug(
  1125. DEBUG_TRACE,
  1126. ( "PSCR!PscrStartDevice: Exit %x\n",
  1127. status )
  1128. );
  1129. }
  1130. return status;
  1131. }
  1132. VOID
  1133. PscrStopDevice(
  1134. PDEVICE_OBJECT DeviceObject
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. Diconnect the interrupt used by the device & unmap the IO port
  1139. --*/
  1140. {
  1141. PDEVICE_EXTENSION DeviceExtension;
  1142. NTSTATUS status;
  1143. LARGE_INTEGER delayPeriod;
  1144. if (DeviceObject == NULL) {
  1145. return;
  1146. }
  1147. SmartcardDebug(
  1148. DEBUG_TRACE,
  1149. ( "PSCR!PscrStopDevice: Enter\n" )
  1150. );
  1151. DeviceExtension = DeviceObject->DeviceExtension;
  1152. KeClearEvent(&DeviceExtension->ReaderStarted);
  1153. // disconnect the interrupt
  1154. if( DeviceExtension->InterruptObject != NULL )
  1155. {
  1156. IoDisconnectInterrupt(DeviceExtension->InterruptObject);
  1157. DeviceExtension->InterruptObject = NULL;
  1158. }
  1159. // unmap ports
  1160. if(DeviceExtension->UnMapPort)
  1161. {
  1162. MmUnmapIoSpace(
  1163. DeviceExtension->SmartcardExtension.ReaderExtension->IOBase,
  1164. DeviceExtension->SmartcardExtension.ReaderExtension->IOWindow
  1165. );
  1166. DeviceExtension->UnMapPort = FALSE;
  1167. }
  1168. SmartcardDebug(
  1169. DEBUG_TRACE,
  1170. ( "PSCR!PscrStopDevice: Exit\n" )
  1171. );
  1172. }
  1173. VOID
  1174. PscrUnloadDevice(
  1175. PDEVICE_OBJECT DeviceObject
  1176. )
  1177. /*++
  1178. Routine Description:
  1179. close connections to smclib.sys and the pcmcia driver, delete symbolic
  1180. link and mark the slot as unused.
  1181. Arguments:
  1182. DeviceObject device to unload
  1183. Return Value:
  1184. void
  1185. --*/
  1186. {
  1187. PDEVICE_EXTENSION DeviceExtension;
  1188. NTSTATUS status;
  1189. if (DeviceObject == NULL) {
  1190. return;
  1191. }
  1192. SmartcardDebug(
  1193. DEBUG_TRACE,
  1194. ( "PSCR!PscrUnloadDevice: Enter\n" )
  1195. );
  1196. DeviceExtension = DeviceObject->DeviceExtension;
  1197. ASSERT(
  1198. DeviceExtension->SmartcardExtension.VendorAttr.UnitNo <
  1199. PSCR_MAX_DEVICE
  1200. );
  1201. if (DeviceExtension->DeviceName.Buffer != NULL) {
  1202. // disble our device so no one can open it
  1203. IoSetDeviceInterfaceState(
  1204. &DeviceExtension->DeviceName,
  1205. FALSE
  1206. );
  1207. }
  1208. // Mark this slot as available
  1209. DeviceSlot[DeviceExtension->SmartcardExtension.VendorAttr.UnitNo] = FALSE;
  1210. // report to the lib that the device will be unloaded
  1211. if(DeviceExtension->SmartcardExtension.OsData != NULL)
  1212. {
  1213. KIRQL CancelIrql;
  1214. PSMARTCARD_EXTENSION SmartcardExtension =
  1215. &DeviceExtension->SmartcardExtension;
  1216. ASSERT(SmartcardExtension->OsData->NotificationIrp == NULL);
  1217. IoAcquireCancelSpinLock( &CancelIrql );
  1218. if( SmartcardExtension->OsData->NotificationIrp != NULL )
  1219. {
  1220. PIRP notificationIrp;
  1221. notificationIrp = InterlockedExchangePointer(
  1222. &(SmartcardExtension->OsData->NotificationIrp),
  1223. NULL
  1224. );
  1225. IoSetCancelRoutine(
  1226. notificationIrp,
  1227. NULL
  1228. );
  1229. IoReleaseCancelSpinLock( CancelIrql );
  1230. SmartcardDebug(
  1231. DEBUG_TRACE,
  1232. ( "PSCR!PscrUnloadDevice: Completing NotificationIrp %lx\n",
  1233. notificationIrp)
  1234. );
  1235. // finish the request
  1236. notificationIrp->IoStatus.Status = STATUS_SUCCESS;
  1237. notificationIrp->IoStatus.Information = 0;
  1238. IoCompleteRequest(
  1239. notificationIrp,
  1240. IO_NO_INCREMENT
  1241. );
  1242. } else {
  1243. IoReleaseCancelSpinLock( CancelIrql );
  1244. }
  1245. // Wait until we can safely unload the device
  1246. SmartcardReleaseRemoveLockAndWait(SmartcardExtension);
  1247. SmartcardExit(&DeviceExtension->SmartcardExtension);
  1248. }
  1249. // delete the symbolic link
  1250. if( DeviceExtension->DeviceName.Buffer != NULL )
  1251. {
  1252. RtlFreeUnicodeString(&DeviceExtension->DeviceName);
  1253. DeviceExtension->DeviceName.Buffer = NULL;
  1254. }
  1255. if (DeviceExtension->SmartcardExtension.ReaderExtension != NULL) {
  1256. ExFreePool(DeviceExtension->SmartcardExtension.ReaderExtension);
  1257. DeviceExtension->SmartcardExtension.ReaderExtension = NULL;
  1258. }
  1259. // Detach from the pcmcia driver
  1260. if (DeviceExtension->AttachedPDO) {
  1261. IoDetachDevice(DeviceExtension->AttachedPDO);
  1262. DeviceExtension->AttachedPDO = NULL;
  1263. }
  1264. // delete the device object
  1265. IoDeleteDevice(DeviceObject);
  1266. SmartcardDebug(
  1267. DEBUG_TRACE,
  1268. ( "PSCR!PscrUnloadDevice: Exit\n" )
  1269. );
  1270. }
  1271. VOID
  1272. PscrUnloadDriver(
  1273. PDRIVER_OBJECT DriverObject
  1274. )
  1275. /*++
  1276. PscrUnloadDriver:
  1277. unloads all devices for a given driver object
  1278. Arguments:
  1279. DriverObject context of driver
  1280. --*/
  1281. {
  1282. SmartcardDebug(
  1283. DEBUG_TRACE,
  1284. ( "PSCR!PscrUnloadDriver\n" )
  1285. );
  1286. }
  1287. NTSTATUS
  1288. PscrCreateClose(
  1289. PDEVICE_OBJECT DeviceObject,
  1290. PIRP Irp
  1291. )
  1292. /*++
  1293. PscrCreateClose:
  1294. allowes only one open process a time
  1295. Arguments:
  1296. DeviceObject context of device
  1297. Irp context of call
  1298. Return Value:
  1299. STATUS_SUCCESS
  1300. STATUS_DEVICE_BUSY
  1301. --*/
  1302. {
  1303. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1304. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1305. NTSTATUS status = STATUS_SUCCESS;
  1306. __try {
  1307. if (irpStack->MajorFunction == IRP_MJ_CREATE) {
  1308. status = SmartcardAcquireRemoveLockWithTag(
  1309. &deviceExtension->SmartcardExtension,
  1310. 'lCrC'
  1311. );
  1312. if (status != STATUS_SUCCESS) {
  1313. status = STATUS_DEVICE_REMOVED;
  1314. __leave;
  1315. }
  1316. // test if the device has been opened already
  1317. if (InterlockedCompareExchange(
  1318. &deviceExtension->ReaderOpen,
  1319. TRUE,
  1320. FALSE) == FALSE) {
  1321. SmartcardDebug(
  1322. DEBUG_DRIVER,
  1323. ("%s!PscrCreateClose: Open\n",
  1324. DRIVER_NAME)
  1325. );
  1326. } else {
  1327. // the device is already in use
  1328. status = STATUS_UNSUCCESSFUL;
  1329. // release the lock
  1330. SmartcardReleaseRemoveLockWithTag(
  1331. &deviceExtension->SmartcardExtension,
  1332. 'lCrC'
  1333. );
  1334. }
  1335. } else {
  1336. SmartcardDebug(
  1337. DEBUG_DRIVER,
  1338. ("%s!PscrCreateClose: Close\n",
  1339. DRIVER_NAME)
  1340. );
  1341. SmartcardReleaseRemoveLockWithTag(
  1342. &deviceExtension->SmartcardExtension,
  1343. 'lCrC'
  1344. );
  1345. deviceExtension->ReaderOpen = FALSE;
  1346. }
  1347. }
  1348. __finally {
  1349. Irp->IoStatus.Status = status;
  1350. Irp->IoStatus.Information = 0;
  1351. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1352. }
  1353. return status;
  1354. }
  1355. NTSTATUS
  1356. PscrSystemControl(
  1357. PDEVICE_OBJECT DeviceObject,
  1358. PIRP Irp
  1359. )
  1360. /*++
  1361. PscrSystemControl:
  1362. --*/
  1363. {
  1364. PDEVICE_EXTENSION DeviceExtension;
  1365. NTSTATUS status = STATUS_SUCCESS;
  1366. DeviceExtension = DeviceObject->DeviceExtension;
  1367. IoSkipCurrentIrpStackLocation(Irp);
  1368. status = IoCallDriver(DeviceExtension->AttachedPDO, Irp);
  1369. return status;
  1370. }
  1371. NTSTATUS
  1372. PscrDeviceIoControl(
  1373. PDEVICE_OBJECT DeviceObject,
  1374. PIRP Irp
  1375. )
  1376. /*++
  1377. PscrDeviceIoControl:
  1378. all IRP's requiring IO are queued to the StartIo routine, other requests
  1379. are served immediately
  1380. --*/
  1381. {
  1382. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1383. NTSTATUS status;
  1384. KIRQL irql;
  1385. LARGE_INTEGER timeout;
  1386. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1387. if (deviceExtension->IoCount == 0) {
  1388. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1389. status = KeWaitForSingleObject(
  1390. &deviceExtension->ReaderStarted,
  1391. Executive,
  1392. KernelMode,
  1393. FALSE,
  1394. NULL
  1395. );
  1396. ASSERT(status == STATUS_SUCCESS);
  1397. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1398. }
  1399. ASSERT(deviceExtension->IoCount >= 0);
  1400. deviceExtension->IoCount++;
  1401. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1402. timeout.QuadPart = 0;
  1403. status = KeWaitForSingleObject(
  1404. &deviceExtension->ReaderRemoved,
  1405. Executive,
  1406. KernelMode,
  1407. FALSE,
  1408. &timeout
  1409. );
  1410. if (status == STATUS_SUCCESS) {
  1411. status = STATUS_DEVICE_REMOVED;
  1412. } else {
  1413. status = SmartcardAcquireRemoveLock(&deviceExtension->SmartcardExtension);
  1414. }
  1415. if (status != STATUS_SUCCESS) {
  1416. // the device has been removed. Fail the call
  1417. Irp->IoStatus.Information = 0;
  1418. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  1419. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1420. return STATUS_DEVICE_REMOVED;
  1421. }
  1422. status = SmartcardDeviceControl(
  1423. &(deviceExtension->SmartcardExtension),
  1424. Irp
  1425. );
  1426. SmartcardReleaseRemoveLock(&deviceExtension->SmartcardExtension);
  1427. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1428. deviceExtension->IoCount--;
  1429. ASSERT(deviceExtension->IoCount >= 0);
  1430. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1431. return status;
  1432. }
  1433. NTSTATUS
  1434. PscrGenericIOCTL(
  1435. PSMARTCARD_EXTENSION SmartcardExtension
  1436. )
  1437. /*++
  1438. PscrGenericIOCTL:
  1439. Performs generic callbacks to the reader
  1440. Arguments:
  1441. SmartcardExtension context of the call
  1442. Return Value:
  1443. STATUS_SUCCESS
  1444. --*/
  1445. {
  1446. NTSTATUS NTStatus;
  1447. PIRP Irp;
  1448. PIO_STACK_LOCATION IrpStack;
  1449. SmartcardDebug(
  1450. DEBUG_TRACE,
  1451. ( "PSCR!PscrGenericIOCTL: Enter\n" )
  1452. );
  1453. //
  1454. // get pointer to current IRP stack location
  1455. //
  1456. Irp = SmartcardExtension->OsData->CurrentIrp;
  1457. IrpStack = IoGetCurrentIrpStackLocation( Irp );
  1458. //
  1459. // assume error
  1460. //
  1461. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  1462. Irp->IoStatus.Information = 0;
  1463. //
  1464. // dispatch IOCTL
  1465. //
  1466. switch( IrpStack->Parameters.DeviceIoControl.IoControlCode )
  1467. {
  1468. case IOCTL_PSCR_COMMAND:
  1469. NTStatus = CmdPscrCommand(
  1470. SmartcardExtension->ReaderExtension,
  1471. (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
  1472. IrpStack->Parameters.DeviceIoControl.InputBufferLength,
  1473. (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
  1474. IrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  1475. (PULONG) &Irp->IoStatus.Information
  1476. );
  1477. //
  1478. // the command could change the active file in the reader file
  1479. // system, so make sure that the status file will be selected
  1480. // before the next read
  1481. //
  1482. SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
  1483. break;
  1484. case IOCTL_GET_VERSIONS:
  1485. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  1486. SIZEOF_VERSION_CONTROL )
  1487. {
  1488. NTStatus = STATUS_BUFFER_TOO_SMALL;
  1489. }
  1490. else
  1491. {
  1492. PVERSION_CONTROL VersionControl;
  1493. VersionControl = (PVERSION_CONTROL)Irp->AssociatedIrp.SystemBuffer;
  1494. VersionControl->SmclibVersion = SmartcardExtension->Version;
  1495. VersionControl->DriverMajor = PSCR_MAJOR_VERSION;
  1496. VersionControl->DriverMinor = PSCR_MINOR_VERSION;
  1497. // update firmware version (changed after update)
  1498. CmdGetFirmwareRevision(
  1499. SmartcardExtension->ReaderExtension
  1500. );
  1501. VersionControl->FirmwareMajor =
  1502. SmartcardExtension->ReaderExtension->FirmwareMajor;
  1503. VersionControl->FirmwareMinor =
  1504. SmartcardExtension->ReaderExtension->FirmwareMinor;
  1505. VersionControl->UpdateKey =
  1506. SmartcardExtension->ReaderExtension->UpdateKey;
  1507. Irp->IoStatus.Information = SIZEOF_VERSION_CONTROL;
  1508. NTStatus = STATUS_SUCCESS;
  1509. }
  1510. break;
  1511. case IOCTL_SET_TIMEOUT:
  1512. {
  1513. ULONG NewLimit;
  1514. //
  1515. // get new timeout limit
  1516. //
  1517. if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength ==
  1518. sizeof( ULONG ))
  1519. {
  1520. NewLimit = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
  1521. }
  1522. else
  1523. {
  1524. NewLimit = 0;
  1525. }
  1526. //
  1527. // report actual timeout limit
  1528. //
  1529. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength ==
  1530. sizeof( ULONG ))
  1531. {
  1532. *(PULONG)Irp->AssociatedIrp.SystemBuffer =
  1533. SmartcardExtension->ReaderExtension->MaxRetries * DELAY_PSCR_WAIT;
  1534. Irp->IoStatus.Information = sizeof( ULONG );
  1535. }
  1536. //
  1537. // set new timeout limit
  1538. //
  1539. if( NewLimit != 0 )
  1540. {
  1541. SmartcardExtension->ReaderExtension->MaxRetries =
  1542. (NewLimit + DELAY_PSCR_WAIT - 1) / DELAY_PSCR_WAIT;
  1543. }
  1544. }
  1545. NTStatus = STATUS_SUCCESS;
  1546. break;
  1547. case IOCTL_GET_CONFIGURATION:
  1548. //
  1549. // return IOBase and IRQ
  1550. //
  1551. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  1552. SIZEOF_PSCR_CONFIGURATION )
  1553. {
  1554. NTStatus = STATUS_BUFFER_TOO_SMALL;
  1555. }
  1556. else
  1557. {
  1558. PPSCR_CONFIGURATION PSCRConfiguration;
  1559. PSCRConfiguration =
  1560. (PPSCR_CONFIGURATION)Irp->AssociatedIrp.SystemBuffer;
  1561. PSCRConfiguration->IOBase =
  1562. SmartcardExtension->ReaderExtension->IOBase;
  1563. PSCRConfiguration->IRQ =
  1564. SmartcardExtension->ReaderExtension->CurrentIRQ;
  1565. Irp->IoStatus.Information = SIZEOF_PSCR_CONFIGURATION;
  1566. NTStatus = STATUS_SUCCESS;
  1567. }
  1568. break;
  1569. default:
  1570. break;
  1571. }
  1572. //
  1573. // set status of the packet
  1574. //
  1575. Irp->IoStatus.Status = NTStatus;
  1576. SmartcardDebug(
  1577. DEBUG_TRACE,
  1578. ( "PSCR!PscrGenericIOCTL: Exit\n" )
  1579. );
  1580. return( NTStatus );
  1581. }
  1582. BOOLEAN
  1583. PscrIrqServiceRoutine(
  1584. PKINTERRUPT Interrupt,
  1585. PDEVICE_EXTENSION DeviceExtension
  1586. )
  1587. /*++
  1588. PscrIrqServiceRoutine:
  1589. because the device not supports shared interrupts, the call is passed
  1590. to the DPC routine immediately and the IRQ is reported as served
  1591. Arguments:
  1592. Interrupt interrupt object related to the interrupt
  1593. DeviceExtension context of call
  1594. Return Value:
  1595. STATUS_SUCCESS
  1596. --*/
  1597. {
  1598. SmartcardDebug(
  1599. DEBUG_TRACE,
  1600. ("PSCR!PscrIrqServiceRoutine: Enter\n")
  1601. );
  1602. //
  1603. // When someone yanks out the card the interrupt handler gets called,
  1604. // but since there is no card anymore when don't need to schedule a DPC
  1605. //
  1606. //
  1607. // the interrupt is caused by a freeze event. the interface will be
  1608. // cleared either by PscrRead() or the DPC routine (depending on
  1609. // which is called first)
  1610. //
  1611. DeviceExtension->SmartcardExtension.ReaderExtension->FreezePending = TRUE;
  1612. InterlockedIncrement(&DeviceExtension->PendingInterrupts);
  1613. KeInsertQueueDpc(
  1614. &DeviceExtension->DpcObject,
  1615. DeviceExtension,
  1616. &DeviceExtension->SmartcardExtension
  1617. );
  1618. SmartcardDebug(
  1619. DEBUG_TRACE,
  1620. ( "PSCR!PscrIrqServiceRoutine: Exit\n" )
  1621. );
  1622. return TRUE;
  1623. }
  1624. VOID
  1625. PscrDpcRoutine(
  1626. PKDPC Dpc,
  1627. PDEVICE_OBJECT DeviceObject,
  1628. PDEVICE_EXTENSION DeviceExtension,
  1629. PSMARTCARD_EXTENSION SmartcardExtension
  1630. )
  1631. /*++
  1632. PscrDpcRoutine:
  1633. finishes interrupt requests. the freeze event data of the reader will be read
  1634. & the card state will be updated if data valid
  1635. Arguments:
  1636. Dpc dpc object related to the call
  1637. DeviceObject context of the device
  1638. DeviceExtension passed as system argument 1
  1639. SmartcardExtension passed as system argument 2
  1640. Return Value:
  1641. void
  1642. --*/
  1643. {
  1644. NTSTATUS status = STATUS_SUCCESS;
  1645. UCHAR Event;
  1646. SmartcardDebug(
  1647. DEBUG_TRACE,
  1648. ( "PSCR!PscrInterruptEvent: IoBase %xh\n",
  1649. SmartcardExtension->ReaderExtension->IOBase)
  1650. );
  1651. //
  1652. // In case of a card change the reader provides a TLV packet describing
  1653. // the event ('freeze event'). If PscrRead was called before the DPC
  1654. // routine is called, this event was cleared; in this case the card state
  1655. // will be updated by reading the card status file
  1656. //
  1657. if( DeviceExtension->IoCount > 0 ) {
  1658. SmartcardExtension->ReaderExtension->RequestCancelled = TRUE;
  1659. }
  1660. do {
  1661. ASSERT(DeviceExtension->PendingInterrupts < 10);
  1662. SmartcardDebug(
  1663. DEBUG_TRACE,
  1664. ( "PSCR!PscrInterruptEvent: PendingInterrupts = %ld\n",
  1665. DeviceExtension->PendingInterrupts)
  1666. );
  1667. PscrFreeze( SmartcardExtension );
  1668. } while (InterlockedDecrement(&DeviceExtension->PendingInterrupts) > 0);
  1669. }
  1670. void
  1671. PscrFreeze(
  1672. PSMARTCARD_EXTENSION SmartcardExtension
  1673. )
  1674. /*++
  1675. PscrFreeze:
  1676. Read & evaluate freeze data
  1677. Arguments:
  1678. ReaderExtension context of call
  1679. pDevice device which causes the freeze event
  1680. Return Value:
  1681. STATUS_SUCCESS
  1682. STATUS_UNSUCCESSFUL
  1683. --*/
  1684. {
  1685. NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
  1686. PREADER_EXTENSION ReaderExtension;
  1687. PPSCR_REGISTERS IOBase;
  1688. UCHAR TLVList[9], CardState;
  1689. ULONG NBytes;
  1690. ULONG Idx, Retries, Status;
  1691. UCHAR ReadFreeze[] = { 0x12, 0x00, 0x05, 0x00, 0xB0, 0x00, 0x00, 0x01, 0xA6 };
  1692. ReaderExtension = SmartcardExtension->ReaderExtension;
  1693. IOBase = ReaderExtension->IOBase;
  1694. ReaderExtension->RequestCancelled = FALSE;
  1695. for (Retries = 0; Retries < 5; Retries++) {
  1696. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  1697. ReaderExtension->InvalidStatus = TRUE;
  1698. if(!( Status & PSCR_DATA_AVAIL_BIT ))
  1699. {
  1700. PscrWriteDirect(
  1701. ReaderExtension,
  1702. ReadFreeze,
  1703. sizeof( ReadFreeze ),
  1704. &NBytes
  1705. );
  1706. SysDelay(15);
  1707. }
  1708. NTStatus = PscrRead(
  1709. ReaderExtension,
  1710. (PUCHAR) TLVList,
  1711. sizeof( TLVList ),
  1712. &NBytes
  1713. );
  1714. ReaderExtension->InvalidStatus = FALSE;
  1715. if( NT_SUCCESS( NTStatus ) && ( NBytes == 9 ))
  1716. {
  1717. // get result
  1718. if( ( TLVList[ PSCR_NAD ] == 0x21 ) &&
  1719. ( TLVList[ PSCR_INF ] == TAG_FREEZE_EVENTS ))
  1720. {
  1721. CardState =
  1722. (TLVList[PSCR_INF + 2] == DEVICE_ICC1 ? PSCR_ICC_PRESENT : PSCR_ICC_ABSENT);
  1723. SmartcardDebug(
  1724. DEBUG_TRACE,
  1725. ( "PSCR!PscrFreeze: CardState = %d\n",
  1726. CardState)
  1727. );
  1728. CBUpdateCardState(SmartcardExtension, CardState, FALSE);
  1729. }
  1730. }
  1731. }
  1732. }
  1733. NTSTATUS
  1734. PscrCancel(
  1735. IN PDEVICE_OBJECT DeviceObject,
  1736. IN PIRP Irp
  1737. )
  1738. /*++
  1739. Routine Description:
  1740. This routine is called by the I/O system
  1741. when the irp should be cancelled
  1742. Arguments:
  1743. DeviceObject - Pointer to device object for this miniport
  1744. Irp - IRP involved.
  1745. Return Value:
  1746. STATUS_CANCELLED
  1747. --*/
  1748. {
  1749. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1750. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1751. SmartcardDebug(
  1752. DEBUG_TRACE,
  1753. ("PSCR!PscrCancel: Enter\n")
  1754. );
  1755. ASSERT(Irp == smartcardExtension->OsData->NotificationIrp);
  1756. smartcardExtension->OsData->NotificationIrp = NULL;
  1757. Irp->IoStatus.Information = 0;
  1758. Irp->IoStatus.Status = STATUS_CANCELLED;
  1759. IoReleaseCancelSpinLock(
  1760. Irp->CancelIrql
  1761. );
  1762. SmartcardDebug(
  1763. DEBUG_DRIVER,
  1764. ("PSCR!PscrCancel: Completing wait for Irp = %lx\n",
  1765. Irp)
  1766. );
  1767. IoCompleteRequest(
  1768. Irp,
  1769. IO_NO_INCREMENT
  1770. );
  1771. SmartcardDebug(
  1772. DEBUG_TRACE,
  1773. ("PSCR!PscrCancel: Exit\n")
  1774. );
  1775. return STATUS_CANCELLED;
  1776. }
  1777. NTSTATUS
  1778. PscrCleanup(
  1779. IN PDEVICE_OBJECT DeviceObject,
  1780. IN PIRP Irp
  1781. )
  1782. /*++
  1783. Routine Description:
  1784. This routine is called by the I/O system when the calling thread terminates
  1785. Arguments:
  1786. DeviceObject - Pointer to device object for this miniport
  1787. Irp - IRP involved.
  1788. Return Value:
  1789. STATUS_CANCELLED
  1790. --*/
  1791. {
  1792. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1793. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1794. NTSTATUS status = STATUS_SUCCESS;
  1795. SmartcardDebug(
  1796. DEBUG_TRACE,
  1797. ("%s!PscrCleanup: Enter\n",
  1798. DRIVER_NAME)
  1799. );
  1800. IoAcquireCancelSpinLock(&(Irp->CancelIrql));
  1801. if (smartcardExtension->OsData->NotificationIrp) {
  1802. // We need to complete the notification irp
  1803. IoSetCancelRoutine(
  1804. smartcardExtension->OsData->NotificationIrp,
  1805. NULL
  1806. );
  1807. PscrCancel(
  1808. DeviceObject,
  1809. smartcardExtension->OsData->NotificationIrp
  1810. );
  1811. } else {
  1812. IoReleaseCancelSpinLock( Irp->CancelIrql );
  1813. }
  1814. SmartcardDebug(
  1815. DEBUG_DRIVER,
  1816. ("%s!PscrCleanup: Completing IRP %lx\n",
  1817. DRIVER_NAME,
  1818. Irp)
  1819. );
  1820. Irp->IoStatus.Information = 0;
  1821. Irp->IoStatus.Status = STATUS_SUCCESS;
  1822. IoCompleteRequest(
  1823. Irp,
  1824. IO_NO_INCREMENT
  1825. );
  1826. SmartcardDebug(
  1827. DEBUG_TRACE,
  1828. ("%s!PscrCleanup: Exit\n",
  1829. DRIVER_NAME)
  1830. );
  1831. return STATUS_SUCCESS;
  1832. }
  1833. void
  1834. SysDelay(
  1835. ULONG Timeout
  1836. )
  1837. /*++
  1838. SysDelay:
  1839. performs a required delay. The usage of KeStallExecutionProcessor is
  1840. very nasty, but it happends only if SysDelay is called in the context of
  1841. our DPC routine (which is only called if a card change was detected).
  1842. For 'normal' IO we have Irql < DISPATCH_LEVEL, so if the reader is polled
  1843. while waiting for response we will not block the entire system
  1844. Arguments:
  1845. Timeout delay in milli seconds
  1846. Return Value:
  1847. void
  1848. --*/
  1849. {
  1850. LARGE_INTEGER SysTimeout;
  1851. if( KeGetCurrentIrql() >= DISPATCH_LEVEL )
  1852. {
  1853. ULONG Cnt = 20 * Timeout;
  1854. while( Cnt-- )
  1855. {
  1856. // KeStallExecutionProcessor: counted in us
  1857. KeStallExecutionProcessor( 50 );
  1858. }
  1859. }
  1860. else
  1861. {
  1862. SysTimeout.QuadPart = (LONGLONG)-10 * 1000 * Timeout;
  1863. // KeDelayExecutionThread: counted in 100 ns
  1864. KeDelayExecutionThread( KernelMode, FALSE, &SysTimeout );
  1865. }
  1866. return;
  1867. }