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.

1122 lines
28 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. pdopnp.c
  5. Abstract:
  6. This module contains the code to handle
  7. the IRP_MJ_PNP dispatches for the PDOs
  8. enumerated by the SD bus driver
  9. Authors:
  10. Neil Sandlin (neilsa) 1-Jan-2002
  11. Environment:
  12. Kernel mode only
  13. Notes:
  14. Revision History:
  15. --*/
  16. #include "pch.h"
  17. //
  18. // Internal References
  19. //
  20. NTSTATUS
  21. SdbusPdoDeviceCapabilities(
  22. IN PDEVICE_OBJECT Pdo,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. SdbusPdoStartDevice(
  27. IN PDEVICE_OBJECT Pdo,
  28. IN PCM_RESOURCE_LIST AllocatedResources,
  29. IN OUT PIRP Irp
  30. );
  31. NTSTATUS
  32. SdbusPdoStopDevice(
  33. IN PDEVICE_OBJECT Pdo
  34. );
  35. NTSTATUS
  36. SdbusPdoRemoveDevice(
  37. IN PDEVICE_OBJECT Pdo,
  38. IN PIRP Irp
  39. );
  40. NTSTATUS
  41. SdbusPdoQueryId(
  42. IN PDEVICE_OBJECT Pdo,
  43. IN PIRP Irp
  44. );
  45. NTSTATUS
  46. SdbusPdoGetBusInformation(
  47. IN PPDO_EXTENSION PdoExtension,
  48. OUT PPNP_BUS_INFORMATION * BusInformation
  49. );
  50. NTSTATUS
  51. SdbusQueryDeviceText(
  52. IN PDEVICE_OBJECT Pdo,
  53. IN OUT PIRP Irp
  54. );
  55. VOID
  56. SdbusPdoGetDeviceInfSettings(
  57. IN PPDO_EXTENSION PdoExtension
  58. );
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(PAGE, SdbusPdoPnpDispatch)
  61. #pragma alloc_text(PAGE, SdbusPdoGetDeviceInfSettings)
  62. #pragma alloc_text(PAGE, SdbusQueryDeviceText)
  63. #pragma alloc_text(PAGE, SdbusPdoGetBusInformation)
  64. #pragma alloc_text(PAGE, SdbusPdoStartDevice)
  65. #pragma alloc_text(PAGE, SdbusPdoStopDevice)
  66. #pragma alloc_text(PAGE, SdbusPdoRemoveDevice)
  67. #pragma alloc_text(PAGE, SdbusPdoDeviceCapabilities)
  68. #pragma alloc_text(PAGE, SdbusPdoGetDeviceInfSettings)
  69. #endif
  70. NTSTATUS
  71. SdbusPdoPnpDispatch(
  72. IN PDEVICE_OBJECT Pdo,
  73. IN PIRP Irp
  74. )
  75. /*++
  76. Routine Description:
  77. This routine handles pnp requests
  78. for the PDOs.
  79. Arguments:
  80. Pdo - pointer to the physical device object
  81. Irp - pointer to the io request packet
  82. Return Value:
  83. status
  84. --*/
  85. {
  86. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  87. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  88. NTSTATUS status;
  89. PAGED_CODE();
  90. #if DBG
  91. if (irpStack->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  92. DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x Unknown minor function %x\n",
  93. Pdo, Irp, irpStack->MinorFunction));
  94. } else {
  95. DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x --> %s\n",
  96. Pdo, Irp, PNP_IRP_STRING(irpStack->MinorFunction)));
  97. }
  98. #endif
  99. switch (irpStack->MinorFunction) {
  100. case IRP_MN_START_DEVICE:
  101. status = SdbusPdoStartDevice(Pdo, irpStack->Parameters.StartDevice.AllocatedResources, Irp);
  102. break;
  103. case IRP_MN_QUERY_STOP_DEVICE:
  104. status = STATUS_SUCCESS;
  105. break;
  106. case IRP_MN_CANCEL_STOP_DEVICE:
  107. status = STATUS_SUCCESS;
  108. break;
  109. case IRP_MN_STOP_DEVICE:
  110. status = SdbusPdoStopDevice(Pdo);
  111. break;
  112. case IRP_MN_QUERY_REMOVE_DEVICE:
  113. status = STATUS_SUCCESS;
  114. break;
  115. case IRP_MN_CANCEL_REMOVE_DEVICE:
  116. status = STATUS_SUCCESS;
  117. break;
  118. case IRP_MN_REMOVE_DEVICE:
  119. status = SdbusPdoRemoveDevice(Pdo, Irp);
  120. break;
  121. case IRP_MN_SURPRISE_REMOVAL:
  122. // SdbusReleaseSocketPower(pdoExtension, NULL);
  123. status = STATUS_SUCCESS;
  124. break;
  125. case IRP_MN_QUERY_ID:
  126. status = SdbusPdoQueryId(Pdo, Irp);
  127. break;
  128. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  129. status = STATUS_SUCCESS;
  130. break;
  131. case IRP_MN_QUERY_RESOURCES:
  132. status = STATUS_SUCCESS;
  133. break;
  134. case IRP_MN_QUERY_DEVICE_RELATIONS: {
  135. PDEVICE_RELATIONS deviceRelations;
  136. if (irpStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) {
  137. status = Irp->IoStatus.Status;
  138. break;
  139. }
  140. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  141. if (deviceRelations == NULL) {
  142. DebugPrint((SDBUS_DEBUG_FAIL,
  143. "SdbusPdoPnpDispatch:unable to allocate memory for device relations\n"));
  144. status = STATUS_INSUFFICIENT_RESOURCES;
  145. break;
  146. }
  147. status = ObReferenceObjectByPointer(Pdo,
  148. 0,
  149. NULL,
  150. KernelMode);
  151. if (!NT_SUCCESS(status)) {
  152. ExFreePool(deviceRelations);
  153. break;
  154. }
  155. deviceRelations->Count = 1;
  156. deviceRelations->Objects[0] = Pdo;
  157. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  158. status = STATUS_SUCCESS;
  159. break;
  160. }
  161. case IRP_MN_QUERY_CAPABILITIES:
  162. status = SdbusPdoDeviceCapabilities(Pdo, Irp);
  163. break;
  164. case IRP_MN_QUERY_DEVICE_TEXT:
  165. status = SdbusQueryDeviceText(Pdo, Irp);
  166. if (status == STATUS_NOT_SUPPORTED ) {
  167. //
  168. // Do not change IRP status if this IRP is
  169. // not handled
  170. //
  171. status = Irp->IoStatus.Status;
  172. }
  173. break;
  174. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  175. status = STATUS_SUCCESS;
  176. break;
  177. case IRP_MN_QUERY_BUS_INFORMATION:
  178. status = SdbusPdoGetBusInformation(pdoExtension,
  179. (PPNP_BUS_INFORMATION *) &Irp->IoStatus.Information);
  180. break;
  181. default:
  182. //
  183. // Retain the status
  184. //
  185. DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x Skipping unsupported irp\n", Pdo, Irp));
  186. status = Irp->IoStatus.Status;
  187. break;
  188. }
  189. Irp->IoStatus.Status = status;
  190. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  191. DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x comp %s %08x\n", Pdo, Irp,
  192. STATUS_STRING(status), status));
  193. return status;
  194. }
  195. NTSTATUS
  196. SdbusPdoGetBusInformation(
  197. IN PPDO_EXTENSION PdoExtension,
  198. OUT PPNP_BUS_INFORMATION * BusInformation
  199. )
  200. /*++
  201. Routine Description:
  202. Returns the bus type information for the pc-card.
  203. Bus type is GUID_BUS_TYPE_SDBUS(legacy type is SdbusBus) for R2 cards
  204. Bus numbers are not implemented for SDBUS, so it's always 0
  205. Arguments:
  206. PdoExtension - pointer to device extension for the pc-card
  207. BusInformation - pointer to the bus information structure that
  208. needs to be filled in
  209. Return value:
  210. Status
  211. --*/
  212. {
  213. PAGED_CODE();
  214. *BusInformation = ExAllocatePool(PagedPool, sizeof (PNP_BUS_INFORMATION));
  215. if (!*BusInformation) {
  216. return STATUS_INSUFFICIENT_RESOURCES;
  217. }
  218. RtlCopyMemory(&((*BusInformation)->BusTypeGuid),
  219. &GUID_BUS_TYPE_SD,
  220. sizeof(GUID));
  221. (*BusInformation)->LegacyBusType = InterfaceTypeUndefined;
  222. (*BusInformation)->BusNumber = 0;
  223. return STATUS_SUCCESS;
  224. }
  225. VOID
  226. SdbusPdoGetDeviceInfSettings(
  227. IN PPDO_EXTENSION PdoExtension
  228. )
  229. /*++
  230. Routine Description:
  231. This routine retrieves settings from the INF for this device.
  232. Arguments:
  233. DeviceExtension - Device extension of the Pc-Card
  234. Return value:
  235. None
  236. --*/
  237. {
  238. NTSTATUS status;
  239. UNICODE_STRING KeyName;
  240. HANDLE instanceHandle;
  241. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
  242. PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
  243. ULONG length;
  244. PAGED_CODE();
  245. status = IoOpenDeviceRegistryKey(PdoExtension->DeviceObject,
  246. PLUGPLAY_REGKEY_DRIVER,
  247. KEY_READ,
  248. &instanceHandle
  249. );
  250. if (NT_SUCCESS(status)) {
  251. #if 0
  252. //
  253. // Look to see if SdbusExclusiveIrq is specified
  254. //
  255. RtlInitUnicodeString(&KeyName, L"SdbusExclusiveIrq");
  256. status = ZwQueryValueKey(instanceHandle,
  257. &KeyName,
  258. KeyValuePartialInformation,
  259. value,
  260. sizeof(buffer),
  261. &length);
  262. //
  263. // If the key doesn't exist, or zero was specified, it means that
  264. // routing is ok
  265. //
  266. if (NT_SUCCESS(status) && (*(PULONG)(value->Data) != 0)) {
  267. SetDeviceFlag(PdoExtension, SDBUS_PDO_EXCLUSIVE_IRQ);
  268. }
  269. #endif
  270. ZwClose(instanceHandle);
  271. }
  272. }
  273. NTSTATUS
  274. SdbusQueryDeviceText(
  275. IN PDEVICE_OBJECT Pdo,
  276. IN OUT PIRP Irp
  277. )
  278. /*++
  279. Routine Description:
  280. Returns descriptive text information about the
  281. PDO (location and device desc.)
  282. Arguments:
  283. Pdo - Pointer to the PC-Card's device object
  284. Irp - IRP_MN_QUERY_DEVICE_TEXT Irp
  285. Return Value:
  286. STATUS_SUCCESS
  287. STATUS_NOT_SUPPORTED - if not supported
  288. --*/
  289. {
  290. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  291. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  292. UNICODE_STRING unicodeString;
  293. ANSI_STRING ansiString;
  294. UCHAR deviceText[128];
  295. NTSTATUS status;
  296. USHORT deviceTextLength;
  297. PAGED_CODE();
  298. if (irpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  299. if (pdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_IO) {
  300. PUCHAR mfg, prod;
  301. if (pdoExtension->FdoExtension->CardData->MfgText[0]) {
  302. mfg = pdoExtension->FdoExtension->CardData->MfgText;
  303. } else {
  304. mfg = "Generic";
  305. }
  306. if (pdoExtension->FdoExtension->CardData->ProductText[0]) {
  307. prod = pdoExtension->FdoExtension->CardData->ProductText;
  308. } else {
  309. prod = "SD IO Device";
  310. }
  311. sprintf(deviceText, "%s %s", mfg, prod);
  312. } else {
  313. sprintf(deviceText, "%s", "Secure Digital Storage Device");
  314. }
  315. RtlInitAnsiString(&ansiString, deviceText);
  316. deviceTextLength = (strlen(deviceText) + 1)*sizeof(WCHAR);
  317. unicodeString.Buffer = ExAllocatePool(PagedPool, deviceTextLength);
  318. if (unicodeString.Buffer == NULL) {
  319. return STATUS_INSUFFICIENT_RESOURCES;
  320. }
  321. unicodeString.MaximumLength = deviceTextLength;
  322. unicodeString.Length = 0;
  323. status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
  324. if (!NT_SUCCESS(status)) {
  325. ExFreePool(unicodeString.Buffer);
  326. return status;
  327. }
  328. unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR)] = L'\0';
  329. Irp->IoStatus.Information = (ULONG_PTR) unicodeString.Buffer;
  330. status = STATUS_SUCCESS;
  331. } else {
  332. status = STATUS_NOT_SUPPORTED ;
  333. }
  334. return status;
  335. }
  336. NTSTATUS
  337. SdbusGenerateDeviceId(
  338. IN PPDO_EXTENSION PdoExtension,
  339. OUT PUCHAR *DeviceId
  340. )
  341. /*++
  342. This routines generates the device id for the given SD device.
  343. Arguments:
  344. Pdo - Pointer to the physical device object for the SD device
  345. DeviceId - Pointer to the string in which device id is returned
  346. Return Value
  347. Status
  348. --*/
  349. {
  350. PUCHAR deviceId;
  351. PAGED_CODE();
  352. deviceId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
  353. if (deviceId == NULL) {
  354. return STATUS_INSUFFICIENT_RESOURCES;
  355. }
  356. if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_IO) {
  357. PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
  358. //
  359. // IO card
  360. //
  361. sprintf(deviceId, "%s\\VID_%04x&PID_%04x",
  362. "SD",
  363. cardData->MfgId,
  364. cardData->MfgInfo);
  365. } else {
  366. UCHAR productName[6];
  367. UCHAR j;
  368. PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
  369. //
  370. // Memory card
  371. //
  372. sprintf(deviceId, "%s\\VID_%02x&OID_%04x&PID_%s&REV_%d.%d",
  373. "SD",
  374. cardData->SdCid.ManufacturerId,
  375. cardData->SdCid.OemId,
  376. cardData->ProductName,
  377. (cardData->SdCid.Revision >> 4) , (cardData->SdCid.Revision & 0xF));
  378. }
  379. *DeviceId = deviceId;
  380. return STATUS_SUCCESS;
  381. }
  382. NTSTATUS
  383. SdbusGetHardwareIds(
  384. IN PPDO_EXTENSION PdoExtension,
  385. OUT PUNICODE_STRING HardwareIds
  386. )
  387. /*++
  388. Routine Description:
  389. This routine generates the hardware id's for the given sd device and returns them
  390. as a Unicode multi-string.
  391. Arguments:
  392. Pdo - Pointer to device object representing the sd device
  393. HardwareIds - Pointer to the unicode string which contains the hardware id's as a multi-string
  394. Return value:
  395. --*/
  396. {
  397. NTSTATUS status;
  398. PSTR strings[4] = {NULL};
  399. PUCHAR hwId;
  400. UCHAR stringCount = 0;
  401. PAGED_CODE();
  402. //
  403. // The first hardware id is identical to the device id
  404. // Generate the device id
  405. //
  406. status = SdbusGenerateDeviceId(PdoExtension,
  407. &strings[stringCount++]);
  408. if (!NT_SUCCESS(status)) {
  409. return status;
  410. }
  411. try {
  412. //
  413. // Add less specific IDs
  414. //
  415. if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
  416. UCHAR productName[6];
  417. UCHAR j;
  418. PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
  419. status = STATUS_INSUFFICIENT_RESOURCES;
  420. hwId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
  421. if (!hwId) {
  422. leave;
  423. }
  424. strings[stringCount++] = hwId;
  425. //
  426. // Memory card
  427. //
  428. sprintf(hwId, "%s\\VID_%02x&OID_%04x&PID_%s",
  429. "SD",
  430. cardData->SdCid.ManufacturerId,
  431. cardData->SdCid.OemId,
  432. cardData->ProductName);
  433. }
  434. status = SdbusStringsToMultiString(strings, stringCount, HardwareIds);
  435. } finally {
  436. while(stringCount != 0) {
  437. ExFreePool(strings[--stringCount]);
  438. }
  439. }
  440. return status;
  441. }
  442. NTSTATUS
  443. SdbusGetCompatibleIds(
  444. IN PPDO_EXTENSION PdoExtension,
  445. OUT PUNICODE_STRING CompatibleIds
  446. )
  447. /*++
  448. Routine Description:
  449. This routine generates the compatible id's for the given sd device and returns them
  450. as a Unicode multi-string.
  451. Arguments:
  452. Pdo - Pointer to device object representing the sd device
  453. HardwareIds - Pointer to the unicode string which contains the hardware id's as a multi-string
  454. Return value:
  455. --*/
  456. {
  457. NTSTATUS status;
  458. PSTR strings[1] = {NULL};
  459. PUCHAR compatId;
  460. UCHAR stringCount = 0;
  461. PAGED_CODE();
  462. try {
  463. //
  464. // Add the class ID
  465. //
  466. status = STATUS_INSUFFICIENT_RESOURCES;
  467. compatId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
  468. if (!compatId) {
  469. leave;
  470. }
  471. strings[stringCount++] = compatId;
  472. if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
  473. sprintf(compatId, "%s\\CLASS_STORAGE", "SD");
  474. } else {
  475. PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
  476. PSD_FUNCTION_DATA functionData;
  477. // find the right function data
  478. for (functionData = cardData->FunctionData;
  479. functionData != NULL;
  480. functionData = functionData->Next) {
  481. if (functionData->Function == PdoExtension->Function) break;
  482. }
  483. if (!functionData || (functionData->IoDeviceInterface == 0)) {
  484. ASSERT(functionData != NULL);
  485. status = STATUS_UNSUCCESSFUL;
  486. leave;
  487. }
  488. sprintf(compatId, "%s\\CLASS_%02x",
  489. "SD",
  490. functionData->IoDeviceInterface);
  491. DebugPrint((SDBUS_DEBUG_INFO, " %s\n", compatId));
  492. }
  493. status = SdbusStringsToMultiString(strings, stringCount, CompatibleIds);
  494. } finally {
  495. ASSERT(stringCount <= 1);
  496. while(stringCount != 0) {
  497. ExFreePool(strings[--stringCount]);
  498. }
  499. }
  500. return status;
  501. }
  502. NTSTATUS
  503. SdbusGetInstanceId(
  504. IN PPDO_EXTENSION PdoExtension,
  505. OUT PUNICODE_STRING InstanceId
  506. )
  507. /*++
  508. Routine Description:
  509. This routine generates a unique instance id (1 upwards) for the supplied
  510. PC-Card which is guaranteed not to clash with any other instance ids under
  511. the same pcmcia controller, for the same type of card.
  512. A new instance id is computed only if it was not already present for the PC-Card.
  513. Arguments:
  514. Pdo - Pointer to the device object representing the PC-Card
  515. InstanceId - Pointer to a unicode string which will contain the generated
  516. instance id.
  517. Memory for the unicode string allocated by this routine.
  518. Caller's responsibility to free it .
  519. Return value:
  520. STATUS_SUCCESS
  521. STATUS_UNSUCCESSFUL - Currently there's a cap on the maximum value of instance id - 999999
  522. This status returned only if more than 999999 PC-Cards exist under
  523. this PCMCIA controller!
  524. Any other status - Something failed in the string allocation/conversion
  525. --*/
  526. {
  527. ULONG instance;
  528. NTSTATUS status;
  529. ANSI_STRING sizeString;
  530. ASSERT(InstanceId);
  531. //
  532. // Allocate memory for the unicode string
  533. // Maximum of 6 digits in the instance..
  534. //
  535. RtlInitAnsiString(&sizeString, "123456");
  536. status = RtlAnsiStringToUnicodeString(InstanceId, &sizeString, TRUE);
  537. if (!NT_SUCCESS(status)) {
  538. return status;
  539. }
  540. status = RtlIntegerToUnicodeString(999, 10, InstanceId);
  541. if (!NT_SUCCESS(status)) {
  542. RtlFreeUnicodeString(InstanceId);
  543. }
  544. return status;
  545. }
  546. NTSTATUS
  547. SdbusPdoQueryId(
  548. IN PDEVICE_OBJECT Pdo,
  549. IN PIRP Irp
  550. )
  551. /*++
  552. Routine Description:
  553. Returns descriptive text information about the
  554. PDO (location and device desc.)
  555. Arguments:
  556. Pdo - Pointer to the SD-Card's device object
  557. Irp - IRP_MN_QUERY_DEVICE_TEXT Irp
  558. Return Value:
  559. STATUS_SUCCESS
  560. STATUS_NOT_SUPPORTED - if not supported
  561. --*/
  562. {
  563. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  564. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  565. UNICODE_STRING unicodeString;
  566. ANSI_STRING ansiString;
  567. UCHAR deviceText[128];
  568. NTSTATUS status;
  569. USHORT deviceTextLength;
  570. UNICODE_STRING unicodeId;
  571. PUCHAR deviceId;
  572. PAGED_CODE();
  573. status = Irp->IoStatus.Status;
  574. RtlInitUnicodeString(&unicodeId, NULL);
  575. switch (irpStack->Parameters.QueryId.IdType) {
  576. case BusQueryDeviceID:
  577. DebugPrint((SDBUS_DEBUG_INFO, " Device Id for pdo %x\n", Pdo));
  578. status = SdbusGenerateDeviceId(pdoExtension, &deviceId);
  579. if (!NT_SUCCESS(status)) {
  580. break;
  581. }
  582. DebugPrint((SDBUS_DEBUG_INFO, "pdo %08x Device Id=%s\n", Pdo, deviceId));
  583. RtlInitAnsiString(&ansiString, deviceId);
  584. status = RtlAnsiStringToUnicodeString(&unicodeId, &ansiString, TRUE);
  585. ExFreePool(deviceId);
  586. if (NT_SUCCESS(status)) {
  587. Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
  588. }
  589. break;
  590. case BusQueryInstanceID:
  591. DebugPrint((SDBUS_DEBUG_INFO, " Instance Id for pdo %x\n", Pdo));
  592. status = SdbusGetInstanceId(pdoExtension, &unicodeId);
  593. if (NT_SUCCESS(status)) {
  594. Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
  595. }
  596. break;
  597. case BusQueryHardwareIDs:
  598. DebugPrint((SDBUS_DEBUG_INFO, " Hardware Ids for pdo %x\n", Pdo));
  599. status = SdbusGetHardwareIds(pdoExtension, &unicodeId);
  600. if (NT_SUCCESS(status)) {
  601. Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
  602. }
  603. break;
  604. case BusQueryCompatibleIDs:
  605. DebugPrint((SDBUS_DEBUG_INFO, " Compatible Ids for pdo %x\n", Pdo));
  606. status = SdbusGetCompatibleIds(pdoExtension, &unicodeId);
  607. if (NT_SUCCESS(status)) {
  608. Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
  609. }
  610. break;
  611. }
  612. return status;
  613. }
  614. NTSTATUS
  615. SdbusPdoStartDevice(
  616. IN PDEVICE_OBJECT Pdo,
  617. IN PCM_RESOURCE_LIST ResourceList,
  618. IN OUT PIRP Irp
  619. )
  620. /*++
  621. Routine Description:
  622. This routine attempts to start the PC-Card by configuring it with the supplied resources.
  623. Arguments:
  624. Pdo - Pointer to the device object representing the PC-Card which needs to be started
  625. ResourceList - Pointer the list of assigned resources for the PC-Card
  626. Return value:
  627. STATUS_INSUFFICIENT_RESOURCES - Not sufficient resources supplied to start device/
  628. could not allocate memory
  629. STATUS_UNSUCCESSFUL - Supplied resources are invalid for this PC-Card
  630. STATUS_SUCCESS - Configured and started the card successfully
  631. --*/
  632. {
  633. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  634. PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
  635. NTSTATUS status;
  636. PAGED_CODE();
  637. if (IsDeviceStarted(pdoExtension)) {
  638. //
  639. // Already started..
  640. //
  641. return STATUS_SUCCESS;
  642. }
  643. if (IsDevicePhysicallyRemoved(pdoExtension)) {
  644. return STATUS_DEVICE_DOES_NOT_EXIST;
  645. }
  646. status = SdbusExecuteWorkSynchronous(SDWP_INITIALIZE_FUNCTION, fdoExtension, pdoExtension);
  647. if (NT_SUCCESS(status)) {
  648. MarkDeviceStarted(pdoExtension);
  649. MarkDeviceLogicallyInserted(pdoExtension);
  650. }
  651. return status;
  652. }
  653. NTSTATUS
  654. SdbusPdoStopDevice(
  655. IN PDEVICE_OBJECT Pdo
  656. )
  657. /*++
  658. Routine Description:
  659. This routine stops and deconfigures the given PC-Card
  660. Arguments:
  661. Pdo - Pointer to the device object representing the PC-Card which needs to be stopped
  662. Return value:
  663. STATUS_SUCCESS - PC-Card was already stopped, or stopped and deconfigured now successfully
  664. --*/
  665. {
  666. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  667. PAGED_CODE();
  668. if (!IsDeviceStarted(pdoExtension)) {
  669. return STATUS_SUCCESS;
  670. }
  671. //
  672. // Need to deconfigure the controller
  673. //
  674. MarkDeviceNotStarted(pdoExtension);
  675. return STATUS_SUCCESS;
  676. }
  677. NTSTATUS
  678. SdbusPdoRemoveDevice(
  679. IN PDEVICE_OBJECT Pdo,
  680. IN PIRP Irp
  681. )
  682. /*++
  683. Routine Description:
  684. Arguments:
  685. Return value:
  686. --*/
  687. {
  688. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  689. NTSTATUS status;
  690. PAGED_CODE();
  691. SdbusPdoStopDevice(Pdo);
  692. // SdbusReleaseSocketPower(pdoExtension, NULL);
  693. if (IsDevicePhysicallyRemoved(pdoExtension)) {
  694. PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
  695. PDEVICE_OBJECT curPdo, prevPdo;
  696. PPDO_EXTENSION curPdoExt;
  697. ULONG waitCount = 0;
  698. #if 0
  699. //
  700. // Synchronize with power routines
  701. // LATER: make these values adjustable
  702. //
  703. while(!SDBUS_TEST_AND_SET(&pdoExtension->DeletionLock)) {
  704. SdbusWait(1000000);
  705. if (waitCount++ > 20) {
  706. ASSERT(waitCount <= 20);
  707. break;
  708. }
  709. }
  710. #endif
  711. //
  712. // Delink this Pdo from the FDO list.
  713. //
  714. for (curPdo = fdoExtension->PdoList, prevPdo = NULL; curPdo!=NULL; prevPdo = curPdo, curPdo=curPdoExt->NextPdoInFdoChain) {
  715. curPdoExt = curPdo->DeviceExtension;
  716. if (curPdo == Pdo) {
  717. if (prevPdo) {
  718. ((PPDO_EXTENSION)prevPdo->DeviceExtension)->NextPdoInFdoChain = pdoExtension->NextPdoInFdoChain;
  719. } else {
  720. fdoExtension->PdoList = pdoExtension->NextPdoInFdoChain;
  721. }
  722. break;
  723. }
  724. }
  725. SdbusCleanupPdo(Pdo);
  726. //
  727. // Delete..
  728. //
  729. if (!IsDeviceDeleted(pdoExtension)) {
  730. MarkDeviceDeleted(pdoExtension);
  731. IoDeleteDevice(Pdo);
  732. }
  733. } else {
  734. //
  735. // We will keep this Pdo around, since this is not physically ejected.
  736. //
  737. MarkDeviceLogicallyRemoved(pdoExtension);
  738. }
  739. return STATUS_SUCCESS;
  740. }
  741. VOID
  742. SdbusCleanupPdo(
  743. IN PDEVICE_OBJECT Pdo
  744. )
  745. /*++
  746. Routine Description:
  747. Arguments:
  748. Return value:
  749. --*/
  750. {
  751. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  752. // currently nothing to do
  753. }
  754. NTSTATUS
  755. SdbusPdoDeviceCapabilities(
  756. IN PDEVICE_OBJECT Pdo,
  757. IN PIRP Irp
  758. )
  759. /*++
  760. Routine Description:
  761. Obtains the device capabilities of the given SD device.
  762. Arguments:
  763. Pdo - Pointer to the device object for the pc-card
  764. Irp - Pointer to the query device capabilities Irp
  765. Return Value:
  766. STATUS_SUCCESS - Capabilities obtained and recorded in the passed in pointer
  767. STATUS_INSUFFICIENT_RESOURCES - Could not allocate memory to cache the capabilities
  768. --*/
  769. {
  770. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  771. PDEVICE_CAPABILITIES capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  772. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  773. PDEVICE_CAPABILITIES busCapabilities = &pdoExtension->FdoExtension->DeviceCapabilities;
  774. PAGED_CODE();
  775. //
  776. // R2 card. Fill in the capabilities ourselves..
  777. //
  778. capabilities->Removable = TRUE;
  779. capabilities->UniqueID = FALSE;
  780. capabilities->EjectSupported = FALSE;
  781. // capabilities->Address = pdoExtension->Socket->RegisterOffset;
  782. capabilities->Address = 0;
  783. // Don't know the UINumber, just leave it alone
  784. if (busCapabilities->DeviceState[PowerSystemWorking] != PowerDeviceUnspecified) {
  785. capabilities->DeviceState[PowerSystemWorking] = busCapabilities->DeviceState[PowerSystemWorking];
  786. capabilities->DeviceState[PowerSystemSleeping1] = busCapabilities->DeviceState[PowerSystemSleeping1];
  787. capabilities->DeviceState[PowerSystemSleeping2] = busCapabilities->DeviceState[PowerSystemSleeping2];
  788. capabilities->DeviceState[PowerSystemSleeping3] = busCapabilities->DeviceState[PowerSystemSleeping3];
  789. capabilities->DeviceState[PowerSystemHibernate] = busCapabilities->DeviceState[PowerSystemHibernate];
  790. capabilities->DeviceState[PowerSystemShutdown] = busCapabilities->DeviceState[PowerSystemShutdown];
  791. capabilities->SystemWake = MIN(PowerSystemSleeping3, busCapabilities->SystemWake);
  792. capabilities->DeviceWake = PowerDeviceD0; // don't rely on FDO mungeing in the right thing for r2 cards
  793. capabilities->D1Latency = busCapabilities->D1Latency;
  794. capabilities->D2Latency = busCapabilities->D2Latency;
  795. capabilities->D3Latency = busCapabilities->D3Latency;
  796. } else {
  797. capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  798. capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
  799. capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
  800. capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  801. capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  802. capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  803. capabilities->SystemWake = PowerSystemUnspecified;
  804. capabilities->DeviceWake = PowerDeviceD0; // don't rely on FDO mungeing in the right thing for r2 cards
  805. capabilities->D1Latency = 0; // No latency - since we do nothing
  806. capabilities->D2Latency = 0; //
  807. capabilities->D3Latency = 100;
  808. }
  809. //
  810. // Store these capabilities away..
  811. //
  812. RtlCopyMemory(&pdoExtension->DeviceCapabilities,
  813. capabilities,
  814. sizeof(DEVICE_CAPABILITIES));
  815. return STATUS_SUCCESS;
  816. }