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.

2205 lines
66 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: chanpdo.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pciidex.h"
  11. #ifdef ALLOC_PRAGMA
  12. #pragma alloc_text(PAGE, ChannelStartDevice)
  13. #pragma alloc_text(PAGE, ChannelQueryStopRemoveDevice)
  14. #pragma alloc_text(PAGE, ChannelRemoveDevice)
  15. #pragma alloc_text(PAGE, ChannelStopDevice)
  16. #pragma alloc_text(PAGE, ChannelStopChannel)
  17. #pragma alloc_text(PAGE, ChannelQueryId)
  18. #pragma alloc_text(PAGE, ChannelBuildDeviceId)
  19. #pragma alloc_text(PAGE, ChannelBuildInstanceId)
  20. #pragma alloc_text(PAGE, ChannelBuildCompatibleId)
  21. #pragma alloc_text(PAGE, ChannelBuildHardwareId)
  22. #pragma alloc_text(PAGE, ChannelQueryCapabitilies)
  23. #pragma alloc_text(PAGE, ChannelQueryResources)
  24. #pragma alloc_text(PAGE, ChannelQueryResourceRequirements)
  25. #pragma alloc_text(PAGE, ChannelInternalDeviceIoControl)
  26. #pragma alloc_text(PAGE, ChannelQueryText)
  27. #pragma alloc_text(PAGE, PciIdeChannelQueryInterface)
  28. #pragma alloc_text(PAGE, ChannelQueryDeviceRelations)
  29. #pragma alloc_text(PAGE, ChannelUsageNotification)
  30. #pragma alloc_text(PAGE, ChannelQueryPnPDeviceState)
  31. #pragma alloc_text(NONPAGE, ChannelGetPdoExtension)
  32. #pragma alloc_text(NONPAGE, ChannelUpdatePdoState)
  33. #pragma alloc_text(NONPAGE, PciIdeChannelTransferModeSelect)
  34. #pragma alloc_text(NONPAGE, PciIdeChannelTransferModeInterface)
  35. #endif // ALLOC_PRAGMA
  36. PCHANPDO_EXTENSION
  37. ChannelGetPdoExtension(
  38. PDEVICE_OBJECT DeviceObject
  39. )
  40. {
  41. KIRQL currentIrql;
  42. PCHANPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
  43. PKSPIN_LOCK spinLock;
  44. spinLock = &pdoExtension->SpinLock;
  45. KeAcquireSpinLock(spinLock, &currentIrql);
  46. if ((pdoExtension->PdoState & PDOS_DEADMEAT) &&
  47. (pdoExtension->PdoState & PDOS_REMOVED)) {
  48. pdoExtension = NULL;
  49. }
  50. KeReleaseSpinLock(spinLock, currentIrql);
  51. return pdoExtension;
  52. }
  53. ULONG
  54. ChannelUpdatePdoState(
  55. PCHANPDO_EXTENSION PdoExtension,
  56. ULONG SetFlags,
  57. ULONG ClearFlags
  58. )
  59. {
  60. ULONG pdoState;
  61. KIRQL currentIrql;
  62. ASSERT (PdoExtension);
  63. KeAcquireSpinLock(&PdoExtension->SpinLock, &currentIrql);
  64. SETMASK (PdoExtension->PdoState, SetFlags);
  65. CLRMASK (PdoExtension->PdoState, ClearFlags);
  66. pdoState = PdoExtension->PdoState;
  67. KeReleaseSpinLock(&PdoExtension->SpinLock, currentIrql);
  68. return pdoState;
  69. }
  70. NTSTATUS
  71. ChannelStartDevice (
  72. IN PDEVICE_OBJECT DeviceObject,
  73. IN OUT PIRP Irp
  74. )
  75. {
  76. PCHANPDO_EXTENSION pdoExtension;
  77. NTSTATUS status;
  78. IDE_CHANNEL_STATE channelState;
  79. PAGED_CODE();
  80. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  81. if (pdoExtension == NULL) {
  82. status = STATUS_NO_SUCH_DEVICE;
  83. } else {
  84. status = STATUS_SUCCESS;
  85. //
  86. // always keep native mode started
  87. //
  88. if (pdoExtension->ParentDeviceExtension->
  89. NativeMode[pdoExtension->ChannelNumber] == FALSE) {
  90. channelState = PciIdeChannelEnabled (
  91. pdoExtension->ParentDeviceExtension,
  92. pdoExtension->ChannelNumber
  93. );
  94. //
  95. // ISSUE: we should free the resources assigned.
  96. //
  97. //ASSERT(channelState != ChannelDisabled);
  98. if (channelState == ChannelStateUnknown) {
  99. //
  100. // we don't really know if this channel
  101. // is acutally enabled
  102. //
  103. // we will do our empty channel test
  104. //
  105. PIO_STACK_LOCATION thisIrpSp;
  106. IDE_RESOURCE ideResource;
  107. PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors;
  108. IDE_REGISTERS_1 baseIoAddress1;
  109. IDE_REGISTERS_2 baseIoAddress2;
  110. ULONG baseIoAddressLength1;
  111. ULONG baseIoAddressLength2;
  112. ULONG maxIdeDevice;
  113. PCM_RESOURCE_LIST resourceList;
  114. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  115. //
  116. // legacy mode channel gets its the start device irp
  117. //
  118. resourceList = thisIrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  119. status = DigestResourceList (
  120. &ideResource,
  121. resourceList,
  122. &irqPartialDescriptors
  123. );
  124. if (NT_SUCCESS(status)) {
  125. AtapiBuildIoAddress (
  126. ideResource.TranslatedCommandBaseAddress,
  127. ideResource.TranslatedControlBaseAddress,
  128. &baseIoAddress1,
  129. &baseIoAddress2,
  130. &baseIoAddressLength1,
  131. &baseIoAddressLength2,
  132. &maxIdeDevice,
  133. NULL
  134. );
  135. if (IdePortChannelEmpty (
  136. &baseIoAddress1,
  137. &baseIoAddress2,
  138. maxIdeDevice)) {
  139. //
  140. // upgrade its state to "disabled"
  141. //
  142. channelState = ChannelDisabled;
  143. } else {
  144. channelState = ChannelEnabled;
  145. }
  146. //
  147. // don't need the io resource anymore
  148. // unmap io space if nesscessary
  149. //
  150. if ((ideResource.CommandBaseAddressSpace == MEMORY_SPACE) &&
  151. (ideResource.TranslatedCommandBaseAddress)) {
  152. MmUnmapIoSpace (
  153. ideResource.TranslatedCommandBaseAddress,
  154. baseIoAddressLength1
  155. );
  156. }
  157. if ((ideResource.ControlBaseAddressSpace == MEMORY_SPACE) &&
  158. (ideResource.TranslatedControlBaseAddress)) {
  159. MmUnmapIoSpace (
  160. ideResource.TranslatedControlBaseAddress,
  161. baseIoAddressLength2
  162. );
  163. }
  164. }
  165. if (channelState == ChannelDisabled) {
  166. pdoExtension->EmptyChannel = TRUE;
  167. //
  168. // channel looks empty
  169. // change our resource requirement to free our irq for other devices
  170. //
  171. if (irqPartialDescriptors) {
  172. SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
  173. IoInvalidateDeviceState (DeviceObject);
  174. }
  175. } else {
  176. pdoExtension->EmptyChannel = FALSE;
  177. }
  178. }
  179. }
  180. if (NT_SUCCESS(status)) {
  181. //
  182. // grab the DmaDetectionLevel from the registry
  183. // default is DdlFirmwareOk
  184. //
  185. pdoExtension->DmaDetectionLevel = DdlFirmwareOk;
  186. status = PciIdeXGetDeviceParameter (
  187. pdoExtension->DeviceObject,
  188. DMA_DETECTION_LEVEL_REG_KEY,
  189. (PULONG)&pdoExtension->DmaDetectionLevel
  190. );
  191. status = BusMasterInitialize (pdoExtension);
  192. }
  193. }
  194. if (NT_SUCCESS(status)) {
  195. //
  196. // get the firmware initialized DMA capable bits
  197. //
  198. if (pdoExtension->BmRegister) {
  199. pdoExtension->BootBmStatus = READ_PORT_UCHAR (&pdoExtension->BmRegister->Status);
  200. }
  201. ChannelUpdatePdoState (
  202. pdoExtension,
  203. PDOS_STARTED,
  204. PDOS_DEADMEAT | PDOS_STOPPED | PDOS_REMOVED
  205. );
  206. #if DBG
  207. {
  208. ULONG data;
  209. USHORT vendorId =0;
  210. USHORT deviceId = 0;
  211. PVOID deviceExtension;
  212. data = 0;
  213. deviceExtension = pdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension;
  214. PciIdeXGetBusData (
  215. deviceExtension,
  216. &vendorId,
  217. FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
  218. sizeof(vendorId)
  219. );
  220. PciIdeXGetBusData (
  221. deviceExtension,
  222. &deviceId,
  223. FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID),
  224. sizeof(deviceId)
  225. );
  226. if (vendorId == 0x8086) {
  227. data = 0;
  228. PciIdeXGetBusData (
  229. deviceExtension,
  230. &data,
  231. 0x40, // IDETIM0
  232. 2
  233. );
  234. PciIdeXSaveDeviceParameter (
  235. deviceExtension,
  236. L"Old IDETIM0",
  237. data
  238. );
  239. data = 0;
  240. PciIdeXGetBusData (
  241. deviceExtension,
  242. &data,
  243. 0x42, // IDETIM1
  244. 2
  245. );
  246. PciIdeXSaveDeviceParameter (
  247. deviceExtension,
  248. L"Old IDETIM1",
  249. data
  250. );
  251. if (deviceId != 0x1230) { // !PIIX
  252. data = 0;
  253. PciIdeXGetBusData (
  254. deviceExtension,
  255. &data,
  256. 0x44,
  257. 1
  258. );
  259. PciIdeXSaveDeviceParameter (
  260. deviceExtension,
  261. L"Old SIDETIM",
  262. data
  263. );
  264. }
  265. if (deviceId == 0x7111) {
  266. USHORT t;
  267. data = 0;
  268. PciIdeXGetBusData (
  269. deviceExtension,
  270. &data,
  271. 0x48,
  272. 1
  273. );
  274. PciIdeXSaveDeviceParameter (
  275. deviceExtension,
  276. L"Old SDMACTL",
  277. data
  278. );
  279. data = 0;
  280. PciIdeXGetBusData (
  281. deviceExtension,
  282. &data,
  283. 0x4a, //SDMATIM0
  284. 1
  285. );
  286. PciIdeXSaveDeviceParameter (
  287. deviceExtension,
  288. L"Old SDMATIM0",
  289. data
  290. );
  291. data = 0;
  292. PciIdeXGetBusData (
  293. deviceExtension,
  294. &data,
  295. 0x4b, //SDMATIM1
  296. 1
  297. );
  298. PciIdeXSaveDeviceParameter (
  299. deviceExtension,
  300. L"Old SDMATIM1",
  301. data
  302. );
  303. }
  304. }
  305. }
  306. #endif // DBG
  307. }
  308. Irp->IoStatus.Status = status;
  309. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  310. return status;
  311. } // ChannelStartDevice
  312. NTSTATUS
  313. ChannelQueryStopRemoveDevice (
  314. IN PDEVICE_OBJECT DeviceObject,
  315. IN OUT PIRP Irp
  316. )
  317. {
  318. NTSTATUS status;
  319. PCHANPDO_EXTENSION pdoExtension;
  320. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  321. if (pdoExtension) {
  322. //
  323. // Check the paging path count for this device.
  324. //
  325. if (pdoExtension->PagingPathCount ||
  326. pdoExtension->CrashDumpPathCount) {
  327. status = STATUS_UNSUCCESSFUL;
  328. } else {
  329. status = STATUS_SUCCESS;
  330. }
  331. } else {
  332. status = STATUS_NO_SUCH_DEVICE;
  333. }
  334. Irp->IoStatus.Status = status;
  335. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  336. return status;
  337. } // ChannelQueryStopRemoveDevice
  338. NTSTATUS
  339. ChannelRemoveDevice (
  340. IN PDEVICE_OBJECT DeviceObject,
  341. IN OUT PIRP Irp
  342. )
  343. {
  344. PCHANPDO_EXTENSION pdoExtension;
  345. NTSTATUS status;
  346. PDEVICE_OBJECT AttacheePdo;
  347. BOOLEAN removeFromParent;
  348. BOOLEAN callIoDeleteDevice;
  349. PAGED_CODE();
  350. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  351. if (pdoExtension) {
  352. PIO_STACK_LOCATION thisIrpSp;
  353. ULONG actionFlag;
  354. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  355. status = ChannelStopChannel (pdoExtension);
  356. ASSERT (NT_SUCCESS(status));
  357. if (thisIrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE) {
  358. if (pdoExtension->PdoState & PDOS_DEADMEAT) {
  359. actionFlag = PDOS_REMOVED;
  360. removeFromParent = TRUE;
  361. callIoDeleteDevice = TRUE;
  362. } else {
  363. actionFlag = PDOS_DISABLED_BY_USER;
  364. removeFromParent = FALSE;
  365. callIoDeleteDevice = FALSE;
  366. }
  367. } else {
  368. actionFlag = PDOS_SURPRISE_REMOVED;
  369. removeFromParent = FALSE;
  370. callIoDeleteDevice = FALSE;
  371. }
  372. ChannelUpdatePdoState (
  373. pdoExtension,
  374. actionFlag,
  375. PDOS_STARTED | PDOS_STOPPED
  376. );
  377. if (removeFromParent) {
  378. PCTRLFDO_EXTENSION fdoExtension;
  379. fdoExtension = pdoExtension->ParentDeviceExtension;
  380. fdoExtension->ChildDeviceExtension[pdoExtension->ChannelNumber] = NULL;
  381. if (callIoDeleteDevice) {
  382. IoDeleteDevice (pdoExtension->DeviceObject);
  383. }
  384. }
  385. if (pdoExtension->NeedToCallIoInvalidateDeviceRelations) {
  386. pdoExtension->NeedToCallIoInvalidateDeviceRelations = FALSE;
  387. IoInvalidateDeviceRelations (
  388. pdoExtension->ParentDeviceExtension->AttacheePdo,
  389. BusRelations
  390. );
  391. }
  392. status = STATUS_SUCCESS;
  393. } else {
  394. status = STATUS_NO_SUCH_DEVICE;
  395. }
  396. Irp->IoStatus.Status = status;
  397. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  398. return status;
  399. } // ChannelRemoveDevice
  400. NTSTATUS
  401. ChannelStopDevice (
  402. IN PDEVICE_OBJECT DeviceObject,
  403. IN OUT PIRP Irp
  404. )
  405. {
  406. PCHANPDO_EXTENSION pdoExtension;
  407. NTSTATUS status;
  408. PAGED_CODE();
  409. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  410. if (pdoExtension == NULL) {
  411. status = STATUS_NO_SUCH_DEVICE;
  412. } else {
  413. status = ChannelStopChannel (pdoExtension);
  414. ASSERT (NT_SUCCESS(status));
  415. ChannelUpdatePdoState (
  416. pdoExtension,
  417. PDOS_STOPPED,
  418. PDOS_STARTED
  419. );
  420. status = STATUS_SUCCESS;
  421. }
  422. Irp->IoStatus.Status = status;
  423. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  424. return status;
  425. } // ChannelRemoveDevice
  426. NTSTATUS
  427. ChannelStopChannel (
  428. PCHANPDO_EXTENSION PdoExtension
  429. )
  430. {
  431. NTSTATUS status;
  432. PAGED_CODE();
  433. status = BusMasterUninitialize (PdoExtension);
  434. ASSERT (NT_SUCCESS(status));
  435. return STATUS_SUCCESS;
  436. } // ChannelStopChannel
  437. NTSTATUS
  438. ChannelQueryId (
  439. IN PDEVICE_OBJECT DeviceObject,
  440. IN OUT PIRP Irp
  441. )
  442. {
  443. PIO_STACK_LOCATION thisIrpSp;
  444. PCHANPDO_EXTENSION pdoExtension;
  445. NTSTATUS status = STATUS_UNSUCCESSFUL;
  446. PWSTR idString = NULL;
  447. PAGED_CODE();
  448. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  449. if (pdoExtension == NULL) {
  450. status = STATUS_NO_SUCH_DEVICE;
  451. } else {
  452. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  453. switch (thisIrpSp->Parameters.QueryId.IdType) {
  454. case BusQueryDeviceID:
  455. //
  456. // Caller wants the bus ID of this device.
  457. //
  458. idString = ChannelBuildDeviceId (pdoExtension);
  459. break;
  460. case BusQueryInstanceID:
  461. //
  462. // Caller wants the unique id of the device
  463. //
  464. idString = ChannelBuildInstanceId (pdoExtension);
  465. break;
  466. case BusQueryCompatibleIDs:
  467. //
  468. // Caller wants the unique id of the device
  469. //
  470. idString = ChannelBuildCompatibleId (pdoExtension);
  471. break;
  472. case BusQueryHardwareIDs:
  473. //
  474. // Caller wants the unique id of the device
  475. //
  476. idString = ChannelBuildHardwareId (pdoExtension);
  477. break;
  478. default:
  479. idString = NULL;
  480. DebugPrint ((1, "pciide: QueryID type %d not supported\n", thisIrpSp->Parameters.QueryId.IdType));
  481. status = STATUS_NOT_SUPPORTED;
  482. break;
  483. }
  484. }
  485. if( idString != NULL ){
  486. Irp->IoStatus.Information = (ULONG_PTR) idString;
  487. status = STATUS_SUCCESS;
  488. }
  489. Irp->IoStatus.Status = status;
  490. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  491. return status;
  492. } // ChannelQueryId
  493. PWSTR
  494. ChannelBuildDeviceId(
  495. IN PCHANPDO_EXTENSION pdoExtension
  496. )
  497. {
  498. PWSTR idString;
  499. ULONG idStringBufLen;
  500. NTSTATUS status;
  501. WCHAR deviceIdFormat[] = L"PCIIDE\\IDEChannel";
  502. PAGED_CODE();
  503. idStringBufLen = ( wcslen( deviceIdFormat ) + 1 ) * sizeof( WCHAR );
  504. idString = ExAllocatePool( PagedPool, idStringBufLen );
  505. if( idString == NULL ){
  506. return NULL;
  507. }
  508. //
  509. // Form the string and return it.
  510. //
  511. wcscpy( idString,
  512. deviceIdFormat);
  513. return idString;
  514. } // ChannelBuildDeviceId
  515. PWSTR
  516. ChannelBuildInstanceId(
  517. IN PCHANPDO_EXTENSION pdoExtension
  518. )
  519. {
  520. PWSTR idString;
  521. ULONG idStringBufLen;
  522. NTSTATUS status;
  523. WCHAR instanceIdFormat[] = L"%d";
  524. PAGED_CODE();
  525. //
  526. // The maximum number of digits that a ulong can hold is 10.
  527. // So the id len should be 10 + 1 (for '\0')
  528. //
  529. idStringBufLen = 11 * sizeof( WCHAR );
  530. idString = ExAllocatePool (PagedPool, idStringBufLen);
  531. if( idString) {
  532. //
  533. // Form the string and return it.
  534. //
  535. swprintf( idString,
  536. instanceIdFormat,
  537. pdoExtension->ChannelNumber);
  538. }
  539. return idString;
  540. } // ChannelBuildInstanceId
  541. //
  542. // Multi-string Compatible IDs
  543. //
  544. WCHAR ChannelCompatibleId[] = {
  545. L"*PNP0600"
  546. };
  547. //
  548. // internal Compatible IDs
  549. //
  550. PWCHAR ChannelInternalCompatibleId[MAX_IDE_CHANNEL] = {
  551. L"Primary_IDE_Channel",
  552. L"Secondary_IDE_Channel"
  553. };
  554. PWSTR
  555. ChannelBuildCompatibleId(
  556. IN PCHANPDO_EXTENSION pdoExtension
  557. )
  558. {
  559. PWSTR idString;
  560. ULONG idStringBufLen;
  561. ULONG i;
  562. PAGED_CODE();
  563. idStringBufLen = sizeof(ChannelCompatibleId);
  564. idString = ExAllocatePool (PagedPool, idStringBufLen + sizeof (WCHAR) * 2);
  565. if( idString == NULL ){
  566. return NULL;
  567. }
  568. RtlCopyMemory (
  569. idString,
  570. ChannelCompatibleId,
  571. idStringBufLen
  572. );
  573. idString[idStringBufLen/2 + 0] = L'\0';
  574. idString[idStringBufLen/2 + 1] = L'\0';
  575. return idString;
  576. } // ChannelBuildCompatibleId
  577. PWSTR
  578. ChannelBuildHardwareId(
  579. IN PCHANPDO_EXTENSION pdoExtension
  580. )
  581. {
  582. NTSTATUS status;
  583. struct {
  584. USHORT VendorId;
  585. USHORT DeviceId;
  586. } hwRawId;
  587. PWSTR vendorIdString;
  588. PWSTR deviceIdString;
  589. WCHAR vendorId[10];
  590. WCHAR deviceId[10];
  591. PWSTR idString;
  592. ULONG idStringBufLen;
  593. ULONG stringLen;
  594. ULONG internalIdLen;
  595. PAGED_CODE();
  596. status = PciIdeBusData (
  597. pdoExtension->ParentDeviceExtension,
  598. &hwRawId,
  599. 0,
  600. sizeof (hwRawId),
  601. TRUE
  602. );
  603. if (!NT_SUCCESS(status)) {
  604. return NULL;
  605. }
  606. vendorIdString = NULL;
  607. deviceIdString = NULL;
  608. switch (hwRawId.VendorId) {
  609. case 0x8086:
  610. vendorIdString = L"Intel";
  611. switch (hwRawId.DeviceId) {
  612. case 0x1230:
  613. deviceIdString = L"PIIX";
  614. break;
  615. case 0x7010:
  616. deviceIdString = L"PIIX3";
  617. break;
  618. case 0x7111:
  619. deviceIdString = L"PIIX4";
  620. break;
  621. }
  622. break;
  623. case 0x1095:
  624. vendorIdString = L"CMD";
  625. break;
  626. case 0x10b9:
  627. vendorIdString = L"ALi";
  628. break;
  629. case 0x1039:
  630. vendorIdString = L"SiS";
  631. break;
  632. case 0x0e11:
  633. vendorIdString = L"Compaq";
  634. break;
  635. case 0x10ad:
  636. vendorIdString = L"WinBond";
  637. break;
  638. }
  639. if (vendorIdString == NULL) {
  640. swprintf (vendorId,
  641. L"%04x",
  642. hwRawId.VendorId);
  643. vendorIdString = vendorId;
  644. }
  645. if (deviceIdString == NULL) {
  646. swprintf (deviceId,
  647. L"%04x",
  648. hwRawId.DeviceId);
  649. deviceIdString = deviceId;
  650. }
  651. idStringBufLen = (256 * sizeof (WCHAR));
  652. idStringBufLen += sizeof(ChannelCompatibleId);
  653. idString = ExAllocatePool( PagedPool, idStringBufLen);
  654. if( idString == NULL ){
  655. return NULL;
  656. }
  657. //
  658. // Form the string and return it.
  659. //
  660. swprintf (idString,
  661. L"%ws-%ws",
  662. vendorIdString,
  663. deviceIdString
  664. );
  665. stringLen = wcslen(idString);
  666. idString[stringLen] = L'\0';
  667. stringLen++;
  668. //
  669. // internal HW id
  670. //
  671. internalIdLen = wcslen(ChannelInternalCompatibleId[pdoExtension->ChannelNumber]);
  672. RtlCopyMemory (
  673. idString + stringLen,
  674. ChannelInternalCompatibleId[pdoExtension->ChannelNumber],
  675. internalIdLen * sizeof (WCHAR)
  676. );
  677. stringLen += internalIdLen;
  678. idString[stringLen] = L'\0';
  679. stringLen++;
  680. //
  681. // generic HW id
  682. //
  683. RtlCopyMemory (
  684. idString + stringLen,
  685. ChannelCompatibleId,
  686. sizeof(ChannelCompatibleId)
  687. );
  688. stringLen += sizeof(ChannelCompatibleId) / sizeof(WCHAR);
  689. idString[stringLen] = L'\0';
  690. stringLen++;
  691. idString[stringLen] = L'\0';
  692. stringLen++;
  693. return idString;
  694. } // ChannelBuildHardwareId
  695. NTSTATUS
  696. ChannelQueryCapabitilies (
  697. IN PDEVICE_OBJECT DeviceObject,
  698. IN OUT PIRP Irp
  699. )
  700. {
  701. PIO_STACK_LOCATION thisIrpSp;
  702. PCHANPDO_EXTENSION pdoExtension;
  703. PDEVICE_CAPABILITIES capabilities;
  704. NTSTATUS status;
  705. PAGED_CODE();
  706. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  707. if (pdoExtension == NULL) {
  708. status = STATUS_NO_SUCH_DEVICE;
  709. } else {
  710. DEVICE_CAPABILITIES parentDeviceCapabilities;
  711. status = IdeGetDeviceCapabilities(
  712. pdoExtension->ParentDeviceExtension->AttacheePdo,
  713. &parentDeviceCapabilities);
  714. if (NT_SUCCESS(status)) {
  715. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  716. capabilities = thisIrpSp->Parameters.DeviceCapabilities.Capabilities;
  717. *capabilities = parentDeviceCapabilities;
  718. capabilities->UniqueID = FALSE;
  719. capabilities->Address = pdoExtension->ChannelNumber;
  720. }
  721. }
  722. Irp->IoStatus.Status = status;
  723. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  724. return status;
  725. } // ChannelQueryCapabitilies
  726. NTSTATUS
  727. ChannelQueryResources(
  728. IN PDEVICE_OBJECT DeviceObject,
  729. IN PIRP Irp
  730. )
  731. {
  732. PCHANPDO_EXTENSION pdoExtension;
  733. PCTRLFDO_EXTENSION fdoExtension;
  734. PIO_STACK_LOCATION thisIrpSp;
  735. NTSTATUS status;
  736. ULONG resourceListSize;
  737. PCM_RESOURCE_LIST resourceList;
  738. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  739. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  740. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  741. IDE_CHANNEL_STATE channelState;
  742. PAGED_CODE();
  743. resourceList = NULL;
  744. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  745. if (pdoExtension == NULL) {
  746. status = STATUS_NO_SUCH_DEVICE;
  747. } else {
  748. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  749. fdoExtension = pdoExtension->ParentDeviceExtension;
  750. if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
  751. //
  752. // Don't make up resources for native mode controller
  753. // PCI bus driver should find them all
  754. //
  755. resourceList = NULL;
  756. status = STATUS_SUCCESS;
  757. goto GetOut;
  758. }
  759. //
  760. // Don't claim resources if the channel is disabled
  761. //
  762. channelState = PciIdeChannelEnabled (
  763. pdoExtension->ParentDeviceExtension,
  764. pdoExtension->ChannelNumber
  765. );
  766. if (channelState == ChannelDisabled) {
  767. resourceList = NULL;
  768. status = STATUS_SUCCESS;
  769. goto GetOut;
  770. }
  771. //
  772. // TEMP CODE for the time without a real PCI driver.
  773. // Actually pciidex should do this
  774. //
  775. resourceListSize = sizeof (CM_RESOURCE_LIST) - sizeof (CM_FULL_RESOURCE_DESCRIPTOR) +
  776. FULL_RESOURCE_LIST_SIZE(3); // primary IO (2) + IRQ
  777. resourceList = ExAllocatePool (PagedPool, resourceListSize);
  778. if (resourceList == NULL) {
  779. status = STATUS_NO_MEMORY;
  780. goto GetOut;
  781. }
  782. RtlZeroMemory(resourceList, resourceListSize);
  783. resourceList->Count = 1;
  784. fullResourceList = resourceList->List;
  785. partialResourceList = &(fullResourceList->PartialResourceList);
  786. partialResourceList->Count = 0;
  787. partialDescriptors = partialResourceList->PartialDescriptors;
  788. fullResourceList->InterfaceType = Isa;
  789. fullResourceList->BusNumber = 0;
  790. if (pdoExtension->ChannelNumber == 0) {
  791. if (!fdoExtension->PdoCmdRegResourceFound[0]) {
  792. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  793. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  794. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  795. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x1f0;
  796. partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
  797. partialResourceList->Count++;
  798. }
  799. if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
  800. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  801. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  802. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  803. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x3f6;
  804. partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
  805. partialResourceList->Count++;
  806. }
  807. if (!fdoExtension->PdoInterruptResourceFound[0]) {
  808. partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt;
  809. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  810. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  811. partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 14;
  812. partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 14;
  813. partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be looked into.
  814. partialResourceList->Count++;
  815. }
  816. } else { // if (pdoExtension->ChannelNumber == 1)
  817. if (!fdoExtension->PdoCmdRegResourceFound[1]) {
  818. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  819. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  820. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  821. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x170;
  822. partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
  823. partialResourceList->Count++;
  824. }
  825. if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
  826. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  827. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  828. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  829. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x376;
  830. partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
  831. partialResourceList->Count++;
  832. }
  833. if (!fdoExtension->PdoInterruptResourceFound[1]) {
  834. partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt;
  835. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  836. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  837. partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 15;
  838. partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 15;
  839. partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be Looked into
  840. partialResourceList->Count++;
  841. }
  842. }
  843. if (!partialResourceList->Count) {
  844. ExFreePool (resourceList);
  845. resourceList = NULL;
  846. }
  847. status = STATUS_SUCCESS;
  848. }
  849. GetOut:
  850. Irp->IoStatus.Information = (ULONG_PTR) resourceList;
  851. Irp->IoStatus.Status = status;
  852. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  853. return status;
  854. } // ChannelQueryResources
  855. NTSTATUS
  856. ChannelQueryResourceRequirements(
  857. IN PDEVICE_OBJECT DeviceObject,
  858. IN PIRP Irp
  859. )
  860. {
  861. PIO_STACK_LOCATION thisIrpSp;
  862. PCHANPDO_EXTENSION pdoExtension;
  863. PCTRLFDO_EXTENSION fdoExtension;
  864. NTSTATUS status;
  865. PIO_RESOURCE_REQUIREMENTS_LIST requirementsList;
  866. PIO_RESOURCE_LIST resourceList;
  867. PIO_RESOURCE_DESCRIPTOR resourceDescriptor;
  868. ULONG requirementsListSize;
  869. BOOLEAN reportIrq;
  870. IDE_CHANNEL_STATE channelState;
  871. PAGED_CODE();
  872. requirementsList = NULL;
  873. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  874. if (pdoExtension == NULL) {
  875. status = STATUS_NO_SUCH_DEVICE;
  876. } else {
  877. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  878. fdoExtension = pdoExtension->ParentDeviceExtension;
  879. if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
  880. //
  881. // Don't make up resources for native mode controller
  882. // PCI bus driver should find them all
  883. //
  884. requirementsList = NULL;
  885. status = STATUS_SUCCESS;
  886. goto GetOut;
  887. }
  888. //
  889. // legacy controller
  890. //
  891. channelState = PciIdeChannelEnabled (
  892. pdoExtension->ParentDeviceExtension,
  893. pdoExtension->ChannelNumber
  894. );
  895. //
  896. // Don't claim resources if the channel is disabled
  897. //
  898. if (channelState == ChannelStateUnknown ) {
  899. if (pdoExtension->EmptyChannel) {
  900. reportIrq = FALSE;
  901. } else {
  902. reportIrq = TRUE;
  903. }
  904. } else if (channelState == ChannelDisabled) {
  905. requirementsList = NULL;
  906. status = STATUS_SUCCESS;
  907. goto GetOut;
  908. }
  909. //
  910. // TEMP CODE for the time without a real PCI driver.
  911. // pciidex should do this.
  912. //
  913. requirementsListSize = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
  914. sizeof (IO_RESOURCE_DESCRIPTOR) * (3 - 1);
  915. requirementsList = ExAllocatePool (PagedPool, requirementsListSize);
  916. if( requirementsList == NULL ){
  917. status = STATUS_NO_MEMORY;
  918. goto GetOut;
  919. }
  920. RtlZeroMemory(requirementsList, requirementsListSize);
  921. requirementsList->ListSize = requirementsListSize;
  922. requirementsList->InterfaceType = Isa;
  923. requirementsList->BusNumber = 0; // ISSUE: 08/30/2000
  924. requirementsList->SlotNumber = 0;
  925. requirementsList->AlternativeLists = 1;
  926. resourceList = requirementsList->List;
  927. resourceList->Version = 1;
  928. resourceList->Revision = 1;
  929. resourceList->Count = 0;
  930. resourceDescriptor = resourceList->Descriptors;
  931. if (pdoExtension->ChannelNumber == 0) {
  932. if (!fdoExtension->PdoCmdRegResourceFound[0]) {
  933. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  934. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  935. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  936. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  937. resourceDescriptor[resourceList->Count].u.Port.Length = 8;
  938. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  939. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x1f0;
  940. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x1f7;
  941. resourceList->Count++;
  942. }
  943. if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
  944. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  945. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  946. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  947. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  948. resourceDescriptor[resourceList->Count].u.Port.Length = 1;
  949. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  950. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x3f6;
  951. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x3f6;
  952. resourceList->Count++;
  953. }
  954. if (!fdoExtension->PdoInterruptResourceFound[0] && reportIrq) {
  955. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  956. resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt;
  957. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  958. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  959. resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xe;
  960. resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xe;
  961. resourceList->Count++;
  962. }
  963. } else { // if (pdoExtension->ChannelNumber == 1)
  964. if (!fdoExtension->PdoCmdRegResourceFound[1]) {
  965. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  966. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  967. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  968. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  969. resourceDescriptor[resourceList->Count].u.Port.Length = 8;
  970. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  971. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x170;
  972. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x177;
  973. resourceList->Count++;
  974. }
  975. if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
  976. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  977. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  978. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  979. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  980. resourceDescriptor[resourceList->Count].u.Port.Length = 1;
  981. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  982. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x376;
  983. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x376;
  984. resourceList->Count++;
  985. }
  986. if (!fdoExtension->PdoInterruptResourceFound[1] && reportIrq) {
  987. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  988. resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt;
  989. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  990. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  991. resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xf;
  992. resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xf;
  993. resourceList->Count++;
  994. }
  995. }
  996. if (!resourceList->Count) {
  997. ExFreePool (requirementsList);
  998. requirementsList = NULL;
  999. }
  1000. status = STATUS_SUCCESS;
  1001. }
  1002. GetOut:
  1003. Irp->IoStatus.Information = (ULONG_PTR) requirementsList;
  1004. Irp->IoStatus.Status = status;
  1005. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1006. return status;
  1007. } // ChannelQueryResourceRequirements
  1008. NTSTATUS
  1009. ChannelInternalDeviceIoControl(
  1010. IN PDEVICE_OBJECT DeviceObject,
  1011. IN PIRP Irp
  1012. )
  1013. {
  1014. PIO_STACK_LOCATION thisIrpSp;
  1015. PCHANPDO_EXTENSION pdoExtension;
  1016. NTSTATUS status;
  1017. PAGED_CODE();
  1018. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1019. if (pdoExtension == NULL) {
  1020. status = STATUS_NO_SUCH_DEVICE;
  1021. } else {
  1022. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1023. switch (thisIrpSp->Parameters.DeviceIoControl.IoControlCode) {
  1024. //
  1025. // TEMP CODE for the time without a real PCI driver.
  1026. // pciidex knows about the resources.
  1027. //
  1028. case IOCTL_IDE_GET_RESOURCES_ALLOCATED:
  1029. {
  1030. PCTRLFDO_EXTENSION fdoExtension;
  1031. ULONG resourceListSize;
  1032. PCM_RESOURCE_LIST resourceList;
  1033. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  1034. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  1035. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  1036. ULONG channel;
  1037. channel = pdoExtension->ChannelNumber;
  1038. fdoExtension = pdoExtension->ParentDeviceExtension;
  1039. resourceListSize = fdoExtension->PdoResourceListSize[channel];
  1040. //
  1041. // have the callee allocate the buffer.
  1042. //
  1043. resourceList = (PCM_RESOURCE_LIST) Irp->AssociatedIrp.SystemBuffer;
  1044. ASSERT(resourceList);
  1045. RtlCopyMemory (
  1046. resourceList,
  1047. fdoExtension->PdoResourceList[channel],
  1048. resourceListSize);
  1049. Irp->IoStatus.Information = resourceListSize;
  1050. status = STATUS_SUCCESS;
  1051. }
  1052. break;
  1053. default:
  1054. DebugPrint ((1,
  1055. "PciIde, Channel PDO got Unknown IoControlCode 0x%x\n",
  1056. thisIrpSp->Parameters.DeviceIoControl.IoControlCode));
  1057. status = STATUS_INVALID_PARAMETER;
  1058. break;
  1059. }
  1060. }
  1061. Irp->IoStatus.Status = status;
  1062. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1063. return status;
  1064. } // ChannelInternalDeviceIoControl
  1065. NTSTATUS
  1066. ChannelQueryText (
  1067. IN PDEVICE_OBJECT DeviceObject,
  1068. IN OUT PIRP Irp
  1069. )
  1070. {
  1071. PIO_STACK_LOCATION thisIrpSp;
  1072. PCHANPDO_EXTENSION pdoExtension;
  1073. PWCHAR returnString;
  1074. ANSI_STRING ansiString;
  1075. UNICODE_STRING unicodeString;
  1076. ULONG stringLen;
  1077. NTSTATUS status;
  1078. PAGED_CODE();
  1079. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1080. if (pdoExtension == NULL) {
  1081. status = STATUS_NO_SUCH_DEVICE;
  1082. } else {
  1083. thisIrpSp = IoGetCurrentIrpStackLocation (Irp);
  1084. returnString = NULL;
  1085. Irp->IoStatus.Information = 0;
  1086. if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  1087. PMESSAGE_RESOURCE_ENTRY messageEntry;
  1088. status = RtlFindMessage(pdoExtension->DriverObject->DriverStart,
  1089. 11,
  1090. LANG_NEUTRAL,
  1091. PCIIDEX_IDE_CHANNEL,
  1092. &messageEntry);
  1093. if (!NT_SUCCESS(status)) {
  1094. returnString = NULL;
  1095. } else {
  1096. if (messageEntry->Flags & MESSAGE_RESOURCE_UNICODE) {
  1097. //
  1098. // Our caller wants a copy they can free, also we need to
  1099. // strip the trailing CR/LF. The Length field of the
  1100. // message structure includes both the header and the
  1101. // actual text.
  1102. //
  1103. // Note: The message resource entry length will always be a
  1104. // multiple of 4 bytes in length. The 2 byte null terminator
  1105. // could be in either the last or second last WCHAR position.
  1106. //
  1107. ULONG textLength;
  1108. textLength = messageEntry->Length -
  1109. FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) -
  1110. 2 * sizeof(WCHAR);
  1111. returnString = (PWCHAR)(messageEntry->Text);
  1112. if (returnString[textLength / sizeof(WCHAR)] == 0) {
  1113. textLength -= sizeof(WCHAR);
  1114. }
  1115. returnString = ExAllocatePool(PagedPool, textLength);
  1116. if (returnString) {
  1117. //
  1118. // Copy the text except for the CR/LF/NULL
  1119. //
  1120. textLength -= sizeof(WCHAR);
  1121. RtlCopyMemory(returnString, messageEntry->Text, textLength);
  1122. //
  1123. // New NULL terminator.
  1124. //
  1125. returnString[textLength / sizeof(WCHAR)] = 0;
  1126. }
  1127. } else {
  1128. //
  1129. // RtlFindMessage returns a string? Wierd.
  1130. //
  1131. ANSI_STRING ansiDescription;
  1132. UNICODE_STRING unicodeDescription;
  1133. RtlInitAnsiString(&ansiDescription, messageEntry->Text);
  1134. //
  1135. // Strip CR/LF off the end of the string.
  1136. //
  1137. ansiDescription.Length -= 2;
  1138. //
  1139. // Turn it all into a unicode string so we can grab the buffer
  1140. // and return that to our caller.
  1141. //
  1142. status = RtlAnsiStringToUnicodeString(
  1143. &unicodeDescription,
  1144. &ansiDescription,
  1145. TRUE
  1146. );
  1147. returnString = unicodeDescription.Buffer;
  1148. }
  1149. }
  1150. } else if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextLocationInformation) {
  1151. stringLen = 100;
  1152. returnString = ExAllocatePool (
  1153. PagedPool,
  1154. stringLen
  1155. );
  1156. if (returnString) {
  1157. swprintf(returnString, L"%ws Channel",
  1158. ((pdoExtension->ChannelNumber == 0) ? L"Primary" :
  1159. L"Secondary"));
  1160. RtlInitUnicodeString (&unicodeString, returnString);
  1161. //
  1162. // null terminate it
  1163. //
  1164. unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 0] = L'\0';
  1165. }
  1166. }
  1167. Irp->IoStatus.Information = (ULONG_PTR) returnString;
  1168. if (Irp->IoStatus.Information) {
  1169. status = STATUS_SUCCESS;
  1170. } else {
  1171. //
  1172. // return the original error code
  1173. //
  1174. status = Irp->IoStatus.Status;
  1175. }
  1176. }
  1177. Irp->IoStatus.Status = status;
  1178. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1179. return status;
  1180. } // ChannelQueryText
  1181. NTSTATUS
  1182. PciIdeChannelQueryInterface (
  1183. IN PDEVICE_OBJECT DeviceObject,
  1184. IN OUT PIRP Irp
  1185. )
  1186. {
  1187. PIO_STACK_LOCATION thisIrpSp;
  1188. PCHANPDO_EXTENSION pdoExtension;
  1189. NTSTATUS status;
  1190. PAGED_CODE();
  1191. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1192. if (pdoExtension == NULL) {
  1193. status = STATUS_NO_SUCH_DEVICE;
  1194. } else {
  1195. status = Irp->IoStatus.Status;
  1196. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  1197. if (RtlEqualMemory(&GUID_PCIIDE_BUSMASTER_INTERFACE,
  1198. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1199. sizeof(GUID)) &&
  1200. (thisIrpSp->Parameters.QueryInterface.Size >=
  1201. sizeof(PCIIDE_BUSMASTER_INTERFACE))) {
  1202. //
  1203. // The query is for an busmaster interface
  1204. //
  1205. status = BmQueryInterface (
  1206. pdoExtension,
  1207. (PPCIIDE_BUSMASTER_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1208. );
  1209. } else if (RtlEqualMemory(&GUID_PCIIDE_SYNC_ACCESS_INTERFACE,
  1210. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1211. sizeof(GUID)) &&
  1212. (thisIrpSp->Parameters.QueryInterface.Size >=
  1213. sizeof(PCIIDE_SYNC_ACCESS_INTERFACE))) {
  1214. //
  1215. // The query is for dual ide channel sync access interface
  1216. //
  1217. status = PciIdeQuerySyncAccessInterface (
  1218. pdoExtension,
  1219. (PPCIIDE_SYNC_ACCESS_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1220. );
  1221. } else if (RtlEqualMemory(&GUID_PCIIDE_XFER_MODE_INTERFACE,
  1222. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1223. sizeof(GUID)) &&
  1224. (thisIrpSp->Parameters.QueryInterface.Size >=
  1225. sizeof(PCIIDE_XFER_MODE_INTERFACE))) {
  1226. //
  1227. // The query is for dual ide channel sync access interface
  1228. //
  1229. status = PciIdeChannelTransferModeInterface (
  1230. pdoExtension,
  1231. (PPCIIDE_XFER_MODE_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1232. );
  1233. #ifdef ENABLE_NATIVE_MODE
  1234. } else if (RtlEqualMemory(&GUID_PCIIDE_INTERRUPT_INTERFACE,
  1235. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1236. sizeof(GUID)) &&
  1237. (thisIrpSp->Parameters.QueryInterface.Size >=
  1238. sizeof(PCIIDE_INTERRUPT_INTERFACE))) {
  1239. //
  1240. // The query is for the channel interrupt interface
  1241. //
  1242. status = PciIdeChannelInterruptInterface (
  1243. pdoExtension,
  1244. (PPCIIDE_INTERRUPT_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1245. );
  1246. #endif
  1247. } else if (RtlEqualMemory(&GUID_PCIIDE_REQUEST_PROPER_RESOURCES,
  1248. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1249. sizeof(GUID)) &&
  1250. (thisIrpSp->Parameters.QueryInterface.Size >=
  1251. sizeof(PCIIDE_REQUEST_PROPER_RESOURCES))) {
  1252. //
  1253. // The query is for dual ide channel sync access interface
  1254. //
  1255. *((PCIIDE_REQUEST_PROPER_RESOURCES *) thisIrpSp->Parameters.QueryInterface.Interface) =
  1256. PciIdeChannelRequestProperResources;
  1257. status = STATUS_SUCCESS;
  1258. }
  1259. }
  1260. Irp->IoStatus.Status = status;
  1261. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1262. return status;
  1263. } // PciIdeChannelQueryInterface
  1264. #ifdef ENABLE_NATIVE_MODE
  1265. NTSTATUS
  1266. PciIdeInterruptControl (
  1267. IN PVOID Context,
  1268. IN ULONG DisConnect
  1269. )
  1270. /*++
  1271. Description:
  1272. Connects or disconnects the controller ISR. This intermediate function provides
  1273. a clean interface to atapi. Since this is not a very frequently used function
  1274. we can afford the extra call
  1275. Arguments :
  1276. Context : Pdo extension
  1277. Disconnect: 1 to disconnect and 0 to connect
  1278. Return Value:
  1279. STATUS_SUCCESS : if the operation succeeds.
  1280. --*/
  1281. {
  1282. PCHANPDO_EXTENSION pdoExtension = Context;
  1283. NTSTATUS status;
  1284. //
  1285. // Call the controller's interrupt control routine
  1286. //
  1287. status = ControllerInterruptControl(pdoExtension->ParentDeviceExtension,
  1288. pdoExtension->ChannelNumber,
  1289. DisConnect
  1290. );
  1291. return status;
  1292. }
  1293. NTSTATUS
  1294. PciIdeChannelInterruptInterface (
  1295. IN PCHANPDO_EXTENSION PdoExtension,
  1296. PPCIIDE_INTERRUPT_INTERFACE InterruptInterface
  1297. )
  1298. {
  1299. //
  1300. // Return an interface only if we are in native mode.
  1301. // Saves a few function calls on non native mode controllers
  1302. //
  1303. if (IsNativeMode(PdoExtension->ParentDeviceExtension)) {
  1304. InterruptInterface->Context = PdoExtension;
  1305. InterruptInterface->PciIdeInterruptControl = PciIdeInterruptControl;
  1306. DebugPrint((1, "PciIdex: returing interrupt interface for channel %x\n",
  1307. PdoExtension->ChannelNumber));
  1308. }
  1309. return STATUS_SUCCESS;
  1310. }
  1311. #endif
  1312. NTSTATUS
  1313. PciIdeChannelTransferModeInterface (
  1314. IN PCHANPDO_EXTENSION PdoExtension,
  1315. PPCIIDE_XFER_MODE_INTERFACE XferMode
  1316. )
  1317. {
  1318. XferMode->TransferModeSelect = PciIdeChannelTransferModeSelect;
  1319. XferMode->TransferModeTimingTable = PdoExtension->ParentDeviceExtension->
  1320. TransferModeTimingTable;
  1321. XferMode->TransferModeTableLength = PdoExtension->ParentDeviceExtension->
  1322. TransferModeTableLength;
  1323. XferMode->Context = PdoExtension;
  1324. XferMode->VendorSpecificDeviceExtension=PdoExtension->
  1325. ParentDeviceExtension->VendorSpecificDeviceEntension;
  1326. XferMode->UdmaModesSupported = PdoExtension->
  1327. ParentDeviceExtension->
  1328. ControllerProperties.PciIdeUdmaModesSupported;
  1329. //
  1330. //NULL is ok. checked in the IdePortDispatchRoutine
  1331. //
  1332. XferMode->UseDma = PdoExtension->
  1333. ParentDeviceExtension->
  1334. ControllerProperties.PciIdeUseDma;
  1335. if (PdoExtension->
  1336. ParentDeviceExtension->
  1337. ControllerProperties.PciIdeTransferModeSelect) {
  1338. //
  1339. // Looks like the miniport fully support timing register programming
  1340. //
  1341. XferMode->SupportLevel = PciIdeFullXferModeSupport;
  1342. } else {
  1343. //
  1344. // Looks like the miniport doens't support timing register programming
  1345. //
  1346. XferMode->SupportLevel = PciIdeBasicXferModeSupport;
  1347. }
  1348. //
  1349. // This function can't fail
  1350. //
  1351. return STATUS_SUCCESS;
  1352. } // PciIdeChannelTransferModeInterface
  1353. NTSTATUS
  1354. PciIdeChannelTransferModeSelect (
  1355. IN PCHANPDO_EXTENSION PdoExtension,
  1356. PPCIIDE_TRANSFER_MODE_SELECT XferMode
  1357. )
  1358. {
  1359. ULONG i;
  1360. NTSTATUS status;
  1361. UCHAR bmRawStatus;
  1362. struct {
  1363. USHORT VendorID;
  1364. USHORT DeviceID;
  1365. } pciId;
  1366. //
  1367. // check the registry for bus master mode
  1368. // and overwrite the current if necessary
  1369. //
  1370. // if DMADetection = 0, clear current dma mode
  1371. // if DMADetection = 1, set current mode
  1372. // if DMADetection = 2, clear all current mode
  1373. if (PdoExtension->DmaDetectionLevel == DdlPioOnly) {
  1374. bmRawStatus = 0;
  1375. for (i=0; i<MAX_IDE_DEVICE * MAX_IDE_LINE; i++) {
  1376. XferMode->DeviceTransferModeSupported[i] &= PIO_SUPPORT;
  1377. XferMode->DeviceTransferModeCurrent[i] &= PIO_SUPPORT;
  1378. }
  1379. } else if (PdoExtension->DmaDetectionLevel == DdlFirmwareOk) {
  1380. if (PdoExtension->BmRegister) {
  1381. //
  1382. // get the firmware ok bits
  1383. // the current value seems to be 0??
  1384. //
  1385. bmRawStatus = PdoExtension->BootBmStatus;
  1386. } else {
  1387. bmRawStatus = 0;
  1388. }
  1389. } else if (PdoExtension->DmaDetectionLevel == DdlAlways) {
  1390. if (PdoExtension->BmRegister) {
  1391. //
  1392. // fake the firmware ok bits
  1393. //
  1394. bmRawStatus = BUSMASTER_DEVICE0_DMA_OK | BUSMASTER_DEVICE1_DMA_OK;
  1395. } else {
  1396. bmRawStatus = 0;
  1397. }
  1398. } else {
  1399. bmRawStatus = 0;
  1400. }
  1401. //
  1402. // in case there is no miniport support
  1403. //
  1404. status = STATUS_UNSUCCESSFUL;
  1405. if (PdoExtension->DmaDetectionLevel != DdlPioOnly) {
  1406. //
  1407. // set up the channel number since the caller (atapi)
  1408. // doesn't know how.
  1409. //
  1410. XferMode->Channel = PdoExtension->ChannelNumber;
  1411. //
  1412. // This decides whether UDMA modes > 2 should be supported or not
  1413. // Currently impacts only the intel chipsets
  1414. //
  1415. XferMode->EnableUDMA66 = PdoExtension->ParentDeviceExtension->EnableUDMA66;
  1416. if (PdoExtension->
  1417. ParentDeviceExtension->
  1418. ControllerProperties.PciIdeTransferModeSelect) {
  1419. status = (*PdoExtension->ParentDeviceExtension->ControllerProperties.PciIdeTransferModeSelect) (
  1420. PdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension,
  1421. XferMode
  1422. );
  1423. }
  1424. }
  1425. DebugPrint((1, "Select in PCIIDEX: RawStatus=%x, current[0]=%x, current[1]=%x\n",
  1426. bmRawStatus,
  1427. XferMode->DeviceTransferModeCurrent[0],
  1428. XferMode->DeviceTransferModeCurrent[1]));
  1429. if (!NT_SUCCESS(status)) {
  1430. status = STATUS_SUCCESS;
  1431. if ((bmRawStatus & BUSMASTER_DEVICE0_DMA_OK) == 0) {
  1432. XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0] & PIO_SUPPORT;
  1433. } else {
  1434. XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0];
  1435. }
  1436. if ((bmRawStatus & BUSMASTER_DEVICE1_DMA_OK) == 0) {
  1437. XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1] & PIO_SUPPORT;
  1438. } else {
  1439. XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1];
  1440. }
  1441. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1442. DebugPrint((1, "Select in PCIIDEX: xfermode[%d]=%x\n",i,
  1443. PdoExtension->ParentDeviceExtension->ControllerProperties.
  1444. SupportedTransferMode[PdoExtension->ChannelNumber][i]));
  1445. if ((PdoExtension->ParentDeviceExtension->ControllerProperties.DefaultPIO == 1) &&
  1446. (IS_DEFAULT(XferMode->UserChoiceTransferMode[i]))) {
  1447. XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT;
  1448. }
  1449. else {
  1450. XferMode->DeviceTransferModeSelected[i] &=
  1451. PdoExtension->ParentDeviceExtension->ControllerProperties.
  1452. SupportedTransferMode[PdoExtension->ChannelNumber][i];
  1453. }
  1454. }
  1455. }
  1456. return status;
  1457. } // PciIdeChannelTransferModeSelect
  1458. NTSTATUS
  1459. ChannelQueryDeviceRelations (
  1460. IN PDEVICE_OBJECT DeviceObject,
  1461. IN OUT PIRP Irp
  1462. )
  1463. {
  1464. PIO_STACK_LOCATION thisIrpSp;
  1465. PDEVICE_RELATIONS deviceRelations;
  1466. NTSTATUS status;
  1467. PAGED_CODE();
  1468. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  1469. switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) {
  1470. case TargetDeviceRelation:
  1471. deviceRelations = ExAllocatePool (NonPagedPool, sizeof(*deviceRelations));
  1472. if (deviceRelations != NULL) {
  1473. deviceRelations->Count = 1;
  1474. deviceRelations->Objects[0] = DeviceObject;
  1475. ObReferenceObjectByPointer(DeviceObject,
  1476. 0,
  1477. 0,
  1478. KernelMode);
  1479. Irp->IoStatus.Status = STATUS_SUCCESS;
  1480. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  1481. } else {
  1482. Irp->IoStatus.Status = STATUS_NO_MEMORY;
  1483. Irp->IoStatus.Information = 0;
  1484. }
  1485. break;
  1486. }
  1487. status = Irp->IoStatus.Status;
  1488. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1489. return status;
  1490. } // ChannelQueryDeviceRelations
  1491. NTSTATUS
  1492. ChannelUsageNotification (
  1493. IN PDEVICE_OBJECT DeviceObject,
  1494. IN OUT PIRP Irp
  1495. )
  1496. {
  1497. NTSTATUS status;
  1498. PCHANPDO_EXTENSION pdoExtension;
  1499. PIO_STACK_LOCATION irpSp;
  1500. PDEVICE_OBJECT targetDeviceObject;
  1501. IO_STATUS_BLOCK ioStatus;
  1502. PULONG deviceUsageCount;
  1503. PAGED_CODE();
  1504. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1505. if (pdoExtension == NULL) {
  1506. status = STATUS_NO_SUCH_DEVICE;
  1507. } else {
  1508. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1509. if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
  1510. //
  1511. // Adjust the paging path count for this device.
  1512. //
  1513. deviceUsageCount = &pdoExtension->PagingPathCount;
  1514. //
  1515. // changing device state
  1516. //
  1517. SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_NOT_DISABLEABLE);
  1518. IoInvalidateDeviceState(pdoExtension->DeviceObject);
  1519. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
  1520. //
  1521. // Adjust the paging path count for this device.
  1522. //
  1523. deviceUsageCount = &pdoExtension->HiberPathCount;
  1524. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
  1525. //
  1526. // Adjust the paging path count for this device.
  1527. //
  1528. deviceUsageCount = &pdoExtension->CrashDumpPathCount;
  1529. } else {
  1530. deviceUsageCount = NULL;
  1531. DebugPrint ((0,
  1532. "PCIIDEX: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n",
  1533. irpSp->Parameters.UsageNotification.Type));
  1534. }
  1535. //
  1536. // get the top of parent's device stack
  1537. //
  1538. targetDeviceObject = IoGetAttachedDeviceReference(
  1539. pdoExtension->
  1540. ParentDeviceExtension->
  1541. DeviceObject);
  1542. ioStatus.Status = STATUS_NOT_SUPPORTED;
  1543. status = PciIdeXSyncSendIrp (targetDeviceObject, irpSp, &ioStatus);
  1544. ObDereferenceObject (targetDeviceObject);
  1545. if (NT_SUCCESS(status)) {
  1546. if (deviceUsageCount) {
  1547. IoAdjustPagingPathCount (
  1548. deviceUsageCount,
  1549. irpSp->Parameters.UsageNotification.InPath
  1550. );
  1551. }
  1552. }
  1553. }
  1554. Irp->IoStatus.Status = status;
  1555. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1556. return status;
  1557. } // ChannelUsageNotification
  1558. NTSTATUS
  1559. ChannelQueryPnPDeviceState (
  1560. IN PDEVICE_OBJECT DeviceObject,
  1561. IN OUT PIRP Irp
  1562. )
  1563. {
  1564. NTSTATUS status;
  1565. PCHANPDO_EXTENSION pdoExtension;
  1566. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1567. if (pdoExtension) {
  1568. PPNP_DEVICE_STATE deviceState;
  1569. DebugPrint((2, "QUERY_DEVICE_STATE for PDOE 0x%x\n", pdoExtension));
  1570. deviceState = (PPNP_DEVICE_STATE) &Irp->IoStatus.Information;
  1571. SETMASK((*deviceState), pdoExtension->PnPDeviceState);
  1572. CLRMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
  1573. status = STATUS_SUCCESS;
  1574. } else {
  1575. status = STATUS_DEVICE_DOES_NOT_EXIST;
  1576. }
  1577. Irp->IoStatus.Status = status;
  1578. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1579. return status;
  1580. } // ChannelQueryPnPDeviceState
  1581. VOID
  1582. PciIdeChannelRequestProperResources(
  1583. IN PDEVICE_OBJECT DeviceObject
  1584. )
  1585. {
  1586. PCHANPDO_EXTENSION pdoExtension;
  1587. //
  1588. // the FDO thinks the channel is not empty
  1589. // anymore
  1590. //
  1591. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1592. if (pdoExtension) {
  1593. pdoExtension->EmptyChannel = FALSE;
  1594. SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
  1595. IoInvalidateDeviceState (DeviceObject);
  1596. }
  1597. }
  1598. NTSTATUS
  1599. ChannelFilterResourceRequirements (
  1600. IN PDEVICE_OBJECT DeviceObject,
  1601. IN OUT PIRP Irp
  1602. )
  1603. {
  1604. NTSTATUS status;
  1605. PCHANPDO_EXTENSION pdoExtension;
  1606. PIO_STACK_LOCATION thisIrpSp;
  1607. ULONG i, j;
  1608. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn = NULL;
  1609. PIO_RESOURCE_LIST resourceListIn;
  1610. PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
  1611. PIO_RESOURCE_LIST resourceListOut;
  1612. PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
  1613. ULONG newCount;
  1614. PAGED_CODE();
  1615. status = STATUS_NOT_SUPPORTED;
  1616. //
  1617. // the value will stay NULL if no filtering required
  1618. //
  1619. #ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
  1620. if (NT_SUCCESS(ChannelFilterPromiseTechResourceRequirements (DeviceObject, Irp))) {
  1621. goto getout;
  1622. }
  1623. #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
  1624. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1625. if (!pdoExtension) {
  1626. goto getout;
  1627. }
  1628. //
  1629. // filter out irq only if the channel is emtpy
  1630. //
  1631. if (!pdoExtension->EmptyChannel) {
  1632. goto getout;
  1633. }
  1634. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  1635. //
  1636. // already filtered.
  1637. //
  1638. requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  1639. } else {
  1640. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1641. requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  1642. }
  1643. if (requirementsListIn == NULL) {
  1644. goto getout;
  1645. }
  1646. if (requirementsListIn->AlternativeLists == 0) {
  1647. goto getout;
  1648. }
  1649. resourceListIn = requirementsListIn->List;
  1650. resourceListOut = resourceListIn;
  1651. for (j=0; j<requirementsListIn->AlternativeLists; j++) {
  1652. ULONG resCount;
  1653. resourceDescriptorIn = resourceListIn->Descriptors;
  1654. RtlMoveMemory (
  1655. resourceListOut,
  1656. resourceListIn,
  1657. FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors));
  1658. resourceDescriptorOut = resourceListOut->Descriptors;
  1659. resCount = resourceListIn->Count;
  1660. for (i=newCount=0; i<resCount; i++) {
  1661. if (resourceDescriptorIn[i].Type != CmResourceTypeInterrupt) {
  1662. resourceDescriptorOut[newCount] = resourceDescriptorIn[i];
  1663. newCount++;
  1664. } else {
  1665. status = STATUS_SUCCESS;
  1666. }
  1667. }
  1668. resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resCount);
  1669. resourceListOut->Count = newCount;
  1670. resourceListOut = (PIO_RESOURCE_LIST) (resourceDescriptorOut + newCount);
  1671. }
  1672. getout:
  1673. if (status != STATUS_NOT_SUPPORTED) {
  1674. Irp->IoStatus.Status = status;
  1675. Irp->IoStatus.Information = (ULONG_PTR) requirementsListIn;
  1676. } else {
  1677. status = Irp->IoStatus.Status;
  1678. }
  1679. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1680. return status;
  1681. }