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.

2447 lines
71 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: ctlrfdo.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pciidex.h"
  11. #ifdef ALLOC_PRAGMA
  12. #pragma alloc_text(PAGE, ControllerAddDevice)
  13. #pragma alloc_text(PAGE, ControllerStartDevice)
  14. #pragma alloc_text(PAGE, ControllerStopDevice)
  15. #pragma alloc_text(PAGE, ControllerStopController)
  16. #pragma alloc_text(PAGE, ControllerSurpriseRemoveDevice)
  17. #pragma alloc_text(PAGE, ControllerRemoveDevice)
  18. #pragma alloc_text(PAGE, ControllerQueryDeviceRelations)
  19. #pragma alloc_text(PAGE, ControllerQueryInterface)
  20. #pragma alloc_text(PAGE, AnalyzeResourceList)
  21. #pragma alloc_text(PAGE, ControllerOpMode)
  22. #pragma alloc_text(PAGE, PciIdeChannelEnabled)
  23. #pragma alloc_text(PAGE, PciIdeCreateTimingTable)
  24. #pragma alloc_text(PAGE, PciIdeInitControllerProperties)
  25. #pragma alloc_text(PAGE, ControllerUsageNotification)
  26. #pragma alloc_text(PAGE, PciIdeGetBusStandardInterface)
  27. #pragma alloc_text(PAGE, ControllerQueryPnPDeviceState)
  28. #pragma alloc_text(NONPAGE, EnablePCIBusMastering)
  29. #pragma alloc_text(NONPAGE, ControllerUsageNotificationCompletionRoutine)
  30. #pragma alloc_text(NONPAGE, ControllerRemoveDeviceCompletionRoutine)
  31. #pragma alloc_text(NONPAGE, ControllerStartDeviceCompletionRoutine)
  32. #endif // ALLOC_PRAGMA
  33. //
  34. // Must match mshdc.inf
  35. //
  36. static PWCHAR ChannelEnableMaskName[MAX_IDE_CHANNEL] = {
  37. L"MasterOnMask",
  38. L"SlaveOnMask"
  39. };
  40. static PWCHAR ChannelEnablePciConfigOffsetName[MAX_IDE_CHANNEL] = {
  41. L"MasterOnConfigOffset",
  42. L"SlaveOnConfigOffset"
  43. };
  44. static ULONG PciIdeXNextControllerNumber = 0;
  45. static ULONG PciIdeXNextChannelNumber = 0;
  46. NTSTATUS
  47. ControllerAddDevice(
  48. IN PDRIVER_OBJECT DriverObject,
  49. IN PDEVICE_OBJECT PhysicalDeviceObject
  50. )
  51. {
  52. PDEVICE_OBJECT deviceObject;
  53. PCTRLFDO_EXTENSION fdoExtension;
  54. NTSTATUS status;
  55. PDRIVER_OBJECT_EXTENSION driverObjectExtension;
  56. ULONG deviceExtensionSize;
  57. UNICODE_STRING deviceName;
  58. WCHAR deviceNameBuffer[64];
  59. ULONG controllerNumber;
  60. PAGED_CODE();
  61. driverObjectExtension =
  62. (PDRIVER_OBJECT_EXTENSION) IoGetDriverObjectExtension(
  63. DriverObject,
  64. DRIVER_OBJECT_EXTENSION_ID
  65. );
  66. ASSERT (driverObjectExtension);
  67. //
  68. // devobj name
  69. //
  70. controllerNumber = InterlockedIncrement(&PciIdeXNextControllerNumber) - 1;
  71. swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\PciIde%d", controllerNumber);
  72. RtlInitUnicodeString(&deviceName, deviceNameBuffer);
  73. deviceExtensionSize = sizeof(CTRLFDO_EXTENSION) +
  74. driverObjectExtension->ExtensionSize;
  75. //
  76. // We've been given the PhysicalDeviceObject for an IDE controller. Create the
  77. // FunctionalDeviceObject. Our FDO will be nameless.
  78. //
  79. status = IoCreateDevice(
  80. DriverObject, // our driver object
  81. deviceExtensionSize, // size of our extension
  82. &deviceName, // our name
  83. FILE_DEVICE_BUS_EXTENDER, // device type
  84. FILE_DEVICE_SECURE_OPEN, // device characteristics
  85. FALSE, // not exclusive
  86. &deviceObject // store new device object here
  87. );
  88. if( !NT_SUCCESS( status )){
  89. return status;
  90. }
  91. fdoExtension = (PCTRLFDO_EXTENSION)deviceObject->DeviceExtension;
  92. RtlZeroMemory (fdoExtension, deviceExtensionSize);
  93. //
  94. // We have our FunctionalDeviceObject, initialize it.
  95. //
  96. fdoExtension->AttacheePdo = PhysicalDeviceObject;
  97. fdoExtension->DeviceObject = deviceObject;
  98. fdoExtension->DriverObject = DriverObject;
  99. fdoExtension->ControllerNumber = controllerNumber;
  100. fdoExtension->VendorSpecificDeviceEntension = fdoExtension + 1;
  101. // Dispatch Table
  102. fdoExtension->DefaultDispatch = PassDownToNextDriver;
  103. fdoExtension->PnPDispatchTable = FdoPnpDispatchTable;
  104. fdoExtension->PowerDispatchTable = FdoPowerDispatchTable;
  105. fdoExtension->WmiDispatchTable = FdoWmiDispatchTable;
  106. //
  107. // Get the Device Control Flags out of the registry
  108. //
  109. fdoExtension->DeviceControlsFlags = 0;
  110. status = PciIdeXGetDeviceParameter (
  111. fdoExtension->AttacheePdo,
  112. L"DeviceControlFlags",
  113. &fdoExtension->DeviceControlsFlags
  114. );
  115. if (!NT_SUCCESS(status)) {
  116. DebugPrint ((1, "PciIdeX: Unable to get DeviceControlFlags from the registry\n"));
  117. //
  118. // this is not a serious error...continue to load
  119. //
  120. status = STATUS_SUCCESS;
  121. }
  122. //
  123. // Now attach to the PDO we were given.
  124. //
  125. fdoExtension->AttacheeDeviceObject = IoAttachDeviceToDeviceStack (
  126. deviceObject,
  127. PhysicalDeviceObject
  128. );
  129. if (fdoExtension->AttacheeDeviceObject == NULL){
  130. //
  131. // Couldn't attach. Delete the FDO.
  132. //
  133. IoDeleteDevice (deviceObject);
  134. } else {
  135. //
  136. // fix up alignment requirement
  137. //
  138. deviceObject->AlignmentRequirement = fdoExtension->AttacheeDeviceObject->AlignmentRequirement;
  139. if (deviceObject->AlignmentRequirement < 1) {
  140. deviceObject->AlignmentRequirement = 1;
  141. }
  142. //
  143. // get the standard bus interface
  144. // (for READ_CONFIG/WRITE_CONFIG
  145. //
  146. status = PciIdeGetBusStandardInterface(fdoExtension);
  147. if (!NT_SUCCESS(status)) {
  148. IoDetachDevice (fdoExtension->AttacheeDeviceObject);
  149. IoDeleteDevice (deviceObject);
  150. return status;
  151. }
  152. //
  153. // Init operating mode (native or legacy)
  154. //
  155. ControllerOpMode (fdoExtension);
  156. #ifdef ENABLE_NATIVE_MODE
  157. if (IsNativeMode(fdoExtension)) {
  158. NTSTATUS interfaceStatus = PciIdeGetNativeModeInterface(fdoExtension);
  159. //
  160. // bad pci.sys.
  161. // we should still work. However, the window where an interrupt fires before
  162. // we are ready to dismiss it would not be closed. Can't do much at this point.
  163. //
  164. //ASSERT(NT_SUCCESS(interfaceStatus));
  165. }
  166. #endif
  167. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  168. }
  169. return status;
  170. } // ControllerAddDevice
  171. NTSTATUS
  172. ControllerStartDevice (
  173. IN PDEVICE_OBJECT DeviceObject,
  174. IN OUT PIRP Irp
  175. )
  176. {
  177. PIO_STACK_LOCATION thisIrpSp;
  178. NTSTATUS status;
  179. PCTRLFDO_EXTENSION fdoExtension;
  180. PCM_RESOURCE_LIST resourceList;
  181. PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors;
  182. ULONG i;
  183. KEVENT event;
  184. POWER_STATE powerState;
  185. PAGED_CODE();
  186. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  187. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  188. resourceList = thisIrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  189. if (!resourceList) {
  190. DebugPrint ((1, "PciIde: Starting with no resource\n"));
  191. }
  192. #ifdef ENABLE_NATIVE_MODE
  193. //
  194. // Let PCI know that we will manage the decodes
  195. //
  196. if (IsNativeMode(fdoExtension)) {
  197. ControllerDisableInterrupt(fdoExtension);
  198. }
  199. #endif
  200. //
  201. // Call the lower level drivers with a the Irp
  202. //
  203. KeInitializeEvent(&event,
  204. SynchronizationEvent,
  205. FALSE);
  206. IoCopyCurrentIrpStackLocationToNext (Irp);
  207. Irp->IoStatus.Status = STATUS_SUCCESS;
  208. IoSetCompletionRoutine(
  209. Irp,
  210. ControllerStartDeviceCompletionRoutine,
  211. &event,
  212. TRUE,
  213. TRUE,
  214. TRUE
  215. );
  216. //
  217. // Pass the irp along
  218. //
  219. status = IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
  220. //
  221. // Wait for it to come back...
  222. //
  223. if (status == STATUS_PENDING) {
  224. KeWaitForSingleObject(
  225. &event,
  226. Executive,
  227. KernelMode,
  228. FALSE,
  229. NULL
  230. );
  231. //
  232. // Grab back the 'real' status
  233. //
  234. status = Irp->IoStatus.Status;
  235. }
  236. if (!NT_SUCCESS(status)) {
  237. goto GetOut;
  238. }
  239. powerState.SystemState = PowerSystemWorking;
  240. status = PciIdeIssueSetPowerState (
  241. fdoExtension,
  242. SystemPowerState,
  243. powerState,
  244. TRUE
  245. );
  246. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  247. //
  248. // The DeviceObject below us does not support power irp,
  249. // we will assume we are powered up
  250. //
  251. fdoExtension->SystemPowerState = PowerSystemWorking;
  252. } else if (!NT_SUCCESS(status)) {
  253. goto GetOut;
  254. }
  255. powerState.DeviceState = PowerDeviceD0;
  256. status= PciIdeIssueSetPowerState (
  257. fdoExtension,
  258. DevicePowerState,
  259. powerState,
  260. TRUE
  261. );
  262. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  263. //
  264. // The DeviceObject Below us does not support power irp,
  265. // pretend we are powered up
  266. //
  267. fdoExtension->DevicePowerState = PowerDeviceD0;
  268. } else if (!NT_SUCCESS(status)) {
  269. goto GetOut;
  270. }
  271. #ifdef ENABLE_NATIVE_MODE
  272. if (!IsNativeMode(fdoExtension)) {
  273. #endif
  274. //
  275. // Turn on PCI busmastering
  276. //
  277. EnablePCIBusMastering (
  278. fdoExtension
  279. );
  280. #ifdef ENABLE_NATIVE_MODE
  281. }
  282. #endif
  283. //
  284. // Initialize a fast mutex for later use
  285. //
  286. KeInitializeSpinLock(
  287. &fdoExtension->PciConfigDataLock
  288. );
  289. if (!NT_SUCCESS(status)) {
  290. goto GetOut;
  291. }
  292. //
  293. // Analyze the resources
  294. //
  295. status = AnalyzeResourceList (fdoExtension, resourceList);
  296. if (!NT_SUCCESS(status)) {
  297. goto GetOut;
  298. }
  299. //
  300. // Initialize controller properties. We need the resources
  301. // at this point for Native mode IDE controllers
  302. //
  303. PciIdeInitControllerProperties (
  304. fdoExtension
  305. );
  306. #ifdef ENABLE_NATIVE_MODE
  307. if (IsNativeMode(fdoExtension)) {
  308. IDE_CHANNEL_STATE channelState;
  309. #if DBG
  310. {
  311. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  312. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  313. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  314. ULONG resourceListSize;
  315. ULONG j;
  316. fullResourceList = resourceList->List;
  317. resourceListSize = 0;
  318. DebugPrint ((1, "Pciidex: Starting native mode device: FDOe\n", fdoExtension));
  319. for (i=0; i<resourceList->Count; i++) {
  320. partialResourceList = &(fullResourceList->PartialResourceList);
  321. partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
  322. for (j=0; j<partialResourceList->Count; j++) {
  323. if (partialDescriptors[j].Type == CmResourceTypePort) {
  324. DebugPrint ((1, "pciidex: IO Port = 0x%x. Lenght = 0x%x\n", partialDescriptors[j].u.Port.Start.LowPart, partialDescriptors[j].u.Port.Length));
  325. } else if (partialDescriptors[j].Type == CmResourceTypeInterrupt) {
  326. DebugPrint ((1, "pciidex: Int Level = 0x%x. Int Vector = 0x%x\n", partialDescriptors[j].u.Interrupt.Level, partialDescriptors[j].u.Interrupt.Vector));
  327. } else {
  328. DebugPrint ((1, "pciidex: Unknown resource\n"));
  329. }
  330. }
  331. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + j);
  332. }
  333. }
  334. #endif // DBG
  335. fdoExtension->ControllerIsrInstalled = FALSE;
  336. for (i=0; i< MAX_IDE_CHANNEL; i++) {
  337. //
  338. // Analyze the resources we are getting
  339. //
  340. status = DigestResourceList(
  341. &fdoExtension->IdeResource,
  342. fdoExtension->PdoResourceList[i],
  343. &fdoExtension->IrqPartialDescriptors[i]
  344. );
  345. if (!NT_SUCCESS(status) ) {
  346. goto GetOut;
  347. }
  348. if (!fdoExtension->IrqPartialDescriptors[i]) {
  349. status = STATUS_INSUFFICIENT_RESOURCES;
  350. goto GetOut;
  351. }
  352. DebugPrint((1,
  353. "Pciidex: Connecting interrupt for channel %x interrupt vector 0x%x\n",
  354. i,
  355. fdoExtension->IrqPartialDescriptors[i]->u.Interrupt.Vector
  356. ));
  357. channelState = PciIdeChannelEnabled (fdoExtension, i);
  358. if (channelState != ChannelDisabled) {
  359. //
  360. // Build io address structure.
  361. //
  362. AtapiBuildIoAddress(
  363. fdoExtension->IdeResource.TranslatedCommandBaseAddress,
  364. fdoExtension->IdeResource.TranslatedControlBaseAddress,
  365. &fdoExtension->BaseIoAddress1[i],
  366. &fdoExtension->BaseIoAddress2[i],
  367. &fdoExtension->BaseIoAddress1Length[i],
  368. &fdoExtension->BaseIoAddress2Length[i],
  369. &fdoExtension->MaxIdeDevice[i],
  370. NULL);
  371. //
  372. // Install the ISR
  373. //
  374. status = ControllerInterruptControl(fdoExtension, i, 0);
  375. if (!NT_SUCCESS(status)) {
  376. break;
  377. }
  378. }
  379. }
  380. if (!NT_SUCCESS(status)) {
  381. goto GetOut;
  382. }
  383. //
  384. // This flag is needed for the ISR to enable interrupts.
  385. //
  386. fdoExtension->ControllerIsrInstalled = TRUE;
  387. //
  388. // Enable the interrupt in both the channels
  389. //
  390. ControllerEnableInterrupt(fdoExtension);
  391. fdoExtension->NativeInterruptEnabled = TRUE;
  392. //
  393. // See the comments in the ISR regarding these flags
  394. //
  395. ASSERT(fdoExtension->ControllerIsrInstalled == TRUE);
  396. ASSERT(fdoExtension->NativeInterruptEnabled == TRUE);
  397. //
  398. // Turn on PCI busmastering
  399. //
  400. EnablePCIBusMastering (
  401. fdoExtension
  402. );
  403. for (i=0; i< MAX_IDE_CHANNEL; i++) {
  404. PIDE_BUS_MASTER_REGISTERS bmRegister;
  405. //
  406. // Check the bus master registers
  407. //
  408. bmRegister = (PIDE_BUS_MASTER_REGISTERS)(((PUCHAR)fdoExtension->TranslatedBusMasterBaseAddress) + i*8);
  409. if (READ_PORT_UCHAR (&bmRegister->Status) & BUSMASTER_ZERO_BITS) {
  410. fdoExtension->NoBusMaster[i] = TRUE;
  411. }
  412. }
  413. }
  414. #endif
  415. status = PciIdeCreateSyncChildAccess (fdoExtension);
  416. if (!NT_SUCCESS(status)) {
  417. goto GetOut;
  418. }
  419. status = PciIdeCreateTimingTable(fdoExtension);
  420. if (!NT_SUCCESS(status)) {
  421. goto GetOut;
  422. }
  423. GetOut:
  424. if (NT_SUCCESS(status)) {
  425. #if DBG
  426. {
  427. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  428. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  429. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  430. ULONG j;
  431. ULONG k;
  432. DebugPrint ((1, "PciIdeX: Starting device:\n"));
  433. for (k=0; k <MAX_IDE_CHANNEL + 1; k++) {
  434. if (k == MAX_IDE_CHANNEL) {
  435. DebugPrint ((1, "PciIdeX: Busmaster resources:\n"));
  436. resourceList = fdoExtension->BmResourceList;
  437. } else {
  438. DebugPrint ((1, "PciIdeX: PDO %d resources:\n", k));
  439. resourceList = fdoExtension->PdoResourceList[k];
  440. }
  441. if (resourceList) {
  442. fullResourceList = resourceList->List;
  443. for (i=0; i<resourceList->Count; i++) {
  444. partialResourceList = &(fullResourceList->PartialResourceList);
  445. partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
  446. for (j=0; j<partialResourceList->Count; j++) {
  447. if (partialDescriptors[j].Type == CmResourceTypePort) {
  448. DebugPrint ((1, "IdePort: IO Port = 0x%x. Lenght = 0x%x\n", partialDescriptors[j].u.Port.Start.LowPart, partialDescriptors[j].u.Port.Length));
  449. } else if (partialDescriptors[j].Type == CmResourceTypeMemory) {
  450. DebugPrint ((1, "IdePort: Memory Port = 0x%x. Lenght = 0x%x\n", partialDescriptors[j].u.Memory.Start.LowPart, partialDescriptors[j].u.Memory.Length));
  451. } else if (partialDescriptors[j].Type == CmResourceTypeInterrupt) {
  452. DebugPrint ((1, "IdePort: Int Level = 0x%x. Int Vector = 0x%x\n", partialDescriptors[j].u.Interrupt.Level, partialDescriptors[j].u.Interrupt.Vector));
  453. } else {
  454. DebugPrint ((1, "IdePort: Unknown resource\n"));
  455. }
  456. }
  457. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + j);
  458. }
  459. }
  460. }
  461. }
  462. #endif // DBG
  463. }
  464. Irp->IoStatus.Status = status;
  465. Irp->IoStatus.Information = 0;
  466. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  467. return status;
  468. } // ControllerStartDevice
  469. NTSTATUS
  470. ControllerStartDeviceCompletionRoutine(
  471. IN PDEVICE_OBJECT DeviceObject,
  472. IN OUT PIRP Irp,
  473. IN OUT PVOID Context
  474. )
  475. {
  476. PKEVENT event = (PKEVENT) Context;
  477. //
  478. // Signal the event
  479. //
  480. KeSetEvent( event, IO_NO_INCREMENT, FALSE );
  481. //
  482. // Always return MORE_PROCESSING_REQUIRED
  483. // will complete it later
  484. //
  485. return STATUS_MORE_PROCESSING_REQUIRED;
  486. } // ControllerStartDeviceCompletionRoutine
  487. NTSTATUS
  488. ControllerStopDevice (
  489. IN PDEVICE_OBJECT DeviceObject,
  490. IN OUT PIRP Irp
  491. )
  492. {
  493. PCTRLFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  494. NTSTATUS status;
  495. PAGED_CODE();
  496. status = ControllerStopController (
  497. fdoExtension
  498. );
  499. ASSERT (NT_SUCCESS(status));
  500. Irp->IoStatus.Status = STATUS_SUCCESS;
  501. IoSkipCurrentIrpStackLocation(Irp);
  502. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  503. } // ControllerStopDevice
  504. NTSTATUS
  505. ControllerStopController (
  506. IN PCTRLFDO_EXTENSION FdoExtension
  507. )
  508. {
  509. ULONG i;
  510. PAGED_CODE();
  511. if (FdoExtension->BmResourceList) {
  512. ExFreePool (FdoExtension->BmResourceList);
  513. FdoExtension->BmResourceList = NULL;
  514. }
  515. for (i=0; i<MAX_IDE_CHANNEL; i++) {
  516. if (FdoExtension->PdoResourceList[i]) {
  517. ExFreePool (FdoExtension->PdoResourceList[i]);
  518. FdoExtension->PdoResourceList[i] = NULL;
  519. }
  520. }
  521. #ifdef ENABLE_NATIVE_MODE
  522. //
  523. // We need to reset the flags in this order. Otherwise an interrupt would
  524. // result in the decodes to be enabled by the ISR. See the comments in the ISR
  525. //
  526. FdoExtension->ControllerIsrInstalled = FALSE;
  527. ControllerDisableInterrupt(FdoExtension);
  528. FdoExtension->NativeInterruptEnabled = FALSE;
  529. for (i=0; i< MAX_IDE_CHANNEL; i++) {
  530. NTSTATUS status;
  531. DebugPrint((1, "Pciidex: DisConnecting interrupt for channel %x\n", i));
  532. //
  533. // Disconnect the ISR
  534. //
  535. status = ControllerInterruptControl(FdoExtension, i, 1 );
  536. ASSERT(NT_SUCCESS(status));
  537. }
  538. ASSERT(FdoExtension->ControllerIsrInstalled == FALSE);
  539. ASSERT(FdoExtension->NativeInterruptEnabled == FALSE);
  540. #endif
  541. PciIdeDeleteSyncChildAccess (FdoExtension);
  542. return STATUS_SUCCESS;
  543. } // ControllerStopController
  544. NTSTATUS
  545. ControllerSurpriseRemoveDevice (
  546. IN PDEVICE_OBJECT DeviceObject,
  547. IN OUT PIRP Irp
  548. )
  549. {
  550. PCTRLFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  551. NTSTATUS status;
  552. ULONG i;
  553. PAGED_CODE();
  554. #if DBG
  555. //
  556. // make sure all the children are removed or surprise removed
  557. //
  558. for (i=0; i<MAX_IDE_CHANNEL; i++) {
  559. PCHANPDO_EXTENSION pdoExtension;
  560. pdoExtension = fdoExtension->ChildDeviceExtension[i];
  561. if (pdoExtension) {
  562. ASSERT (pdoExtension->PdoState & (PDOS_SURPRISE_REMOVED | PDOS_REMOVED));
  563. }
  564. }
  565. #endif // DBG
  566. status = ControllerStopController (fdoExtension);
  567. ASSERT (NT_SUCCESS(status));
  568. Irp->IoStatus.Status = STATUS_SUCCESS;
  569. IoSkipCurrentIrpStackLocation ( Irp );
  570. return IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
  571. } // ControllerSurpriseRemoveDevice
  572. NTSTATUS
  573. ControllerRemoveDevice (
  574. IN PDEVICE_OBJECT DeviceObject,
  575. IN OUT PIRP Irp
  576. )
  577. {
  578. PCTRLFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  579. NTSTATUS status;
  580. KEVENT event;
  581. ULONG i;
  582. PAGED_CODE();
  583. //
  584. // Kill all the children if any
  585. //
  586. for (i=0; i<MAX_IDE_CHANNEL; i++) {
  587. PCHANPDO_EXTENSION pdoExtension;
  588. pdoExtension = fdoExtension->ChildDeviceExtension[i];
  589. if (pdoExtension) {
  590. status = ChannelStopChannel (pdoExtension);
  591. ASSERT (NT_SUCCESS(status));
  592. //
  593. // mark this device invalid
  594. //
  595. ChannelUpdatePdoState (
  596. pdoExtension,
  597. PDOS_DEADMEAT | PDOS_REMOVED,
  598. 0
  599. );
  600. IoDeleteDevice (pdoExtension->DeviceObject);
  601. fdoExtension->ChildDeviceExtension[i] = NULL;
  602. }
  603. }
  604. status = ControllerStopController (fdoExtension);
  605. ASSERT (NT_SUCCESS(status));
  606. if (fdoExtension->TransferModeTimingTable) {
  607. ExFreePool(fdoExtension->TransferModeTimingTable);
  608. fdoExtension->TransferModeTimingTable = NULL;
  609. fdoExtension->TransferModeTableLength = 0;
  610. }
  611. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  612. IoCopyCurrentIrpStackLocationToNext (Irp);
  613. IoSetCompletionRoutine(
  614. Irp,
  615. ControllerRemoveDeviceCompletionRoutine,
  616. &event,
  617. TRUE,
  618. TRUE,
  619. TRUE
  620. );
  621. status = IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  622. if (status == STATUS_PENDING) {
  623. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  624. }
  625. IoDetachDevice (fdoExtension->AttacheeDeviceObject);
  626. IoDeleteDevice (DeviceObject);
  627. //return STATUS_SUCCESS;
  628. return status;
  629. } // ControllerRemoveDevice
  630. NTSTATUS
  631. ControllerRemoveDeviceCompletionRoutine (
  632. IN PDEVICE_OBJECT DeviceObject,
  633. IN PIRP Irp,
  634. IN PVOID Context
  635. )
  636. {
  637. PKEVENT event = Context;
  638. KeSetEvent(event, 0, FALSE);
  639. return STATUS_SUCCESS;
  640. } // ControllerRemoveDeviceCompletionRoutine
  641. NTSTATUS
  642. ControllerQueryDeviceRelations (
  643. IN PDEVICE_OBJECT DeviceObject,
  644. IN OUT PIRP Irp
  645. )
  646. {
  647. PIO_STACK_LOCATION thisIrpSp;
  648. PCTRLFDO_EXTENSION fdoExtension;
  649. PDEVICE_RELATIONS deviceRelations;
  650. NTSTATUS status;
  651. ULONG deviceRelationsSize;
  652. ULONG channel;
  653. PCONFIGURATION_INFORMATION configurationInformation = IoGetConfigurationInformation();
  654. ULONG nextUniqueNumber;
  655. PAGED_CODE();
  656. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  657. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  658. status = STATUS_SUCCESS;
  659. switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) {
  660. case BusRelations:
  661. DebugPrint ((3, "ControllerQueryDeviceRelations: bus relations\n"));
  662. deviceRelationsSize = FIELD_OFFSET (DEVICE_RELATIONS, Objects) +
  663. MAX_IDE_CHANNEL * sizeof(PDEVICE_OBJECT);
  664. deviceRelations = ExAllocatePool (PagedPool, deviceRelationsSize);
  665. if(!deviceRelations) {
  666. DebugPrint ((1,
  667. "IdeQueryDeviceRelations: Unable to allocate DeviceRelations structures\n"));
  668. status = STATUS_INSUFFICIENT_RESOURCES;
  669. }
  670. if (NT_SUCCESS(status)) {
  671. LARGE_INTEGER tickCount;
  672. ULONG newBusScanTime;
  673. ULONG newBusScanTimeDelta;
  674. BOOLEAN reportUnknownAsNewChild;
  675. //
  676. // determine if we should return unknown child as new child
  677. // unknown child is IDE channel which we don't know
  678. // it is enabled or not unless we pnp start the channel
  679. // and poke at it to find out.
  680. //
  681. // since we don't want to go into an infinite cycle of
  682. // starting and failing start on a unknown child, we will
  683. // limit our frequency
  684. //
  685. KeQueryTickCount(&tickCount);
  686. newBusScanTime = (ULONG) ((tickCount.QuadPart *
  687. ((ULONGLONG) KeQueryTimeIncrement())) / ((ULONGLONG) 10000000));
  688. newBusScanTimeDelta = newBusScanTime - fdoExtension->LastBusScanTime;
  689. DebugPrint ((1, "PCIIDEX: Last rescan was %d seconds ago.\n", newBusScanTimeDelta));
  690. if ((newBusScanTimeDelta < MIN_BUS_SCAN_PERIOD_IN_SEC) &&
  691. (fdoExtension->LastBusScanTime != 0)) {
  692. reportUnknownAsNewChild = FALSE;
  693. } else {
  694. reportUnknownAsNewChild = TRUE;
  695. }
  696. fdoExtension->LastBusScanTime = newBusScanTime;
  697. RtlZeroMemory (deviceRelations, deviceRelationsSize);
  698. for (channel = 0; channel < MAX_IDE_CHANNEL; channel++) {
  699. PDEVICE_OBJECT deviceObject;
  700. PCHANPDO_EXTENSION pdoExtension;
  701. UNICODE_STRING deviceName;
  702. WCHAR deviceNameBuffer[256];
  703. PDEVICE_OBJECT deviceObjectToReturn;
  704. IDE_CHANNEL_STATE channelState;
  705. deviceObjectToReturn = NULL;
  706. pdoExtension = fdoExtension->ChildDeviceExtension[channel];
  707. channelState = PciIdeChannelEnabled (fdoExtension, channel);
  708. if (pdoExtension) {
  709. //
  710. // already got a DeviceObject for this channel
  711. //
  712. if (channelState == ChannelDisabled) {
  713. ULONG pdoState;
  714. pdoState = ChannelUpdatePdoState (
  715. pdoExtension,
  716. PDOS_DEADMEAT,
  717. 0
  718. );
  719. } else {
  720. deviceObjectToReturn = pdoExtension->DeviceObject;
  721. }
  722. } else if ((channelState == ChannelEnabled) ||
  723. ((channelState == ChannelStateUnknown) && reportUnknownAsNewChild)) {
  724. if (!fdoExtension->NativeMode[channel]) {
  725. if (channel == 0) {
  726. configurationInformation->AtDiskPrimaryAddressClaimed = TRUE;
  727. } else {
  728. configurationInformation->AtDiskSecondaryAddressClaimed = TRUE;
  729. }
  730. }
  731. //
  732. // Remove this when pnp mgr can deal with pdo with no names
  733. //
  734. nextUniqueNumber = InterlockedIncrement(&PciIdeXNextChannelNumber) - 1;
  735. swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\PciIde%dChannel%d-%x", fdoExtension->ControllerNumber, channel, nextUniqueNumber);
  736. RtlInitUnicodeString (&deviceName, deviceNameBuffer);
  737. status = IoCreateDevice(
  738. fdoExtension->DriverObject, // our driver object
  739. sizeof(CHANPDO_EXTENSION), // size of our extension
  740. &deviceName, // our name
  741. FILE_DEVICE_CONTROLLER, // device type
  742. FILE_DEVICE_SECURE_OPEN, // device characteristics
  743. FALSE, // not exclusive
  744. &deviceObject // store new device object here
  745. );
  746. if (NT_SUCCESS(status)) {
  747. pdoExtension = (PCHANPDO_EXTENSION) deviceObject->DeviceExtension;
  748. RtlZeroMemory (pdoExtension, sizeof(CHANPDO_EXTENSION));
  749. pdoExtension->DeviceObject = deviceObject;
  750. pdoExtension->DriverObject = fdoExtension->DriverObject;
  751. pdoExtension->ParentDeviceExtension = fdoExtension;
  752. pdoExtension->ChannelNumber = channel;
  753. //
  754. // Dispatch Table
  755. //
  756. pdoExtension->DefaultDispatch = NoSupportIrp;
  757. pdoExtension->PnPDispatchTable = PdoPnpDispatchTable;
  758. pdoExtension->PowerDispatchTable = PdoPowerDispatchTable;
  759. pdoExtension->WmiDispatchTable = PdoWmiDispatchTable;
  760. KeInitializeSpinLock(&pdoExtension->SpinLock);
  761. fdoExtension->ChildDeviceExtension[channel] = pdoExtension;
  762. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  763. fdoExtension->NumberOfChildren++;
  764. InterlockedIncrement(&fdoExtension->NumberOfChildrenPowerUp);
  765. //
  766. // fix up alignment requirement
  767. // check with the miniport also
  768. //
  769. deviceObject->AlignmentRequirement = fdoExtension->ControllerProperties.AlignmentRequirement;
  770. if (deviceObject->AlignmentRequirement < fdoExtension->AttacheeDeviceObject->AlignmentRequirement) {
  771. deviceObject->AlignmentRequirement =
  772. fdoExtension->DeviceObject->AlignmentRequirement;
  773. }
  774. if (deviceObject->AlignmentRequirement < 1) {
  775. deviceObject->AlignmentRequirement = 1;
  776. }
  777. //
  778. // return this new DeviceObject
  779. //
  780. deviceObjectToReturn = deviceObject;
  781. }
  782. }
  783. if (deviceObjectToReturn) {
  784. deviceRelations->Objects[(deviceRelations)->Count] = deviceObjectToReturn;
  785. ObReferenceObjectByPointer(deviceObjectToReturn,
  786. 0,
  787. 0,
  788. KernelMode);
  789. deviceRelations->Count++;
  790. }
  791. }
  792. }
  793. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  794. Irp->IoStatus.Status = status;
  795. break;
  796. default:
  797. status=STATUS_SUCCESS;
  798. DebugPrint ((1, "PciIdeQueryDeviceRelations: Unsupported device relation\n"));
  799. break;
  800. }
  801. if (NT_SUCCESS(status)) {
  802. IoSkipCurrentIrpStackLocation ( Irp );
  803. return IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
  804. } else {
  805. //
  806. //Complete the request
  807. //
  808. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  809. return status;
  810. }
  811. } // ControllerQueryDeviceRelations
  812. NTSTATUS
  813. ControllerQueryInterface (
  814. IN PDEVICE_OBJECT DeviceObject,
  815. IN OUT PIRP Irp
  816. )
  817. {
  818. PIO_STACK_LOCATION thisIrpSp;
  819. PCTRLFDO_EXTENSION fdoExtension;
  820. NTSTATUS status;
  821. PTRANSLATOR_INTERFACE translator;
  822. ULONG busNumber;
  823. PAGED_CODE();
  824. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  825. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  826. status = Irp->IoStatus.Status;
  827. if (RtlEqualMemory(&GUID_TRANSLATOR_INTERFACE_STANDARD,
  828. thisIrpSp->Parameters.QueryInterface.InterfaceType,
  829. sizeof(GUID))
  830. && (thisIrpSp->Parameters.QueryInterface.Size >=
  831. sizeof(TRANSLATOR_INTERFACE))
  832. && (PtrToUlong(thisIrpSp->Parameters.QueryInterface.InterfaceSpecificData) ==
  833. CmResourceTypeInterrupt)) {
  834. if (!fdoExtension->NativeMode[0] && !fdoExtension->NativeMode[1]) {
  835. //
  836. // we only return a translator only if we are legacy controller
  837. //
  838. status = HalGetInterruptTranslator(
  839. PCIBus,
  840. 0,
  841. InterfaceTypeUndefined, // special "IDE" cookie
  842. thisIrpSp->Parameters.QueryInterface.Size,
  843. thisIrpSp->Parameters.QueryInterface.Version,
  844. (PTRANSLATOR_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface,
  845. &busNumber
  846. );
  847. }
  848. }
  849. //
  850. // Pass down.
  851. //
  852. Irp->IoStatus.Status = status;
  853. IoSkipCurrentIrpStackLocation ( Irp );
  854. return IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
  855. } // ControllerQueryInterface
  856. //
  857. // initialize PCTRLFDO_EXTENSION->PCM_PARTIAL_RESOURCE_DESCRIPTOR(s)
  858. //
  859. NTSTATUS
  860. AnalyzeResourceList (
  861. PCTRLFDO_EXTENSION FdoExtension,
  862. PCM_RESOURCE_LIST ResourceList
  863. )
  864. {
  865. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  866. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  867. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  868. ULONG i;
  869. ULONG j;
  870. ULONG k;
  871. ULONG cmdChannel;
  872. ULONG ctrlChannel;
  873. ULONG intrChannel;
  874. ULONG bmAddr;
  875. ULONG pdoResourceListSize;
  876. PCM_RESOURCE_LIST pdoResourceList[MAX_IDE_CHANNEL];
  877. PCM_FULL_RESOURCE_DESCRIPTOR pdoFullResourceList[MAX_IDE_CHANNEL];
  878. PCM_PARTIAL_RESOURCE_LIST pdoPartialResourceList[MAX_IDE_CHANNEL];
  879. PCM_PARTIAL_RESOURCE_DESCRIPTOR pdoPartialDescriptors[MAX_IDE_CHANNEL];
  880. ULONG bmResourceListSize;
  881. PCM_RESOURCE_LIST bmResourceList;
  882. PCM_FULL_RESOURCE_DESCRIPTOR bmFullResourceList;
  883. PCM_PARTIAL_RESOURCE_LIST bmPartialResourceList;
  884. PCM_PARTIAL_RESOURCE_DESCRIPTOR bmPartialDescriptors;
  885. NTSTATUS status;
  886. PAGED_CODE();
  887. if (!ResourceList) {
  888. return STATUS_SUCCESS;
  889. }
  890. bmResourceListSize =
  891. sizeof (CM_RESOURCE_LIST) * ResourceList->Count; // This will have one CM_PARTIAL_RESOURCE_LIST
  892. bmResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, bmResourceListSize);
  893. if (bmResourceList == NULL) {
  894. return STATUS_NO_MEMORY;
  895. }
  896. RtlZeroMemory (bmResourceList, bmResourceListSize);
  897. pdoResourceListSize =
  898. sizeof (CM_RESOURCE_LIST) * ResourceList->Count + // This will have one CM_PARTIAL_RESOURCE_LIST
  899. sizeof (CM_PARTIAL_RESOURCE_LIST) * 2;
  900. for (i=0; i<MAX_IDE_CHANNEL; i++) {
  901. pdoResourceList[i] = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, pdoResourceListSize);
  902. if (pdoResourceList[i] == NULL) {
  903. DebugPrint ((0, "Unable to allocate resourceList for PDOs\n"));
  904. for (j=0; j<i; j++) {
  905. ExFreePool (pdoResourceList[j]);
  906. }
  907. ExFreePool (bmResourceList);
  908. return STATUS_NO_MEMORY;
  909. }
  910. RtlZeroMemory (pdoResourceList[i], pdoResourceListSize);
  911. }
  912. fullResourceList = ResourceList->List;
  913. bmResourceList->Count = 0;
  914. bmFullResourceList = bmResourceList->List;
  915. for (k=0; k<MAX_IDE_CHANNEL; k++) {
  916. pdoResourceList[k]->Count = 0;
  917. pdoFullResourceList[k] = pdoResourceList[k]->List;
  918. }
  919. cmdChannel = ctrlChannel = intrChannel = bmAddr = 0;
  920. for (j=0; j<ResourceList->Count; j++) {
  921. partialResourceList = &(fullResourceList->PartialResourceList);
  922. partialDescriptors = partialResourceList->PartialDescriptors;
  923. RtlCopyMemory (
  924. bmFullResourceList,
  925. fullResourceList,
  926. FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors)
  927. );
  928. bmPartialResourceList = &(bmFullResourceList->PartialResourceList);
  929. bmPartialResourceList->Count = 0;
  930. bmPartialDescriptors = bmPartialResourceList->PartialDescriptors;
  931. for (k=0; k<MAX_IDE_CHANNEL; k++) {
  932. RtlCopyMemory (
  933. pdoFullResourceList[k],
  934. fullResourceList,
  935. FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors)
  936. );
  937. pdoPartialResourceList[k] = &(pdoFullResourceList[k]->PartialResourceList);
  938. pdoPartialResourceList[k]->Count = 0;
  939. pdoPartialDescriptors[k] = pdoPartialResourceList[k]->PartialDescriptors;
  940. }
  941. for (i=0; i<partialResourceList->Count; i++) {
  942. if (((partialDescriptors[j].Type == CmResourceTypePort) ||
  943. (partialDescriptors[j].Type == CmResourceTypeMemory)) &&
  944. (partialDescriptors[i].u.Port.Length == 8) &&
  945. (cmdChannel < MAX_IDE_CHANNEL)) {
  946. ASSERT (cmdChannel < MAX_IDE_CHANNEL);
  947. RtlCopyMemory (
  948. pdoPartialDescriptors[cmdChannel] + pdoPartialResourceList[cmdChannel]->Count,
  949. partialDescriptors + i,
  950. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR)
  951. );
  952. pdoPartialResourceList[cmdChannel]->Count++;
  953. cmdChannel++;
  954. } else if (((partialDescriptors[j].Type == CmResourceTypePort) ||
  955. (partialDescriptors[j].Type == CmResourceTypeMemory)) &&
  956. (partialDescriptors[i].u.Port.Length == 4) &&
  957. (ctrlChannel < MAX_IDE_CHANNEL)) {
  958. ASSERT (ctrlChannel < MAX_IDE_CHANNEL);
  959. RtlCopyMemory (
  960. pdoPartialDescriptors[ctrlChannel] + pdoPartialResourceList[ctrlChannel]->Count,
  961. partialDescriptors + i,
  962. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR)
  963. );
  964. pdoPartialResourceList[ctrlChannel]->Count++;
  965. ctrlChannel++;
  966. } else if (((partialDescriptors[j].Type == CmResourceTypePort) ||
  967. (partialDescriptors[j].Type == CmResourceTypeMemory)) &&
  968. (partialDescriptors[i].u.Port.Length == 16) &&
  969. (bmAddr < 1)) {
  970. ASSERT (bmAddr < 1);
  971. RtlCopyMemory (
  972. bmPartialDescriptors + bmPartialResourceList->Count,
  973. partialDescriptors + i,
  974. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR)
  975. );
  976. bmPartialResourceList->Count++;
  977. bmAddr++;
  978. } else if ((partialDescriptors[i].Type == CmResourceTypeInterrupt) &&
  979. (intrChannel < MAX_IDE_CHANNEL)) {
  980. ASSERT (intrChannel < MAX_IDE_CHANNEL);
  981. RtlCopyMemory (
  982. pdoPartialDescriptors[intrChannel] + pdoPartialResourceList[intrChannel]->Count,
  983. partialDescriptors + i,
  984. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR)
  985. );
  986. pdoPartialResourceList[intrChannel]->Count++;
  987. if (intrChannel == 0) {
  988. if (FdoExtension->NativeMode[1]) {
  989. intrChannel++;
  990. //
  991. // ISSUE: 08/30/2000
  992. // do I need to mark it sharable?
  993. // this needs to be revisited. (there are more issues)
  994. //
  995. RtlCopyMemory (
  996. pdoPartialDescriptors[intrChannel] + pdoPartialResourceList[intrChannel]->Count,
  997. partialDescriptors + i,
  998. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR)
  999. );
  1000. pdoPartialResourceList[intrChannel]->Count++;
  1001. }
  1002. }
  1003. intrChannel++;
  1004. } else if (partialDescriptors[i].Type == CmResourceTypeDeviceSpecific) {
  1005. partialDescriptors += partialDescriptors[i].u.DeviceSpecificData.DataSize;
  1006. }
  1007. }
  1008. if (bmPartialResourceList->Count) {
  1009. bmResourceList->Count++;
  1010. bmFullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR)
  1011. (bmPartialDescriptors + bmPartialResourceList->Count);
  1012. }
  1013. for (k=0; k<MAX_IDE_CHANNEL; k++) {
  1014. if (pdoPartialResourceList[k]->Count) {
  1015. pdoResourceList[k]->Count++;
  1016. pdoFullResourceList[k] = (PCM_FULL_RESOURCE_DESCRIPTOR)
  1017. (pdoPartialDescriptors[k] + pdoPartialResourceList[k]->Count);
  1018. }
  1019. }
  1020. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + i);
  1021. }
  1022. status = STATUS_SUCCESS;
  1023. for (k=0; k<MAX_IDE_CHANNEL; k++) {
  1024. if (FdoExtension->NativeMode[k]) {
  1025. //
  1026. // If the controller is in native mode, we should have all the resources
  1027. //
  1028. if ((k < cmdChannel) &&
  1029. (k < ctrlChannel) &&
  1030. (k < intrChannel)) {
  1031. //
  1032. // This is good
  1033. //
  1034. } else {
  1035. cmdChannel = 0;
  1036. ctrlChannel = 0;
  1037. intrChannel = 0;
  1038. bmAddr = 0;
  1039. status = STATUS_INSUFFICIENT_RESOURCES;
  1040. }
  1041. }
  1042. }
  1043. //
  1044. // If the controller is in legacy mode, we should not have any resources
  1045. //
  1046. if (!FdoExtension->NativeMode[0] && !FdoExtension->NativeMode[1]) {
  1047. //
  1048. // both channels in legacy mode
  1049. //
  1050. cmdChannel = 0;
  1051. ctrlChannel = 0;
  1052. intrChannel = 0;
  1053. }
  1054. FdoExtension->TranslatedBusMasterBaseAddress = NULL;
  1055. if (0 < bmAddr) {
  1056. FdoExtension->BmResourceList = bmResourceList;
  1057. FdoExtension->BmResourceListSize = (ULONG)(((PUCHAR)bmFullResourceList) - ((PUCHAR)bmResourceList));
  1058. if (FdoExtension->BmResourceList->List[0].PartialResourceList.PartialDescriptors->Type == CmResourceTypePort) {
  1059. //
  1060. // address is in i/o space
  1061. //
  1062. FdoExtension->TranslatedBusMasterBaseAddress =
  1063. (PIDE_BUS_MASTER_REGISTERS) (ULONG_PTR)FdoExtension->BmResourceList->List[0].PartialResourceList.PartialDescriptors->u.Port.Start.QuadPart;
  1064. FdoExtension->BusMasterBaseAddressSpace = IO_SPACE;
  1065. } else if (FdoExtension->BmResourceList->List[0].PartialResourceList.PartialDescriptors->Type == CmResourceTypeMemory) {
  1066. //
  1067. // address is in memory space
  1068. //
  1069. FdoExtension->TranslatedBusMasterBaseAddress =
  1070. (PIDE_BUS_MASTER_REGISTERS) MmMapIoSpace(
  1071. FdoExtension->BmResourceList->List[0].PartialResourceList.PartialDescriptors->u.Port.Start,
  1072. 16,
  1073. FALSE);
  1074. ASSERT (FdoExtension->TranslatedBusMasterBaseAddress);
  1075. // free mapped io resouces in stop/remove device
  1076. // unmapiospace doesn't do anything. it is ok not to call it
  1077. FdoExtension->BusMasterBaseAddressSpace = MEMORY_SPACE;
  1078. } else {
  1079. FdoExtension->TranslatedBusMasterBaseAddress = NULL;
  1080. ASSERT (FALSE);
  1081. }
  1082. }
  1083. if (FdoExtension->TranslatedBusMasterBaseAddress == NULL) {
  1084. ExFreePool (bmResourceList);
  1085. FdoExtension->BmResourceList = bmResourceList = NULL;
  1086. }
  1087. for (k=0; k<MAX_IDE_CHANNEL; k++) {
  1088. if ((k < cmdChannel) ||
  1089. (k < ctrlChannel) ||
  1090. (k < intrChannel)) {
  1091. FdoExtension->PdoResourceList[k] = pdoResourceList[k];
  1092. FdoExtension->PdoResourceListSize[k] = (ULONG)(((PUCHAR)pdoFullResourceList[k]) - ((PUCHAR)pdoResourceList[k]));
  1093. if (k < cmdChannel) {
  1094. FdoExtension->PdoCmdRegResourceFound[k] = TRUE;
  1095. }
  1096. if (k < ctrlChannel) {
  1097. FdoExtension->PdoCtrlRegResourceFound[k] = TRUE;
  1098. }
  1099. if (k < intrChannel) {
  1100. FdoExtension->PdoInterruptResourceFound[k] = TRUE;
  1101. }
  1102. } else {
  1103. ExFreePool (pdoResourceList[k]);
  1104. FdoExtension->PdoResourceList[k] =
  1105. pdoResourceList[k] = NULL;
  1106. }
  1107. }
  1108. return status;
  1109. } // AnalyzeResourceList
  1110. VOID
  1111. ControllerOpMode (
  1112. IN PCTRLFDO_EXTENSION FdoExtension
  1113. )
  1114. {
  1115. NTSTATUS status;
  1116. PCIIDE_CONFIG_HEADER pciIdeConfigHeader;
  1117. PAGED_CODE();
  1118. status = PciIdeBusData(
  1119. FdoExtension,
  1120. &pciIdeConfigHeader,
  1121. 0,
  1122. sizeof (pciIdeConfigHeader),
  1123. TRUE
  1124. );
  1125. FdoExtension->NativeMode[0] = FALSE;
  1126. FdoExtension->NativeMode[1] = FALSE;
  1127. if (NT_SUCCESS(status)) {
  1128. //
  1129. // ISSUE: 02/05/01: This should be removed. In pci we check for sublclass = 0x1
  1130. //
  1131. if ((pciIdeConfigHeader.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
  1132. (pciIdeConfigHeader.SubClass == PCI_SUBCLASS_MSC_RAID_CTLR)) {
  1133. //
  1134. // We have a Promise Technology IDE "raid" controller
  1135. //
  1136. FdoExtension->NativeMode[0] = TRUE;
  1137. FdoExtension->NativeMode[1] = TRUE;
  1138. } else {
  1139. if ((pciIdeConfigHeader.Chan0OpMode) &&
  1140. (pciIdeConfigHeader.Chan1OpMode)) {
  1141. //
  1142. // we can't support a channel being legacy
  1143. // and the other is in native because
  1144. // we don't know what irq is for the native
  1145. // channel
  1146. //
  1147. FdoExtension->NativeMode[0] = TRUE;
  1148. FdoExtension->NativeMode[1] = TRUE;
  1149. }
  1150. }
  1151. //
  1152. // Have to be both TRUE or both FALSE
  1153. //
  1154. ASSERT ((FdoExtension->NativeMode[0] == FALSE) == (FdoExtension->NativeMode[1] == FALSE));
  1155. }
  1156. return;
  1157. } // ControllerOpMode
  1158. VOID
  1159. EnablePCIBusMastering (
  1160. IN PCTRLFDO_EXTENSION FdoExtension
  1161. )
  1162. {
  1163. NTSTATUS status;
  1164. PCIIDE_CONFIG_HEADER pciIdeConfigHeader;
  1165. status = PciIdeBusData(
  1166. FdoExtension,
  1167. &pciIdeConfigHeader,
  1168. 0,
  1169. sizeof (PCIIDE_CONFIG_HEADER),
  1170. TRUE
  1171. );
  1172. //
  1173. // pci bus master disabled?
  1174. //
  1175. if (NT_SUCCESS(status) &&
  1176. pciIdeConfigHeader.MasterIde &&
  1177. !pciIdeConfigHeader.Command.b.MasterEnable) {
  1178. //
  1179. // Try to turn on pci bus mastering
  1180. //
  1181. pciIdeConfigHeader.Command.b.MasterEnable = 1;
  1182. status = PciIdeBusData(
  1183. FdoExtension,
  1184. &pciIdeConfigHeader.Command.w,
  1185. FIELD_OFFSET (PCIIDE_CONFIG_HEADER, Command),
  1186. sizeof (pciIdeConfigHeader.Command.w),
  1187. FALSE
  1188. );
  1189. }
  1190. return;
  1191. } // EnablePCIBusMastering
  1192. #ifdef DBG
  1193. ULONG PciIdeXDebugFakeMissingChild = 0;
  1194. #endif // DBG
  1195. IDE_CHANNEL_STATE
  1196. PciIdeChannelEnabled (
  1197. IN PCTRLFDO_EXTENSION FdoExtension,
  1198. IN ULONG Channel
  1199. )
  1200. {
  1201. NTSTATUS status;
  1202. ULONG longMask;
  1203. UCHAR channelEnableMask;
  1204. ULONG channelEnablePciConfigOffset;
  1205. UCHAR pciConfigData;
  1206. PAGED_CODE();
  1207. #if DBG
  1208. if (PciIdeXDebugFakeMissingChild & 0xff000000) {
  1209. DebugPrint ((0, "PciIdeXDebugFakeMissingChild: fake missing channel 0x%x\n", Channel));
  1210. if ((PciIdeXDebugFakeMissingChild & 0x0000ff) == Channel) {
  1211. PciIdeXDebugFakeMissingChild = 0;
  1212. return ChannelDisabled;
  1213. }
  1214. }
  1215. #endif
  1216. longMask = 0;
  1217. status = PciIdeXGetDeviceParameter (
  1218. FdoExtension->AttacheePdo,
  1219. ChannelEnableMaskName[Channel],
  1220. &longMask
  1221. );
  1222. channelEnableMask = (UCHAR) longMask;
  1223. if (!NT_SUCCESS(status)) {
  1224. DebugPrint ((1, "PciIdeX: Unable to get ChannelEnableMask from the registry\n"));
  1225. } else {
  1226. channelEnablePciConfigOffset = 0;
  1227. status = PciIdeXGetDeviceParameter (
  1228. FdoExtension->AttacheePdo,
  1229. ChannelEnablePciConfigOffsetName[Channel],
  1230. &channelEnablePciConfigOffset
  1231. );
  1232. if (!NT_SUCCESS(status)) {
  1233. DebugPrint ((1, "PciIdeX: Unable to get ChannelEnablePciConfigOffset from the registry\n"));
  1234. } else {
  1235. status = PciIdeBusData(
  1236. FdoExtension,
  1237. &pciConfigData,
  1238. channelEnablePciConfigOffset,
  1239. sizeof (pciConfigData),
  1240. TRUE // Read
  1241. );
  1242. if (NT_SUCCESS(status)) {
  1243. return (pciConfigData & channelEnableMask) ? ChannelEnabled : ChannelDisabled;
  1244. }
  1245. }
  1246. }
  1247. //
  1248. // couldn't figure out whether is channel enabled
  1249. // try the miniport port
  1250. //
  1251. if (FdoExtension->ControllerProperties.PciIdeChannelEnabled) {
  1252. return FdoExtension->ControllerProperties.PciIdeChannelEnabled (
  1253. FdoExtension->VendorSpecificDeviceEntension,
  1254. Channel
  1255. );
  1256. }
  1257. return ChannelStateUnknown;
  1258. } // PciIdeChannelEnabled
  1259. NTSTATUS
  1260. PciIdeCreateTimingTable (
  1261. IN PCTRLFDO_EXTENSION FdoExtension
  1262. )
  1263. {
  1264. PULONG timingTable = NULL;
  1265. PWSTR regTimingList = NULL;
  1266. ULONG i;
  1267. ULONG temp;
  1268. ULONG length = 0;
  1269. NTSTATUS status;
  1270. PAGED_CODE();
  1271. //
  1272. // Try to procure the timing table from the registry
  1273. //
  1274. status = PciIdeXGetDeviceParameterEx (
  1275. FdoExtension->AttacheePdo,
  1276. L"TransferModeTiming",
  1277. &(regTimingList)
  1278. );
  1279. //
  1280. // Fill in the table entries
  1281. //
  1282. if (NT_SUCCESS(status) && regTimingList) {
  1283. PWSTR string = regTimingList;
  1284. UNICODE_STRING unicodeString;
  1285. i=0;
  1286. while (string[0]) {
  1287. RtlInitUnicodeString(
  1288. &unicodeString,
  1289. string
  1290. );
  1291. RtlUnicodeStringToInteger(&unicodeString,10, &temp);
  1292. //
  1293. // The first entry is the length of the table
  1294. //
  1295. if (i==0) {
  1296. length = temp;
  1297. ASSERT(length <=31);
  1298. if (length > 31) {
  1299. length=temp=31;
  1300. }
  1301. //
  1302. // The table should atleast be MAX_XFER_MODE long.
  1303. // if not fill it up with 0s
  1304. //
  1305. if (temp < MAX_XFER_MODE) {
  1306. temp=MAX_XFER_MODE;
  1307. }
  1308. timingTable = ExAllocatePool(NonPagedPool, temp*sizeof(ULONG));
  1309. if (timingTable == NULL) {
  1310. length = 0;
  1311. status = STATUS_INSUFFICIENT_RESOURCES;
  1312. break;
  1313. } else {
  1314. ULONG j;
  1315. //
  1316. // Initialize the known xferModes (default)
  1317. //
  1318. SetDefaultTiming(timingTable, j);
  1319. for (j=MAX_XFER_MODE; j<temp;j++) {
  1320. timingTable[j]=timingTable[MAX_XFER_MODE-1];
  1321. }
  1322. }
  1323. } else {
  1324. if (i > length) {
  1325. DebugPrint((0, "Pciidex: Timing table overflow\n"));
  1326. break;
  1327. }
  1328. //
  1329. // The timings (PIO0-...)
  1330. // Use the default values if the cycletime is 0.
  1331. //
  1332. if (temp) {
  1333. timingTable[i-1]=temp;
  1334. }
  1335. }
  1336. i++;
  1337. string += (unicodeString.Length / sizeof(WCHAR)) + 1;
  1338. }
  1339. if (length < MAX_XFER_MODE) {
  1340. length = MAX_XFER_MODE;
  1341. }
  1342. ExFreePool(regTimingList);
  1343. } else {
  1344. DebugPrint((1, "Pciidex: Unsuccessful regop status %x, regTimingList %x\n",
  1345. status, regTimingList));
  1346. //
  1347. // Nothing in the registry. Fill in the table with known transfer mode
  1348. // timings.
  1349. //
  1350. status = STATUS_SUCCESS;
  1351. timingTable=ExAllocatePool(NonPagedPool, MAX_XFER_MODE*sizeof(ULONG));
  1352. if (timingTable == NULL) {
  1353. length =0;
  1354. status = STATUS_INSUFFICIENT_RESOURCES;
  1355. } else {
  1356. SetDefaultTiming(timingTable, length);
  1357. }
  1358. }
  1359. FdoExtension->TransferModeTimingTable=timingTable;
  1360. FdoExtension->TransferModeTableLength= length;
  1361. /*
  1362. for (i=0;i<FdoExtension->TransferModeTableLength;i++) {
  1363. DebugPrint((0, "Table[%d]=%d\n",
  1364. i,
  1365. FdoExtension->TransferModeTimingTable[i]));
  1366. }
  1367. */
  1368. return status;
  1369. }
  1370. VOID
  1371. PciIdeInitControllerProperties (
  1372. IN PCTRLFDO_EXTENSION FdoExtension
  1373. )
  1374. {
  1375. #if 1
  1376. NTSTATUS status;
  1377. PDRIVER_OBJECT_EXTENSION driverObjectExtension;
  1378. ULONG i, j;
  1379. PAGED_CODE();
  1380. driverObjectExtension =
  1381. (PDRIVER_OBJECT_EXTENSION) IoGetDriverObjectExtension(
  1382. FdoExtension->DriverObject,
  1383. DRIVER_OBJECT_EXTENSION_ID
  1384. );
  1385. ASSERT (driverObjectExtension);
  1386. FdoExtension->ControllerProperties.Size = sizeof (IDE_CONTROLLER_PROPERTIES);
  1387. FdoExtension->ControllerProperties.DefaultPIO = 0;
  1388. status = (*driverObjectExtension->PciIdeGetControllerProperties) (
  1389. FdoExtension->VendorSpecificDeviceEntension,
  1390. &FdoExtension->ControllerProperties
  1391. );
  1392. //
  1393. // Look in the registry to determine whether
  1394. // UDMA 66 should be enabled for INTEL chipsets
  1395. //
  1396. FdoExtension->EnableUDMA66 = 0;
  1397. status = PciIdeXGetDeviceParameter (
  1398. FdoExtension->AttacheePdo,
  1399. L"EnableUDMA66",
  1400. &(FdoExtension->EnableUDMA66)
  1401. );
  1402. #else
  1403. NTSTATUS status;
  1404. PCIIDE_CONFIG_HEADER pciHeader;
  1405. ULONG ultraDmaSupport;
  1406. ULONG xferMode;
  1407. ULONG i;
  1408. ULONG j;
  1409. PAGED_CODE();
  1410. //
  1411. // grab ultra dma flag from the registry
  1412. //
  1413. ultraDmaSupport = 0;
  1414. status = PciIdeXGetDeviceParameter (
  1415. FdoExtension,
  1416. UltraDmaSupport,
  1417. &ultraDmaSupport
  1418. );
  1419. //
  1420. // grab ultra dma flag from the registry
  1421. //
  1422. status = PciIdeXGetBusData (
  1423. FdoExtension,
  1424. &pciHeader,
  1425. 0,
  1426. sizeof (pciHeader)
  1427. );
  1428. if (!NT_SUCCESS(status)) {
  1429. //
  1430. // could get the pci config data, fake it
  1431. //
  1432. pciHeader.MasterIde = 0;
  1433. pciHeader.Command.b.MasterEnable = 0;
  1434. }
  1435. xferMode = PIO_SUPPORT;
  1436. if (pciHeader.MasterIde && pciHeader.Command.b.MasterEnable) {
  1437. xferMode |= SWDMA_SUPPORT | MWDMA_SUPPORT;
  1438. if (ultraDmaSupport) {
  1439. xferMode |= UDMA_SUPPORT;
  1440. }
  1441. }
  1442. for (i=0; i<MAX_IDE_CHANNEL; i++) {
  1443. for (i=0; i<MAX_IDE_DEVICE; i++) {
  1444. FdoExtension->ControllerProperties.SupportedTransferMode[i][j] = xferMode;
  1445. }
  1446. }
  1447. #endif
  1448. } // PciIdeInitControllerProperties
  1449. NTSTATUS
  1450. ControllerUsageNotification (
  1451. IN PDEVICE_OBJECT DeviceObject,
  1452. IN OUT PIRP Irp
  1453. )
  1454. {
  1455. PCTRLFDO_EXTENSION fdoExtension;
  1456. PIO_STACK_LOCATION irpSp;
  1457. PULONG deviceUsageCount;
  1458. ASSERT (DeviceObject);
  1459. ASSERT (Irp);
  1460. PAGED_CODE();
  1461. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  1462. ASSERT (fdoExtension);
  1463. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1464. if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
  1465. //
  1466. // Adjust the paging path count for this device.
  1467. //
  1468. deviceUsageCount = &fdoExtension->PagingPathCount;
  1469. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
  1470. //
  1471. // Adjust the paging path count for this device.
  1472. //
  1473. deviceUsageCount = &fdoExtension->HiberPathCount;
  1474. } else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
  1475. //
  1476. // Adjust the paging path count for this device.
  1477. //
  1478. deviceUsageCount = &fdoExtension->CrashDumpPathCount;
  1479. } else {
  1480. deviceUsageCount = NULL;
  1481. DebugPrint ((0,
  1482. "PCIIDEX: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n",
  1483. irpSp->Parameters.UsageNotification.Type));
  1484. }
  1485. IoCopyCurrentIrpStackLocationToNext (Irp);
  1486. IoSetCompletionRoutine (
  1487. Irp,
  1488. ControllerUsageNotificationCompletionRoutine,
  1489. deviceUsageCount,
  1490. TRUE,
  1491. TRUE,
  1492. TRUE);
  1493. ASSERT(fdoExtension->AttacheeDeviceObject);
  1494. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  1495. } // ControllerUsageNotification
  1496. NTSTATUS
  1497. ControllerUsageNotificationCompletionRoutine (
  1498. IN PDEVICE_OBJECT DeviceObject,
  1499. IN PIRP Irp,
  1500. IN PVOID Context
  1501. )
  1502. {
  1503. PCTRLFDO_EXTENSION fdoExtension;
  1504. PIO_STACK_LOCATION irpSp;
  1505. PULONG deviceUsageCount = Context;
  1506. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  1507. ASSERT (fdoExtension);
  1508. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1509. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  1510. if (deviceUsageCount) {
  1511. IoAdjustPagingPathCount (
  1512. deviceUsageCount,
  1513. irpSp->Parameters.UsageNotification.InPath
  1514. );
  1515. }
  1516. }
  1517. return Irp->IoStatus.Status;
  1518. } // ControllerUsageNotificationCompletionRoutine
  1519. NTSTATUS
  1520. PciIdeGetBusStandardInterface(
  1521. IN PCTRLFDO_EXTENSION FdoExtension
  1522. )
  1523. /*++
  1524. Routine Description:
  1525. This routine gets the bus iterface standard information from the PDO.
  1526. Arguments:
  1527. Return Value:
  1528. NT status.
  1529. --*/
  1530. {
  1531. KEVENT event;
  1532. NTSTATUS status;
  1533. PIRP irp;
  1534. IO_STATUS_BLOCK ioStatusBlock;
  1535. PIO_STACK_LOCATION irpStack;
  1536. KeInitializeEvent( &event, NotificationEvent, FALSE );
  1537. irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
  1538. FdoExtension->AttacheeDeviceObject,
  1539. NULL,
  1540. 0,
  1541. NULL,
  1542. &event,
  1543. &ioStatusBlock );
  1544. if (irp == NULL) {
  1545. return STATUS_INSUFFICIENT_RESOURCES;
  1546. }
  1547. irpStack = IoGetNextIrpStackLocation( irp );
  1548. irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  1549. irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
  1550. irpStack->Parameters.QueryInterface.Size = sizeof( BUS_INTERFACE_STANDARD );
  1551. irpStack->Parameters.QueryInterface.Version = 1;
  1552. irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->BusInterface;
  1553. irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1554. //
  1555. // Initialize the status to error in case the ACPI driver decides not to
  1556. // set it correctly.
  1557. //
  1558. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1559. status = IoCallDriver(FdoExtension->AttacheeDeviceObject, irp);
  1560. if (!NT_SUCCESS( status)) {
  1561. return status;
  1562. }
  1563. if (status == STATUS_PENDING) {
  1564. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  1565. }
  1566. if (NT_SUCCESS(ioStatusBlock.Status)) {
  1567. ASSERT (FdoExtension->BusInterface.SetBusData);
  1568. ASSERT (FdoExtension->BusInterface.GetBusData);
  1569. }
  1570. return ioStatusBlock.Status;
  1571. }
  1572. NTSTATUS
  1573. ControllerQueryPnPDeviceState (
  1574. IN PDEVICE_OBJECT DeviceObject,
  1575. IN OUT PIRP Irp
  1576. )
  1577. {
  1578. PCTRLFDO_EXTENSION fdoExtension;
  1579. PPNP_DEVICE_STATE deviceState;
  1580. fdoExtension = (PCTRLFDO_EXTENSION) DeviceObject->DeviceExtension;
  1581. DebugPrint((2, "QUERY_DEVICE_STATE for FDOE 0x%x\n", fdoExtension));
  1582. if(fdoExtension->PagingPathCount != 0) {
  1583. deviceState = (PPNP_DEVICE_STATE) &(Irp->IoStatus.Information);
  1584. SETMASK((*deviceState), PNP_DEVICE_NOT_DISABLEABLE);
  1585. }
  1586. Irp->IoStatus.Status = STATUS_SUCCESS;
  1587. IoSkipCurrentIrpStackLocation (Irp);
  1588. return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  1589. } // ControllerQueryPnPDeviceState
  1590. #ifdef ENABLE_NATIVE_MODE
  1591. NTSTATUS
  1592. ControllerInterruptControl (
  1593. IN PCTRLFDO_EXTENSION FdoExtension,
  1594. IN ULONG Channel,
  1595. IN ULONG Disconnect
  1596. )
  1597. {
  1598. NTSTATUS status;
  1599. PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors;
  1600. PCM_RESOURCE_LIST resourceListForKeep = NULL;
  1601. ULONG i;
  1602. status = STATUS_SUCCESS;
  1603. if (Disconnect) {
  1604. DebugPrint((1, "PciIdex: Interrupt control for %x - disconnect\n", Channel));
  1605. //
  1606. // Disconnect the ISR
  1607. //
  1608. if ( (FdoExtension->InterruptObject[Channel])) {
  1609. IoDisconnectInterrupt (
  1610. FdoExtension->InterruptObject[Channel]
  1611. );
  1612. FdoExtension->InterruptObject[Channel] = 0;
  1613. }
  1614. } else {
  1615. //
  1616. // connect the ISR
  1617. //
  1618. PPCIIDE_INTERRUPT_CONTEXT context;
  1619. DebugPrint((1, "PciIdex: Interrupt control for %x - reconnect\n", Channel));
  1620. irqPartialDescriptors = FdoExtension->IrqPartialDescriptors[Channel];
  1621. if (!irqPartialDescriptors) {
  1622. return STATUS_UNSUCCESSFUL;
  1623. }
  1624. //
  1625. // Fill in the context
  1626. //
  1627. context = (PPCIIDE_INTERRUPT_CONTEXT) &(FdoExtension->InterruptContext[Channel]);
  1628. context->DeviceExtension = (PVOID)FdoExtension;
  1629. context->ChannelNumber = Channel;
  1630. status = IoConnectInterrupt(&FdoExtension->InterruptObject[Channel],
  1631. (PKSERVICE_ROUTINE) ControllerInterrupt,
  1632. (PVOID) context,
  1633. (PKSPIN_LOCK) NULL,
  1634. irqPartialDescriptors->u.Interrupt.Vector,
  1635. (KIRQL) irqPartialDescriptors->u.Interrupt.Level,
  1636. (KIRQL) irqPartialDescriptors->u.Interrupt.Level,
  1637. irqPartialDescriptors->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive,
  1638. (BOOLEAN) (irqPartialDescriptors->ShareDisposition == CmResourceShareShared),
  1639. irqPartialDescriptors->u.Interrupt.Affinity,
  1640. FALSE);
  1641. if (!NT_SUCCESS(status)) {
  1642. DebugPrint((1,
  1643. "PciIde: Can't connect interrupt %d\n",
  1644. irqPartialDescriptors->u.Interrupt.Vector));
  1645. FdoExtension->InterruptObject[Channel] = NULL;
  1646. }
  1647. }
  1648. return status;
  1649. }
  1650. #define SelectDevice(BaseIoAddress, deviceNumber, additional) \
  1651. WRITE_PORT_UCHAR ((BaseIoAddress)->DriveSelect, (UCHAR)((((deviceNumber) & 0x1) << 4) | 0xA0 | additional))
  1652. BOOLEAN
  1653. ControllerInterrupt(
  1654. IN PKINTERRUPT Interrupt,
  1655. PVOID Context
  1656. )
  1657. {
  1658. UCHAR statusByte;
  1659. PPCIIDE_INTERRUPT_CONTEXT context = Context;
  1660. PCTRLFDO_EXTENSION fdoExtension = context->DeviceExtension;
  1661. ULONG channel = context->ChannelNumber;
  1662. PIDE_REGISTERS_1 baseIoAddress1 = &(fdoExtension->BaseIoAddress1[channel]);
  1663. BOOLEAN interruptCleared = FALSE;
  1664. DebugPrint((1, "Pciidex: ISR called for channel %d\n", channel));
  1665. //
  1666. // Check if the interrupts are enabled.
  1667. // Don't enable the interrupts if both the isrs are not installed
  1668. //
  1669. if (!fdoExtension->NativeInterruptEnabled) {
  1670. if (fdoExtension->ControllerIsrInstalled) {
  1671. //
  1672. // we have just connected the ISRs. At this point we don't know whether
  1673. // we actually enabled the decodes or not. So enable the decodes and set the
  1674. // flag
  1675. //
  1676. //
  1677. // if this fails we already bugchecked.
  1678. //
  1679. ControllerEnableInterrupt(fdoExtension);
  1680. fdoExtension->NativeInterruptEnabled = TRUE;
  1681. } else {
  1682. //
  1683. // cannot be us
  1684. //
  1685. return FALSE;
  1686. }
  1687. } else {
  1688. if (!fdoExtension->ControllerIsrInstalled) {
  1689. //
  1690. // At this point we don't know whether the decodes are disabled or not. We should
  1691. // enable them.
  1692. //
  1693. //
  1694. // if this fails we already bugchecked.
  1695. //
  1696. ControllerEnableInterrupt(fdoExtension);
  1697. //
  1698. // Now fall thru and determine whether it is our interrupt.
  1699. // we will disable the decodes after that.
  1700. //
  1701. } else {
  1702. //
  1703. // all is well. Go process the interrupt.
  1704. //
  1705. }
  1706. }
  1707. //
  1708. // Both the ISRs should be installed and the interrupts should
  1709. // be enabled at this point
  1710. //
  1711. ASSERT(fdoExtension->NativeInterruptEnabled);
  1712. // ControllerIsrInstalled need not be set.
  1713. // if we get called, then it means that we are still connected
  1714. // however, if the flag ControllerIsrInstalled is not set, then it is
  1715. // safe to assume that we are in the process of stopping the controller.
  1716. // Just dismiss the interrupt, the normal way. We are yet to turn off the decodes.
  1717. //
  1718. //
  1719. // Clear interrupt by reading status.
  1720. //
  1721. GetStatus(baseIoAddress1, statusByte);
  1722. //
  1723. // Check the Bus master registers
  1724. //
  1725. if (!fdoExtension->NoBusMaster[channel]) {
  1726. BMSTATUS bmStatus;
  1727. PIDE_BUS_MASTER_REGISTERS bmRegister;
  1728. //
  1729. // Get the correct bus master register
  1730. //
  1731. bmRegister = (PIDE_BUS_MASTER_REGISTERS)(((PUCHAR)fdoExtension->TranslatedBusMasterBaseAddress) + channel*8);
  1732. bmStatus = READ_PORT_UCHAR (&bmRegister->Status);
  1733. DebugPrint((1, "BmStatus = 0x%x\n", bmStatus));
  1734. //
  1735. // is Interrupt bit set?
  1736. //
  1737. if (bmStatus & BMSTATUS_INTERRUPT) {
  1738. WRITE_PORT_UCHAR (&bmRegister->Command, 0x0); // disable BM
  1739. WRITE_PORT_UCHAR (&bmRegister->Status, BUSMASTER_INTERRUPT); // clear interrupt BM
  1740. interruptCleared = TRUE;
  1741. }
  1742. }
  1743. DebugPrint((1, "ISR for %d returning %d\n", channel, interruptCleared?1:0));
  1744. //
  1745. // NativeInterruptEnabled should be set at this point
  1746. //
  1747. if (!fdoExtension->ControllerIsrInstalled) {
  1748. // we are in the stop or remove code path where this flag has been cleared and
  1749. // we are about to disconnect the ISR. Disable the decodes.
  1750. //
  1751. ControllerDisableInterrupt(fdoExtension);
  1752. //
  1753. // we have dismissed our interrupt. Now clear the interruptEnabled flag.
  1754. //
  1755. fdoExtension->NativeInterruptEnabled = FALSE;
  1756. //
  1757. // return InterruptCleared.
  1758. //
  1759. }
  1760. return interruptCleared;
  1761. }
  1762. /***
  1763. NTSTATUS
  1764. ControllerEnableDecode(
  1765. IN PCTRLFDO_EXTENSION FdoExtension,
  1766. IN BOOLEAN Enable
  1767. )
  1768. {
  1769. USHORT cmd;
  1770. NTSTATUS status;
  1771. PCIIDE_CONFIG_HEADER pciIdeConfigHeader;
  1772. status = PciIdeBusData(
  1773. FdoExtension,
  1774. &pciIdeConfigHeader,
  1775. 0,
  1776. sizeof (PCIIDE_CONFIG_HEADER),
  1777. TRUE
  1778. );
  1779. //
  1780. // get pci command register
  1781. //
  1782. if (!NT_SUCCESS(status)) {
  1783. return status;
  1784. }
  1785. cmd = pciIdeConfigHeader.Command.w;
  1786. cmd &= ~(PCI_ENABLE_IO_SPACE |
  1787. PCI_ENABLE_MEMORY_SPACE |
  1788. PCI_ENABLE_BUS_MASTER);
  1789. if (Enable) {
  1790. //
  1791. // Set enables
  1792. //
  1793. cmd |= (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER);
  1794. }
  1795. //
  1796. // Set the new command register into the device.
  1797. //
  1798. status = PciIdeBusData(
  1799. FdoExtension,
  1800. &cmd,
  1801. FIELD_OFFSET (PCIIDE_CONFIG_HEADER, Command),
  1802. sizeof (pciIdeConfigHeader.Command.w),
  1803. FALSE
  1804. );
  1805. return status;
  1806. }
  1807. **/
  1808. NTSTATUS
  1809. PciIdeGetNativeModeInterface(
  1810. IN PCTRLFDO_EXTENSION FdoExtension
  1811. )
  1812. /*++
  1813. Routine Description:
  1814. This routine gets the native ide iterface information from the PDO.
  1815. Arguments:
  1816. Return Value:
  1817. NT status.
  1818. --*/
  1819. {
  1820. KEVENT event;
  1821. NTSTATUS status;
  1822. PIRP irp;
  1823. IO_STATUS_BLOCK ioStatusBlock;
  1824. PIO_STACK_LOCATION irpStack;
  1825. KeInitializeEvent( &event, NotificationEvent, FALSE );
  1826. irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
  1827. FdoExtension->AttacheeDeviceObject,
  1828. NULL,
  1829. 0,
  1830. NULL,
  1831. &event,
  1832. &ioStatusBlock );
  1833. if (irp == NULL) {
  1834. return STATUS_INSUFFICIENT_RESOURCES;
  1835. }
  1836. irpStack = IoGetNextIrpStackLocation( irp );
  1837. irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  1838. irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCI_NATIVE_IDE_INTERFACE;
  1839. irpStack->Parameters.QueryInterface.Size = sizeof( PCI_NATIVE_IDE_INTERFACE );
  1840. irpStack->Parameters.QueryInterface.Version = 1;
  1841. irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->NativeIdeInterface;
  1842. irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  1843. //
  1844. // Initialize the status to error in case the ACPI driver decides not to
  1845. // set it correctly.
  1846. //
  1847. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1848. status = IoCallDriver(FdoExtension->AttacheeDeviceObject, irp);
  1849. if (!NT_SUCCESS( status)) {
  1850. return status;
  1851. }
  1852. if (status == STATUS_PENDING) {
  1853. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  1854. }
  1855. if (NT_SUCCESS(ioStatusBlock.Status)) {
  1856. ASSERT (FdoExtension->NativeIdeInterface.InterruptControl);
  1857. }
  1858. return ioStatusBlock.Status;
  1859. }
  1860. #endif