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.

3141 lines
92 KiB

  1. /*++
  2. Copyright (C) 1993-99 Microsoft Corporation
  3. Module Name:
  4. chanfdo.c
  5. Abstract:
  6. --*/
  7. #include "ideport.h"
  8. #ifdef ALLOC_PRAGMA
  9. #pragma alloc_text(PAGE, ChannelAddDevice)
  10. #pragma alloc_text(PAGE, ChannelAddChannel)
  11. #pragma alloc_text(PAGE, ChannelStartDevice)
  12. #pragma alloc_text(PAGE, ChannelStartChannel)
  13. #pragma alloc_text(PAGE, ChannelCreateSymblicLinks)
  14. #pragma alloc_text(PAGE, ChannelDeleteSymblicLinks)
  15. #pragma alloc_text(PAGE, ChannelRemoveDevice)
  16. #pragma alloc_text(PAGE, ChannelSurpriseRemoveDevice)
  17. #pragma alloc_text(PAGE, ChannelStopDevice)
  18. #pragma alloc_text(PAGE, ChannelRemoveChannel)
  19. #pragma alloc_text(PAGE, ChannelQueryDeviceRelations)
  20. #pragma alloc_text(PAGE, ChannelQueryBusRelation)
  21. #pragma alloc_text(PAGE, ChannelQueryId)
  22. #pragma alloc_text(PAGE, ChannelUsageNotification)
  23. #pragma alloc_text(PAGE, DigestResourceList)
  24. #pragma alloc_text(PAGE, ChannelQueryBusMasterInterface)
  25. #pragma alloc_text(PAGE, ChannelQueryTransferModeInterface)
  26. #pragma alloc_text(PAGE, ChannelUnbindBusMasterParent)
  27. #pragma alloc_text(PAGE, ChannelQuerySyncAccessInterface)
  28. #pragma alloc_text(PAGE, ChannelEnableInterrupt)
  29. #pragma alloc_text(PAGE, ChannelDisableInterrupt)
  30. #pragma alloc_text(PAGE, ChannelFilterResourceRequirements)
  31. #pragma alloc_text(PAGE, ChannelQueryPnPDeviceState)
  32. #pragma alloc_text(PAGE, ChannelQueryPcmciaParent)
  33. #ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
  34. #pragma alloc_text(PAGE, ChannelFilterPromiseTechResourceRequirements)
  35. #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
  36. #pragma alloc_text(NONPAGE, ChannelDeviceIoControl)
  37. #pragma alloc_text(NONPAGE, ChannelRemoveDeviceCompletionRoutine)
  38. #pragma alloc_text(NONPAGE, ChannelQueryIdCompletionRoutine)
  39. #pragma alloc_text(NONPAGE, ChannelUsageNotificationCompletionRoutine)
  40. #pragma alloc_text(NONPAGE, ChannelAcpiTransferModeSelect)
  41. #pragma alloc_text(NONPAGE, ChannelRestoreTiming)
  42. #pragma alloc_text(NONPAGE, ChannelStartDeviceCompletionRoutine)
  43. #endif // ALLOC_PRAGMA
  44. static ULONG AtapiNextIdePortNumber = 0;
  45. NTSTATUS
  46. ChannelAddDevice(
  47. IN PDRIVER_OBJECT DriverObject,
  48. IN PDEVICE_OBJECT PhysicalDeviceObject
  49. )
  50. {
  51. PFDO_EXTENSION fdoExtension;
  52. return ChannelAddChannel(DriverObject,
  53. PhysicalDeviceObject,
  54. &fdoExtension);
  55. }
  56. NTSTATUS
  57. ChannelAddChannel(
  58. IN PDRIVER_OBJECT DriverObject,
  59. IN PDEVICE_OBJECT PhysicalDeviceObject,
  60. OUT PFDO_EXTENSION *FdoExtension
  61. )
  62. {
  63. PDEVICE_OBJECT functionalDeviceObject;
  64. PFDO_EXTENSION fdoExtension;
  65. PPDO_EXTENSION pdoExtension;
  66. PDEVICE_OBJECT childDeviceObject;
  67. ULONG deviceExtensionSize;
  68. NTSTATUS status;
  69. UNICODE_STRING deviceName;
  70. WCHAR deviceNameBuffer[64];
  71. PAGED_CODE();
  72. swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\IdePort%d", AtapiNextIdePortNumber);
  73. RtlInitUnicodeString(&deviceName, deviceNameBuffer);
  74. //
  75. // We've been given the PhysicalDeviceObject for a IDE controller. Create the
  76. // FunctionalDeviceObject. Our FDO will be nameless.
  77. //
  78. deviceExtensionSize = sizeof(FDO_EXTENSION) + sizeof(HW_DEVICE_EXTENSION);
  79. status = IoCreateDevice(
  80. DriverObject, // our driver object
  81. deviceExtensionSize, // size of our extension
  82. &deviceName, // our name
  83. FILE_DEVICE_CONTROLLER, // device type
  84. FILE_DEVICE_SECURE_OPEN, // device characteristics
  85. FALSE, // not exclusive
  86. &functionalDeviceObject // store new device object here
  87. );
  88. if( !NT_SUCCESS( status )){
  89. return status;
  90. }
  91. fdoExtension = (PFDO_EXTENSION)functionalDeviceObject->DeviceExtension;
  92. RtlZeroMemory (fdoExtension, deviceExtensionSize);
  93. fdoExtension->HwDeviceExtension = (PVOID)(fdoExtension + 1);
  94. //
  95. // We have our FunctionalDeviceObject, initialize it.
  96. //
  97. fdoExtension->AttacheePdo = PhysicalDeviceObject;
  98. fdoExtension->DriverObject = DriverObject;
  99. fdoExtension->DeviceObject = functionalDeviceObject;
  100. // Dispatch Table
  101. fdoExtension->DefaultDispatch = IdePortPassDownToNextDriver;
  102. fdoExtension->PnPDispatchTable = FdoPnpDispatchTable;
  103. fdoExtension->PowerDispatchTable = FdoPowerDispatchTable;
  104. fdoExtension->WmiDispatchTable = FdoWmiDispatchTable;
  105. //
  106. // Now attach to the PDO we were given.
  107. //
  108. fdoExtension->AttacheeDeviceObject = IoAttachDeviceToDeviceStack (
  109. functionalDeviceObject,
  110. PhysicalDeviceObject
  111. );
  112. if (fdoExtension->AttacheeDeviceObject == NULL) {
  113. //
  114. // Couldn't attach. Delete the FDO.
  115. //
  116. IoDeleteDevice (functionalDeviceObject);
  117. status = STATUS_UNSUCCESSFUL;
  118. } else {
  119. //
  120. // fix up alignment requirement
  121. //
  122. functionalDeviceObject->AlignmentRequirement = fdoExtension->AttacheeDeviceObject->AlignmentRequirement;
  123. if (functionalDeviceObject->AlignmentRequirement < 1) {
  124. functionalDeviceObject->AlignmentRequirement = 1;
  125. }
  126. fdoExtension->IdePortNumber = AtapiNextIdePortNumber;
  127. AtapiNextIdePortNumber++;
  128. *FdoExtension = fdoExtension;
  129. CLRMASK (functionalDeviceObject->Flags, DO_DEVICE_INITIALIZING);
  130. }
  131. DebugPrint((DBG_PNP, "DeviceObject %x returnd status %x from Addevice\n",
  132. PhysicalDeviceObject, status));
  133. return status;
  134. }
  135. NTSTATUS
  136. ChannelStartDevice (
  137. IN PDEVICE_OBJECT DeviceObject,
  138. IN OUT PIRP Irp
  139. )
  140. {
  141. PIO_STACK_LOCATION thisIrpSp;
  142. NTSTATUS status;
  143. PFDO_EXTENSION fdoExtension;
  144. PCM_RESOURCE_LIST resourceList;
  145. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  146. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  147. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  148. ULONG resourceListSize;
  149. ULONG i;
  150. PCM_RESOURCE_LIST resourceListForKeep = NULL;
  151. PIRP newIrp;
  152. KEVENT event;
  153. IO_STATUS_BLOCK ioStatusBlock;
  154. ULONG parentResourceListSize;
  155. PCM_RESOURCE_LIST parentResourceList = NULL;
  156. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  157. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  158. ASSERT (!(fdoExtension->FdoState & FDOS_STARTED));
  159. resourceList = thisIrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  160. //
  161. // TEMP CODE for the time without a real PCI driver.
  162. //
  163. resourceListSize = 0;
  164. if (resourceList) {
  165. fullResourceList = resourceList->List;
  166. for (i=0; i<resourceList->Count; i++) {
  167. ULONG partialResourceListSize;
  168. partialResourceList = &(fullResourceList->PartialResourceList);
  169. partialDescriptors = partialResourceList->PartialDescriptors;
  170. partialResourceListSize = 0;
  171. for (i=0; i<partialResourceList->Count; i++) {
  172. partialResourceListSize += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  173. if (partialDescriptors[i].Type == CmResourceTypeDeviceSpecific) {
  174. partialResourceListSize += partialDescriptors[i].u.DeviceSpecificData.DataSize;
  175. }
  176. }
  177. resourceListSize += partialResourceListSize +
  178. FIELD_OFFSET (CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors);
  179. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (((UCHAR *) fullResourceList) + resourceListSize);
  180. }
  181. resourceListSize += FIELD_OFFSET (CM_RESOURCE_LIST, List);
  182. }
  183. parentResourceListSize = sizeof (CM_RESOURCE_LIST) - sizeof (CM_FULL_RESOURCE_DESCRIPTOR) +
  184. FULL_RESOURCE_LIST_SIZE(3); // primary IO (2) + IRQ
  185. parentResourceList = ExAllocatePool (PagedPool, parentResourceListSize);
  186. if (!parentResourceList) {
  187. status = STATUS_INSUFFICIENT_RESOURCES;
  188. goto GetOut;
  189. }
  190. RtlZeroMemory (parentResourceList, parentResourceListSize);
  191. KeInitializeEvent(&event,
  192. NotificationEvent,
  193. FALSE);
  194. newIrp = IoBuildDeviceIoControlRequest (
  195. IOCTL_IDE_GET_RESOURCES_ALLOCATED,
  196. fdoExtension->AttacheeDeviceObject,
  197. parentResourceList,
  198. parentResourceListSize,
  199. parentResourceList,
  200. parentResourceListSize,
  201. TRUE,
  202. &event,
  203. &ioStatusBlock);
  204. if (newIrp == NULL) {
  205. DebugPrint ((0, "Unable to allocate irp to bind with busmaster parent\n"));
  206. status = STATUS_INSUFFICIENT_RESOURCES;
  207. goto GetOut;
  208. } else {
  209. status = IoCallDriver(fdoExtension->AttacheeDeviceObject, newIrp);
  210. if (status == STATUS_PENDING) {
  211. status = KeWaitForSingleObject(&event,
  212. Executive,
  213. KernelMode,
  214. FALSE,
  215. NULL);
  216. status = ioStatusBlock.Status;
  217. }
  218. }
  219. if (!NT_SUCCESS(status)) {
  220. parentResourceListSize = 0;
  221. } else {
  222. parentResourceListSize = (ULONG)ioStatusBlock.Information;
  223. }
  224. if (resourceListSize + parentResourceListSize) {
  225. resourceListForKeep = ExAllocatePool (NonPagedPool, resourceListSize + parentResourceListSize);
  226. } else {
  227. resourceListForKeep = NULL;
  228. }
  229. if (resourceListForKeep) {
  230. PUCHAR d;
  231. resourceListForKeep->Count = 0;
  232. d = (PUCHAR) resourceListForKeep->List;
  233. if (resourceListSize) {
  234. RtlCopyMemory (
  235. d,
  236. resourceList->List,
  237. resourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List)
  238. );
  239. resourceListForKeep->Count = resourceList->Count;
  240. d += resourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List);
  241. }
  242. if (parentResourceListSize) {
  243. RtlCopyMemory (
  244. d,
  245. parentResourceList->List,
  246. parentResourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List)
  247. );
  248. resourceListForKeep->Count += parentResourceList->Count;
  249. }
  250. } else {
  251. status = STATUS_INSUFFICIENT_RESOURCES;
  252. goto GetOut;
  253. }
  254. KeInitializeEvent(&event,
  255. SynchronizationEvent,
  256. FALSE);
  257. IoCopyCurrentIrpStackLocationToNext (Irp);
  258. Irp->IoStatus.Status = STATUS_SUCCESS ;
  259. IoSetCompletionRoutine(
  260. Irp,
  261. ChannelStartDeviceCompletionRoutine,
  262. &event,
  263. TRUE,
  264. TRUE,
  265. TRUE
  266. );
  267. //
  268. // Pass the irp along
  269. //
  270. status = IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
  271. //
  272. // Wait for it to come back...
  273. //
  274. if (status == STATUS_PENDING) {
  275. KeWaitForSingleObject(
  276. &event,
  277. Executive,
  278. KernelMode,
  279. FALSE,
  280. NULL
  281. );
  282. //
  283. // Grab back the 'real' status
  284. //
  285. status = Irp->IoStatus.Status;
  286. }
  287. if (!NT_SUCCESS(status)) {
  288. ExFreePool (resourceListForKeep);
  289. goto GetOut;
  290. }
  291. status = ChannelStartChannel (fdoExtension,
  292. resourceListForKeep);
  293. if (!NT_SUCCESS(status)) {
  294. ExFreePool (resourceListForKeep);
  295. goto GetOut;
  296. }
  297. GetOut:
  298. if (parentResourceList) {
  299. ExFreePool (parentResourceList);
  300. parentResourceList = NULL;
  301. }
  302. Irp->IoStatus.Status = status;
  303. Irp->IoStatus.Information = 0;
  304. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  305. return status;
  306. }
  307. NTSTATUS
  308. ChannelStartDeviceCompletionRoutine(
  309. IN PDEVICE_OBJECT DeviceObject,
  310. IN OUT PIRP Irp,
  311. IN OUT PVOID Context
  312. )
  313. {
  314. PKEVENT event = (PKEVENT) Context;
  315. //
  316. // Signal the event
  317. //
  318. KeSetEvent( event, IO_NO_INCREMENT, FALSE );
  319. //
  320. // Always return MORE_PROCESSING_REQUIRED
  321. // will complete it later
  322. //
  323. return STATUS_MORE_PROCESSING_REQUIRED;
  324. }
  325. NTSTATUS
  326. ChannelStartChannel (
  327. PFDO_EXTENSION FdoExtension,
  328. PCM_RESOURCE_LIST ResourceListToKeep
  329. )
  330. {
  331. NTSTATUS status;
  332. PLOGICAL_UNIT_EXTENSION logUnitExtension;
  333. IDE_PATH_ID pathId;
  334. POWER_STATE newState;
  335. PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors;
  336. ULONG i;
  337. #if DBG
  338. {
  339. PCM_RESOURCE_LIST resourceList;
  340. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  341. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  342. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  343. ULONG resourceListSize;
  344. ULONG i;
  345. ULONG j;
  346. resourceList = ResourceListToKeep;
  347. fullResourceList = resourceList->List;
  348. resourceListSize = 0;
  349. DebugPrint ((1, "IdePort: Starting device: FDOe\n", FdoExtension));
  350. for (i=0; i<resourceList->Count; i++) {
  351. partialResourceList = &(fullResourceList->PartialResourceList);
  352. partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
  353. for (j=0; j<partialResourceList->Count; j++) {
  354. if (partialDescriptors[j].Type == CmResourceTypePort) {
  355. DebugPrint ((1, "IdePort: IO Port = 0x%x. Lenght = 0x%x\n", partialDescriptors[j].u.Port.Start.LowPart, partialDescriptors[j].u.Port.Length));
  356. } else if (partialDescriptors[j].Type == CmResourceTypeInterrupt) {
  357. DebugPrint ((1, "IdePort: Int Level = 0x%x. Int Vector = 0x%x\n", partialDescriptors[j].u.Interrupt.Level, partialDescriptors[j].u.Interrupt.Vector));
  358. } else {
  359. DebugPrint ((1, "IdePort: Unknown resource\n"));
  360. }
  361. }
  362. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + j);
  363. }
  364. }
  365. #endif // DBG
  366. //
  367. // Analyze the resources we are getting
  368. //
  369. status = DigestResourceList (
  370. &FdoExtension->IdeResource,
  371. ResourceListToKeep,
  372. &irqPartialDescriptors
  373. );
  374. if (!NT_SUCCESS(status)) {
  375. goto GetOut;
  376. } else {
  377. PCONFIGURATION_INFORMATION configurationInformation;
  378. configurationInformation = IoGetConfigurationInformation();
  379. if (FdoExtension->IdeResource.AtdiskPrimaryClaimed) {
  380. FdoExtension->HwDeviceExtension->PrimaryAddress = TRUE;
  381. FdoExtension->HwDeviceExtension->SecondaryAddress = FALSE;
  382. configurationInformation->AtDiskPrimaryAddressClaimed = TRUE;
  383. }
  384. if (FdoExtension->IdeResource.AtdiskSecondaryClaimed) {
  385. FdoExtension->HwDeviceExtension->PrimaryAddress = FALSE;
  386. FdoExtension->HwDeviceExtension->SecondaryAddress = TRUE;
  387. configurationInformation->AtDiskSecondaryAddressClaimed = TRUE;
  388. }
  389. }
  390. //
  391. // Build io address structure.
  392. //
  393. AtapiBuildIoAddress(
  394. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  395. FdoExtension->IdeResource.TranslatedControlBaseAddress,
  396. &FdoExtension->HwDeviceExtension->BaseIoAddress1,
  397. &FdoExtension->HwDeviceExtension->BaseIoAddress2,
  398. &FdoExtension->HwDeviceExtension->BaseIoAddress1Length,
  399. &FdoExtension->HwDeviceExtension->BaseIoAddress2Length,
  400. &FdoExtension->HwDeviceExtension->MaxIdeDevice,
  401. &FdoExtension->HwDeviceExtension->MaxIdeTargetId);
  402. //
  403. // check for panasonic controller
  404. //
  405. FdoExtension->panasonicController =
  406. IdePortIsThisAPanasonicPCMCIACard(FdoExtension);
  407. newState.DeviceState = PowerSystemWorking;
  408. status = IdePortIssueSetPowerState (
  409. (PDEVICE_EXTENSION_HEADER) FdoExtension,
  410. SystemPowerState,
  411. newState,
  412. TRUE // sync call
  413. );
  414. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  415. //
  416. // The DeviceObject Below us does not support power irp,
  417. // we will assume we are powered up
  418. //
  419. FdoExtension->SystemPowerState = PowerSystemWorking;
  420. } else if (!NT_SUCCESS(status)) {
  421. goto GetOut;
  422. }
  423. newState.DeviceState = PowerDeviceD0;
  424. status = IdePortIssueSetPowerState (
  425. (PDEVICE_EXTENSION_HEADER) FdoExtension,
  426. DevicePowerState,
  427. newState,
  428. TRUE // sync call
  429. );
  430. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  431. //
  432. // The DeviceObject Below us does not support power irp,
  433. // we will assume we are powered up
  434. //
  435. FdoExtension->DevicePowerState = PowerDeviceD0;
  436. } else if (!NT_SUCCESS(status)) {
  437. goto GetOut;
  438. }
  439. //
  440. // Initialize "miniport" data structure
  441. //
  442. FdoExtension->HwDeviceExtension->InterruptMode = FdoExtension->IdeResource.InterruptMode;
  443. #ifdef ENABLE_NATIVE_MODE
  444. //
  445. // Get parent's interrupt interface
  446. //
  447. ChannelQueryInterruptInterface (
  448. FdoExtension
  449. );
  450. #endif
  451. //
  452. // Connect our interrupt
  453. //
  454. if (irqPartialDescriptors) {
  455. status = IoConnectInterrupt(&FdoExtension->InterruptObject,
  456. (PKSERVICE_ROUTINE) IdePortInterrupt,
  457. FdoExtension->DeviceObject,
  458. (PKSPIN_LOCK) NULL,
  459. irqPartialDescriptors->u.Interrupt.Vector,
  460. (KIRQL) irqPartialDescriptors->u.Interrupt.Level,
  461. (KIRQL) irqPartialDescriptors->u.Interrupt.Level,
  462. irqPartialDescriptors->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive,
  463. (BOOLEAN) (irqPartialDescriptors->ShareDisposition == CmResourceShareShared),
  464. irqPartialDescriptors->u.Interrupt.Affinity,
  465. FALSE);
  466. if (!NT_SUCCESS(status)) {
  467. DebugPrint((0, "IdePort: Can't connect interrupt %d\n", irqPartialDescriptors->u.Interrupt.Vector));
  468. FdoExtension->InterruptObject = NULL;
  469. goto GetOut;
  470. }
  471. #ifdef ENABLE_NATIVE_MODE
  472. //
  473. // Disconnect the parent ISR stub
  474. //
  475. if ( FdoExtension->InterruptInterface.PciIdeInterruptControl) {
  476. DebugPrint((1, "IdePort: %d fdoe 0x%x Invoking disconnect\n",
  477. irqPartialDescriptors->u.Interrupt.Vector,
  478. FdoExtension
  479. ));
  480. status = FdoExtension->InterruptInterface.PciIdeInterruptControl (
  481. FdoExtension->InterruptInterface.Context,
  482. 1
  483. );
  484. ASSERT(NT_SUCCESS(status));
  485. }
  486. #endif
  487. //
  488. // Enable Interrupt
  489. //
  490. ChannelEnableInterrupt (FdoExtension);
  491. }
  492. if (FdoExtension->FdoState & FDOS_STOPPED) {
  493. //
  494. // we are restarting, no need to do the rest of start code
  495. //
  496. status = STATUS_SUCCESS;
  497. goto GetOut;
  498. }
  499. //
  500. // Get parent's busmaster interface
  501. //
  502. ChannelQueryBusMasterInterface (
  503. FdoExtension
  504. );
  505. //
  506. // Maintain a default timing table
  507. //
  508. if (FdoExtension->DefaultTransferModeTimingTable == NULL) {
  509. ULONG length=0;
  510. PULONG transferModeTimingTable = ExAllocatePool(NonPagedPool, MAX_XFER_MODE*sizeof(ULONG));
  511. if (transferModeTimingTable != NULL) {
  512. SetDefaultTiming(transferModeTimingTable, length);
  513. FdoExtension->DefaultTransferModeTimingTable = transferModeTimingTable;
  514. } else {
  515. status = STATUS_INSUFFICIENT_RESOURCES;
  516. goto GetOut;
  517. }
  518. }
  519. ASSERT(FdoExtension->DefaultTransferModeTimingTable);
  520. //
  521. // Get parent's access token to serialize access with siblings (broken pci-ide)
  522. //
  523. ChannelQuerySyncAccessInterface (
  524. FdoExtension
  525. );
  526. //
  527. // get an interface that tells parent to invalidate out resource requirement
  528. //
  529. ChannelQueryRequestProperResourceInterface (
  530. FdoExtension
  531. );
  532. //
  533. // Create legacy object names
  534. //
  535. status = ChannelCreateSymblicLinks (
  536. FdoExtension
  537. );
  538. if (!NT_SUCCESS(status)) {
  539. goto GetOut;
  540. }
  541. //
  542. // FDO Init Data
  543. //
  544. IdePortInitFdo (FdoExtension);
  545. //
  546. // Allocate reserve error log packets to log insufficient resource events
  547. //
  548. for (i=0;i<MAX_IDE_DEVICE;i++) {
  549. if (FdoExtension->ReserveAllocFailureLogEntry[i] == NULL) {
  550. FdoExtension->ReserveAllocFailureLogEntry[i] = IoAllocateErrorLogEntry(
  551. FdoExtension->DeviceObject,
  552. ALLOC_FAILURE_LOGSIZE
  553. );
  554. }
  555. }
  556. //
  557. // Pre-allocate memory for enumeration
  558. //
  559. if (!IdePreAllocEnumStructs(FdoExtension)) {
  560. status=STATUS_INSUFFICIENT_RESOURCES;
  561. goto GetOut;
  562. }
  563. //
  564. // Reserve pages to perform I/O under low memory conditions
  565. //
  566. if (FdoExtension->ReservedPages == NULL) {
  567. FdoExtension->ReservedPages = MmAllocateMappingAddress( IDE_NUM_RESERVED_PAGES * PAGE_SIZE,
  568. 'PedI'
  569. );
  570. ASSERT(FdoExtension->ReservedPages);
  571. }
  572. GetOut:
  573. if (NT_SUCCESS(status)) {
  574. //
  575. // End of Init.
  576. //
  577. CLRMASK (FdoExtension->FdoState, FDOS_STOPPED);
  578. SETMASK (FdoExtension->FdoState, FDOS_STARTED);
  579. if (FdoExtension->ResourceList) {
  580. ExFreePool(FdoExtension->ResourceList);
  581. FdoExtension->ResourceList = NULL;
  582. }
  583. FdoExtension->ResourceList = ResourceListToKeep;
  584. } else {
  585. ChannelRemoveChannel (FdoExtension);
  586. }
  587. return status;
  588. }
  589. NTSTATUS
  590. ChannelCreateSymblicLinks (
  591. PFDO_EXTENSION FdoExtension
  592. )
  593. {
  594. NTSTATUS status;
  595. ULONG i;
  596. PULONG scsiportNumber;
  597. UNICODE_STRING deviceName;
  598. WCHAR deviceNameBuffer[64];
  599. UNICODE_STRING symbolicDeviceName;
  600. WCHAR symbolicDeviceNameBuffer[64];
  601. swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\IdePort%d", FdoExtension->IdePortNumber);
  602. RtlInitUnicodeString(&deviceName, deviceNameBuffer);
  603. scsiportNumber = &IoGetConfigurationInformation()->ScsiPortCount;
  604. for (i=0; i <= (*scsiportNumber); i++) {
  605. swprintf(symbolicDeviceNameBuffer, L"\\Device\\ScsiPort%d", i);
  606. RtlInitUnicodeString(&symbolicDeviceName, symbolicDeviceNameBuffer);
  607. status = IoCreateSymbolicLink(
  608. &symbolicDeviceName,
  609. &deviceName
  610. );
  611. if (NT_SUCCESS (status)) {
  612. swprintf(symbolicDeviceNameBuffer, L"\\DosDevices\\Scsi%d:", i);
  613. RtlInitUnicodeString(&symbolicDeviceName, symbolicDeviceNameBuffer);
  614. IoAssignArcName (
  615. &symbolicDeviceName,
  616. &deviceName
  617. );
  618. break;
  619. }
  620. }
  621. if (NT_SUCCESS(status)) {
  622. FdoExtension->SymbolicLinkCreated = TRUE;
  623. FdoExtension->ScsiPortNumber = i;
  624. (*scsiportNumber)++;
  625. }
  626. return status;
  627. }
  628. NTSTATUS
  629. ChannelDeleteSymblicLinks (
  630. PFDO_EXTENSION FdoExtension
  631. )
  632. {
  633. NTSTATUS status;
  634. ULONG i;
  635. UNICODE_STRING deviceName;
  636. WCHAR deviceNameBuffer[64];
  637. if (!FdoExtension->SymbolicLinkCreated) {
  638. return STATUS_SUCCESS;
  639. }
  640. swprintf(deviceNameBuffer, L"\\Device\\ScsiPort%d", FdoExtension->ScsiPortNumber);
  641. RtlInitUnicodeString(&deviceName, deviceNameBuffer);
  642. IoDeleteSymbolicLink(
  643. &deviceName
  644. );
  645. swprintf(deviceNameBuffer, L"\\DosDevices\\Scsi%d:", FdoExtension->ScsiPortNumber);
  646. RtlInitUnicodeString(&deviceName, deviceNameBuffer);
  647. IoDeassignArcName(&deviceName);
  648. FdoExtension->SymbolicLinkCreated = FALSE;
  649. IoGetConfigurationInformation()->ScsiPortCount--;
  650. return STATUS_SUCCESS;
  651. }
  652. NTSTATUS
  653. ChannelSurpriseRemoveDevice (
  654. IN PDEVICE_OBJECT DeviceObject,
  655. IN OUT PIRP Irp
  656. )
  657. {
  658. PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  659. PPDO_EXTENSION pdoExtension;
  660. IDE_PATH_ID pathId;
  661. NTSTATUS status;
  662. //
  663. // all my childred should be surprise removed or removed
  664. //
  665. pathId.l = 0;
  666. while (pdoExtension = NextLogUnitExtensionWithTag (
  667. fdoExtension,
  668. &pathId,
  669. TRUE,
  670. ChannelSurpriseRemoveDevice
  671. )) {
  672. //ASSERT (pdoExtension->PdoState & (PDOS_SURPRISE_REMOVED | PDOS_REMOVED));
  673. CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP);
  674. UnrefPdoWithTag(
  675. pdoExtension,
  676. ChannelSurpriseRemoveDevice
  677. );
  678. }
  679. status = ChannelRemoveChannel (fdoExtension);
  680. ASSERT (NT_SUCCESS(status));
  681. Irp->IoStatus.Status = STATUS_SUCCESS;
  682. IoSkipCurrentIrpStackLocation (Irp);
  683. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  684. }
  685. NTSTATUS
  686. ChannelRemoveDevice (
  687. IN PDEVICE_OBJECT DeviceObject,
  688. IN OUT PIRP Irp
  689. )
  690. {
  691. PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  692. PPDO_EXTENSION pdoExtension;
  693. NTSTATUS status;
  694. KEVENT event;
  695. IDE_PATH_ID pathId;
  696. DebugPrint ((
  697. DBG_PNP,
  698. "fdoe 0x%x 0x%x got a STOP device\n",
  699. fdoExtension,
  700. fdoExtension->IdeResource.TranslatedCommandBaseAddress
  701. ));
  702. //
  703. // Kill all the children if any
  704. //
  705. pathId.l = 0;
  706. while (pdoExtension = NextLogUnitExtensionWithTag (
  707. fdoExtension,
  708. &pathId,
  709. TRUE,
  710. ChannelRemoveDevice
  711. )) {
  712. if (pdoExtension->PdoState & PDOS_SURPRISE_REMOVED) {
  713. CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP);
  714. continue;
  715. }
  716. FreePdoWithTag(
  717. pdoExtension,
  718. TRUE,
  719. TRUE,
  720. ChannelRemoveDevice
  721. );
  722. }
  723. status = ChannelRemoveChannel (fdoExtension);
  724. ASSERT (NT_SUCCESS(status));
  725. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  726. IoCopyCurrentIrpStackLocationToNext (Irp);
  727. IoSetCompletionRoutine(
  728. Irp,
  729. ChannelRemoveDeviceCompletionRoutine,
  730. &event,
  731. TRUE,
  732. TRUE,
  733. TRUE
  734. );
  735. status = IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  736. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  737. IoDetachDevice (fdoExtension->AttacheeDeviceObject);
  738. IoDeleteDevice (DeviceObject);
  739. //return STATUS_SUCCESS;
  740. return status;
  741. }
  742. NTSTATUS
  743. ChannelRemoveDeviceCompletionRoutine (
  744. IN PDEVICE_OBJECT DeviceObject,
  745. IN PIRP Irp,
  746. IN PVOID Context
  747. )
  748. {
  749. PKEVENT event = Context;
  750. KeSetEvent(event, 0, FALSE);
  751. return STATUS_SUCCESS;
  752. }
  753. NTSTATUS
  754. ChannelStopDevice (
  755. IN PDEVICE_OBJECT DeviceObject,
  756. IN OUT PIRP Irp
  757. )
  758. {
  759. PFDO_EXTENSION fdoExtension;
  760. fdoExtension = DeviceObject->DeviceExtension;
  761. DebugPrint ((
  762. DBG_PNP,
  763. "fdoe 0x%x 0x%x got a STOP device\n",
  764. fdoExtension,
  765. fdoExtension->IdeResource.TranslatedCommandBaseAddress
  766. ));
  767. //
  768. // disable interrupt
  769. //
  770. ChannelDisableInterrupt (fdoExtension);
  771. if (fdoExtension->InterruptObject) {
  772. #ifdef ENABLE_NATIVE_MODE
  773. //
  774. // Reconnect the parent ISR stub
  775. //
  776. if (fdoExtension->InterruptInterface.PciIdeInterruptControl) {
  777. NTSTATUS status;
  778. DebugPrint((1, "fdoe 0x%x invoking reconnect\n", fdoExtension));
  779. status = fdoExtension->InterruptInterface.PciIdeInterruptControl (
  780. fdoExtension->InterruptInterface.Context,
  781. 0
  782. );
  783. ASSERT(NT_SUCCESS(status));
  784. }
  785. #endif
  786. IoDisconnectInterrupt (
  787. fdoExtension->InterruptObject
  788. );
  789. fdoExtension->InterruptObject = 0;
  790. }
  791. if (fdoExtension->FdoState & FDOS_STARTED) {
  792. //
  793. // indicate we have been stopped only if we have started
  794. //
  795. CLRMASK (fdoExtension->FdoState, FDOS_STARTED);
  796. SETMASK (fdoExtension->FdoState, FDOS_STOPPED);
  797. }
  798. Irp->IoStatus.Status = STATUS_SUCCESS;
  799. IoSkipCurrentIrpStackLocation (Irp);
  800. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  801. }
  802. NTSTATUS
  803. ChannelRemoveChannel (
  804. PFDO_EXTENSION FdoExtension
  805. )
  806. {
  807. PCONFIGURATION_INFORMATION configurationInformation;
  808. ULONG i;
  809. configurationInformation = IoGetConfigurationInformation();
  810. DebugPrint((1, "ChannelRemoveChannel for FDOe %x\n", FdoExtension));
  811. if (FdoExtension->IdeResource.AtdiskPrimaryClaimed) {
  812. configurationInformation->AtDiskPrimaryAddressClaimed = FALSE;
  813. }
  814. if (FdoExtension->IdeResource.AtdiskSecondaryClaimed) {
  815. configurationInformation->AtDiskSecondaryAddressClaimed = FALSE;
  816. }
  817. FdoExtension->IdeResource.AtdiskPrimaryClaimed = FALSE;
  818. FdoExtension->IdeResource.AtdiskSecondaryClaimed = FALSE;
  819. FdoExtension->HwDeviceExtension->PrimaryAddress = FALSE;
  820. if ((FdoExtension->IdeResource.CommandBaseAddressSpace == MEMORY_SPACE) &&
  821. (FdoExtension->IdeResource.TranslatedCommandBaseAddress)) {
  822. MmUnmapIoSpace (
  823. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  824. FdoExtension->HwDeviceExtension->BaseIoAddress1Length
  825. );
  826. }
  827. FdoExtension->IdeResource.TranslatedCommandBaseAddress = 0;
  828. if ((FdoExtension->IdeResource.ControlBaseAddressSpace == MEMORY_SPACE) &&
  829. (FdoExtension->IdeResource.TranslatedControlBaseAddress)) {
  830. MmUnmapIoSpace (
  831. FdoExtension->IdeResource.TranslatedControlBaseAddress,
  832. 1
  833. );
  834. }
  835. FdoExtension->IdeResource.TranslatedControlBaseAddress = 0;
  836. if (FdoExtension->InterruptObject) {
  837. #ifdef ENABLE_NATIVE_MODE
  838. //
  839. // Reconnect the parent ISR stub
  840. //
  841. if (FdoExtension->InterruptInterface.PciIdeInterruptControl) {
  842. NTSTATUS status;
  843. DebugPrint((1, "fdoe 0x%x invoking reconnect\n", FdoExtension));
  844. status = FdoExtension->InterruptInterface.PciIdeInterruptControl (
  845. FdoExtension->InterruptInterface.Context,
  846. 0
  847. );
  848. ASSERT(NT_SUCCESS(status));
  849. }
  850. #endif
  851. IoDisconnectInterrupt (
  852. FdoExtension->InterruptObject
  853. );
  854. FdoExtension->InterruptObject = 0;
  855. }
  856. // unbind from the bm stuff if NECESSARY
  857. // release parent's access token to serialize access with siblings (broken pci-ide)
  858. if (FdoExtension->ResourceList) {
  859. ExFreePool (FdoExtension->ResourceList);
  860. FdoExtension->ResourceList = NULL;
  861. }
  862. else {
  863. DebugPrint((1, "ATAPI: Resource list for FDOe %x already freed\n",
  864. FdoExtension));
  865. }
  866. //
  867. // Lock
  868. //
  869. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 1, 0) == 0);
  870. //
  871. // Free pre-allocated memory
  872. //
  873. IdeFreeEnumStructs(FdoExtension->PreAllocEnumStruct);
  874. FdoExtension->PreAllocEnumStruct = NULL;
  875. //
  876. // Unlock
  877. //
  878. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  879. //
  880. // Free the reserve error log entries
  881. //
  882. for (i=0; i< MAX_IDE_DEVICE; i++) {
  883. PVOID entry;
  884. PVOID currentValue;
  885. entry = FdoExtension->ReserveAllocFailureLogEntry[i];
  886. if (entry == NULL) {
  887. continue;
  888. }
  889. //
  890. // We have to ensure that we are the only instance to use this
  891. // event. To do so, we attempt to NULL the event in the driver
  892. // extension. If somebody else beats us to it, they own the
  893. // event and we have to give up.
  894. //
  895. currentValue = InterlockedCompareExchangePointer(
  896. &(FdoExtension->ReserveAllocFailureLogEntry[i]),
  897. NULL,
  898. entry
  899. );
  900. if (entry != currentValue) {
  901. continue;
  902. }
  903. // Note that you cannot ExFreePool the entry
  904. // because Io returns an offset into the pool allocation, not the start.
  905. // Use the API provided by Iomanager
  906. IoFreeErrorLogEntry(entry);
  907. }
  908. //
  909. // Free the default timing table
  910. //
  911. if (FdoExtension->DefaultTransferModeTimingTable) {
  912. ExFreePool(FdoExtension->DefaultTransferModeTimingTable);
  913. FdoExtension->DefaultTransferModeTimingTable = NULL;
  914. FdoExtension->TransferModeInterface.TransferModeTimingTable = NULL;
  915. FdoExtension->TransferModeInterface.TransferModeTableLength =0;
  916. }
  917. //
  918. // Unmap the reserved mapping
  919. //
  920. if (FdoExtension->ReservedPages != NULL) {
  921. MmFreeMappingAddress(FdoExtension->ReservedPages,
  922. 'PedI'
  923. );
  924. FdoExtension->ReservedPages = NULL;
  925. }
  926. ChannelDeleteSymblicLinks (
  927. FdoExtension
  928. );
  929. return STATUS_SUCCESS;
  930. }
  931. NTSTATUS
  932. ChannelQueryDeviceRelations (
  933. IN PDEVICE_OBJECT DeviceObject,
  934. IN OUT PIRP Irp
  935. )
  936. {
  937. PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  938. PIO_STACK_LOCATION thisIrpSp;
  939. PIDE_WORK_ITEM_CONTEXT workItemContext;
  940. PENUMERATION_STRUCT enumStruct = fdoExtension->PreAllocEnumStruct;
  941. if (!(fdoExtension->FdoState & FDOS_STARTED)) {
  942. Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
  943. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  944. return STATUS_DEVICE_NOT_READY;
  945. }
  946. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  947. switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) {
  948. case BusRelations:
  949. DebugPrint ((DBG_BUSSCAN, "IdeQueryDeviceRelations: bus relations\n"));
  950. ASSERT(enumStruct);
  951. workItemContext = (PIDE_WORK_ITEM_CONTEXT) enumStruct->EnumWorkItemContext;
  952. ASSERT(workItemContext);
  953. ASSERT(workItemContext->WorkItem);
  954. workItemContext->Irp = Irp;
  955. #ifdef SYNC_DEVICE_RELATIONS
  956. return ChannelQueryBusRelation (
  957. DeviceObject,
  958. workItemContext);
  959. #else
  960. Irp->IoStatus.Status = STATUS_PENDING;
  961. IoMarkIrpPending(Irp);
  962. IoQueueWorkItem(
  963. workItemContext->WorkItem,
  964. ChannelQueryBusRelation,
  965. DelayedWorkQueue,
  966. workItemContext
  967. );
  968. return STATUS_PENDING;
  969. #endif //!SYNC_DEVICE_RELATIONS
  970. break;
  971. default:
  972. DebugPrint ((1, "IdeQueryDeviceRelations: Unsupported device relation\n"));
  973. //
  974. // Don't set the status if it is not success and is being passed
  975. // down
  976. //
  977. //Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  978. break;
  979. }
  980. IoSkipCurrentIrpStackLocation (Irp);
  981. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  982. }
  983. NTSTATUS
  984. ChannelQueryBusRelation (
  985. IN PDEVICE_OBJECT DeviceObject,
  986. IN PIDE_WORK_ITEM_CONTEXT WorkItemContext
  987. )
  988. {
  989. PIRP irp;
  990. PFDO_EXTENSION fdoExtension;
  991. PIO_STACK_LOCATION thisIrpSp;
  992. PDEVICE_RELATIONS deviceRelations;
  993. LARGE_INTEGER tickCount;
  994. ULONG timeDiff;
  995. irp = WorkItemContext->Irp;
  996. //
  997. // do not release resource for this worker item as they are pre-alloced
  998. //
  999. // IoFreeWorkItem(WorkItemContext->WorkItem);
  1000. //ExFreePool (WorkItemContext);
  1001. thisIrpSp = IoGetCurrentIrpStackLocation(irp);
  1002. fdoExtension = thisIrpSp->DeviceObject->DeviceExtension;
  1003. LogBusScanStartTimer(&tickCount);
  1004. //
  1005. // grab the acpi/bios timing settings if any
  1006. // GTM should be called for every enumeration
  1007. //
  1008. DeviceQueryChannelTimingSettings (
  1009. fdoExtension,
  1010. &fdoExtension->AcpiTimingSettings
  1011. );
  1012. //
  1013. // Get parent's xfer mode interface
  1014. //
  1015. ChannelQueryTransferModeInterface (
  1016. fdoExtension
  1017. );
  1018. //
  1019. // scan the bus
  1020. //
  1021. IdePortScanBus (fdoExtension);
  1022. timeDiff = LogBusScanStopTimer(&tickCount);
  1023. LogBusScanTimeDiff(fdoExtension, L"IdeTotalBusScanTime", timeDiff);
  1024. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  1025. if (timeDiff > 7000) {
  1026. DebugPrint ((DBG_WARNING, "WARNING: **************************************\n"));
  1027. DebugPrint ((DBG_WARNING, "WARNING: IdePortScanBus 0x%x took %u millisec\n", fdoExtension->IdeResource.TranslatedCommandBaseAddress, timeDiff));
  1028. DebugPrint ((DBG_WARNING, "WARNING: **************************************\n"));
  1029. } else {
  1030. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus 0x%x took %u millisec\n", fdoExtension->IdeResource.TranslatedCommandBaseAddress, timeDiff));
  1031. }
  1032. #endif
  1033. deviceRelations = ChannelBuildDeviceRelationList (
  1034. fdoExtension
  1035. );
  1036. irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  1037. irp->IoStatus.Status = STATUS_SUCCESS;
  1038. IoSkipCurrentIrpStackLocation (irp);
  1039. return IoCallDriver (fdoExtension->AttacheeDeviceObject, irp);
  1040. }
  1041. PDEVICE_RELATIONS
  1042. ChannelBuildDeviceRelationList (
  1043. PFDO_EXTENSION FdoExtension
  1044. )
  1045. {
  1046. IDE_PATH_ID pathId;
  1047. ULONG numPdoChildren;
  1048. NTSTATUS status;
  1049. PPDO_EXTENSION pdoExtension;
  1050. ULONG deviceRelationsSize;
  1051. PDEVICE_RELATIONS deviceRelations;
  1052. status = STATUS_SUCCESS;
  1053. pathId.l = 0;
  1054. numPdoChildren = 0;
  1055. while (pdoExtension = NextLogUnitExtensionWithTag(
  1056. FdoExtension,
  1057. &pathId,
  1058. TRUE,
  1059. ChannelBuildDeviceRelationList
  1060. )) {
  1061. UnrefLogicalUnitExtensionWithTag (
  1062. FdoExtension,
  1063. pdoExtension,
  1064. ChannelBuildDeviceRelationList
  1065. );
  1066. numPdoChildren++;
  1067. }
  1068. if (numPdoChildren) {
  1069. deviceRelationsSize = FIELD_OFFSET (DEVICE_RELATIONS, Objects) +
  1070. numPdoChildren * sizeof(PDEVICE_OBJECT);
  1071. } else {
  1072. // Current build expect a DEVICE_RELATIONS with a Count of 0
  1073. // if we don't have any PDO to return
  1074. deviceRelationsSize = FIELD_OFFSET( DEVICE_RELATIONS, Objects ) +
  1075. 1 * sizeof( PDEVICE_OBJECT );
  1076. }
  1077. deviceRelations = ExAllocatePool (NonPagedPool, deviceRelationsSize);
  1078. if(!deviceRelations) {
  1079. DebugPrint ((DBG_ALWAYS, "ChannelBuildDeviceRelationList: Unable to allocate DeviceRelations structures\n"));
  1080. status = STATUS_NO_MEMORY;
  1081. }
  1082. if (NT_SUCCESS(status)) {
  1083. (deviceRelations)->Count = 0;
  1084. pathId.l = 0;
  1085. while ((deviceRelations->Count < numPdoChildren) &&
  1086. (pdoExtension = NextLogUnitExtensionWithTag(
  1087. FdoExtension,
  1088. &pathId,
  1089. TRUE,
  1090. ChannelBuildDeviceRelationList
  1091. ))) {
  1092. KIRQL currentIrql;
  1093. BOOLEAN deadMeat;
  1094. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1095. deadMeat = pdoExtension->PdoState & PDOS_DEADMEAT ? TRUE : FALSE;
  1096. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1097. if (!deadMeat) {
  1098. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1099. SETMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP);
  1100. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1101. deviceRelations->Objects[deviceRelations->Count] = pdoExtension->DeviceObject;
  1102. ObReferenceObjectByPointer(deviceRelations->Objects[deviceRelations->Count],
  1103. 0,
  1104. 0,
  1105. KernelMode);
  1106. deviceRelations->Count++;
  1107. } else {
  1108. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1109. CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP);
  1110. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1111. DebugPrint ((DBG_BUSSCAN, "0x%x target 0x%x pdoExtension 0x%x is marked DEADMEAT\n",
  1112. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  1113. pdoExtension->TargetId,
  1114. pdoExtension));
  1115. }
  1116. UnrefLogicalUnitExtensionWithTag (
  1117. FdoExtension,
  1118. pdoExtension,
  1119. ChannelBuildDeviceRelationList
  1120. );
  1121. }
  1122. DebugPrint ((DBG_BUSSCAN, "ChannelBuildDeviceRelationList: returning %d children\n", deviceRelations->Count));
  1123. }
  1124. return deviceRelations;
  1125. }
  1126. NTSTATUS
  1127. ChannelQueryId (
  1128. IN PDEVICE_OBJECT DeviceObject,
  1129. IN OUT PIRP Irp
  1130. )
  1131. {
  1132. PIO_STACK_LOCATION thisIrpSp;
  1133. PFDO_EXTENSION fdoExtension;
  1134. NTSTATUS status;
  1135. PWCHAR returnString;
  1136. ANSI_STRING ansiString;
  1137. UNICODE_STRING unicodeString;
  1138. PAGED_CODE();
  1139. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  1140. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  1141. if (!(fdoExtension->FdoState & FDOS_STARTED)) {
  1142. Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
  1143. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1144. return STATUS_DEVICE_NOT_READY;
  1145. }
  1146. unicodeString.Buffer = NULL;
  1147. switch (thisIrpSp->Parameters.QueryId.IdType) {
  1148. case BusQueryCompatibleIDs:
  1149. case BusQueryHardwareIDs:
  1150. unicodeString.Length = 0;
  1151. unicodeString.MaximumLength = 50 * sizeof(WCHAR);
  1152. unicodeString.Buffer = ExAllocatePool(PagedPool, unicodeString.MaximumLength);
  1153. //
  1154. // Caller wants the unique id of the device
  1155. //
  1156. RtlInitAnsiString (
  1157. &ansiString,
  1158. "*PNP0600"
  1159. );
  1160. break;
  1161. default:
  1162. break;
  1163. }
  1164. if (unicodeString.Buffer) {
  1165. RtlAnsiStringToUnicodeString(
  1166. &unicodeString,
  1167. &ansiString,
  1168. FALSE
  1169. );
  1170. //
  1171. // double null terminate it
  1172. //
  1173. unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 0] = L'\0';
  1174. unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 1] = L'\0';
  1175. IoMarkIrpPending(Irp);
  1176. //
  1177. // we need to check if the lower driver handles this irp
  1178. // registry a completion routine. we can check
  1179. // when the irp comes back
  1180. //
  1181. IoCopyCurrentIrpStackLocationToNext (Irp);
  1182. IoSetCompletionRoutine(
  1183. Irp,
  1184. ChannelQueryIdCompletionRoutine,
  1185. unicodeString.Buffer,
  1186. TRUE,
  1187. TRUE,
  1188. TRUE
  1189. );
  1190. } else {
  1191. //
  1192. // we don't care much about this irp
  1193. //
  1194. IoSkipCurrentIrpStackLocation (Irp);
  1195. }
  1196. status = IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  1197. if (unicodeString.Buffer) {
  1198. return STATUS_PENDING;
  1199. } else {
  1200. return status;
  1201. }
  1202. }
  1203. NTSTATUS
  1204. ChannelQueryIdCompletionRoutine (
  1205. PDEVICE_OBJECT DeviceObject,
  1206. PIRP Irp,
  1207. PVOID Context
  1208. )
  1209. {
  1210. if (Irp->IoStatus.Status == STATUS_NOT_SUPPORTED) {
  1211. //
  1212. // the lower level driver didn't handle the irp
  1213. // return the device text string we created early
  1214. //
  1215. Irp->IoStatus.Information = (ULONG_PTR) Context;
  1216. Irp->IoStatus.Status = STATUS_SUCCESS;
  1217. } else {
  1218. //
  1219. // the lower driver handled the irp,
  1220. // we don't need to return our device text string
  1221. //
  1222. ExFreePool (Context);
  1223. }
  1224. return Irp->IoStatus.Status;
  1225. }
  1226. NTSTATUS
  1227. ChannelUsageNotification (
  1228. IN PDEVICE_OBJECT DeviceObject,
  1229. IN OUT PIRP Irp
  1230. )
  1231. {
  1232. PFDO_EXTENSION fdoExtension;
  1233. PIO_STACK_LOCATION irpSp;
  1234. PULONG deviceUsageCount;
  1235. ASSERT (DeviceObject);
  1236. ASSERT (Irp);
  1237. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  1238. ASSERT (fdoExtension);
  1239. if (!(fdoExtension->FdoState & FDOS_STARTED)) {
  1240. Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
  1241. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1242. return STATUS_DEVICE_NOT_READY;
  1243. }
  1244. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1245. if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
  1246. //
  1247. // Adjust the paging path count for this device.
  1248. //
  1249. deviceUsageCount = &fdoExtension->PagingPathCount;
  1250. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
  1251. //
  1252. // Adjust the paging path count for this device.
  1253. //
  1254. deviceUsageCount = &fdoExtension->HiberPathCount;
  1255. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
  1256. //
  1257. // Adjust the paging path count for this device.
  1258. //
  1259. deviceUsageCount = &fdoExtension->CrashDumpPathCount;
  1260. } else {
  1261. deviceUsageCount = NULL;
  1262. DebugPrint ((DBG_ALWAYS,
  1263. "ATAPI: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n",
  1264. irpSp->Parameters.UsageNotification.Type));
  1265. }
  1266. IoCopyCurrentIrpStackLocationToNext (Irp);
  1267. IoSetCompletionRoutine (
  1268. Irp,
  1269. ChannelUsageNotificationCompletionRoutine,
  1270. deviceUsageCount,
  1271. TRUE,
  1272. TRUE,
  1273. TRUE);
  1274. ASSERT(fdoExtension->AttacheeDeviceObject);
  1275. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  1276. } // ChannelPagingNotification
  1277. NTSTATUS
  1278. ChannelUsageNotificationCompletionRoutine (
  1279. IN PDEVICE_OBJECT DeviceObject,
  1280. IN PIRP Irp,
  1281. IN PVOID Context
  1282. )
  1283. {
  1284. PFDO_EXTENSION fdoExtension;
  1285. PULONG deviceUsageCount = Context;
  1286. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  1287. ASSERT (fdoExtension);
  1288. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  1289. if (deviceUsageCount) {
  1290. IoAdjustPagingPathCount (
  1291. deviceUsageCount,
  1292. IoGetCurrentIrpStackLocation(Irp)->Parameters.UsageNotification.InPath
  1293. );
  1294. }
  1295. }
  1296. return Irp->IoStatus.Status;
  1297. }
  1298. NTSTATUS
  1299. ChannelDeviceIoControl(
  1300. IN PDEVICE_OBJECT DeviceObject,
  1301. IN PIRP Irp
  1302. )
  1303. {
  1304. PIO_STACK_LOCATION thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1305. PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  1306. PSTORAGE_PROPERTY_QUERY storageQuery;
  1307. STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor;
  1308. ULONG outBufferSize;
  1309. NTSTATUS status;
  1310. // pass it down if not supported and it is for the FDO stack
  1311. switch (thisIrpSp->Parameters.DeviceIoControl.IoControlCode) {
  1312. case IOCTL_STORAGE_QUERY_PROPERTY:
  1313. storageQuery = Irp->AssociatedIrp.SystemBuffer;
  1314. if (thisIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) {
  1315. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  1316. } else {
  1317. if (storageQuery->PropertyId == StorageAdapterProperty) { // device property
  1318. switch (storageQuery->QueryType) {
  1319. case PropertyStandardQuery:
  1320. DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyStandardQuery\n"));
  1321. RtlZeroMemory (&adapterDescriptor, sizeof(adapterDescriptor));
  1322. //
  1323. // BuildAtaDeviceDescriptor
  1324. //
  1325. adapterDescriptor.Version = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
  1326. adapterDescriptor.Size = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
  1327. adapterDescriptor.MaximumTransferLength = MAX_TRANSFER_SIZE_PER_SRB;
  1328. adapterDescriptor.MaximumPhysicalPages = SP_UNINITIALIZED_VALUE;
  1329. adapterDescriptor.AlignmentMask = DeviceObject->AlignmentRequirement;
  1330. adapterDescriptor.AdapterUsesPio = TRUE; // We always support PIO
  1331. adapterDescriptor.AdapterScansDown = FALSE;
  1332. adapterDescriptor.CommandQueueing = FALSE;
  1333. adapterDescriptor.AcceleratedTransfer = FALSE;
  1334. adapterDescriptor.BusType = BusTypeAta; // Bus type should be ATA
  1335. adapterDescriptor.BusMajorVersion = 1; // Major version
  1336. adapterDescriptor.BusMinorVersion = 0; //
  1337. if (thisIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1338. sizeof(STORAGE_ADAPTER_DESCRIPTOR)) {
  1339. outBufferSize = thisIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  1340. } else {
  1341. outBufferSize = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
  1342. }
  1343. RtlCopyMemory (Irp->AssociatedIrp.SystemBuffer,
  1344. &adapterDescriptor,
  1345. outBufferSize);
  1346. Irp->IoStatus.Information = outBufferSize;
  1347. Irp->IoStatus.Status = STATUS_SUCCESS;
  1348. break;
  1349. case PropertyExistsQuery:
  1350. DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyExistsQuery\n"));
  1351. Irp->IoStatus.Status = STATUS_SUCCESS;
  1352. break;
  1353. case PropertyMaskQuery:
  1354. DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyMaskQuery\n"));
  1355. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  1356. break;
  1357. default:
  1358. DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY unknown type\n"));
  1359. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  1360. break;
  1361. }
  1362. }
  1363. }
  1364. break;
  1365. default:
  1366. //
  1367. // we don't know what this deviceIoControl Irp is
  1368. //
  1369. if (thisIrpSp->DeviceObject == DeviceObject) {
  1370. //
  1371. // this irp could come from the PDO stack
  1372. //
  1373. // forward this unknown request if and only
  1374. // if this irp is for the FDO stack
  1375. //
  1376. IoSkipCurrentIrpStackLocation (Irp);
  1377. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  1378. break;
  1379. }
  1380. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  1381. break;
  1382. }
  1383. status = Irp->IoStatus.Status;
  1384. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1385. return status;
  1386. }
  1387. VOID
  1388. ChannelQueryBusMasterInterface (
  1389. PFDO_EXTENSION FdoExtension
  1390. )
  1391. {
  1392. IO_STACK_LOCATION irpSp;
  1393. NTSTATUS status;
  1394. FdoExtension->BoundWithBmParent = FALSE;
  1395. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1396. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_BUSMASTER_INTERFACE;
  1397. irpSp.Parameters.QueryInterface.Version = 1;
  1398. irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->HwDeviceExtension->BusMasterInterface);
  1399. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->HwDeviceExtension->BusMasterInterface;
  1400. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1401. irpSp.MajorFunction = IRP_MJ_PNP;
  1402. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1403. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1404. if (NT_SUCCESS(status)) {
  1405. FdoExtension->BoundWithBmParent = TRUE;
  1406. }
  1407. return;
  1408. }
  1409. #ifdef ENABLE_NATIVE_MODE
  1410. VOID
  1411. ChannelQueryInterruptInterface (
  1412. PFDO_EXTENSION FdoExtension
  1413. )
  1414. {
  1415. IO_STACK_LOCATION irpSp;
  1416. NTSTATUS status;
  1417. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1418. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_INTERRUPT_INTERFACE;
  1419. irpSp.Parameters.QueryInterface.Version = 1;
  1420. irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->InterruptInterface);
  1421. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->InterruptInterface;
  1422. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1423. irpSp.MajorFunction = IRP_MJ_PNP;
  1424. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1425. DebugPrint((1, "Querying interrupt interface for Fdoe 0x%x\n", FdoExtension));
  1426. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1427. return;
  1428. }
  1429. #endif
  1430. VOID
  1431. ChannelQueryTransferModeInterface (
  1432. PFDO_EXTENSION FdoExtension
  1433. )
  1434. {
  1435. IO_STACK_LOCATION irpSp;
  1436. NTSTATUS status;
  1437. ULONG i;
  1438. PAGED_CODE();
  1439. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1440. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_XFER_MODE_INTERFACE;
  1441. irpSp.Parameters.QueryInterface.Version = 1;
  1442. irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->TransferModeInterface);
  1443. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->TransferModeInterface;
  1444. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1445. irpSp.MajorFunction = IRP_MJ_PNP;
  1446. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1447. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1448. if (NT_SUCCESS(status)) {
  1449. if (FdoExtension->TransferModeInterface.SupportLevel
  1450. != PciIdeFullXferModeSupport) {
  1451. //
  1452. // We got the sfer mode interface from our parent,
  1453. // but it has only the basic functionality. It
  1454. // just relies on the BIOS to program its timing
  1455. // registers during POST. It doesn't really know
  1456. // how to program its timing registers.
  1457. //
  1458. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1459. if (FdoExtension->AcpiTimingSettings.Speed[i].Pio != ACPI_XFER_MODE_NOT_SUPPORT) {
  1460. //
  1461. // looks like ACPI is present and it knows how to program
  1462. // ide timing registers. Let's forget our parent xfer mode
  1463. // interface and go with the ACPI xfer mode interface
  1464. //
  1465. status = STATUS_UNSUCCESSFUL;
  1466. }
  1467. }
  1468. }
  1469. ASSERT (FdoExtension->TransferModeInterface.TransferModeTimingTable);
  1470. }
  1471. #ifdef ALWAYS_USE_APCI_IF_AVAILABLE
  1472. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1473. if (FdoExtension->AcpiTimingSettings.Speed[i].Pio != ACPI_XFER_MODE_NOT_SUPPORT) {
  1474. status = STATUS_UNSUCCESSFUL;
  1475. }
  1476. }
  1477. #endif // ALWAYS_USE_APCI_IF_AVAILABLE
  1478. if (!NT_SUCCESS(status)) {
  1479. PULONG transferModeTimingTable = FdoExtension->TransferModeInterface.TransferModeTimingTable;
  1480. //
  1481. // if we can't get the TransferModeInterface,
  1482. // we will default to the ACPI TransferModeInterface
  1483. //
  1484. if ((FdoExtension->AcpiTimingSettings.Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) ||
  1485. (FdoExtension->AcpiTimingSettings.Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT)) {
  1486. FdoExtension->TransferModeInterface.SupportLevel = PciIdeFullXferModeSupport;
  1487. } else {
  1488. FdoExtension->TransferModeInterface.SupportLevel = PciIdeBasicXferModeSupport;
  1489. }
  1490. FdoExtension->TransferModeInterface.Context = FdoExtension;
  1491. FdoExtension->TransferModeInterface.TransferModeSelect = ChannelAcpiTransferModeSelect;
  1492. //
  1493. // Fill up the timingTable with the default cycle times.
  1494. //
  1495. if (transferModeTimingTable == NULL) {
  1496. FdoExtension->TransferModeInterface.TransferModeTimingTable = FdoExtension->
  1497. DefaultTransferModeTimingTable;
  1498. FdoExtension->TransferModeInterface.TransferModeTableLength = MAX_XFER_MODE;
  1499. }
  1500. }
  1501. if (FdoExtension->TransferModeInterface.SupportLevel ==
  1502. PciIdeBasicXferModeSupport) {
  1503. //
  1504. // we don't really have code to set the correct
  1505. // xfer mode timing on the controller.
  1506. // our TransferModeInterface is really picking
  1507. // whatever mode set by the bios. and since there
  1508. // is no way to figure what the current PIO mode
  1509. // the drive is in, we are setting a flag in
  1510. // the HwDeviceExtension so that we won't try
  1511. // to change the pio transfer mode
  1512. //
  1513. FdoExtension->HwDeviceExtension->NoPioSetTransferMode = TRUE;
  1514. }
  1515. ASSERT (FdoExtension->TransferModeInterface.TransferModeSelect);
  1516. ASSERT (FdoExtension->TransferModeInterface.TransferModeTimingTable);
  1517. return;
  1518. }
  1519. VOID
  1520. ChannelUnbindBusMasterParent (
  1521. PFDO_EXTENSION FdoExtension
  1522. )
  1523. {
  1524. // ISSUE: 08/30/2000 implement me!!!
  1525. return;
  1526. }
  1527. VOID
  1528. ChannelQuerySyncAccessInterface (
  1529. PFDO_EXTENSION FdoExtension
  1530. )
  1531. {
  1532. IO_STACK_LOCATION irpSp;
  1533. NTSTATUS status;
  1534. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1535. RtlZeroMemory (
  1536. &FdoExtension->SyncAccessInterface,
  1537. sizeof (FdoExtension->SyncAccessInterface)
  1538. );
  1539. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_SYNC_ACCESS_INTERFACE;
  1540. irpSp.Parameters.QueryInterface.Version = 1;
  1541. irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->SyncAccessInterface);
  1542. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->SyncAccessInterface;
  1543. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1544. irpSp.MajorFunction = IRP_MJ_PNP;
  1545. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1546. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1547. //
  1548. // parent doesn't support access token,
  1549. //
  1550. if (!NT_SUCCESS(status)) {
  1551. FdoExtension->SyncAccessInterface.AllocateAccessToken = 0;
  1552. FdoExtension->SyncAccessInterface.Token = 0;
  1553. }
  1554. return;
  1555. }
  1556. VOID
  1557. ChannelQueryRequestProperResourceInterface (
  1558. PFDO_EXTENSION FdoExtension
  1559. )
  1560. {
  1561. IO_STACK_LOCATION irpSp;
  1562. NTSTATUS status;
  1563. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1564. RtlZeroMemory (
  1565. &FdoExtension->RequestProperResourceInterface,
  1566. sizeof (FdoExtension->RequestProperResourceInterface)
  1567. );
  1568. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_REQUEST_PROPER_RESOURCES;
  1569. irpSp.Parameters.QueryInterface.Version = 1;
  1570. irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->RequestProperResourceInterface);
  1571. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->RequestProperResourceInterface;
  1572. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1573. irpSp.MajorFunction = IRP_MJ_PNP;
  1574. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1575. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1576. return;
  1577. }
  1578. __inline
  1579. VOID
  1580. ChannelEnableInterrupt (
  1581. IN PFDO_EXTENSION FdoExtension
  1582. )
  1583. {
  1584. ULONG i;
  1585. for (i=0; i<(FdoExtension->HwDeviceExtension->MaxIdeDevice/MAX_IDE_DEVICE);i++) {
  1586. SelectIdeLine(&FdoExtension->HwDeviceExtension->BaseIoAddress1,i);
  1587. IdePortOutPortByte (
  1588. FdoExtension->HwDeviceExtension->BaseIoAddress2.DeviceControl,
  1589. IDE_DC_REENABLE_CONTROLLER
  1590. );
  1591. }
  1592. }
  1593. __inline
  1594. VOID
  1595. ChannelDisableInterrupt (
  1596. IN PFDO_EXTENSION FdoExtension
  1597. )
  1598. {
  1599. ULONG i;
  1600. for (i=0; i<(FdoExtension->HwDeviceExtension->MaxIdeDevice/MAX_IDE_DEVICE);i++) {
  1601. SelectIdeLine(&FdoExtension->HwDeviceExtension->BaseIoAddress1,i);
  1602. IdePortOutPortByte (
  1603. FdoExtension->HwDeviceExtension->BaseIoAddress2.DeviceControl,
  1604. IDE_DC_DISABLE_INTERRUPTS
  1605. );
  1606. }
  1607. }
  1608. NTSTATUS
  1609. ChannelAcpiTransferModeSelect (
  1610. IN PVOID Context,
  1611. PPCIIDE_TRANSFER_MODE_SELECT XferMode
  1612. )
  1613. {
  1614. PFDO_EXTENSION fdoExtension = Context;
  1615. ULONG i;
  1616. BOOLEAN useUdmaMode[MAX_IDE_DEVICE];
  1617. BOOLEAN dmaMode;
  1618. PIDENTIFY_DATA ataIdentifyData[MAX_IDE_DEVICE];
  1619. NTSTATUS status;
  1620. ULONG numDevices;
  1621. ULONG timingMode[MAX_IDE_DEVICE];
  1622. ULONG cycleTime[MAX_IDE_DEVICE];
  1623. ULONG dmaTiming;
  1624. PACPI_IDE_TIMING acpiTimingSettings;
  1625. ACPI_IDE_TIMING newAcpiTimingSettings;
  1626. PULONG transferModeTimingTable=XferMode->TransferModeTimingTable;
  1627. ASSERT(transferModeTimingTable);
  1628. ASSERT (IsNEC_98 == FALSE);
  1629. if (fdoExtension->DeviceChanged) {
  1630. DebugPrint((DBG_XFERMODE, "Updating boot acpi timing settings\n"));
  1631. RtlCopyMemory (&fdoExtension->BootAcpiTimingSettings,
  1632. &fdoExtension->AcpiTimingSettings,
  1633. sizeof(newAcpiTimingSettings)
  1634. );
  1635. }
  1636. acpiTimingSettings = &fdoExtension->BootAcpiTimingSettings;
  1637. RtlZeroMemory (&newAcpiTimingSettings, sizeof(newAcpiTimingSettings));
  1638. newAcpiTimingSettings.Flags.b.IndependentTiming =
  1639. acpiTimingSettings->Flags.b.IndependentTiming;
  1640. //
  1641. // how many devices do we have?
  1642. //
  1643. for (i=numDevices=0; i<MAX_IDE_DEVICE; i++) {
  1644. if (XferMode->DevicePresent[i]) {
  1645. numDevices++;
  1646. }
  1647. }
  1648. ASSERT (numDevices);
  1649. //
  1650. // pick the device pio timing
  1651. //
  1652. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1653. ULONG mode;
  1654. if (!XferMode->DevicePresent[i]) {
  1655. continue;
  1656. }
  1657. GetHighestPIOTransferMode(XferMode->DeviceTransferModeSupported[i], mode);
  1658. timingMode[i] = 1<<mode;
  1659. cycleTime[i] = XferMode->BestPioCycleTime[i];
  1660. }
  1661. if ((numDevices > 1) && !acpiTimingSettings->Flags.b.IndependentTiming) {
  1662. //
  1663. // pick the slower of the two timings
  1664. // (the smaller timing mode value, the slower it is)
  1665. //
  1666. if (timingMode[0] < timingMode[1]) {
  1667. cycleTime[1] = cycleTime[0];
  1668. timingMode[1] = timingMode[0];
  1669. } else {
  1670. cycleTime[0] = cycleTime[1];
  1671. timingMode[0] = timingMode[1];
  1672. }
  1673. }
  1674. //
  1675. // store the pio mode selected
  1676. //
  1677. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1678. if (XferMode->DevicePresent[i]) {
  1679. XferMode->DeviceTransferModeSelected[i] = timingMode[i];
  1680. newAcpiTimingSettings.Speed[i].Pio = cycleTime[i];
  1681. if (i == 0) {
  1682. newAcpiTimingSettings.Flags.b.IoChannelReady0 = XferMode->IoReadySupported[i];
  1683. } else {
  1684. newAcpiTimingSettings.Flags.b.IoChannelReady1 = XferMode->IoReadySupported[i];
  1685. }
  1686. } else {
  1687. XferMode->DeviceTransferModeSelected[i] = 0;
  1688. }
  1689. }
  1690. //
  1691. // pick the device dma timing
  1692. //
  1693. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1694. ULONG mode;
  1695. BOOLEAN useDma = TRUE;
  1696. timingMode[i] = 0;
  1697. cycleTime[i]= ACPI_XFER_MODE_NOT_SUPPORT;
  1698. if (!XferMode->DevicePresent[i]) {
  1699. continue;
  1700. }
  1701. //
  1702. // check the acpi flag for ultra dma
  1703. //
  1704. if (i == 0) {
  1705. useUdmaMode[i] = acpiTimingSettings->Flags.b.UltraDma0 ? TRUE: FALSE;
  1706. } else {
  1707. ASSERT (i==1);
  1708. useUdmaMode[i] = acpiTimingSettings->Flags.b.UltraDma1 ? TRUE: FALSE;
  1709. }
  1710. //
  1711. // get the dma timing specified in _GTM
  1712. //
  1713. dmaTiming = acpiTimingSettings->Speed[i].Dma;
  1714. //
  1715. // if dma is not supported, don't do anything, We have already set the PIO mode.
  1716. //
  1717. if (dmaTiming == ACPI_XFER_MODE_NOT_SUPPORT) {
  1718. useUdmaMode[i]=0;
  1719. useDma = FALSE;
  1720. mode = PIO0;
  1721. }
  1722. //
  1723. // Find the highest UDMA mode
  1724. //
  1725. if (useUdmaMode[i]) {
  1726. GetHighestDMATransferMode(XferMode->DeviceTransferModeSupported[i], mode);
  1727. while (mode>= UDMA0) {
  1728. if ((dmaTiming <= transferModeTimingTable[mode]) &&
  1729. (XferMode->DeviceTransferModeSupported[i] & (1<<mode))) {
  1730. timingMode[i] = 1<<mode;
  1731. cycleTime[i] = transferModeTimingTable[mode];
  1732. ASSERT(cycleTime[i]);
  1733. // we got a udma mode. so don't try to find a dma mode.
  1734. useDma = FALSE;
  1735. break;
  1736. }
  1737. mode--;
  1738. }
  1739. }
  1740. //
  1741. // highest DMA mode
  1742. // useDma is false only when either dma is not supported or an udma mode is
  1743. // already selected.
  1744. //
  1745. if (useDma) {
  1746. ULONG tempMode;
  1747. // we shouldn't be using UDMA now.
  1748. // this will set the flags for STM correctly.
  1749. useUdmaMode[i]=FALSE;
  1750. // mask out UDMA and MWDMA0
  1751. tempMode = XferMode->
  1752. DeviceTransferModeSupported[i] & (SWDMA_SUPPORT | MWDMA_SUPPORT);
  1753. tempMode &= (~MWDMA_MODE0);
  1754. GetHighestDMATransferMode(tempMode, mode);
  1755. if (mode >= MWDMA1) {
  1756. timingMode[i] = 1<<mode;
  1757. cycleTime[i] = XferMode->BestMwDmaCycleTime[i];
  1758. ASSERT(cycleTime[i]);
  1759. } else if (mode == SWDMA2) {
  1760. timingMode[i] = 1<<mode;
  1761. cycleTime[i] = XferMode->BestSwDmaCycleTime[i];
  1762. ASSERT(cycleTime[i]);
  1763. }
  1764. // else don't do anything. PIO is already set
  1765. }
  1766. }
  1767. if ((numDevices > 1) && !acpiTimingSettings->Flags.b.IndependentTiming) {
  1768. //
  1769. // pick the slower of the two timings
  1770. // (the smaller timing mode value, the slower it is)
  1771. //
  1772. if (timingMode[0] < timingMode[1]) {
  1773. cycleTime[1] = cycleTime[0];
  1774. timingMode[1] = timingMode[0];
  1775. } else {
  1776. cycleTime[0] = cycleTime[1];
  1777. timingMode[0] = timingMode[1];
  1778. }
  1779. //
  1780. // both dma mode have to be the same
  1781. //
  1782. if (useUdmaMode[0] != useUdmaMode[1]) {
  1783. useUdmaMode[0] = 0;
  1784. useUdmaMode[1] = 0;
  1785. }
  1786. }
  1787. //
  1788. // store the dma mode selected
  1789. //
  1790. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1791. if (XferMode->DevicePresent[i]) {
  1792. XferMode->DeviceTransferModeSelected[i] |= timingMode[i];
  1793. newAcpiTimingSettings.Speed[i].Dma = cycleTime[i];
  1794. if (i==0) {
  1795. newAcpiTimingSettings.Flags.b.UltraDma0 = useUdmaMode[i];
  1796. } else {
  1797. newAcpiTimingSettings.Flags.b.UltraDma1 = useUdmaMode[i];
  1798. }
  1799. }
  1800. }
  1801. if (fdoExtension->DmaDetectionLevel == DdlPioOnly) {
  1802. //
  1803. // remove all DMA modes
  1804. //
  1805. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1806. XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT;
  1807. }
  1808. }
  1809. if ((acpiTimingSettings->Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) ||
  1810. (acpiTimingSettings->Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT)) {
  1811. //
  1812. // looks like we are on an ACPI machine and
  1813. // it supports IDE timing control method (_STM)
  1814. //
  1815. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1816. if (XferMode->DevicePresent[i]) {
  1817. ataIdentifyData[i] = fdoExtension->HwDeviceExtension->IdentifyData + i;
  1818. } else {
  1819. ataIdentifyData[i] = NULL;
  1820. }
  1821. }
  1822. //
  1823. // save the new timing settings
  1824. //
  1825. RtlCopyMemory (
  1826. &fdoExtension->AcpiTimingSettings,
  1827. &newAcpiTimingSettings,
  1828. sizeof(newAcpiTimingSettings));
  1829. //
  1830. // call ACPI to program the timing registers
  1831. //
  1832. status = ChannelSyncSetACPITimingSettings (
  1833. fdoExtension,
  1834. &newAcpiTimingSettings,
  1835. ataIdentifyData
  1836. );
  1837. } else {
  1838. //
  1839. // legacy controller
  1840. //
  1841. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1842. XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT;
  1843. }
  1844. status = STATUS_SUCCESS;
  1845. }
  1846. return status;
  1847. }
  1848. NTSTATUS
  1849. ChannelRestoreTiming (
  1850. IN PFDO_EXTENSION FdoExtension,
  1851. IN PSET_ACPI_TIMING_COMPLETION_ROUTINE CallerCompletionRoutine,
  1852. IN PVOID CallerContext
  1853. )
  1854. {
  1855. ULONG i;
  1856. PIDENTIFY_DATA ataIdentifyData[MAX_IDE_DEVICE];
  1857. NTSTATUS status;
  1858. PACPI_IDE_TIMING acpiTimingSettings;
  1859. acpiTimingSettings = &FdoExtension->AcpiTimingSettings;
  1860. if (FdoExtension->NumberOfLogicalUnits &&
  1861. ((acpiTimingSettings->Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) ||
  1862. (acpiTimingSettings->Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT))) {
  1863. //
  1864. // looks like we are on an ACPI machine and
  1865. // it supports IDE timing control method (_STM)
  1866. //
  1867. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1868. if (FdoExtension->HwDeviceExtension->DeviceFlags[i] &
  1869. DFLAGS_DEVICE_PRESENT) {
  1870. ataIdentifyData[i] = FdoExtension->HwDeviceExtension->IdentifyData + i;
  1871. } else {
  1872. ataIdentifyData[i] = NULL;
  1873. }
  1874. }
  1875. //
  1876. // call ACPI to program the timing registers
  1877. //
  1878. status = ChannelSetACPITimingSettings (
  1879. FdoExtension,
  1880. acpiTimingSettings,
  1881. ataIdentifyData,
  1882. CallerCompletionRoutine,
  1883. CallerContext
  1884. );
  1885. } else {
  1886. //
  1887. // non-acpi controller
  1888. //
  1889. if (FdoExtension->NumberOfLogicalUnits) {
  1890. AtapiSyncSelectTransferMode (
  1891. FdoExtension,
  1892. FdoExtension->HwDeviceExtension,
  1893. FdoExtension->TimingModeAllowed
  1894. );
  1895. }
  1896. (*CallerCompletionRoutine) (
  1897. FdoExtension->DeviceObject,
  1898. STATUS_SUCCESS,
  1899. CallerContext
  1900. );
  1901. status = STATUS_SUCCESS;
  1902. }
  1903. return status;
  1904. }
  1905. NTSTATUS
  1906. ChannelRestoreTimingCompletionRoutine (
  1907. IN PDEVICE_OBJECT DeviceObject,
  1908. IN NTSTATUS Status,
  1909. IN PVOID Context
  1910. )
  1911. {
  1912. PIO_STACK_LOCATION thisIrpSp;
  1913. PFDO_POWER_CONTEXT context = Context;
  1914. PIRP originalPowerIrp;
  1915. context->TimingRestored = TRUE;
  1916. originalPowerIrp = context->OriginalPowerIrp;
  1917. originalPowerIrp->IoStatus.Status = Status;
  1918. thisIrpSp = IoGetCurrentIrpStackLocation(originalPowerIrp);
  1919. //
  1920. // finish off the original power irp
  1921. //
  1922. FdoPowerCompletionRoutine (
  1923. thisIrpSp->DeviceObject,
  1924. originalPowerIrp,
  1925. Context
  1926. );
  1927. //
  1928. // continue with the irp completion
  1929. //
  1930. IoCompleteRequest (originalPowerIrp, IO_NO_INCREMENT);
  1931. return Status;
  1932. }
  1933. NTSTATUS
  1934. ChannelFilterResourceRequirements (
  1935. IN PDEVICE_OBJECT DeviceObject,
  1936. IN OUT PIRP Irp
  1937. )
  1938. {
  1939. NTSTATUS status;
  1940. PFDO_EXTENSION fdoExtension;
  1941. ULONG i, j, k;
  1942. IO_STACK_LOCATION irpSp;
  1943. PCIIDE_XFER_MODE_INTERFACE xferModeInterface;
  1944. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn;
  1945. PIO_RESOURCE_LIST resourceListIn;
  1946. PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
  1947. PIO_RESOURCE_DESCRIPTOR cmdRegResourceDescriptor;
  1948. PIO_RESOURCE_DESCRIPTOR ctrlRegResourceDescriptor;
  1949. PIO_RESOURCE_DESCRIPTOR intRegResourceDescriptor;
  1950. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListOut;
  1951. ULONG requirementsListSizeOut;
  1952. PIO_RESOURCE_LIST resourceListOut;
  1953. PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
  1954. PAGED_CODE();
  1955. //
  1956. // the value will stay NULL if no filtering required
  1957. //
  1958. requirementsListOut = NULL;
  1959. #ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
  1960. if (NT_SUCCESS(ChannelFilterPromiseTechResourceRequirements (DeviceObject, Irp))) {
  1961. goto getout;
  1962. }
  1963. #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
  1964. //
  1965. // do a simple test to check if we have a pciidex parent
  1966. //
  1967. RtlZeroMemory (&irpSp, sizeof(irpSp));
  1968. irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_XFER_MODE_INTERFACE;
  1969. irpSp.Parameters.QueryInterface.Version = 1;
  1970. irpSp.Parameters.QueryInterface.Size = sizeof (xferModeInterface);
  1971. irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &xferModeInterface;
  1972. irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1973. irpSp.MajorFunction = IRP_MJ_PNP;
  1974. irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
  1975. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  1976. status = IdePortSyncSendIrp (fdoExtension->AttacheeDeviceObject, &irpSp, NULL);
  1977. if (NT_SUCCESS(status)) {
  1978. //
  1979. // we have a pciidex as a parent. it would
  1980. // take care of the resource requirement
  1981. // no need to filter
  1982. //
  1983. goto getout;
  1984. }
  1985. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  1986. ASSERT (Irp->IoStatus.Information);
  1987. requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  1988. } else {
  1989. PIO_STACK_LOCATION thisIrpSp;
  1990. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  1991. requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  1992. }
  1993. if (requirementsListIn == NULL) {
  1994. goto getout;
  1995. }
  1996. if (requirementsListIn->AlternativeLists == 0) {
  1997. goto getout;
  1998. }
  1999. requirementsListSizeOut = requirementsListIn->ListSize +
  2000. requirementsListIn->AlternativeLists *
  2001. sizeof(IO_RESOURCE_DESCRIPTOR);
  2002. requirementsListOut = ExAllocatePool (PagedPool, requirementsListSizeOut);
  2003. if (requirementsListOut == NULL) {
  2004. goto getout;
  2005. }
  2006. *requirementsListOut = *requirementsListIn;
  2007. requirementsListOut->ListSize = requirementsListSizeOut;
  2008. //
  2009. // some init.
  2010. //
  2011. resourceListIn = requirementsListIn->List;
  2012. resourceListOut = requirementsListOut->List;
  2013. for (j=0; j<requirementsListIn->AlternativeLists; j++) {
  2014. resourceDescriptorIn = resourceListIn->Descriptors;
  2015. //
  2016. // analyze what resources we are getting
  2017. //
  2018. cmdRegResourceDescriptor = NULL;
  2019. ctrlRegResourceDescriptor = NULL;
  2020. intRegResourceDescriptor = NULL;
  2021. for (i=0; i<resourceListIn->Count; i++) {
  2022. switch (resourceDescriptorIn[i].Type) {
  2023. case CmResourceTypePort: {
  2024. if ((resourceDescriptorIn[i].u.Port.Length == 8) &&
  2025. (cmdRegResourceDescriptor == NULL)) {
  2026. cmdRegResourceDescriptor = resourceDescriptorIn + i;
  2027. } else if (((resourceDescriptorIn[i].u.Port.Length == 1) ||
  2028. (resourceDescriptorIn[i].u.Port.Length == 2) ||
  2029. (resourceDescriptorIn[i].u.Port.Length == 4)) &&
  2030. (ctrlRegResourceDescriptor == NULL)) {
  2031. ctrlRegResourceDescriptor = resourceDescriptorIn + i;
  2032. } else if ((resourceDescriptorIn[i].u.Port.Length >= 0x10) &&
  2033. (cmdRegResourceDescriptor == NULL) &&
  2034. (ctrlRegResourceDescriptor == NULL)) {
  2035. //
  2036. // probably pcmcia device. it likes to combine
  2037. // both io ranges into 1.
  2038. //
  2039. cmdRegResourceDescriptor = resourceDescriptorIn + i;
  2040. ctrlRegResourceDescriptor = resourceDescriptorIn + i;
  2041. }
  2042. }
  2043. break;
  2044. case CmResourceTypeInterrupt: {
  2045. if (intRegResourceDescriptor == NULL) {
  2046. intRegResourceDescriptor = resourceDescriptorIn + i;
  2047. }
  2048. }
  2049. break;
  2050. default:
  2051. break;
  2052. }
  2053. }
  2054. //
  2055. // making a new copy
  2056. //
  2057. *resourceListOut = *resourceListIn;
  2058. //
  2059. // figure out what is missing
  2060. //
  2061. if (cmdRegResourceDescriptor &&
  2062. ((cmdRegResourceDescriptor->u.Port.MaximumAddress.QuadPart -
  2063. cmdRegResourceDescriptor->u.Port.MinimumAddress.QuadPart + 1) == 8) &&
  2064. (ctrlRegResourceDescriptor == NULL)) {
  2065. //
  2066. // missing controller register resource descriptor.
  2067. //
  2068. resourceDescriptorOut = resourceListOut->Descriptors;
  2069. for (i=0; i<resourceListOut->Count; i++) {
  2070. *resourceDescriptorOut = resourceDescriptorIn[i];
  2071. resourceDescriptorOut++;
  2072. if ((resourceDescriptorIn + i) == cmdRegResourceDescriptor) {
  2073. //
  2074. // add the control register resource
  2075. //
  2076. *resourceDescriptorOut = resourceDescriptorIn[i];
  2077. resourceDescriptorOut->u.Port.Length = 1;
  2078. resourceDescriptorOut->u.Port.Alignment = 1;
  2079. resourceDescriptorOut->u.Port.MinimumAddress.QuadPart =
  2080. resourceDescriptorOut->u.Port.MaximumAddress.QuadPart =
  2081. cmdRegResourceDescriptor->u.Port.MinimumAddress.QuadPart + 0x206;
  2082. resourceDescriptorOut++;
  2083. }
  2084. }
  2085. //
  2086. // account for the new control register resource
  2087. //
  2088. resourceListOut->Count++;
  2089. } else {
  2090. resourceDescriptorOut = resourceListOut->Descriptors;
  2091. k = resourceListOut->Count;
  2092. for (i = 0; i < k; i++) {
  2093. if (IsNEC_98) {
  2094. //
  2095. // NEC98 DevNode includes the ide rom memory resource.
  2096. // But it should be gotten by NTDETECT.COM&HAL.DLL, so ignore it here.
  2097. //
  2098. if ((resourceDescriptorIn[i].Type == CmResourceTypeMemory) &&
  2099. (resourceDescriptorIn[i].u.Memory.MinimumAddress.QuadPart == 0xd8000) &&
  2100. (resourceDescriptorIn[i].u.Memory.Length == 0x4000)) {
  2101. resourceListOut->Count--;
  2102. continue;
  2103. }
  2104. }
  2105. *resourceDescriptorOut = resourceDescriptorIn[i];
  2106. resourceDescriptorOut++;
  2107. }
  2108. }
  2109. resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resourceListIn->Count);
  2110. resourceListOut = (PIO_RESOURCE_LIST) resourceDescriptorOut;
  2111. }
  2112. getout:
  2113. if (requirementsListOut) {
  2114. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  2115. ExFreePool ((PVOID) Irp->IoStatus.Information);
  2116. } else {
  2117. Irp->IoStatus.Status = STATUS_SUCCESS;
  2118. }
  2119. Irp->IoStatus.Information = (ULONG_PTR) requirementsListOut;
  2120. }
  2121. return IdePortPassDownToNextDriver (DeviceObject, Irp);
  2122. }
  2123. static PCWSTR PcmciaIdeChannelDeviceId = L"PCMCIA\\*PNP0600";
  2124. BOOLEAN
  2125. ChannelQueryPcmciaParent (
  2126. PFDO_EXTENSION FdoExtension
  2127. )
  2128. {
  2129. BOOLEAN foundIt = FALSE;
  2130. NTSTATUS status;
  2131. IO_STATUS_BLOCK ioStatus;
  2132. IO_STACK_LOCATION irpSp;
  2133. PAGED_CODE();
  2134. //
  2135. // do a simple test to check if we have a pciidex parent
  2136. //
  2137. RtlZeroMemory (&irpSp, sizeof(irpSp));
  2138. irpSp.Parameters.QueryId.IdType = BusQueryHardwareIDs;
  2139. irpSp.MajorFunction = IRP_MJ_PNP;
  2140. irpSp.MinorFunction = IRP_MN_QUERY_ID;
  2141. ioStatus.Status = STATUS_NOT_SUPPORTED;
  2142. status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, &ioStatus);
  2143. if (NT_SUCCESS(status)) {
  2144. PWSTR wstr;
  2145. UNICODE_STRING hwId;
  2146. UNICODE_STRING targetId;
  2147. RtlInitUnicodeString(
  2148. &targetId,
  2149. PcmciaIdeChannelDeviceId);
  2150. wstr = (PWSTR) ioStatus.Information;
  2151. while (*wstr) {
  2152. RtlInitUnicodeString(&hwId, wstr);
  2153. if (!RtlCompareUnicodeString(
  2154. &hwId,
  2155. &targetId,
  2156. FALSE)) {
  2157. ExFreePool ((PVOID) ioStatus.Information);
  2158. DebugPrint ((DBG_PNP, "ATAPI: pcmcia parent\n"));
  2159. return TRUE;
  2160. }
  2161. wstr += hwId.Length / sizeof(WCHAR);
  2162. wstr++; // NULL character
  2163. }
  2164. ExFreePool ((PVOID) ioStatus.Information);
  2165. }
  2166. return FALSE;
  2167. }
  2168. #ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
  2169. static PCWSTR PromiseTechDeviceId[] = {
  2170. L"ISAPNP\\BJB1000"
  2171. };
  2172. #define NUM_PROMISE_TECH_ID (sizeof(PromiseTechDeviceId)/sizeof(PCWSTR))
  2173. NTSTATUS
  2174. ChannelFilterPromiseTechResourceRequirements (
  2175. IN PDEVICE_OBJECT DeviceObject,
  2176. IN OUT PIRP Irp
  2177. )
  2178. {
  2179. BOOLEAN foundIt = FALSE;
  2180. BOOLEAN firstIrq = FALSE;
  2181. ULONG numExtraIoResDescriptor = 0;
  2182. NTSTATUS status;
  2183. IO_STATUS_BLOCK ioStatus;
  2184. PFDO_EXTENSION fdoExtension;
  2185. ULONG i, j, k;
  2186. IO_STACK_LOCATION irpSp;
  2187. PCIIDE_XFER_MODE_INTERFACE xferModeInterface;
  2188. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn;
  2189. PIO_RESOURCE_LIST resourceListIn;
  2190. PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
  2191. PIO_RESOURCE_DESCRIPTOR brokenResourceDescriptor;
  2192. PIO_RESOURCE_DESCRIPTOR cmdRegResourceDescriptor;
  2193. PIO_RESOURCE_DESCRIPTOR ctrlRegResourceDescriptor;
  2194. PIO_RESOURCE_DESCRIPTOR intRegResourceDescriptor;
  2195. PIO_RESOURCE_REQUIREMENTS_LIST requirementsListOut;
  2196. ULONG requirementsListSizeOut;
  2197. PIO_RESOURCE_LIST resourceListOut;
  2198. PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
  2199. PAGED_CODE();
  2200. //
  2201. // the value will stay NULL if no filtering required
  2202. //
  2203. requirementsListOut = NULL;
  2204. //
  2205. // do a simple test to check if we have a pciidex parent
  2206. //
  2207. RtlZeroMemory (&irpSp, sizeof(irpSp));
  2208. irpSp.Parameters.QueryId.IdType = BusQueryDeviceID;
  2209. irpSp.MajorFunction = IRP_MJ_PNP;
  2210. irpSp.MinorFunction = IRP_MN_QUERY_ID;
  2211. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  2212. ioStatus.Status = STATUS_NOT_SUPPORTED;
  2213. status = IdePortSyncSendIrp (fdoExtension->AttacheeDeviceObject, &irpSp, &ioStatus);
  2214. if (NT_SUCCESS(status)) {
  2215. UNICODE_STRING deviceId;
  2216. UNICODE_STRING promiseTechDeviceId;
  2217. RtlInitUnicodeString(
  2218. &deviceId,
  2219. (PCWSTR) ioStatus.Information);
  2220. for (i=0; i<NUM_PROMISE_TECH_ID && !foundIt; i++) {
  2221. RtlInitUnicodeString(
  2222. &promiseTechDeviceId,
  2223. PromiseTechDeviceId[i]);
  2224. if (deviceId.Length >= promiseTechDeviceId.Length) {
  2225. deviceId.Length = promiseTechDeviceId.Length;
  2226. if (!RtlCompareUnicodeString(
  2227. &promiseTechDeviceId,
  2228. &deviceId,
  2229. FALSE)) {
  2230. foundIt = TRUE;
  2231. }
  2232. }
  2233. }
  2234. ExFreePool ((PVOID) ioStatus.Information);
  2235. }
  2236. if (!foundIt) {
  2237. goto getout;
  2238. }
  2239. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  2240. ASSERT (Irp->IoStatus.Information);
  2241. requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  2242. } else {
  2243. PIO_STACK_LOCATION thisIrpSp;
  2244. thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
  2245. requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  2246. }
  2247. if (requirementsListIn == NULL) {
  2248. goto getout;
  2249. }
  2250. if (requirementsListIn->AlternativeLists == 0) {
  2251. goto getout;
  2252. }
  2253. //
  2254. // look for the bad resource descriptior
  2255. //
  2256. resourceListIn = requirementsListIn->List;
  2257. brokenResourceDescriptor = NULL;
  2258. for (j=0; j<requirementsListIn->AlternativeLists; j++) {
  2259. resourceDescriptorIn = resourceListIn->Descriptors;
  2260. //
  2261. // analyze what resources we are getting
  2262. //
  2263. for (i=0; i<resourceListIn->Count; i++) {
  2264. switch (resourceDescriptorIn[i].Type) {
  2265. case CmResourceTypePort: {
  2266. ULONG alignmentMask;
  2267. alignmentMask = resourceDescriptorIn[i].u.Port.Alignment - 1;
  2268. if (resourceDescriptorIn[i].u.Port.MinimumAddress.LowPart & alignmentMask) {
  2269. //
  2270. // broken resource requirement;
  2271. //
  2272. brokenResourceDescriptor = resourceDescriptorIn + i;
  2273. }
  2274. }
  2275. break;
  2276. default:
  2277. break;
  2278. }
  2279. }
  2280. }
  2281. if (brokenResourceDescriptor) {
  2282. ULONG alignmentMask;
  2283. PHYSICAL_ADDRESS minAddress;
  2284. PHYSICAL_ADDRESS addressRange;
  2285. alignmentMask = brokenResourceDescriptor->u.Port.Alignment - 1;
  2286. alignmentMask = ~alignmentMask;
  2287. minAddress = brokenResourceDescriptor->u.Port.MinimumAddress;
  2288. minAddress.LowPart &= alignmentMask;
  2289. addressRange.QuadPart = (brokenResourceDescriptor->u.Port.MaximumAddress.QuadPart - minAddress.QuadPart);
  2290. numExtraIoResDescriptor = (ULONG) (addressRange.QuadPart / brokenResourceDescriptor->u.Port.Alignment);
  2291. }
  2292. requirementsListSizeOut = requirementsListIn->ListSize +
  2293. numExtraIoResDescriptor *
  2294. sizeof(IO_RESOURCE_DESCRIPTOR);
  2295. requirementsListOut = ExAllocatePool (PagedPool, requirementsListSizeOut);
  2296. if (requirementsListOut == NULL) {
  2297. goto getout;
  2298. }
  2299. *requirementsListOut = *requirementsListIn;
  2300. requirementsListOut->ListSize = requirementsListSizeOut;
  2301. //
  2302. // some init.
  2303. //
  2304. resourceListIn = requirementsListIn->List;
  2305. resourceListOut = requirementsListOut->List;
  2306. for (j=0; j<requirementsListIn->AlternativeLists; j++) {
  2307. resourceDescriptorIn = resourceListIn->Descriptors;
  2308. //
  2309. // making a new copy
  2310. //
  2311. *resourceListOut = *resourceListIn;
  2312. resourceListOut->Count = 0;
  2313. //
  2314. // analyze what resources we are getting
  2315. //
  2316. resourceDescriptorOut = resourceListOut->Descriptors;
  2317. firstIrq = TRUE;
  2318. for (i=0; i<resourceListIn->Count; i++) {
  2319. switch (resourceDescriptorIn[i].Type) {
  2320. case CmResourceTypePort: {
  2321. if ((resourceDescriptorIn + i == brokenResourceDescriptor) &&
  2322. (numExtraIoResDescriptor)) {
  2323. for (k=0; k<numExtraIoResDescriptor; k++) {
  2324. *resourceDescriptorOut = resourceDescriptorIn[i];
  2325. if (k != 0) {
  2326. resourceDescriptorOut->Option = IO_RESOURCE_ALTERNATIVE;
  2327. }
  2328. resourceDescriptorOut->u.Port.Alignment = 1;
  2329. resourceDescriptorOut->u.Port.MinimumAddress.QuadPart =
  2330. brokenResourceDescriptor->u.Port.MinimumAddress.QuadPart +
  2331. k * brokenResourceDescriptor->u.Port.Alignment;
  2332. resourceDescriptorOut->u.Port.MaximumAddress.QuadPart =
  2333. resourceDescriptorOut->u.Port.MinimumAddress.QuadPart +
  2334. resourceDescriptorOut->u.Port.Length - 1;
  2335. resourceDescriptorOut++;
  2336. resourceListOut->Count++;
  2337. }
  2338. } else {
  2339. *resourceDescriptorOut = resourceDescriptorIn[i];
  2340. resourceDescriptorOut++;
  2341. resourceListOut->Count++;
  2342. }
  2343. }
  2344. break;
  2345. case CmResourceTypeInterrupt: {
  2346. //
  2347. // keep all irqs except 9 which doesn't really work
  2348. //
  2349. if (!((resourceDescriptorIn[i].u.Interrupt.MinimumVector == 0x9) &&
  2350. (resourceDescriptorIn[i].u.Interrupt.MaximumVector == 0x9))) {
  2351. *resourceDescriptorOut = resourceDescriptorIn[i];
  2352. if (firstIrq) {
  2353. resourceDescriptorOut->Option = 0;
  2354. firstIrq = FALSE;
  2355. } else {
  2356. resourceDescriptorOut->Option = IO_RESOURCE_ALTERNATIVE;
  2357. }
  2358. resourceDescriptorOut++;
  2359. resourceListOut->Count++;
  2360. }
  2361. }
  2362. break;
  2363. default:
  2364. *resourceDescriptorOut = resourceDescriptorIn[i];
  2365. resourceDescriptorOut++;
  2366. resourceListOut->Count++;
  2367. break;
  2368. }
  2369. }
  2370. resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resourceListIn->Count);
  2371. resourceListOut = (PIO_RESOURCE_LIST) resourceDescriptorOut;
  2372. }
  2373. getout:
  2374. if (requirementsListOut) {
  2375. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  2376. ExFreePool ((PVOID) Irp->IoStatus.Information);
  2377. } else {
  2378. Irp->IoStatus.Status = STATUS_SUCCESS;
  2379. }
  2380. Irp->IoStatus.Information = (ULONG_PTR) requirementsListOut;
  2381. return STATUS_SUCCESS;
  2382. } else {
  2383. return STATUS_INVALID_PARAMETER;
  2384. }
  2385. }
  2386. #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
  2387. NTSTATUS
  2388. ChannelQueryPnPDeviceState (
  2389. IN PDEVICE_OBJECT DeviceObject,
  2390. IN OUT PIRP Irp
  2391. )
  2392. {
  2393. PFDO_EXTENSION fdoExtension;
  2394. PPNP_DEVICE_STATE deviceState;
  2395. fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
  2396. DebugPrint((DBG_PNP, "QUERY_DEVICE_STATE for FDOE 0x%x\n", fdoExtension));
  2397. if(fdoExtension->PagingPathCount != 0) {
  2398. deviceState = (PPNP_DEVICE_STATE) &(Irp->IoStatus.Information);
  2399. SETMASK((*deviceState), PNP_DEVICE_NOT_DISABLEABLE);
  2400. }
  2401. Irp->IoStatus.Status = STATUS_SUCCESS;
  2402. IoSkipCurrentIrpStackLocation (Irp);
  2403. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  2404. }