Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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