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.

894 lines
24 KiB

  1. /*++
  2. Copyright (c) 1991-1998 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. Author:
  7. Neil Sandlin (neilsa) 26-Apr-99
  8. Environment:
  9. Kernel mode only.
  10. --*/
  11. #include "pch.h"
  12. //
  13. // Internal References
  14. //
  15. NTSTATUS
  16. MemCardStartDevice(
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PIRP Irp
  19. );
  20. NTSTATUS
  21. MemCardGetResourceRequirements(
  22. IN PDEVICE_OBJECT DeviceObject,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. MemCardPnpComplete (
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp,
  29. IN PVOID Context
  30. );
  31. NTSTATUS
  32. MemCardGetDeviceParameters(
  33. IN PMEMCARD_EXTENSION memcardExtension
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE,MemCardAddDevice)
  37. #pragma alloc_text(PAGE,MemCardPnp)
  38. #pragma alloc_text(PAGE,MemCardStartDevice)
  39. #endif
  40. #define MEMCARD_DEVICE_NAME L"\\Device\\Memcard"
  41. #define MEMCARD_LINK_NAME L"\\DosDevices\\Memcard"
  42. #define MEMCARD_REGISTRY_NODRIVE_KEY L"NoDrive"
  43. #define MEMCARD_REGISTRY_MTD_KEY L"Mtd"
  44. NTSTATUS
  45. MemCardAddDevice(
  46. IN PDRIVER_OBJECT DriverObject,
  47. IN OUT PDEVICE_OBJECT PhysicalDeviceObject
  48. )
  49. /*++
  50. Routine Description:
  51. This routine is the driver's pnp add device entry point. It is
  52. called by the pnp manager to initialize the driver.
  53. Add device creates and initializes a device object for this FDO and
  54. attaches to the underlying PDO.
  55. Arguments:
  56. DriverObject - a pointer to the object that represents this device driver.
  57. PhysicalDeviceObject - a pointer to the underlying PDO to which this new device will attach.
  58. Return Value:
  59. If we successfully create a device object, STATUS_SUCCESS is
  60. returned. Otherwise, return the appropriate error code.
  61. --*/
  62. {
  63. NTSTATUS status = STATUS_SUCCESS;
  64. PDEVICE_OBJECT deviceObject;
  65. PMEMCARD_EXTENSION memcardExtension;
  66. WCHAR NameBuffer[128];
  67. UNICODE_STRING deviceName;
  68. UNICODE_STRING linkName;
  69. LONG deviceNumber = -1;
  70. KEVENT event;
  71. PIRP irp;
  72. IO_STATUS_BLOCK statusBlock;
  73. PIO_STACK_LOCATION irpSp;
  74. MemCardDump(MEMCARDSHOW, ("MemCard: AddDevice...\n"));
  75. //
  76. // Create a device. We will use the first available device name for
  77. // this device.
  78. //
  79. do {
  80. swprintf(NameBuffer, L"%s%d", MEMCARD_DEVICE_NAME, ++deviceNumber);
  81. RtlInitUnicodeString(&deviceName, NameBuffer);
  82. status = IoCreateDevice(DriverObject,
  83. sizeof(MEMCARD_EXTENSION),
  84. &deviceName,
  85. FILE_DEVICE_DISK,
  86. FILE_REMOVABLE_MEDIA,
  87. FALSE,
  88. &deviceObject);
  89. } while (status == STATUS_OBJECT_NAME_COLLISION);
  90. if (!NT_SUCCESS(status)) {
  91. return status;
  92. }
  93. memcardExtension = (PMEMCARD_EXTENSION)deviceObject->DeviceExtension;
  94. RtlZeroMemory(memcardExtension, sizeof(MEMCARD_EXTENSION));
  95. memcardExtension->DeviceObject = deviceObject;
  96. //
  97. // Save the device name.
  98. //
  99. MemCardDump(MEMCARDSHOW | MEMCARDPNP,
  100. ("MemCard: AddDevice - Device Object Name - %S\n", NameBuffer));
  101. memcardExtension->DeviceName.Buffer = ExAllocatePool(PagedPool, deviceName.Length);
  102. if (memcardExtension->DeviceName.Buffer == NULL) {
  103. status = STATUS_INSUFFICIENT_RESOURCES;
  104. goto errorExit;
  105. }
  106. memcardExtension->DeviceName.Length = 0;
  107. memcardExtension->DeviceName.MaximumLength = deviceName.Length;
  108. RtlCopyUnicodeString(&memcardExtension->DeviceName, &deviceName);
  109. //
  110. // create the link name
  111. //
  112. swprintf(NameBuffer, L"%s%d", MEMCARD_LINK_NAME, deviceNumber);
  113. RtlInitUnicodeString(&linkName, NameBuffer);
  114. memcardExtension->LinkName.Buffer = ExAllocatePool(PagedPool, linkName.Length);
  115. if (memcardExtension->LinkName.Buffer == NULL) {
  116. status = STATUS_INSUFFICIENT_RESOURCES;
  117. goto errorExit;
  118. }
  119. memcardExtension->LinkName.Length = 0;
  120. memcardExtension->LinkName.MaximumLength = linkName.Length;
  121. RtlCopyUnicodeString(&memcardExtension->LinkName, &linkName);
  122. status = IoCreateSymbolicLink(&memcardExtension->LinkName, &memcardExtension->DeviceName);
  123. if (!NT_SUCCESS(status)) {
  124. goto errorExit;
  125. }
  126. //
  127. // Set the PDO for use with PlugPlay functions
  128. //
  129. memcardExtension->UnderlyingPDO = PhysicalDeviceObject;
  130. MemCardDump(MEMCARDSHOW, ("MemCard: AddDevice attaching %p to %p\n", deviceObject, PhysicalDeviceObject));
  131. memcardExtension->TargetObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  132. MemCardDump(MEMCARDSHOW,
  133. ("MemCard: AddDevice TargetObject = %p\n",
  134. memcardExtension->TargetObject));
  135. //
  136. // Get pcmcia interfaces
  137. //
  138. KeInitializeEvent(&event, NotificationEvent, FALSE);
  139. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, memcardExtension->UnderlyingPDO,
  140. NULL, 0, 0, &event, &statusBlock);
  141. if (!irp) {
  142. status = STATUS_INSUFFICIENT_RESOURCES;
  143. goto errorExit;
  144. }
  145. irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
  146. irp->IoStatus.Information = 0;
  147. irpSp = IoGetNextIrpStackLocation(irp);
  148. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  149. irpSp->Parameters.QueryInterface.InterfaceType= &GUID_PCMCIA_INTERFACE_STANDARD;
  150. irpSp->Parameters.QueryInterface.Size = sizeof(PCMCIA_INTERFACE_STANDARD);
  151. irpSp->Parameters.QueryInterface.Version = 1;
  152. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &memcardExtension->PcmciaInterface;
  153. status = IoCallDriver(memcardExtension->UnderlyingPDO, irp);
  154. if (status == STATUS_PENDING) {
  155. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  156. status = statusBlock.Status;
  157. }
  158. if (!NT_SUCCESS(status)) {
  159. goto errorExit;
  160. }
  161. KeInitializeEvent(&event, NotificationEvent, FALSE);
  162. irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, memcardExtension->UnderlyingPDO,
  163. NULL, 0, 0, &event, &statusBlock);
  164. if (!irp) {
  165. status = STATUS_INSUFFICIENT_RESOURCES;
  166. goto errorExit;
  167. }
  168. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  169. irp->IoStatus.Information = 0;
  170. irpSp = IoGetNextIrpStackLocation(irp);
  171. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  172. irpSp->Parameters.QueryInterface.InterfaceType= &GUID_PCMCIA_BUS_INTERFACE_STANDARD;
  173. irpSp->Parameters.QueryInterface.Size = sizeof(PCMCIA_BUS_INTERFACE_STANDARD);
  174. irpSp->Parameters.QueryInterface.Version = 1;
  175. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &memcardExtension->PcmciaBusInterface;
  176. status = IoCallDriver(memcardExtension->UnderlyingPDO, irp);
  177. if (status == STATUS_PENDING) {
  178. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  179. status = statusBlock.Status;
  180. }
  181. if (!NT_SUCCESS(status)) {
  182. goto errorExit;
  183. }
  184. status = MemCardGetDeviceParameters(memcardExtension);
  185. if (!NT_SUCCESS(status)) {
  186. goto errorExit;
  187. }
  188. //
  189. // done
  190. //
  191. deviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
  192. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  193. memcardExtension->IsStarted = FALSE;
  194. memcardExtension->IsRemoved = FALSE;
  195. return STATUS_SUCCESS;
  196. errorExit:
  197. if (memcardExtension->DeviceName.Buffer != NULL) {
  198. ExFreePool(memcardExtension->DeviceName.Buffer);
  199. }
  200. if (memcardExtension->LinkName.Buffer != NULL) {
  201. IoDeleteSymbolicLink(&memcardExtension->LinkName);
  202. ExFreePool(memcardExtension->LinkName.Buffer);
  203. }
  204. if (memcardExtension->TargetObject) {
  205. IoDetachDevice(memcardExtension->TargetObject);
  206. }
  207. IoDeleteDevice(deviceObject);
  208. return status;
  209. }
  210. NTSTATUS
  211. MemCardPnp(
  212. IN PDEVICE_OBJECT DeviceObject,
  213. IN PIRP Irp
  214. )
  215. /*++
  216. Routine Description:
  217. Main PNP irp dispatch routine
  218. Arguments:
  219. DeviceObject - a pointer to the object that represents the device
  220. that I/O is to be done on.
  221. Irp - a pointer to the I/O Request Packet for this request.
  222. Return Value:
  223. status
  224. --*/
  225. {
  226. PIO_STACK_LOCATION irpSp;
  227. PMEMCARD_EXTENSION memcardExtension;
  228. NTSTATUS status = STATUS_SUCCESS;
  229. ULONG i;
  230. memcardExtension = DeviceObject->DeviceExtension;
  231. irpSp = IoGetCurrentIrpStackLocation(Irp);
  232. MemCardDump(MEMCARDPNP, ("MemCard: DO %.8x Irp %.8x PNP func %x\n",
  233. DeviceObject, Irp, irpSp->MinorFunction));
  234. if (memcardExtension->IsRemoved) {
  235. //
  236. // Since the device is stopped, but we don't hold IRPs,
  237. // this is a surprise removal. Just fail it.
  238. //
  239. Irp->IoStatus.Information = 0;
  240. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  241. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  242. return STATUS_DELETE_PENDING;
  243. }
  244. switch (irpSp->MinorFunction) {
  245. case IRP_MN_START_DEVICE:
  246. status = MemCardStartDevice(DeviceObject, Irp);
  247. break;
  248. case IRP_MN_QUERY_STOP_DEVICE:
  249. case IRP_MN_QUERY_REMOVE_DEVICE:
  250. if (irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) {
  251. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_QUERY_STOP_DEVICE\n"));
  252. } else {
  253. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_QUERY_REMOVE_DEVICE\n"));
  254. }
  255. if (!memcardExtension->IsStarted) {
  256. //
  257. // If we aren't started, we'll just pass the irp down.
  258. //
  259. IoSkipCurrentIrpStackLocation (Irp);
  260. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  261. return status;
  262. }
  263. Irp->IoStatus.Status = STATUS_SUCCESS;
  264. IoSkipCurrentIrpStackLocation(Irp);
  265. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  266. break;
  267. case IRP_MN_CANCEL_STOP_DEVICE:
  268. case IRP_MN_CANCEL_REMOVE_DEVICE:
  269. if (irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) {
  270. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_CANCEL_STOP_DEVICE\n"));
  271. } else {
  272. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  273. }
  274. if (!memcardExtension->IsStarted) {
  275. //
  276. // Nothing to do, just pass the irp down:
  277. // no need to start the device
  278. //
  279. IoSkipCurrentIrpStackLocation (Irp);
  280. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  281. } else {
  282. KEVENT doneEvent;
  283. //
  284. // Set the status to STATUS_SUCCESS
  285. //
  286. Irp->IoStatus.Status = STATUS_SUCCESS;
  287. //
  288. // We need to wait for the lower drivers to do their job.
  289. //
  290. IoCopyCurrentIrpStackLocationToNext (Irp);
  291. //
  292. // Clear the event: it will be set in the completion
  293. // routine.
  294. //
  295. KeInitializeEvent(&doneEvent,
  296. SynchronizationEvent,
  297. FALSE);
  298. IoSetCompletionRoutine(Irp,
  299. MemCardPnpComplete,
  300. &doneEvent,
  301. TRUE, TRUE, TRUE);
  302. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  303. if (status == STATUS_PENDING) {
  304. KeWaitForSingleObject(&doneEvent,
  305. Executive,
  306. KernelMode,
  307. FALSE,
  308. NULL);
  309. status = Irp->IoStatus.Status;
  310. }
  311. //
  312. // We must now complete the IRP, since we stopped it in the
  313. // completetion routine with MORE_PROCESSING_REQUIRED.
  314. //
  315. Irp->IoStatus.Status = status;
  316. Irp->IoStatus.Information = 0;
  317. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  318. }
  319. break;
  320. case IRP_MN_STOP_DEVICE:
  321. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_STOP_DEVICE\n"));
  322. if (memcardExtension->IsMemoryMapped) {
  323. MmUnmapIoSpace(memcardExtension->MemoryWindowBase, memcardExtension->MemoryWindowSize);
  324. memcardExtension->MemoryWindowBase = 0;
  325. memcardExtension->MemoryWindowSize = 0;
  326. memcardExtension->IsMemoryMapped = FALSE;
  327. }
  328. memcardExtension->IsStarted = FALSE;
  329. Irp->IoStatus.Status = STATUS_SUCCESS;
  330. IoSkipCurrentIrpStackLocation(Irp);
  331. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  332. break;
  333. case IRP_MN_REMOVE_DEVICE:
  334. MemCardDump(MEMCARDPNP,("MemCard: IRP_MN_REMOVE_DEVICE\n"));
  335. //
  336. // We need to mark the fact that we don't hold requests first, since
  337. // we asserted earlier that we are holding requests only if
  338. // we're not removed.
  339. //
  340. memcardExtension->IsStarted = FALSE;
  341. memcardExtension->IsRemoved = TRUE;
  342. //
  343. // Forward this Irp to the underlying PDO
  344. //
  345. IoSkipCurrentIrpStackLocation(Irp);
  346. Irp->IoStatus.Status = STATUS_SUCCESS;
  347. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  348. //
  349. // Send notification that we are going away.
  350. //
  351. if (memcardExtension->InterfaceString.Buffer != NULL) {
  352. IoSetDeviceInterfaceState(&memcardExtension->InterfaceString,
  353. FALSE);
  354. RtlFreeUnicodeString(&memcardExtension->InterfaceString);
  355. RtlInitUnicodeString(&memcardExtension->InterfaceString, NULL);
  356. }
  357. //
  358. // Remove our link
  359. //
  360. IoDeleteSymbolicLink(&memcardExtension->LinkName);
  361. RtlFreeUnicodeString(&memcardExtension->LinkName);
  362. RtlInitUnicodeString(&memcardExtension->LinkName, NULL);
  363. RtlFreeUnicodeString(&memcardExtension->DeviceName);
  364. RtlInitUnicodeString(&memcardExtension->DeviceName, NULL);
  365. //
  366. // Detatch from the undelying device.
  367. //
  368. IoDetachDevice(memcardExtension->TargetObject);
  369. //
  370. // And delete the device.
  371. //
  372. IoDeleteDevice(DeviceObject);
  373. break;
  374. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  375. status = MemCardGetResourceRequirements(DeviceObject, Irp);
  376. break;
  377. default:
  378. MemCardDump(MEMCARDPNP, ("MemCardPnp: Unsupported PNP Request %x - Irp: %p\n",irpSp->MinorFunction, Irp));
  379. IoSkipCurrentIrpStackLocation(Irp);
  380. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  381. }
  382. return status;
  383. }
  384. NTSTATUS
  385. MemCardStartDevice(
  386. IN PDEVICE_OBJECT DeviceObject,
  387. IN PIRP Irp
  388. )
  389. /*++
  390. Routine Description:
  391. Start device routine
  392. Arguments:
  393. DeviceObject - a pointer to the object that represents the device
  394. that I/O is to be done on.
  395. Irp - a pointer to the I/O Request Packet for this request.
  396. Return Value:
  397. status
  398. --*/
  399. {
  400. NTSTATUS status;
  401. NTSTATUS pnpStatus;
  402. KEVENT doneEvent;
  403. PCM_RESOURCE_LIST ResourceList;
  404. PCM_RESOURCE_LIST TranslatedResourceList;
  405. PCM_PARTIAL_RESOURCE_LIST partialResourceList, partialTranslatedList;
  406. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDesc, partialTranslatedDesc;
  407. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceDesc, fullTranslatedDesc;
  408. PMEMCARD_EXTENSION memcardExtension = (PMEMCARD_EXTENSION)DeviceObject->DeviceExtension;
  409. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  410. MemCardDump(MEMCARDPNP,("MemCard: StartDevice\n"));
  411. MemCardDump(MEMCARDSHOW, (" AllocatedResources = %08x\n",irpSp->Parameters.StartDevice.AllocatedResources));
  412. MemCardDump(MEMCARDSHOW, (" AllocatedResourcesTranslated = %08x\n",irpSp->Parameters.StartDevice.AllocatedResourcesTranslated));
  413. //
  414. // First we must pass this Irp on to the PDO.
  415. //
  416. KeInitializeEvent(&doneEvent, NotificationEvent, FALSE);
  417. IoCopyCurrentIrpStackLocationToNext(Irp);
  418. IoSetCompletionRoutine(Irp,
  419. MemCardPnpComplete,
  420. &doneEvent,
  421. TRUE, TRUE, TRUE);
  422. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  423. if (status == STATUS_PENDING) {
  424. status = KeWaitForSingleObject(&doneEvent,
  425. Executive,
  426. KernelMode,
  427. FALSE,
  428. NULL);
  429. ASSERT(status == STATUS_SUCCESS);
  430. status = Irp->IoStatus.Status;
  431. }
  432. if (!NT_SUCCESS(status)) {
  433. Irp->IoStatus.Status = status;
  434. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  435. return status;
  436. }
  437. //
  438. // Parse the resources to map the memory window
  439. //
  440. ResourceList = irpSp->Parameters.StartDevice.AllocatedResources;
  441. TranslatedResourceList = irpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  442. fullResourceDesc = &ResourceList->List[0];
  443. fullTranslatedDesc = &TranslatedResourceList->List[0];
  444. partialResourceList = &fullResourceDesc->PartialResourceList;
  445. partialTranslatedList = &fullTranslatedDesc->PartialResourceList;
  446. partialResourceDesc = partialResourceList->PartialDescriptors;
  447. partialTranslatedDesc = partialTranslatedList->PartialDescriptors;
  448. if (partialResourceDesc->Type != CmResourceTypeMemory) {
  449. ASSERT(partialResourceDesc->Type == CmResourceTypeMemory);
  450. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  451. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  452. return STATUS_INVALID_PARAMETER;
  453. }
  454. memcardExtension->HostBase = partialTranslatedDesc->u.Memory.Start.QuadPart;
  455. memcardExtension->MemoryWindowSize = partialTranslatedDesc->u.Memory.Length;
  456. //
  457. //
  458. switch (partialTranslatedDesc->Type) {
  459. case CmResourceTypeMemory:
  460. memcardExtension->MemoryWindowBase = MmMapIoSpace(partialTranslatedDesc->u.Memory.Start,
  461. partialTranslatedDesc->u.Memory.Length,
  462. FALSE);
  463. memcardExtension->IsMemoryMapped = TRUE;
  464. break;
  465. case CmResourceTypePort:
  466. memcardExtension->MemoryWindowBase = (PUCHAR) partialResourceDesc->u.Port.Start.QuadPart;
  467. memcardExtension->IsMemoryMapped = FALSE;
  468. break;
  469. default:
  470. ASSERT(FALSE);
  471. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  472. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  473. return STATUS_INVALID_PARAMETER;
  474. }
  475. //
  476. // Try to get the capacity of the card
  477. //
  478. memcardExtension->ByteCapacity = MemCardGetCapacity(memcardExtension);
  479. //
  480. // If we can't get the capacity, the must be broken in some way
  481. //
  482. if (!memcardExtension->ByteCapacity) {
  483. Irp->IoStatus.Status = STATUS_UNRECOGNIZED_MEDIA;
  484. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  485. return STATUS_UNRECOGNIZED_MEDIA;
  486. }
  487. if (!memcardExtension->NoDrive) {
  488. pnpStatus = IoRegisterDeviceInterface(memcardExtension->UnderlyingPDO,
  489. (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID,
  490. NULL,
  491. &memcardExtension->InterfaceString);
  492. if ( NT_SUCCESS(pnpStatus) ) {
  493. pnpStatus = IoSetDeviceInterfaceState(&memcardExtension->InterfaceString,
  494. TRUE);
  495. }
  496. }
  497. memcardExtension->IsStarted = TRUE;
  498. Irp->IoStatus.Status = status;
  499. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  500. return status;
  501. }
  502. NTSTATUS
  503. MemCardPnpComplete (
  504. IN PDEVICE_OBJECT DeviceObject,
  505. IN PIRP Irp,
  506. IN PVOID Context
  507. )
  508. /*++
  509. Routine Description:
  510. A completion routine for use when calling the lower device objects to
  511. which our bus (FDO) is attached.
  512. --*/
  513. {
  514. KeSetEvent ((PKEVENT) Context, 1, FALSE);
  515. // No special priority
  516. // No Wait
  517. return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
  518. }
  519. NTSTATUS
  520. MemCardGetResourceRequirements(
  521. IN PDEVICE_OBJECT DeviceObject,
  522. IN PIRP Irp
  523. )
  524. /*++
  525. Routine Description:
  526. Provides a memory resource requirement in case the bus driver
  527. doesn't.
  528. Arguments:
  529. DeviceObject - a pointer to the object that represents the device
  530. that I/O is to be done on.
  531. Irp - a pointer to the I/O Request Packet for this request.
  532. Return Value:
  533. status
  534. --*/
  535. {
  536. NTSTATUS status;
  537. KEVENT doneEvent;
  538. PIO_RESOURCE_REQUIREMENTS_LIST ioResourceRequirementsList;
  539. PIO_RESOURCE_LIST ioResourceList;
  540. PIO_RESOURCE_DESCRIPTOR ioResourceDesc;
  541. PMEMCARD_EXTENSION memcardExtension = (PMEMCARD_EXTENSION)DeviceObject->DeviceExtension;
  542. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  543. ULONG listSize;
  544. //
  545. // First we must pass this Irp on to the PDO.
  546. //
  547. KeInitializeEvent(&doneEvent, NotificationEvent, FALSE);
  548. IoCopyCurrentIrpStackLocationToNext(Irp);
  549. IoSetCompletionRoutine(Irp,
  550. MemCardPnpComplete,
  551. &doneEvent,
  552. TRUE, TRUE, TRUE);
  553. status = IoCallDriver(memcardExtension->TargetObject, Irp);
  554. if (status == STATUS_PENDING) {
  555. status = KeWaitForSingleObject(&doneEvent,
  556. Executive,
  557. KernelMode,
  558. FALSE,
  559. NULL);
  560. ASSERT(status == STATUS_SUCCESS);
  561. status = Irp->IoStatus.Status;
  562. }
  563. if (NT_SUCCESS(status) && (Irp->IoStatus.Information == 0)) {
  564. listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
  565. ioResourceRequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, listSize);
  566. RtlZeroMemory(ioResourceRequirementsList, listSize);
  567. ioResourceRequirementsList->ListSize = listSize;
  568. ioResourceRequirementsList->AlternativeLists = 1;
  569. //
  570. // NOTE: not quite sure if the following values are the best choices
  571. //
  572. ioResourceRequirementsList->InterfaceType = Isa;
  573. ioResourceRequirementsList->BusNumber = 0;
  574. ioResourceRequirementsList->SlotNumber = 0;
  575. ioResourceList = &ioResourceRequirementsList->List[0];
  576. ioResourceList->Version = 1;
  577. ioResourceList->Revision = 1;
  578. ioResourceList->Count = 1;
  579. ioResourceDesc = &ioResourceList->Descriptors[0];
  580. ioResourceDesc->Option = 0;
  581. ioResourceDesc->Type = CmResourceTypeMemory;
  582. ioResourceDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  583. ioResourceDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  584. ioResourceDesc->u.Memory.MinimumAddress.QuadPart = 0;
  585. ioResourceDesc->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)-1;
  586. ioResourceDesc->u.Memory.Length = 0x2000;
  587. ioResourceDesc->u.Memory.Alignment = 0x2000;
  588. Irp->IoStatus.Information = (ULONG_PTR)ioResourceRequirementsList;
  589. }
  590. Irp->IoStatus.Status = status;
  591. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  592. return status;
  593. }
  594. NTSTATUS
  595. MemCardGetDeviceParameters(
  596. IN PMEMCARD_EXTENSION memcardExtension
  597. )
  598. /*++
  599. Routine Description:
  600. Loads device specific parameters from the registry
  601. Arguments:
  602. memcardExtension - device extension of the device
  603. Return Value:
  604. status
  605. --*/
  606. {
  607. NTSTATUS status;
  608. HANDLE instanceHandle;
  609. UNICODE_STRING KeyName;
  610. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32*sizeof(UCHAR)];
  611. PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
  612. ULONG length;
  613. if (!memcardExtension->UnderlyingPDO) {
  614. return STATUS_UNSUCCESSFUL;
  615. }
  616. status = IoOpenDeviceRegistryKey(memcardExtension->UnderlyingPDO,
  617. PLUGPLAY_REGKEY_DRIVER,
  618. KEY_READ,
  619. &instanceHandle
  620. );
  621. if (!NT_SUCCESS(status)) {
  622. return(status);
  623. }
  624. //
  625. // Read in the "NoDrive" parameter
  626. //
  627. RtlInitUnicodeString(&KeyName, MEMCARD_REGISTRY_NODRIVE_KEY);
  628. status = ZwQueryValueKey(instanceHandle,
  629. &KeyName,
  630. KeyValuePartialInformation,
  631. value,
  632. sizeof(buffer),
  633. &length);
  634. if (NT_SUCCESS(status)) {
  635. memcardExtension->NoDrive = (BOOLEAN) (*(PULONG)(value->Data) != 0);
  636. }
  637. //
  638. // Read in the MTD name
  639. //
  640. RtlInitUnicodeString(&KeyName, MEMCARD_REGISTRY_MTD_KEY);
  641. status = ZwQueryValueKey(instanceHandle,
  642. &KeyName,
  643. KeyValuePartialInformation,
  644. value,
  645. sizeof(buffer),
  646. &length);
  647. if (NT_SUCCESS(status)) {
  648. UNICODE_STRING TechnologyName;
  649. RtlInitUnicodeString(&TechnologyName, (PVOID)value->Data);
  650. status = MemCardInitializeMtd(memcardExtension, &TechnologyName);
  651. }
  652. ZwClose(instanceHandle);
  653. return status;
  654. }