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.

2201 lines
64 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. }
  207. #if DBG
  208. {
  209. ULONG data;
  210. USHORT vendorId =0;
  211. USHORT deviceId = 0;
  212. PVOID deviceExtension;
  213. data = 0;
  214. deviceExtension = pdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension;
  215. PciIdeXGetBusData (
  216. deviceExtension,
  217. &vendorId,
  218. FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
  219. sizeof(vendorId)
  220. );
  221. PciIdeXGetBusData (
  222. deviceExtension,
  223. &deviceId,
  224. FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID),
  225. sizeof(deviceId)
  226. );
  227. if (vendorId == 0x8086) {
  228. data = 0;
  229. PciIdeXGetBusData (
  230. deviceExtension,
  231. &data,
  232. 0x40, // IDETIM0
  233. 2
  234. );
  235. PciIdeXSaveDeviceParameter (
  236. deviceExtension,
  237. L"Old IDETIM0",
  238. data
  239. );
  240. data = 0;
  241. PciIdeXGetBusData (
  242. deviceExtension,
  243. &data,
  244. 0x42, // IDETIM1
  245. 2
  246. );
  247. PciIdeXSaveDeviceParameter (
  248. deviceExtension,
  249. L"Old IDETIM1",
  250. data
  251. );
  252. if (deviceId != 0x1230) { // !PIIX
  253. data = 0;
  254. PciIdeXGetBusData (
  255. deviceExtension,
  256. &data,
  257. 0x44,
  258. 1
  259. );
  260. PciIdeXSaveDeviceParameter (
  261. deviceExtension,
  262. L"Old SIDETIM",
  263. data
  264. );
  265. }
  266. if (deviceId == 0x7111) {
  267. USHORT t;
  268. data = 0;
  269. PciIdeXGetBusData (
  270. deviceExtension,
  271. &data,
  272. 0x48,
  273. 1
  274. );
  275. PciIdeXSaveDeviceParameter (
  276. deviceExtension,
  277. L"Old SDMACTL",
  278. data
  279. );
  280. data = 0;
  281. PciIdeXGetBusData (
  282. deviceExtension,
  283. &data,
  284. 0x4a, //SDMATIM0
  285. 1
  286. );
  287. PciIdeXSaveDeviceParameter (
  288. deviceExtension,
  289. L"Old SDMATIM0",
  290. data
  291. );
  292. data = 0;
  293. PciIdeXGetBusData (
  294. deviceExtension,
  295. &data,
  296. 0x4b, //SDMATIM1
  297. 1
  298. );
  299. PciIdeXSaveDeviceParameter (
  300. deviceExtension,
  301. L"Old SDMATIM1",
  302. data
  303. );
  304. }
  305. }
  306. }
  307. #endif // DBG
  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. swprintf( 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. idStringBufLen = 10 * sizeof( WCHAR );
  526. idString = ExAllocatePool (PagedPool, idStringBufLen);
  527. if( idString == NULL ){
  528. return NULL;
  529. }
  530. //
  531. // Form the string and return it.
  532. //
  533. swprintf( idString,
  534. instanceIdFormat,
  535. pdoExtension->ChannelNumber);
  536. return idString;
  537. } // ChannelBuildInstanceId
  538. //
  539. // Multi-string Compatible IDs
  540. //
  541. WCHAR ChannelCompatibleId[] = {
  542. L"*PNP0600"
  543. };
  544. //
  545. // internal Compatible IDs
  546. //
  547. PWCHAR ChannelInternalCompatibleId[MAX_IDE_CHANNEL] = {
  548. L"Primary_IDE_Channel",
  549. L"Secondary_IDE_Channel"
  550. };
  551. PWSTR
  552. ChannelBuildCompatibleId(
  553. IN PCHANPDO_EXTENSION pdoExtension
  554. )
  555. {
  556. PWSTR idString;
  557. ULONG idStringBufLen;
  558. ULONG i;
  559. PAGED_CODE();
  560. idStringBufLen = sizeof(ChannelCompatibleId);
  561. idString = ExAllocatePool (PagedPool, idStringBufLen + sizeof (WCHAR) * 2);
  562. if( idString == NULL ){
  563. return NULL;
  564. }
  565. RtlCopyMemory (
  566. idString,
  567. ChannelCompatibleId,
  568. idStringBufLen
  569. );
  570. idString[idStringBufLen/2 + 0] = L'\0';
  571. idString[idStringBufLen/2 + 1] = L'\0';
  572. return idString;
  573. } // ChannelBuildCompatibleId
  574. PWSTR
  575. ChannelBuildHardwareId(
  576. IN PCHANPDO_EXTENSION pdoExtension
  577. )
  578. {
  579. NTSTATUS status;
  580. struct {
  581. USHORT VendorId;
  582. USHORT DeviceId;
  583. } hwRawId;
  584. PWSTR vendorIdString;
  585. PWSTR deviceIdString;
  586. WCHAR vendorId[10];
  587. WCHAR deviceId[10];
  588. PWSTR idString;
  589. ULONG idStringBufLen;
  590. ULONG stringLen;
  591. ULONG internalIdLen;
  592. PAGED_CODE();
  593. status = PciIdeBusData (
  594. pdoExtension->ParentDeviceExtension,
  595. &hwRawId,
  596. 0,
  597. sizeof (hwRawId),
  598. TRUE
  599. );
  600. if (!NT_SUCCESS(status)) {
  601. return NULL;
  602. }
  603. vendorIdString = NULL;
  604. deviceIdString = NULL;
  605. switch (hwRawId.VendorId) {
  606. case 0x8086:
  607. vendorIdString = L"Intel";
  608. switch (hwRawId.DeviceId) {
  609. case 0x1230:
  610. deviceIdString = L"PIIX";
  611. break;
  612. case 0x7010:
  613. deviceIdString = L"PIIX3";
  614. break;
  615. case 0x7111:
  616. deviceIdString = L"PIIX4";
  617. break;
  618. }
  619. break;
  620. case 0x1095:
  621. vendorIdString = L"CMD";
  622. break;
  623. case 0x10b9:
  624. vendorIdString = L"ALi";
  625. break;
  626. case 0x1039:
  627. vendorIdString = L"SiS";
  628. break;
  629. case 0x0e11:
  630. vendorIdString = L"Compaq";
  631. break;
  632. case 0x10ad:
  633. vendorIdString = L"WinBond";
  634. break;
  635. }
  636. if (vendorIdString == NULL) {
  637. swprintf (vendorId,
  638. L"%04x",
  639. hwRawId.VendorId);
  640. vendorIdString = vendorId;
  641. }
  642. if (deviceIdString == NULL) {
  643. swprintf (deviceId,
  644. L"%04x",
  645. hwRawId.DeviceId);
  646. deviceIdString = deviceId;
  647. }
  648. idStringBufLen = (256 * sizeof (WCHAR));
  649. idStringBufLen += sizeof(ChannelCompatibleId);
  650. idString = ExAllocatePool( PagedPool, idStringBufLen);
  651. if( idString == NULL ){
  652. return NULL;
  653. }
  654. //
  655. // Form the string and return it.
  656. //
  657. swprintf (idString,
  658. L"%ws-%ws",
  659. vendorIdString,
  660. deviceIdString
  661. );
  662. stringLen = wcslen(idString);
  663. idString[stringLen] = L'\0';
  664. stringLen++;
  665. //
  666. // internal HW id
  667. //
  668. internalIdLen = wcslen(ChannelInternalCompatibleId[pdoExtension->ChannelNumber]);
  669. RtlCopyMemory (
  670. idString + stringLen,
  671. ChannelInternalCompatibleId[pdoExtension->ChannelNumber],
  672. internalIdLen * sizeof (WCHAR)
  673. );
  674. stringLen += internalIdLen;
  675. idString[stringLen] = L'\0';
  676. stringLen++;
  677. //
  678. // generic HW id
  679. //
  680. RtlCopyMemory (
  681. idString + stringLen,
  682. ChannelCompatibleId,
  683. sizeof(ChannelCompatibleId)
  684. );
  685. stringLen += sizeof(ChannelCompatibleId) / sizeof(WCHAR);
  686. idString[stringLen] = L'\0';
  687. stringLen++;
  688. idString[stringLen] = L'\0';
  689. stringLen++;
  690. return idString;
  691. } // ChannelBuildHardwareId
  692. NTSTATUS
  693. ChannelQueryCapabitilies (
  694. IN PDEVICE_OBJECT DeviceObject,
  695. IN OUT PIRP Irp
  696. )
  697. {
  698. PIO_STACK_LOCATION thisIrpSp;
  699. PCHANPDO_EXTENSION pdoExtension;
  700. PDEVICE_CAPABILITIES capabilities;
  701. NTSTATUS status;
  702. PAGED_CODE();
  703. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  704. if (pdoExtension == NULL) {
  705. status = STATUS_NO_SUCH_DEVICE;
  706. } else {
  707. DEVICE_CAPABILITIES parentDeviceCapabilities;
  708. status = IdeGetDeviceCapabilities(
  709. pdoExtension->ParentDeviceExtension->AttacheePdo,
  710. &parentDeviceCapabilities);
  711. if (NT_SUCCESS(status)) {
  712. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  713. capabilities = thisIrpSp->Parameters.DeviceCapabilities.Capabilities;
  714. *capabilities = parentDeviceCapabilities;
  715. capabilities->UniqueID = FALSE;
  716. capabilities->Address = pdoExtension->ChannelNumber;
  717. }
  718. }
  719. Irp->IoStatus.Status = status;
  720. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  721. return status;
  722. } // ChannelQueryCapabitilies
  723. NTSTATUS
  724. ChannelQueryResources(
  725. IN PDEVICE_OBJECT DeviceObject,
  726. IN PIRP Irp
  727. )
  728. {
  729. PCHANPDO_EXTENSION pdoExtension;
  730. PCTRLFDO_EXTENSION fdoExtension;
  731. PIO_STACK_LOCATION thisIrpSp;
  732. NTSTATUS status;
  733. ULONG resourceListSize;
  734. PCM_RESOURCE_LIST resourceList;
  735. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  736. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  737. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  738. IDE_CHANNEL_STATE channelState;
  739. PAGED_CODE();
  740. resourceList = NULL;
  741. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  742. if (pdoExtension == NULL) {
  743. status = STATUS_NO_SUCH_DEVICE;
  744. } else {
  745. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  746. fdoExtension = pdoExtension->ParentDeviceExtension;
  747. if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
  748. //
  749. // Don't make up resources for native mode controller
  750. // PCI bus driver should find them all
  751. //
  752. resourceList = NULL;
  753. status = STATUS_SUCCESS;
  754. goto GetOut;
  755. }
  756. //
  757. // Don't claim resources if the channel is disabled
  758. //
  759. channelState = PciIdeChannelEnabled (
  760. pdoExtension->ParentDeviceExtension,
  761. pdoExtension->ChannelNumber
  762. );
  763. if (channelState == ChannelDisabled) {
  764. resourceList = NULL;
  765. status = STATUS_SUCCESS;
  766. goto GetOut;
  767. }
  768. //
  769. // TEMP CODE for the time without a real PCI driver.
  770. // Actually pciidex should do this
  771. //
  772. resourceListSize = sizeof (CM_RESOURCE_LIST) - sizeof (CM_FULL_RESOURCE_DESCRIPTOR) +
  773. FULL_RESOURCE_LIST_SIZE(3); // primary IO (2) + IRQ
  774. resourceList = ExAllocatePool (PagedPool, resourceListSize);
  775. if (resourceList == NULL) {
  776. status = STATUS_NO_MEMORY;
  777. goto GetOut;
  778. }
  779. RtlZeroMemory(resourceList, resourceListSize);
  780. resourceList->Count = 1;
  781. fullResourceList = resourceList->List;
  782. partialResourceList = &(fullResourceList->PartialResourceList);
  783. partialResourceList->Count = 0;
  784. partialDescriptors = partialResourceList->PartialDescriptors;
  785. fullResourceList->InterfaceType = Isa;
  786. fullResourceList->BusNumber = 0;
  787. if (pdoExtension->ChannelNumber == 0) {
  788. if (!fdoExtension->PdoCmdRegResourceFound[0]) {
  789. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  790. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  791. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  792. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x1f0;
  793. partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
  794. partialResourceList->Count++;
  795. }
  796. if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
  797. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  798. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  799. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  800. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x3f6;
  801. partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
  802. partialResourceList->Count++;
  803. }
  804. if (!fdoExtension->PdoInterruptResourceFound[0]) {
  805. partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt;
  806. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  807. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  808. partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 14;
  809. partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 14;
  810. partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be looked into.
  811. partialResourceList->Count++;
  812. }
  813. } else { // if (pdoExtension->ChannelNumber == 1)
  814. if (!fdoExtension->PdoCmdRegResourceFound[1]) {
  815. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  816. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  817. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  818. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x170;
  819. partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
  820. partialResourceList->Count++;
  821. }
  822. if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
  823. partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort;
  824. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  825. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  826. partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x376;
  827. partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
  828. partialResourceList->Count++;
  829. }
  830. if (!fdoExtension->PdoInterruptResourceFound[1]) {
  831. partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt;
  832. partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  833. partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  834. partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 15;
  835. partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 15;
  836. partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be Looked into
  837. partialResourceList->Count++;
  838. }
  839. }
  840. if (!partialResourceList->Count) {
  841. ExFreePool (resourceList);
  842. resourceList = NULL;
  843. }
  844. status = STATUS_SUCCESS;
  845. }
  846. GetOut:
  847. Irp->IoStatus.Information = (ULONG_PTR) resourceList;
  848. Irp->IoStatus.Status = status;
  849. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  850. return status;
  851. } // ChannelQueryResources
  852. NTSTATUS
  853. ChannelQueryResourceRequirements(
  854. IN PDEVICE_OBJECT DeviceObject,
  855. IN PIRP Irp
  856. )
  857. {
  858. PIO_STACK_LOCATION thisIrpSp;
  859. PCHANPDO_EXTENSION pdoExtension;
  860. PCTRLFDO_EXTENSION fdoExtension;
  861. NTSTATUS status;
  862. PIO_RESOURCE_REQUIREMENTS_LIST requirementsList;
  863. PIO_RESOURCE_LIST resourceList;
  864. PIO_RESOURCE_DESCRIPTOR resourceDescriptor;
  865. ULONG requirementsListSize;
  866. BOOLEAN reportIrq;
  867. IDE_CHANNEL_STATE channelState;
  868. PAGED_CODE();
  869. requirementsList = NULL;
  870. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  871. if (pdoExtension == NULL) {
  872. status = STATUS_NO_SUCH_DEVICE;
  873. } else {
  874. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  875. fdoExtension = pdoExtension->ParentDeviceExtension;
  876. if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
  877. //
  878. // Don't make up resources for native mode controller
  879. // PCI bus driver should find them all
  880. //
  881. requirementsList = NULL;
  882. status = STATUS_SUCCESS;
  883. goto GetOut;
  884. }
  885. //
  886. // legacy controller
  887. //
  888. channelState = PciIdeChannelEnabled (
  889. pdoExtension->ParentDeviceExtension,
  890. pdoExtension->ChannelNumber
  891. );
  892. //
  893. // Don't claim resources if the channel is disabled
  894. //
  895. if (channelState == ChannelStateUnknown ) {
  896. if (pdoExtension->EmptyChannel) {
  897. reportIrq = FALSE;
  898. } else {
  899. reportIrq = TRUE;
  900. }
  901. } else if (channelState == ChannelDisabled) {
  902. requirementsList = NULL;
  903. status = STATUS_SUCCESS;
  904. goto GetOut;
  905. }
  906. //
  907. // TEMP CODE for the time without a real PCI driver.
  908. // pciidex should do this.
  909. //
  910. requirementsListSize = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
  911. sizeof (IO_RESOURCE_DESCRIPTOR) * (3 - 1);
  912. requirementsList = ExAllocatePool (PagedPool, requirementsListSize);
  913. if( requirementsList == NULL ){
  914. status = STATUS_NO_MEMORY;
  915. goto GetOut;
  916. }
  917. RtlZeroMemory(requirementsList, requirementsListSize);
  918. requirementsList->ListSize = requirementsListSize;
  919. requirementsList->InterfaceType = Isa;
  920. requirementsList->BusNumber = 0; // ISSUE: 08/30/2000
  921. requirementsList->SlotNumber = 0;
  922. requirementsList->AlternativeLists = 1;
  923. resourceList = requirementsList->List;
  924. resourceList->Version = 1;
  925. resourceList->Revision = 1;
  926. resourceList->Count = 0;
  927. resourceDescriptor = resourceList->Descriptors;
  928. if (pdoExtension->ChannelNumber == 0) {
  929. if (!fdoExtension->PdoCmdRegResourceFound[0]) {
  930. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  931. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  932. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  933. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  934. resourceDescriptor[resourceList->Count].u.Port.Length = 8;
  935. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  936. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x1f0;
  937. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x1f7;
  938. resourceList->Count++;
  939. }
  940. if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
  941. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  942. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  943. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  944. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  945. resourceDescriptor[resourceList->Count].u.Port.Length = 1;
  946. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  947. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x3f6;
  948. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x3f6;
  949. resourceList->Count++;
  950. }
  951. if (!fdoExtension->PdoInterruptResourceFound[0] && reportIrq) {
  952. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  953. resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt;
  954. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  955. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  956. resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xe;
  957. resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xe;
  958. resourceList->Count++;
  959. }
  960. } else { // if (pdoExtension->ChannelNumber == 1)
  961. if (!fdoExtension->PdoCmdRegResourceFound[1]) {
  962. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  963. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  964. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  965. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  966. resourceDescriptor[resourceList->Count].u.Port.Length = 8;
  967. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  968. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x170;
  969. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x177;
  970. resourceList->Count++;
  971. }
  972. if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
  973. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  974. resourceDescriptor[resourceList->Count].Type = CmResourceTypePort;
  975. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  976. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  977. resourceDescriptor[resourceList->Count].u.Port.Length = 1;
  978. resourceDescriptor[resourceList->Count].u.Port.Alignment = 1;
  979. resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x376;
  980. resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x376;
  981. resourceList->Count++;
  982. }
  983. if (!fdoExtension->PdoInterruptResourceFound[1] && reportIrq) {
  984. resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED;
  985. resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt;
  986. resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive;
  987. resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  988. resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xf;
  989. resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xf;
  990. resourceList->Count++;
  991. }
  992. }
  993. if (!resourceList->Count) {
  994. ExFreePool (requirementsList);
  995. requirementsList = NULL;
  996. }
  997. status = STATUS_SUCCESS;
  998. }
  999. GetOut:
  1000. Irp->IoStatus.Information = (ULONG_PTR) requirementsList;
  1001. Irp->IoStatus.Status = status;
  1002. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1003. return status;
  1004. } // ChannelQueryResourceRequirements
  1005. NTSTATUS
  1006. ChannelInternalDeviceIoControl(
  1007. IN PDEVICE_OBJECT DeviceObject,
  1008. IN PIRP Irp
  1009. )
  1010. {
  1011. PIO_STACK_LOCATION thisIrpSp;
  1012. PCHANPDO_EXTENSION pdoExtension;
  1013. NTSTATUS status;
  1014. PAGED_CODE();
  1015. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1016. if (pdoExtension == NULL) {
  1017. status = STATUS_NO_SUCH_DEVICE;
  1018. } else {
  1019. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1020. switch (thisIrpSp->Parameters.DeviceIoControl.IoControlCode) {
  1021. //
  1022. // TEMP CODE for the time without a real PCI driver.
  1023. // pciidex knows about the resources.
  1024. //
  1025. case IOCTL_IDE_GET_RESOURCES_ALLOCATED:
  1026. {
  1027. PCTRLFDO_EXTENSION fdoExtension;
  1028. ULONG resourceListSize;
  1029. PCM_RESOURCE_LIST resourceList;
  1030. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  1031. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  1032. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  1033. ULONG channel;
  1034. channel = pdoExtension->ChannelNumber;
  1035. fdoExtension = pdoExtension->ParentDeviceExtension;
  1036. resourceListSize = fdoExtension->PdoResourceListSize[channel];
  1037. //
  1038. // have the callee allocate the buffer.
  1039. //
  1040. resourceList = (PCM_RESOURCE_LIST) Irp->AssociatedIrp.SystemBuffer;
  1041. ASSERT(resourceList);
  1042. RtlCopyMemory (
  1043. resourceList,
  1044. fdoExtension->PdoResourceList[channel],
  1045. resourceListSize);
  1046. Irp->IoStatus.Information = resourceListSize;
  1047. status = STATUS_SUCCESS;
  1048. }
  1049. break;
  1050. default:
  1051. DebugPrint ((1,
  1052. "PciIde, Channel PDO got Unknown IoControlCode 0x%x\n",
  1053. thisIrpSp->Parameters.DeviceIoControl.IoControlCode));
  1054. status = STATUS_INVALID_PARAMETER;
  1055. break;
  1056. }
  1057. }
  1058. Irp->IoStatus.Status = status;
  1059. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1060. return status;
  1061. } // ChannelInternalDeviceIoControl
  1062. NTSTATUS
  1063. ChannelQueryText (
  1064. IN PDEVICE_OBJECT DeviceObject,
  1065. IN OUT PIRP Irp
  1066. )
  1067. {
  1068. PIO_STACK_LOCATION thisIrpSp;
  1069. PCHANPDO_EXTENSION pdoExtension;
  1070. PWCHAR returnString;
  1071. ANSI_STRING ansiString;
  1072. UNICODE_STRING unicodeString;
  1073. ULONG stringLen;
  1074. NTSTATUS status;
  1075. PAGED_CODE();
  1076. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1077. if (pdoExtension == NULL) {
  1078. status = STATUS_NO_SUCH_DEVICE;
  1079. } else {
  1080. thisIrpSp = IoGetCurrentIrpStackLocation (Irp);
  1081. returnString = NULL;
  1082. Irp->IoStatus.Information = 0;
  1083. if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  1084. PMESSAGE_RESOURCE_ENTRY messageEntry;
  1085. status = RtlFindMessage(pdoExtension->DriverObject->DriverStart,
  1086. 11,
  1087. LANG_NEUTRAL,
  1088. PCIIDEX_IDE_CHANNEL,
  1089. &messageEntry);
  1090. if (!NT_SUCCESS(status)) {
  1091. returnString = NULL;
  1092. } else {
  1093. if (messageEntry->Flags & MESSAGE_RESOURCE_UNICODE) {
  1094. //
  1095. // Our caller wants a copy they can free, also we need to
  1096. // strip the trailing CR/LF. The Length field of the
  1097. // message structure includes both the header and the
  1098. // actual text.
  1099. //
  1100. // Note: The message resource entry length will always be a
  1101. // multiple of 4 bytes in length. The 2 byte null terminator
  1102. // could be in either the last or second last WCHAR position.
  1103. //
  1104. ULONG textLength;
  1105. textLength = messageEntry->Length -
  1106. FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) -
  1107. 2 * sizeof(WCHAR);
  1108. returnString = (PWCHAR)(messageEntry->Text);
  1109. if (returnString[textLength / sizeof(WCHAR)] == 0) {
  1110. textLength -= sizeof(WCHAR);
  1111. }
  1112. returnString = ExAllocatePool(PagedPool, textLength);
  1113. if (returnString) {
  1114. //
  1115. // Copy the text except for the CR/LF/NULL
  1116. //
  1117. textLength -= sizeof(WCHAR);
  1118. RtlCopyMemory(returnString, messageEntry->Text, textLength);
  1119. //
  1120. // New NULL terminator.
  1121. //
  1122. returnString[textLength / sizeof(WCHAR)] = 0;
  1123. }
  1124. } else {
  1125. //
  1126. // RtlFindMessage returns a string? Wierd.
  1127. //
  1128. ANSI_STRING ansiDescription;
  1129. UNICODE_STRING unicodeDescription;
  1130. RtlInitAnsiString(&ansiDescription, messageEntry->Text);
  1131. //
  1132. // Strip CR/LF off the end of the string.
  1133. //
  1134. ansiDescription.Length -= 2;
  1135. //
  1136. // Turn it all into a unicode string so we can grab the buffer
  1137. // and return that to our caller.
  1138. //
  1139. status = RtlAnsiStringToUnicodeString(
  1140. &unicodeDescription,
  1141. &ansiDescription,
  1142. TRUE
  1143. );
  1144. returnString = unicodeDescription.Buffer;
  1145. }
  1146. }
  1147. } else if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextLocationInformation) {
  1148. stringLen = 100;
  1149. returnString = ExAllocatePool (
  1150. PagedPool,
  1151. stringLen
  1152. );
  1153. if (returnString) {
  1154. swprintf(returnString, L"%ws Channel",
  1155. ((pdoExtension->ChannelNumber == 0) ? L"Primary" :
  1156. L"Secondary"));
  1157. RtlInitUnicodeString (&unicodeString, returnString);
  1158. //
  1159. // null terminate it
  1160. //
  1161. unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 0] = L'\0';
  1162. }
  1163. }
  1164. Irp->IoStatus.Information = (ULONG_PTR) returnString;
  1165. if (Irp->IoStatus.Information) {
  1166. status = STATUS_SUCCESS;
  1167. } else {
  1168. //
  1169. // return the original error code
  1170. //
  1171. status = Irp->IoStatus.Status;
  1172. }
  1173. }
  1174. Irp->IoStatus.Status = status;
  1175. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1176. return status;
  1177. } // ChannelQueryText
  1178. NTSTATUS
  1179. PciIdeChannelQueryInterface (
  1180. IN PDEVICE_OBJECT DeviceObject,
  1181. IN OUT PIRP Irp
  1182. )
  1183. {
  1184. PIO_STACK_LOCATION thisIrpSp;
  1185. PCHANPDO_EXTENSION pdoExtension;
  1186. NTSTATUS status;
  1187. PAGED_CODE();
  1188. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1189. if (pdoExtension == NULL) {
  1190. status = STATUS_NO_SUCH_DEVICE;
  1191. } else {
  1192. status = Irp->IoStatus.Status;
  1193. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  1194. if (RtlEqualMemory(&GUID_PCIIDE_BUSMASTER_INTERFACE,
  1195. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1196. sizeof(GUID)) &&
  1197. (thisIrpSp->Parameters.QueryInterface.Size >=
  1198. sizeof(PCIIDE_BUSMASTER_INTERFACE))) {
  1199. //
  1200. // The query is for an busmaster interface
  1201. //
  1202. status = BmQueryInterface (
  1203. pdoExtension,
  1204. (PPCIIDE_BUSMASTER_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1205. );
  1206. } else if (RtlEqualMemory(&GUID_PCIIDE_SYNC_ACCESS_INTERFACE,
  1207. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1208. sizeof(GUID)) &&
  1209. (thisIrpSp->Parameters.QueryInterface.Size >=
  1210. sizeof(PCIIDE_SYNC_ACCESS_INTERFACE))) {
  1211. //
  1212. // The query is for dual ide channel sync access interface
  1213. //
  1214. status = PciIdeQuerySyncAccessInterface (
  1215. pdoExtension,
  1216. (PPCIIDE_SYNC_ACCESS_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1217. );
  1218. } else if (RtlEqualMemory(&GUID_PCIIDE_XFER_MODE_INTERFACE,
  1219. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1220. sizeof(GUID)) &&
  1221. (thisIrpSp->Parameters.QueryInterface.Size >=
  1222. sizeof(PCIIDE_XFER_MODE_INTERFACE))) {
  1223. //
  1224. // The query is for dual ide channel sync access interface
  1225. //
  1226. status = PciIdeChannelTransferModeInterface (
  1227. pdoExtension,
  1228. (PPCIIDE_XFER_MODE_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1229. );
  1230. #ifdef ENABLE_NATIVE_MODE
  1231. } else if (RtlEqualMemory(&GUID_PCIIDE_INTERRUPT_INTERFACE,
  1232. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1233. sizeof(GUID)) &&
  1234. (thisIrpSp->Parameters.QueryInterface.Size >=
  1235. sizeof(PCIIDE_INTERRUPT_INTERFACE))) {
  1236. //
  1237. // The query is for the channel interrupt interface
  1238. //
  1239. status = PciIdeChannelInterruptInterface (
  1240. pdoExtension,
  1241. (PPCIIDE_INTERRUPT_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface
  1242. );
  1243. #endif
  1244. } else if (RtlEqualMemory(&GUID_PCIIDE_REQUEST_PROPER_RESOURCES,
  1245. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  1246. sizeof(GUID)) &&
  1247. (thisIrpSp->Parameters.QueryInterface.Size >=
  1248. sizeof(PCIIDE_REQUEST_PROPER_RESOURCES))) {
  1249. //
  1250. // The query is for dual ide channel sync access interface
  1251. //
  1252. *((PCIIDE_REQUEST_PROPER_RESOURCES *) thisIrpSp->Parameters.QueryInterface.Interface) =
  1253. PciIdeChannelRequestProperResources;
  1254. status = STATUS_SUCCESS;
  1255. }
  1256. }
  1257. Irp->IoStatus.Status = status;
  1258. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1259. return status;
  1260. } // PciIdeChannelQueryInterface
  1261. #ifdef ENABLE_NATIVE_MODE
  1262. NTSTATUS
  1263. PciIdeInterruptControl (
  1264. IN PVOID Context,
  1265. IN ULONG DisConnect
  1266. )
  1267. /*++
  1268. Description:
  1269. Connects or disconnects the controller ISR. This intermediate function provides
  1270. a clean interface to atapi. Since this is not a very frequently used function
  1271. we can afford the extra call
  1272. Arguments :
  1273. Context : Pdo extension
  1274. Disconnect: 1 to disconnect and 0 to connect
  1275. Return Value:
  1276. STATUS_SUCCESS : if the operation succeeds.
  1277. --*/
  1278. {
  1279. PCHANPDO_EXTENSION pdoExtension = Context;
  1280. NTSTATUS status;
  1281. //
  1282. // Call the controller's interrupt control routine
  1283. //
  1284. status = ControllerInterruptControl(pdoExtension->ParentDeviceExtension,
  1285. pdoExtension->ChannelNumber,
  1286. DisConnect
  1287. );
  1288. return status;
  1289. }
  1290. NTSTATUS
  1291. PciIdeChannelInterruptInterface (
  1292. IN PCHANPDO_EXTENSION PdoExtension,
  1293. PPCIIDE_INTERRUPT_INTERFACE InterruptInterface
  1294. )
  1295. {
  1296. //
  1297. // Return an interface only if we are in native mode.
  1298. // Saves a few function calls on non native mode controllers
  1299. //
  1300. if (IsNativeMode(PdoExtension->ParentDeviceExtension)) {
  1301. InterruptInterface->Context = PdoExtension;
  1302. InterruptInterface->PciIdeInterruptControl = PciIdeInterruptControl;
  1303. DebugPrint((1, "PciIdex: returing interrupt interface for channel %x\n",
  1304. PdoExtension->ChannelNumber));
  1305. }
  1306. return STATUS_SUCCESS;
  1307. }
  1308. #endif
  1309. NTSTATUS
  1310. PciIdeChannelTransferModeInterface (
  1311. IN PCHANPDO_EXTENSION PdoExtension,
  1312. PPCIIDE_XFER_MODE_INTERFACE XferMode
  1313. )
  1314. {
  1315. XferMode->TransferModeSelect = PciIdeChannelTransferModeSelect;
  1316. XferMode->TransferModeTimingTable = PdoExtension->ParentDeviceExtension->
  1317. TransferModeTimingTable;
  1318. XferMode->TransferModeTableLength = PdoExtension->ParentDeviceExtension->
  1319. TransferModeTableLength;
  1320. XferMode->Context = PdoExtension;
  1321. XferMode->VendorSpecificDeviceExtension=PdoExtension->
  1322. ParentDeviceExtension->VendorSpecificDeviceEntension;
  1323. XferMode->UdmaModesSupported = PdoExtension->
  1324. ParentDeviceExtension->
  1325. ControllerProperties.PciIdeUdmaModesSupported;
  1326. //
  1327. //NULL is ok. checked in the IdePortDispatchRoutine
  1328. //
  1329. XferMode->UseDma = PdoExtension->
  1330. ParentDeviceExtension->
  1331. ControllerProperties.PciIdeUseDma;
  1332. if (PdoExtension->
  1333. ParentDeviceExtension->
  1334. ControllerProperties.PciIdeTransferModeSelect) {
  1335. //
  1336. // Looks like the miniport fully support timing register programming
  1337. //
  1338. XferMode->SupportLevel = PciIdeFullXferModeSupport;
  1339. } else {
  1340. //
  1341. // Looks like the miniport doens't support timing register programming
  1342. //
  1343. XferMode->SupportLevel = PciIdeBasicXferModeSupport;
  1344. }
  1345. //
  1346. // This function can't fail
  1347. //
  1348. return STATUS_SUCCESS;
  1349. } // PciIdeChannelTransferModeInterface
  1350. NTSTATUS
  1351. PciIdeChannelTransferModeSelect (
  1352. IN PCHANPDO_EXTENSION PdoExtension,
  1353. PPCIIDE_TRANSFER_MODE_SELECT XferMode
  1354. )
  1355. {
  1356. ULONG i;
  1357. NTSTATUS status;
  1358. UCHAR bmRawStatus;
  1359. struct {
  1360. USHORT VendorID;
  1361. USHORT DeviceID;
  1362. } pciId;
  1363. //
  1364. // check the registry for bus master mode
  1365. // and overwrite the current if necessary
  1366. //
  1367. // if DMADetection = 0, clear current dma mode
  1368. // if DMADetection = 1, set current mode
  1369. // if DMADetection = 2, clear all current mode
  1370. if (PdoExtension->DmaDetectionLevel == DdlPioOnly) {
  1371. bmRawStatus = 0;
  1372. for (i=0; i<MAX_IDE_DEVICE * MAX_IDE_LINE; i++) {
  1373. XferMode->DeviceTransferModeSupported[i] &= PIO_SUPPORT;
  1374. XferMode->DeviceTransferModeCurrent[i] &= PIO_SUPPORT;
  1375. }
  1376. } else if (PdoExtension->DmaDetectionLevel == DdlFirmwareOk) {
  1377. if (PdoExtension->BmRegister) {
  1378. //
  1379. // get the firmware ok bits
  1380. // the current value seems to be 0??
  1381. //
  1382. bmRawStatus = PdoExtension->BootBmStatus;
  1383. } else {
  1384. bmRawStatus = 0;
  1385. }
  1386. } else if (PdoExtension->DmaDetectionLevel == DdlAlways) {
  1387. if (PdoExtension->BmRegister) {
  1388. //
  1389. // fake the firmware ok bits
  1390. //
  1391. bmRawStatus = BUSMASTER_DEVICE0_DMA_OK | BUSMASTER_DEVICE1_DMA_OK;
  1392. } else {
  1393. bmRawStatus = 0;
  1394. }
  1395. } else {
  1396. bmRawStatus = 0;
  1397. }
  1398. //
  1399. // in case there is no miniport support
  1400. //
  1401. status = STATUS_UNSUCCESSFUL;
  1402. if (PdoExtension->DmaDetectionLevel != DdlPioOnly) {
  1403. //
  1404. // set up the channel number since the caller (atapi)
  1405. // doesn't know how.
  1406. //
  1407. XferMode->Channel = PdoExtension->ChannelNumber;
  1408. //
  1409. // This decides whether UDMA modes > 2 should be supported or not
  1410. // Currently impacts only the intel chipsets
  1411. //
  1412. XferMode->EnableUDMA66 = PdoExtension->ParentDeviceExtension->EnableUDMA66;
  1413. if (PdoExtension->
  1414. ParentDeviceExtension->
  1415. ControllerProperties.PciIdeTransferModeSelect) {
  1416. status = (*PdoExtension->ParentDeviceExtension->ControllerProperties.PciIdeTransferModeSelect) (
  1417. PdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension,
  1418. XferMode
  1419. );
  1420. }
  1421. }
  1422. DebugPrint((1, "Select in PCIIDEX: RawStatus=%x, current[0]=%x, current[1]=%x\n",
  1423. bmRawStatus,
  1424. XferMode->DeviceTransferModeCurrent[0],
  1425. XferMode->DeviceTransferModeCurrent[1]));
  1426. if (!NT_SUCCESS(status)) {
  1427. status = STATUS_SUCCESS;
  1428. if ((bmRawStatus & BUSMASTER_DEVICE0_DMA_OK) == 0) {
  1429. XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0] & PIO_SUPPORT;
  1430. } else {
  1431. XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0];
  1432. }
  1433. if ((bmRawStatus & BUSMASTER_DEVICE1_DMA_OK) == 0) {
  1434. XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1] & PIO_SUPPORT;
  1435. } else {
  1436. XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1];
  1437. }
  1438. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1439. DebugPrint((1, "Select in PCIIDEX: xfermode[%d]=%x\n",i,
  1440. PdoExtension->ParentDeviceExtension->ControllerProperties.
  1441. SupportedTransferMode[PdoExtension->ChannelNumber][i]));
  1442. if ((PdoExtension->ParentDeviceExtension->ControllerProperties.DefaultPIO == 1) &&
  1443. (IS_DEFAULT(XferMode->UserChoiceTransferMode[i]))) {
  1444. XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT;
  1445. }
  1446. else {
  1447. XferMode->DeviceTransferModeSelected[i] &=
  1448. PdoExtension->ParentDeviceExtension->ControllerProperties.
  1449. SupportedTransferMode[PdoExtension->ChannelNumber][i];
  1450. }
  1451. }
  1452. }
  1453. return status;
  1454. } // PciIdeChannelTransferModeSelect
  1455. NTSTATUS
  1456. ChannelQueryDeviceRelations (
  1457. IN PDEVICE_OBJECT DeviceObject,
  1458. IN OUT PIRP Irp
  1459. )
  1460. {
  1461. PIO_STACK_LOCATION thisIrpSp;
  1462. PDEVICE_RELATIONS deviceRelations;
  1463. NTSTATUS status;
  1464. PAGED_CODE();
  1465. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  1466. switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) {
  1467. case TargetDeviceRelation:
  1468. deviceRelations = ExAllocatePool (NonPagedPool, sizeof(*deviceRelations));
  1469. if (deviceRelations != NULL) {
  1470. deviceRelations->Count = 1;
  1471. deviceRelations->Objects[0] = DeviceObject;
  1472. ObReferenceObjectByPointer(DeviceObject,
  1473. 0,
  1474. 0,
  1475. KernelMode);
  1476. Irp->IoStatus.Status = STATUS_SUCCESS;
  1477. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  1478. } else {
  1479. Irp->IoStatus.Status = STATUS_NO_MEMORY;
  1480. Irp->IoStatus.Information = 0;
  1481. }
  1482. break;
  1483. }
  1484. status = Irp->IoStatus.Status;
  1485. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1486. return status;
  1487. } // ChannelQueryDeviceRelations
  1488. NTSTATUS
  1489. ChannelUsageNotification (
  1490. IN PDEVICE_OBJECT DeviceObject,
  1491. IN OUT PIRP Irp
  1492. )
  1493. {
  1494. NTSTATUS status;
  1495. PCHANPDO_EXTENSION pdoExtension;
  1496. PIO_STACK_LOCATION irpSp;
  1497. PDEVICE_OBJECT targetDeviceObject;
  1498. IO_STATUS_BLOCK ioStatus;
  1499. PULONG deviceUsageCount;
  1500. PAGED_CODE();
  1501. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1502. if (pdoExtension == NULL) {
  1503. status = STATUS_NO_SUCH_DEVICE;
  1504. } else {
  1505. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1506. if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
  1507. //
  1508. // Adjust the paging path count for this device.
  1509. //
  1510. deviceUsageCount = &pdoExtension->PagingPathCount;
  1511. //
  1512. // changing device state
  1513. //
  1514. SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_NOT_DISABLEABLE);
  1515. IoInvalidateDeviceState(pdoExtension->DeviceObject);
  1516. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
  1517. //
  1518. // Adjust the paging path count for this device.
  1519. //
  1520. deviceUsageCount = &pdoExtension->HiberPathCount;
  1521. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
  1522. //
  1523. // Adjust the paging path count for this device.
  1524. //
  1525. deviceUsageCount = &pdoExtension->CrashDumpPathCount;
  1526. } else {
  1527. deviceUsageCount = NULL;
  1528. DebugPrint ((0,
  1529. "PCIIDEX: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n",
  1530. irpSp->Parameters.UsageNotification.Type));
  1531. }
  1532. //
  1533. // get the top of parent's device stack
  1534. //
  1535. targetDeviceObject = IoGetAttachedDeviceReference(
  1536. pdoExtension->
  1537. ParentDeviceExtension->
  1538. DeviceObject);
  1539. ioStatus.Status = STATUS_NOT_SUPPORTED;
  1540. status = PciIdeXSyncSendIrp (targetDeviceObject, irpSp, &ioStatus);
  1541. ObDereferenceObject (targetDeviceObject);
  1542. if (NT_SUCCESS(status)) {
  1543. if (deviceUsageCount) {
  1544. IoAdjustPagingPathCount (
  1545. deviceUsageCount,
  1546. irpSp->Parameters.UsageNotification.InPath
  1547. );
  1548. }
  1549. }
  1550. }
  1551. Irp->IoStatus.Status = status;
  1552. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1553. return status;
  1554. } // ChannelUsageNotification
  1555. NTSTATUS
  1556. ChannelQueryPnPDeviceState (
  1557. IN PDEVICE_OBJECT DeviceObject,
  1558. IN OUT PIRP Irp
  1559. )
  1560. {
  1561. NTSTATUS status;
  1562. PCHANPDO_EXTENSION pdoExtension;
  1563. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1564. if (pdoExtension) {
  1565. PPNP_DEVICE_STATE deviceState;
  1566. DebugPrint((2, "QUERY_DEVICE_STATE for PDOE 0x%x\n", pdoExtension));
  1567. deviceState = (PPNP_DEVICE_STATE) &Irp->IoStatus.Information;
  1568. SETMASK((*deviceState), pdoExtension->PnPDeviceState);
  1569. CLRMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
  1570. status = STATUS_SUCCESS;
  1571. } else {
  1572. status = STATUS_DEVICE_DOES_NOT_EXIST;
  1573. }
  1574. Irp->IoStatus.Status = status;
  1575. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1576. return status;
  1577. } // ChannelQueryPnPDeviceState
  1578. VOID
  1579. PciIdeChannelRequestProperResources(
  1580. IN PDEVICE_OBJECT DeviceObject
  1581. )
  1582. {
  1583. PCHANPDO_EXTENSION pdoExtension;
  1584. //
  1585. // the FDO thinks the channel is not empty
  1586. // anymore
  1587. //
  1588. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1589. if (pdoExtension) {
  1590. pdoExtension->EmptyChannel = FALSE;
  1591. SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
  1592. IoInvalidateDeviceState (DeviceObject);
  1593. }
  1594. }
  1595. NTSTATUS
  1596. ChannelFilterResourceRequirements (
  1597. IN PDEVICE_OBJECT DeviceObject,
  1598. IN OUT PIRP Irp
  1599. )
  1600. {
  1601. NTSTATUS status;
  1602. PCHANPDO_EXTENSION pdoExtension;
  1603. PIO_STACK_LOCATION thisIrpSp;
  1604. ULONG i, j;
  1605. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn = NULL;
  1606. PIO_RESOURCE_LIST resourceListIn;
  1607. PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
  1608. PIO_RESOURCE_LIST resourceListOut;
  1609. PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
  1610. ULONG newCount;
  1611. PAGED_CODE();
  1612. status = STATUS_NOT_SUPPORTED;
  1613. //
  1614. // the value will stay NULL if no filtering required
  1615. //
  1616. #ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
  1617. if (NT_SUCCESS(ChannelFilterPromiseTechResourceRequirements (DeviceObject, Irp))) {
  1618. goto getout;
  1619. }
  1620. #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
  1621. pdoExtension = ChannelGetPdoExtension(DeviceObject);
  1622. if (!pdoExtension) {
  1623. goto getout;
  1624. }
  1625. //
  1626. // filter out irq only if the channel is emtpy
  1627. //
  1628. if (!pdoExtension->EmptyChannel) {
  1629. goto getout;
  1630. }
  1631. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  1632. //
  1633. // already filtered.
  1634. //
  1635. requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  1636. } else {
  1637. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1638. requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  1639. }
  1640. if (requirementsListIn == NULL) {
  1641. goto getout;
  1642. }
  1643. if (requirementsListIn->AlternativeLists == 0) {
  1644. goto getout;
  1645. }
  1646. resourceListIn = requirementsListIn->List;
  1647. resourceListOut = resourceListIn;
  1648. for (j=0; j<requirementsListIn->AlternativeLists; j++) {
  1649. ULONG resCount;
  1650. resourceDescriptorIn = resourceListIn->Descriptors;
  1651. RtlMoveMemory (
  1652. resourceListOut,
  1653. resourceListIn,
  1654. FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors));
  1655. resourceDescriptorOut = resourceListOut->Descriptors;
  1656. resCount = resourceListIn->Count;
  1657. for (i=newCount=0; i<resCount; i++) {
  1658. if (resourceDescriptorIn[i].Type != CmResourceTypeInterrupt) {
  1659. resourceDescriptorOut[newCount] = resourceDescriptorIn[i];
  1660. newCount++;
  1661. } else {
  1662. status = STATUS_SUCCESS;
  1663. }
  1664. }
  1665. resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resCount);
  1666. resourceListOut->Count = newCount;
  1667. resourceListOut = (PIO_RESOURCE_LIST) (resourceDescriptorOut + newCount);
  1668. }
  1669. getout:
  1670. if (status != STATUS_NOT_SUPPORTED) {
  1671. Irp->IoStatus.Status = status;
  1672. Irp->IoStatus.Information = (ULONG_PTR) requirementsListIn;
  1673. } else {
  1674. status = Irp->IoStatus.Status;
  1675. }
  1676. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1677. return status;
  1678. }