Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3378 lines
111 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. atapinit.c
  5. Abstract:
  6. This contain routine to enumrate IDE devices on the IDE bus
  7. Author:
  8. Joe Dai (joedai)
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "ideport.h"
  15. extern PULONG InitSafeBootMode; // imported from NTOS (init.c), must use a pointer to reference the data
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, IdePortInitHwDeviceExtension)
  18. #pragma alloc_text(PAGE, AtapiDetectDevice)
  19. #pragma alloc_text(PAGE, IdePreAllocEnumStructs)
  20. #pragma alloc_text(PAGE, IdeFreeEnumStructs)
  21. #pragma alloc_text(NONPAGE, AtapiSyncSelectTransferMode)
  22. #pragma alloc_text(PAGESCAN, AnalyzeDeviceCapabilities)
  23. #pragma alloc_text(PAGESCAN, AtapiDMACapable)
  24. #pragma alloc_text(PAGESCAN, IdePortSelectCHS)
  25. #pragma alloc_text(PAGESCAN, IdePortScanBus)
  26. LONG IdePAGESCANLockCount = 0;
  27. #endif // ALLOC_PRAGMA
  28. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  29. static PWCHAR IdePortBootTimeRegKey[6]= {
  30. L"IdeBusResetTime",
  31. L"IdeEmptyChannelCheckTime",
  32. L"IdeDetectMasterDeviceTime",
  33. L"IdeDetectSlaveDeviceTime",
  34. L"IdeCriticalSectionTime",
  35. L"IdeLastStageScanTime"
  36. };
  37. #endif
  38. static PWCHAR IdePortRegistryDeviceTimeout[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  39. MASTER_DEVICE_TIMEOUT,
  40. SLAVE_DEVICE_TIMEOUT
  41. };
  42. static PWCHAR IdePortRegistryDeviceTypeName[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  43. MASTER_DEVICE_TYPE_REG_KEY,
  44. SLAVE_DEVICE_TYPE_REG_KEY,
  45. MASTER_DEVICE_TYPE2_REG_KEY,
  46. SLAVE_DEVICE_TYPE2_REG_KEY
  47. };
  48. static PWCHAR IdePortRegistryDeviceTimingModeName[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  49. MASTER_DEVICE_TIMING_MODE,
  50. SLAVE_DEVICE_TIMING_MODE,
  51. MASTER_DEVICE_TIMING_MODE2,
  52. SLAVE_DEVICE_TIMING_MODE2
  53. };
  54. static PWCHAR IdePortRegistryDeviceTimingModeAllowedName[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  55. MASTER_DEVICE_TIMING_MODE_ALLOWED,
  56. SLAVE_DEVICE_TIMING_MODE_ALLOWED,
  57. MASTER_DEVICE_TIMING_MODE_ALLOWED2,
  58. SLAVE_DEVICE_TIMING_MODE_ALLOWED2
  59. };
  60. static PWCHAR IdePortRegistryIdentifyDataChecksum[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  61. MASTER_IDDATA_CHECKSUM,
  62. SLAVE_IDDATA_CHECKSUM,
  63. MASTER_IDDATA_CHECKSUM2,
  64. SLAVE_IDDATA_CHECKSUM2
  65. };
  66. static PWCHAR IdePortUserRegistryDeviceTypeName[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  67. USER_MASTER_DEVICE_TYPE_REG_KEY,
  68. USER_SLAVE_DEVICE_TYPE_REG_KEY,
  69. USER_MASTER_DEVICE_TYPE2_REG_KEY,
  70. USER_SLAVE_DEVICE_TYPE2_REG_KEY
  71. };
  72. static PWCHAR IdePortRegistryUserDeviceTimingModeAllowedName[MAX_IDE_DEVICE * MAX_IDE_LINE] = {
  73. USER_MASTER_DEVICE_TIMING_MODE_ALLOWED,
  74. USER_SLAVE_DEVICE_TIMING_MODE_ALLOWED,
  75. USER_MASTER_DEVICE_TIMING_MODE_ALLOWED2,
  76. USER_SLAVE_DEVICE_TIMING_MODE_ALLOWED2
  77. };
  78. VOID
  79. AnalyzeDeviceCapabilities(
  80. IN OUT PFDO_EXTENSION FdoExtension,
  81. IN BOOLEAN MustBePio[MAX_IDE_DEVICE * MAX_IDE_LINE]
  82. )
  83. /*++
  84. Routine Description:
  85. software-initialize devices on the ide bus
  86. figure out
  87. if the attached devices are dma capable
  88. if the attached devices are LBA ready
  89. Arguments:
  90. HwDeviceExtension - HW Device Extension
  91. Return Value:
  92. none
  93. --*/
  94. {
  95. PHW_DEVICE_EXTENSION deviceExtension = FdoExtension->HwDeviceExtension;
  96. ULONG deviceNumber;
  97. BOOLEAN pioDevicePresent;
  98. PIDENTIFY_DATA identifyData;
  99. struct _DEVICE_PARAMETERS * deviceParameters;
  100. ULONG cycleTime;
  101. ULONG xferMode;
  102. ULONG bestXferMode;
  103. ULONG currentMode;
  104. ULONG tempMode;
  105. ULONG numberOfCylinders;
  106. ULONG numberOfHeads;
  107. ULONG sectorsPerTrack;
  108. PULONG TransferModeTimingTable=FdoExtension->TransferModeInterface.TransferModeTimingTable;
  109. ULONG transferModeTableLength=FdoExtension->TransferModeInterface.TransferModeTableLength;
  110. ASSERT(TransferModeTimingTable);
  111. //
  112. // Code is paged until locked down.
  113. //
  114. PAGED_CODE();
  115. #ifdef ALLOC_PRAGMA
  116. ASSERT(IdePAGESCANLockCount > 0);
  117. #endif
  118. //
  119. // Figure out who can do DMA and who cannot
  120. //
  121. for (deviceNumber = 0; deviceNumber < deviceExtension->MaxIdeDevice; deviceNumber++) {
  122. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT) {
  123. //
  124. // check LBA capabilities
  125. //
  126. CLRMASK (deviceExtension->DeviceFlags[deviceNumber], DFLAGS_LBA);
  127. // Some drives lie about their ability to do LBA
  128. // we don't want to do LBA unless we have to (>8G drive)
  129. if (deviceExtension->IdentifyData[deviceNumber].UserAddressableSectors > MAX_NUM_CHS_ADDRESSABLE_SECTORS) {
  130. // some device has a bogus value in the UserAddressableSectors field
  131. // make sure these 3 fields are max. out as defined in ATA-3 (X3T10 Rev. 6)
  132. if ((deviceExtension->IdentifyData[deviceNumber].NumCylinders == 16383) &&
  133. (deviceExtension->IdentifyData[deviceNumber].NumHeads<= 16) &&
  134. (deviceExtension->IdentifyData[deviceNumber].NumSectorsPerTrack== 63)) {
  135. deviceExtension->DeviceFlags[deviceNumber] |= DFLAGS_LBA;
  136. }
  137. if (!Is98LegacyIde(&deviceExtension->BaseIoAddress1)) {
  138. //
  139. // words 1, 3 and 6
  140. //
  141. numberOfCylinders = deviceExtension->IdentifyData[deviceNumber].NumCylinders;
  142. numberOfHeads = deviceExtension->IdentifyData[deviceNumber].NumHeads;
  143. sectorsPerTrack = deviceExtension->IdentifyData[deviceNumber].NumSectorsPerTrack;
  144. if (deviceExtension->IdentifyData[deviceNumber].UserAddressableSectors >
  145. (numberOfCylinders * numberOfHeads * sectorsPerTrack)) {
  146. //
  147. // some ide driver has a 2G jumer to get around bios
  148. // problem. make sure we are not tricked the same way.
  149. //
  150. if ((numberOfCylinders <= 0xfff) &&
  151. (numberOfHeads == 0x10) &&
  152. (sectorsPerTrack == 0x3f)) {
  153. deviceExtension->DeviceFlags[deviceNumber] |= DFLAGS_LBA;
  154. }
  155. }
  156. }
  157. }
  158. #ifdef ENABLE_48BIT_LBA
  159. {
  160. USHORT commandSetSupport = deviceExtension->IdentifyData[deviceNumber].CommandSetSupport;
  161. USHORT commandSetActive = deviceExtension->IdentifyData[deviceNumber].CommandSetActive;
  162. if ((commandSetSupport & IDE_IDDATA_48BIT_LBA_SUPPORT) &&
  163. (commandSetActive & IDE_IDDATA_48BIT_LBA_SUPPORT)) {
  164. ULONG maxLBA;
  165. //
  166. // get words 100-103 and make sure that it is the same or
  167. // greater than words 57-58.
  168. //
  169. ASSERT(deviceExtension->IdentifyData[deviceNumber].Max48BitLBA[0] != 0);
  170. maxLBA = deviceExtension->IdentifyData[deviceNumber].Max48BitLBA[0];
  171. ASSERT(deviceExtension->IdentifyData[deviceNumber].Max48BitLBA[1] == 0);
  172. ASSERT(maxLBA >= deviceExtension->IdentifyData[deviceNumber].UserAddressableSectors);
  173. DebugPrint((0,
  174. "Max LBA supported is 0x%x\n",
  175. maxLBA
  176. ));
  177. if ((FdoExtension->EnableBigLba == 1) &&
  178. (maxLBA >= MAX_28BIT_LBA)) {
  179. deviceExtension->DeviceFlags[deviceNumber] |= DFLAGS_48BIT_LBA;
  180. deviceExtension->DeviceFlags[deviceNumber] |= DFLAGS_LBA;
  181. } else {
  182. DebugPrint((1, "big lba disabled\n"));
  183. }
  184. }
  185. }
  186. #endif
  187. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_LBA) {
  188. DebugPrint ((DBG_BUSSCAN, "atapi: target %d supports LBA\n", deviceNumber));
  189. }
  190. xferMode = 0;
  191. cycleTime = UNINITIALIZED_CYCLE_TIME;
  192. bestXferMode = 0;
  193. //
  194. // check for IoReady Line
  195. //
  196. if (deviceExtension->IdentifyData[deviceNumber].Capabilities & IDENTIFY_CAPABILITIES_IOREADY_SUPPORTED) {
  197. deviceExtension->DeviceParameters[deviceNumber].IoReadyEnabled = TRUE;
  198. } else {
  199. deviceExtension->DeviceParameters[deviceNumber].IoReadyEnabled = FALSE;
  200. }
  201. //
  202. // Check for PIO mode
  203. //
  204. bestXferMode = (deviceExtension->IdentifyData[deviceNumber].PioCycleTimingMode & 0x00ff)+PIO0;
  205. if (bestXferMode > PIO2) {
  206. bestXferMode = PIO0;
  207. }
  208. ASSERT(bestXferMode < PIO3);
  209. cycleTime = TransferModeTimingTable[bestXferMode];
  210. ASSERT(cycleTime);
  211. GenTransferModeMask(bestXferMode, xferMode);
  212. currentMode = 1<<bestXferMode;
  213. if (deviceExtension->IdentifyData[deviceNumber].TranslationFieldsValid & (1 << 1)) {
  214. if (deviceExtension->DeviceParameters[deviceNumber].IoReadyEnabled) {
  215. cycleTime = deviceExtension->IdentifyData[deviceNumber].MinimumPIOCycleTimeIORDY;
  216. } else {
  217. cycleTime = deviceExtension->IdentifyData[deviceNumber].MinimumPIOCycleTime;
  218. }
  219. if (deviceExtension->IdentifyData[deviceNumber].AdvancedPIOModes & (1 << 0)) {
  220. xferMode |= PIO_MODE3;
  221. bestXferMode = 3;
  222. currentMode = PIO_MODE3;
  223. }
  224. if (deviceExtension->IdentifyData[deviceNumber].AdvancedPIOModes & (1 << 1)) {
  225. xferMode |= PIO_MODE4;
  226. bestXferMode = 4;
  227. currentMode = PIO_MODE4;
  228. }
  229. // check if any of the bits > 1 are set. If so, default to PIO_MODE4
  230. if (deviceExtension->IdentifyData[deviceNumber].AdvancedPIOModes) {
  231. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].AdvancedPIOModes,
  232. bestXferMode);
  233. bestXferMode += PIO3;
  234. if (bestXferMode > PIO4) {
  235. DebugPrint((DBG_ALWAYS,
  236. "ATAPI: AdvancePIOMode > PIO_MODE4. Defaulting to PIO_MODE4. \n"));
  237. bestXferMode = PIO4;
  238. }
  239. currentMode = 1<<bestXferMode;
  240. xferMode |= currentMode;
  241. }
  242. DebugPrint ((DBG_BUSSCAN,
  243. "atapi: target %d IdentifyData AdvancedPIOModes = 0x%x\n",
  244. deviceNumber,
  245. deviceExtension->IdentifyData[deviceNumber].AdvancedPIOModes));
  246. }
  247. ASSERT (cycleTime != UNINITIALIZED_CYCLE_TIME);
  248. ASSERT (xferMode);
  249. ASSERT (currentMode);
  250. deviceExtension->DeviceParameters[deviceNumber].BestPioCycleTime = cycleTime;
  251. deviceExtension->DeviceParameters[deviceNumber].BestPioMode = bestXferMode;
  252. //
  253. // can't really figure out the current PIO mode
  254. // just use the best mode
  255. //
  256. deviceExtension->DeviceParameters[deviceNumber].TransferModeCurrent = currentMode;
  257. //
  258. // figure out all the DMA transfer mode this device supports
  259. //
  260. currentMode = 0;
  261. //
  262. // check singleword DMA timing
  263. //
  264. cycleTime = UNINITIALIZED_CYCLE_TIME;
  265. bestXferMode = UNINITIALIZED_TRANSFER_MODE;
  266. if (deviceExtension->IdentifyData[deviceNumber].SingleWordDMASupport) {
  267. DebugPrint ((DBG_BUSSCAN,
  268. "atapi: target %d IdentifyData SingleWordDMASupport = 0x%x\n",
  269. deviceNumber,
  270. deviceExtension->IdentifyData[deviceNumber].SingleWordDMASupport));
  271. DebugPrint ((DBG_BUSSCAN,
  272. "atapi: target %d IdentifyData SingleWordDMAActive = 0x%x\n",
  273. deviceNumber,
  274. deviceExtension->IdentifyData[deviceNumber].SingleWordDMAActive));
  275. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].SingleWordDMASupport,
  276. bestXferMode);
  277. if ((bestXferMode+SWDMA0) > SWDMA2) {
  278. bestXferMode = SWDMA2-SWDMA0;
  279. }
  280. cycleTime = TransferModeTimingTable[bestXferMode+SWDMA0];
  281. ASSERT(cycleTime);
  282. tempMode = 0;
  283. GenTransferModeMask(bestXferMode, tempMode);
  284. xferMode |= (tempMode << SWDMA0);
  285. if (deviceExtension->IdentifyData[deviceNumber].SingleWordDMAActive) {
  286. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].SingleWordDMAActive,
  287. currentMode);
  288. if ((currentMode+SWDMA0) > SWDMA2) {
  289. currentMode = SWDMA2 - SWDMA0;
  290. }
  291. currentMode = 1 << (currentMode+SWDMA0);
  292. }
  293. }
  294. deviceExtension->DeviceParameters[deviceNumber].BestSwDmaCycleTime = cycleTime;
  295. deviceExtension->DeviceParameters[deviceNumber].BestSwDmaMode = bestXferMode;
  296. //
  297. // check multiword DMA timing
  298. //
  299. cycleTime = UNINITIALIZED_CYCLE_TIME;
  300. bestXferMode = UNINITIALIZED_TRANSFER_MODE;
  301. if (deviceExtension->IdentifyData[deviceNumber].MultiWordDMASupport) {
  302. DebugPrint ((DBG_BUSSCAN,
  303. "atapi: target %d IdentifyData MultiWordDMASupport = 0x%x\n",
  304. deviceNumber,
  305. deviceExtension->IdentifyData[deviceNumber].MultiWordDMASupport));
  306. DebugPrint ((DBG_BUSSCAN,
  307. "atapi: target %d IdentifyData MultiWordDMAActive = 0x%x\n",
  308. deviceNumber,
  309. deviceExtension->IdentifyData[deviceNumber].MultiWordDMAActive));
  310. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].MultiWordDMASupport,
  311. bestXferMode);
  312. if ((bestXferMode+MWDMA0) > MWDMA2) {
  313. bestXferMode = MWDMA2 - MWDMA0;
  314. }
  315. cycleTime = TransferModeTimingTable[bestXferMode+MWDMA0];
  316. ASSERT(cycleTime);
  317. tempMode = 0;
  318. GenTransferModeMask(bestXferMode, tempMode);
  319. xferMode |= (tempMode << MWDMA0);
  320. if (deviceExtension->IdentifyData[deviceNumber].MultiWordDMAActive) {
  321. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].MultiWordDMAActive,
  322. currentMode);
  323. if ((currentMode+MWDMA0) > MWDMA2) {
  324. currentMode = MWDMA2 - MWDMA0;
  325. }
  326. currentMode = 1 << (currentMode+MWDMA0);
  327. }
  328. }
  329. if (deviceExtension->IdentifyData[deviceNumber].TranslationFieldsValid & (1 << 1)) {
  330. DebugPrint ((DBG_BUSSCAN, "atapi: target %d IdentifyData word 64-70 are valid\n", deviceNumber));
  331. if (deviceExtension->IdentifyData[deviceNumber].MinimumMWXferCycleTime &&
  332. deviceExtension->IdentifyData[deviceNumber].RecommendedMWXferCycleTime) {
  333. DebugPrint ((DBG_BUSSCAN,
  334. "atapi: target %d IdentifyData MinimumMWXferCycleTime = 0x%x\n",
  335. deviceNumber,
  336. deviceExtension->IdentifyData[deviceNumber].MinimumMWXferCycleTime));
  337. DebugPrint ((DBG_BUSSCAN,
  338. "atapi: target %d IdentifyData RecommendedMWXferCycleTime = 0x%x\n",
  339. deviceNumber,
  340. deviceExtension->IdentifyData[deviceNumber].RecommendedMWXferCycleTime));
  341. cycleTime = deviceExtension->IdentifyData[deviceNumber].MinimumMWXferCycleTime;
  342. }
  343. }
  344. deviceExtension->DeviceParameters[deviceNumber].BestMwDmaCycleTime = cycleTime;
  345. deviceExtension->DeviceParameters[deviceNumber].BestMwDmaMode = bestXferMode;
  346. //
  347. // figure out the ultra DMA timing the device supports
  348. //
  349. cycleTime = UNINITIALIZED_CYCLE_TIME;
  350. bestXferMode = UNINITIALIZED_TRANSFER_MODE;
  351. tempMode = UNINITIALIZED_TRANSFER_MODE; // to set the current mode correctly
  352. //
  353. // Consult the channel driver for the UDMA modes that are supported.
  354. // This will allow new udma modes to be supported. Always trust this funtion.
  355. //
  356. if (FdoExtension->TransferModeInterface.UdmaModesSupported) {
  357. NTSTATUS status = FdoExtension->TransferModeInterface.UdmaModesSupported (
  358. deviceExtension->IdentifyData[deviceNumber],
  359. &bestXferMode,
  360. &tempMode
  361. );
  362. if (!NT_SUCCESS(status)) {
  363. bestXferMode = UNINITIALIZED_TRANSFER_MODE;
  364. tempMode = UNINITIALIZED_TRANSFER_MODE;
  365. }
  366. } else {
  367. //
  368. // No udma support funtions to interpret Identify data in the channel driver.
  369. // Interpret in the known way.
  370. //
  371. if (deviceExtension->IdentifyData[deviceNumber].TranslationFieldsValid & (1 << 2)) {
  372. if (deviceExtension->IdentifyData[deviceNumber].UltraDMASupport) {
  373. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].UltraDMASupport,
  374. bestXferMode);
  375. }
  376. if (deviceExtension->IdentifyData[deviceNumber].UltraDMAActive) {
  377. GetHighestTransferMode( deviceExtension->IdentifyData[deviceNumber].UltraDMAActive,
  378. tempMode);
  379. }
  380. }
  381. }
  382. //
  383. // Use the current mode if we actually got one
  384. //
  385. if (tempMode != UNINITIALIZED_TRANSFER_MODE) {
  386. currentMode = tempMode;
  387. if (transferModeTableLength <= (currentMode + UDMA0)) {
  388. currentMode = transferModeTableLength-UDMA0-1;
  389. }
  390. currentMode = 1 << (currentMode+UDMA0);
  391. }
  392. //
  393. // make sure that bestXferMode is initialized. if not it indicates that
  394. // the device does not support udma.
  395. //
  396. if (bestXferMode != UNINITIALIZED_TRANSFER_MODE) {
  397. if (transferModeTableLength <= (bestXferMode + UDMA0)) {
  398. bestXferMode = transferModeTableLength-UDMA0-1;
  399. }
  400. cycleTime = TransferModeTimingTable[bestXferMode+UDMA0];
  401. ASSERT(cycleTime);
  402. tempMode = 0;
  403. GenTransferModeMask(bestXferMode, tempMode);
  404. xferMode |= (tempMode << UDMA0);
  405. }
  406. //
  407. // Doesn't really know the ultra dma cycle time
  408. //
  409. deviceExtension->DeviceParameters[deviceNumber].BestUDmaCycleTime = cycleTime;
  410. deviceExtension->DeviceParameters[deviceNumber].BestUDmaMode = bestXferMode;
  411. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported = xferMode;
  412. deviceExtension->DeviceParameters[deviceNumber].TransferModeCurrent |= currentMode;
  413. //
  414. // Check to see if the device is in the Hall of Shame!
  415. //
  416. if (MustBePio[deviceNumber] ||
  417. !AtapiDMACapable (FdoExtension, deviceNumber) ||
  418. (*InitSafeBootMode == SAFEBOOT_MINIMAL)) {
  419. DebugPrint((DBG_XFERMODE,
  420. "ATAPI: Reseting DMA Information\n"
  421. ));
  422. //
  423. // Remove all DMA info
  424. //
  425. deviceExtension->DeviceParameters[deviceNumber].BestSwDmaCycleTime = 0;
  426. deviceExtension->DeviceParameters[deviceNumber].BestMwDmaCycleTime = 0;
  427. deviceExtension->DeviceParameters[deviceNumber].BestUDmaCycleTime = 0;
  428. deviceExtension->DeviceParameters[deviceNumber].BestSwDmaMode = 0;
  429. deviceExtension->DeviceParameters[deviceNumber].BestMwDmaMode = 0;
  430. deviceExtension->DeviceParameters[deviceNumber].BestUDmaMode = 0;
  431. deviceExtension->DeviceParameters[deviceNumber].TransferModeCurrent &= PIO_SUPPORT;
  432. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported &= PIO_SUPPORT;
  433. }
  434. // if DMADetectionLevel = 0, clear current DMA mode
  435. // if DMADetectionLevel = 1, set current mode
  436. // if DMADetectionLevel = 2, clear all current mode
  437. // pciidex takes care of this for non-acpi machines.
  438. // In acpi systems, it is better to trust the GTM settings.
  439. //
  440. // If a device supports any of the advanced PIO mode, we are assuming that
  441. // the device is a "newer" drive and IDE_COMMAND_READ_MULTIPLE should work.
  442. // Otherwise, we will turn off IDE_COMMAND_READ_MULTIPLE
  443. //
  444. if (deviceExtension->DeviceParameters[deviceNumber].BestPioMode > 2) {
  445. if (!Is98LegacyIde(&deviceExtension->BaseIoAddress1)) {
  446. deviceExtension->MaximumBlockXfer[deviceNumber] =
  447. (UCHAR)(deviceExtension->IdentifyData[deviceNumber].MaximumBlockTransfer & 0xFF);
  448. } else {
  449. //
  450. // MaximumBlockXfer is less or equal 16
  451. //
  452. deviceExtension->MaximumBlockXfer[deviceNumber] =
  453. ((UCHAR)(deviceExtension->IdentifyData[deviceNumber].MaximumBlockTransfer & 0xFF) > 16)?
  454. 16 : (UCHAR)(deviceExtension->IdentifyData[deviceNumber].MaximumBlockTransfer & 0xFF);
  455. }
  456. } else {
  457. deviceExtension->MaximumBlockXfer[deviceNumber] = 0;
  458. }
  459. DebugPrint ((DBG_XFERMODE,
  460. "atapi: target %d transfer timing:\n"
  461. "atapi: PIO mode supported = %4x and best cycle time = %5d ns\n"
  462. "atapi: SWDMA mode supported = %4x and best cycle time = %5d ns\n"
  463. "atapi: MWDMA mode supported = %4x and best cycle time = %5d ns\n"
  464. "atapi: UDMA mode supported = %x and best cycle time = %5d ns\n"
  465. "atapi: Current mode bitmap = %4x\n",
  466. deviceNumber,
  467. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported & PIO_SUPPORT,
  468. deviceExtension->DeviceParameters[deviceNumber].BestPioCycleTime,
  469. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported & SWDMA_SUPPORT,
  470. deviceExtension->DeviceParameters[deviceNumber].BestSwDmaCycleTime,
  471. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported & MWDMA_SUPPORT,
  472. deviceExtension->DeviceParameters[deviceNumber].BestMwDmaCycleTime,
  473. deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported & UDMA_SUPPORT,
  474. deviceExtension->DeviceParameters[deviceNumber].BestUDmaCycleTime,
  475. deviceExtension->DeviceParameters[deviceNumber].TransferModeCurrent
  476. ));
  477. }
  478. }
  479. } // AnalyzeDeviceCapabilities
  480. VOID
  481. AtapiSyncSelectTransferMode (
  482. IN PFDO_EXTENSION FdoExtension,
  483. IN OUT PHW_DEVICE_EXTENSION DeviceExtension,
  484. IN ULONG TimingModeAllowed[MAX_IDE_TARGETID * MAX_IDE_LINE]
  485. )
  486. /*++
  487. Routine Description:
  488. query the best transfer mode for our devices
  489. Arguments:
  490. FdoExtension
  491. DeviceExtension - HW Device Extension
  492. TimingModeAllowed - Allowed transfer modes
  493. Return Value:
  494. none
  495. --*/
  496. {
  497. PCIIDE_TRANSFER_MODE_SELECT transferModeSelect;
  498. ULONG i;
  499. NTSTATUS status;
  500. if (!IsNEC_98) {
  501. RtlZeroMemory (&transferModeSelect, sizeof(transferModeSelect));
  502. for (i=0; i<DeviceExtension->MaxIdeDevice; i++) {
  503. transferModeSelect.DevicePresent[i] = DeviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT ? TRUE : FALSE;
  504. //
  505. // ISSUE: 07/31/2000: How about atapi hard disk
  506. // We don't know of any. This would suffice for the time being.
  507. //
  508. transferModeSelect.FixedDisk[i] = !(DeviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE);
  509. transferModeSelect.BestPioCycleTime[i] = DeviceExtension->DeviceParameters[i].BestPioCycleTime;
  510. transferModeSelect.BestSwDmaCycleTime[i] = DeviceExtension->DeviceParameters[i].BestSwDmaCycleTime;
  511. transferModeSelect.BestMwDmaCycleTime[i] = DeviceExtension->DeviceParameters[i].BestMwDmaCycleTime;
  512. transferModeSelect.BestUDmaCycleTime[i] = DeviceExtension->DeviceParameters[i].BestUDmaCycleTime;
  513. transferModeSelect.IoReadySupported[i] = DeviceExtension->DeviceParameters[i].IoReadyEnabled;
  514. transferModeSelect.DeviceTransferModeSupported[i] = DeviceExtension->DeviceParameters[i].TransferModeSupported;
  515. transferModeSelect.DeviceTransferModeCurrent[i] = DeviceExtension->DeviceParameters[i].TransferModeCurrent;
  516. //
  517. // if we don't have a busmaster capable parent or
  518. // the device is a tape, stay with pio mode
  519. //
  520. // (tape may transfer fewer bytes than requested.
  521. // we can't figure exactly byte transfered with DMA)
  522. //
  523. // if ((!FdoExtension->BoundWithBmParent) ||
  524. // (DeviceExtension->DeviceFlags[i] & DFLAGS_TAPE_DEVICE)) {
  525. if (!FdoExtension->BoundWithBmParent) {
  526. transferModeSelect.DeviceTransferModeSupported[i] &= PIO_SUPPORT;
  527. transferModeSelect.DeviceTransferModeCurrent[i] &= PIO_SUPPORT;
  528. }
  529. //
  530. // Some miniports need this
  531. //
  532. transferModeSelect.IdentifyData[i]=DeviceExtension->IdentifyData[i];
  533. transferModeSelect.UserChoiceTransferMode[i] = FdoExtension->UserChoiceTransferMode[i];
  534. //
  535. // honor user's choice and/or last knowen good mode
  536. //
  537. transferModeSelect.DeviceTransferModeSupported[i] &= TimingModeAllowed[i];
  538. transferModeSelect.DeviceTransferModeCurrent[i] &= TimingModeAllowed[i];
  539. // should look at dmadetectionlevel and set DeviceTransferModeDesired
  540. // we look at dmaDetectionlecel in TransferModeSelect function below.
  541. // the parameters set here should be honoured anyways, I feel.
  542. }
  543. transferModeSelect.TransferModeTimingTable= FdoExtension->
  544. TransferModeInterface.TransferModeTimingTable;
  545. transferModeSelect.TransferModeTableLength= FdoExtension->
  546. TransferModeInterface.TransferModeTableLength;
  547. ASSERT(FdoExtension->TransferModeInterface.TransferModeSelect);
  548. status = FdoExtension->TransferModeInterface.TransferModeSelect (
  549. FdoExtension->TransferModeInterface.Context,
  550. &transferModeSelect
  551. );
  552. } else {
  553. //
  554. // Always fail for nec98 machines
  555. //
  556. status = STATUS_UNSUCCESSFUL;
  557. }
  558. if (!NT_SUCCESS(status)) {
  559. //
  560. // Unable to get the mode select, default to current PIO mode
  561. //
  562. for (i=0; i<DeviceExtension->MaxIdeDevice; i++) {
  563. DeviceExtension->DeviceParameters[i].TransferModeSelected =
  564. DeviceExtension->DeviceParameters[i].TransferModeCurrent & PIO_SUPPORT;
  565. DebugPrint ((DBG_XFERMODE,
  566. "Atapi: DEFAULT device %d transfer mode current 0x%x and selected bitmap 0x%x\n",
  567. i,
  568. DeviceExtension->DeviceParameters[i].TransferModeCurrent,
  569. DeviceExtension->DeviceParameters[i].TransferModeSelected));
  570. }
  571. } else {
  572. for (i=0; i<DeviceExtension->MaxIdeDevice; i++) {
  573. DeviceExtension->DeviceParameters[i].TransferModeSelected =
  574. transferModeSelect.DeviceTransferModeSelected[i];
  575. DebugPrint ((DBG_XFERMODE,
  576. "Atapi: device %d transfer mode current 0x%x and selected bitmap 0x%x\n",
  577. i,
  578. DeviceExtension->DeviceParameters[i].TransferModeCurrent,
  579. DeviceExtension->DeviceParameters[i].TransferModeSelected));
  580. }
  581. }
  582. return;
  583. } // AtapiSelectTransferMode
  584. UCHAR SpecialWDDevicesFWVersion[][9] = {
  585. {"14.04E28"},
  586. {"25.26H35"},
  587. {"26.27J38"},
  588. {"27.25C38"},
  589. {"27.25C39"}
  590. };
  591. #define NUMBER_OF_SPECIAL_WD_DEVICES (sizeof(SpecialWDDevicesFWVersion) / (sizeof (UCHAR) * 9))
  592. BOOLEAN
  593. AtapiDMACapable (
  594. IN OUT PFDO_EXTENSION FdoExtension,
  595. IN ULONG deviceNumber
  596. )
  597. /*++
  598. Routine Description:
  599. check the given device whether it is on our bad device list (non dma device)
  600. Arguments:
  601. HwDeviceExtension - HBA miniport driver's adapter data storage
  602. deviceNumber - device number
  603. Return Value:
  604. TRUE if dma capable
  605. FALSE if not dma capable
  606. --*/
  607. {
  608. PHW_DEVICE_EXTENSION deviceExtension = FdoExtension->HwDeviceExtension;
  609. UCHAR modelNumber[41];
  610. UCHAR firmwareVersion[9];
  611. ULONG i;
  612. BOOLEAN turnOffDMA = FALSE;
  613. //
  614. // Code is paged until locked down.
  615. //
  616. PAGED_CODE();
  617. #ifdef ALLOC_PRAGMA
  618. ASSERT(IdePAGESCANLockCount > 0);
  619. #endif
  620. if (!(deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT)) {
  621. return FALSE;
  622. }
  623. //
  624. // byte swap model number
  625. //
  626. for (i=0; i<40; i+=2) {
  627. modelNumber[i + 0] = deviceExtension->IdentifyData[deviceNumber].ModelNumber[i + 1];
  628. modelNumber[i + 1] = deviceExtension->IdentifyData[deviceNumber].ModelNumber[i + 0];
  629. }
  630. modelNumber[i] = 0;
  631. //
  632. // if we have a Western Digial device
  633. // if the best dma mode is multi word dma mode 1
  634. // if the identify data word offset 129 is not 0x5555
  635. // turn off dma unless
  636. // if the device firmware version is on the list and
  637. // it is the only drive on the bus
  638. //
  639. if (3 == RtlCompareMemory(modelNumber, "WDC", 3)) {
  640. if ((deviceExtension->DeviceParameters[deviceNumber].TransferModeSupported &
  641. (MWDMA_MODE2 | MWDMA_MODE1)) == MWDMA_MODE1) {
  642. for (i=0; i<8; i+=2) {
  643. firmwareVersion[i + 0] = deviceExtension->IdentifyData[deviceNumber].FirmwareRevision[i + 1];
  644. firmwareVersion[i + 1] = deviceExtension->IdentifyData[deviceNumber].FirmwareRevision[i + 0];
  645. }
  646. firmwareVersion[i] = 0;
  647. //
  648. // Check the special flag. If not found, can't use dma
  649. //
  650. if (*(((PUSHORT)&deviceExtension->IdentifyData[deviceNumber]) + 129) != 0x5555) {
  651. DebugPrint ((0, "ATAPI: found mode 1 WD drive. no dma unless it is the only device\n"));
  652. turnOffDMA = TRUE;
  653. for (i=0; i<NUMBER_OF_SPECIAL_WD_DEVICES; i++) {
  654. if (8 == RtlCompareMemory (firmwareVersion, SpecialWDDevicesFWVersion[i], 8)) {
  655. ULONG otherDeviceNumber;
  656. //
  657. // 0 becomes 1
  658. // 1 becomes 0
  659. // 2 becomes 3
  660. // 3 becomes 2
  661. //
  662. otherDeviceNumber = ((deviceNumber & 0x2) | ((deviceNumber & 0x1) ^ 1));
  663. //
  664. // if the device is alone on the bus, we can use dma
  665. //
  666. if (!(deviceExtension->DeviceFlags[otherDeviceNumber] & DFLAGS_DEVICE_PRESENT)) {
  667. turnOffDMA = FALSE;
  668. break;
  669. }
  670. }
  671. }
  672. }
  673. }
  674. }
  675. if (turnOffDMA) {
  676. return FALSE;
  677. } else {
  678. return TRUE;
  679. }
  680. }
  681. IDE_DEVICETYPE
  682. AtapiDetectDevice (
  683. IN OUT PFDO_EXTENSION FdoExtension,
  684. IN OUT PPDO_EXTENSION PdoExtension,
  685. IN OUT PIDENTIFY_DATA IdentifyData,
  686. IN BOOLEAN MustSucceed
  687. )
  688. /**++
  689. Routine Description:
  690. Detect the device at this location.
  691. 1. Send "ec".
  692. 2. if success read the Identify data and return the device type
  693. 3. else send "a1"
  694. 4. if success read the Identify data and return the device type
  695. 5. else return no device
  696. Arguments:
  697. FdoExtension:
  698. PdoExtension:
  699. IdentifyData: Identify data is copied into this buffer if a device is detected.
  700. MustSucceed: TRUE if pre-alloced memory is to be used.
  701. Return Value:
  702. device type: ATA, ATAPI or NO Device
  703. --**/
  704. {
  705. PATA_PASS_THROUGH ataPassThroughData;
  706. UCHAR ataPassThroughDataBuffer[sizeof(*ataPassThroughData) + sizeof (*IdentifyData)];
  707. BOOLEAN foundIt;
  708. NTSTATUS status;
  709. PIDE_REGISTERS_1 cmdRegBase;
  710. UCHAR statusByte1;
  711. LONG i;
  712. ULONG j;
  713. IDEREGS identifyCommand[3];
  714. IDE_DEVICETYPE deviceType;
  715. BOOLEAN resetController = FALSE;
  716. LARGE_INTEGER tickCount;
  717. ULONG timeDiff;
  718. ULONG timeoutValue = 0;
  719. ULONG retryCount = 0;
  720. BOOLEAN defaultTimeout = FALSE;
  721. HANDLE deviceHandle;
  722. PAGED_CODE();
  723. ASSERT(FdoExtension);
  724. ASSERT(PdoExtension);
  725. ASSERT(PdoExtension->PathId == 0);
  726. ASSERT(PdoExtension->TargetId < FdoExtension->HwDeviceExtension->MaxIdeTargetId);
  727. #ifdef ENABLE_ATAPI_VERIFIER
  728. if (ViIdeFakeMissingDevice(FdoExtension, PdoExtension->TargetId)) {
  729. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  730. PdoExtension->DeadmeatRecord.LineNumber
  731. );
  732. return DeviceNotExist;
  733. }
  734. #endif //ENABLE_ATAPI_VERIFIER
  735. ataPassThroughData = (PATA_PASS_THROUGH)ataPassThroughDataBuffer;
  736. foundIt = FALSE;
  737. cmdRegBase = &FdoExtension->HwDeviceExtension->BaseIoAddress1;
  738. if (FdoExtension->UserChoiceDeviceType[PdoExtension->TargetId] == DeviceNotExist) {
  739. deviceType = DeviceNotExist;
  740. } else {
  741. //
  742. // Look into the registry for last boot configration
  743. //
  744. deviceType = DeviceUnknown;
  745. IdePortGetDeviceParameter(
  746. FdoExtension,
  747. IdePortRegistryDeviceTypeName[PdoExtension->TargetId],
  748. (PULONG)&deviceType
  749. );
  750. DebugPrint((DBG_BUSSCAN,
  751. "AtapiDetectDevice - last boot config deviceType = 0x%x\n",
  752. deviceType));
  753. //
  754. // Obtain the timeout value.
  755. // ISSUE: should not be in the class section.
  756. //
  757. /*****
  758. status = IoOpenDeviceRegistryKey(
  759. FdoExtension->AttacheePdo,
  760. PLUGPLAY_REGKEY_DEVICE,
  761. KEY_QUERY_VALUE,
  762. &deviceHandle);
  763. DebugPrint((0, "DetectDevice status = %x\n", status));
  764. ZwClose(deviceHandle);
  765. ****/
  766. IdePortGetDeviceParameter(
  767. FdoExtension,
  768. IdePortRegistryDeviceTimeout[PdoExtension->TargetId],
  769. (PULONG)&timeoutValue
  770. );
  771. //
  772. // if there is no registry entry use the default
  773. //
  774. if (timeoutValue == 0) {
  775. timeoutValue = (PdoExtension->TargetId & 0x1)==0 ? 10 : 3;
  776. defaultTimeout = TRUE;
  777. }
  778. //
  779. // Use 3s timeout for slave devices in safe boot mode. Why??
  780. //
  781. if (*InitSafeBootMode == SAFEBOOT_MINIMAL) {
  782. timeoutValue = (PdoExtension->TargetId & 0x1)==0 ? 10 : 3;
  783. }
  784. //
  785. // invalidate the last boot configuration
  786. // we will update it with a new setting if we
  787. // detect a device
  788. //
  789. IdePortSaveDeviceParameter(
  790. FdoExtension,
  791. IdePortRegistryDeviceTypeName[PdoExtension->TargetId],
  792. DeviceUnknown
  793. );
  794. if ((PdoExtension->TargetId == 1) &&
  795. (FdoExtension->MayHaveSlaveDevice == 0)) {
  796. deviceType = DeviceNotExist;
  797. }
  798. }
  799. if (Is98LegacyIde(cmdRegBase)) {
  800. UCHAR signatureLow;
  801. UCHAR signatureHigh;
  802. UCHAR statusByte1;
  803. if ((PdoExtension->TargetId & 0x1) == 1) {
  804. //
  805. // Slave device phese.
  806. //
  807. if (!EnhancedIdeSupport()) {
  808. //
  809. // Enhanced ide machine can not have the slave device.
  810. //
  811. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  812. PdoExtension->DeadmeatRecord.LineNumber
  813. );
  814. return DeviceNotExist;
  815. }
  816. if (FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId - 1] & DFLAGS_WD_MODE) {
  817. //
  818. // WD-Mode cd-rom can not has slave device.
  819. //
  820. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  821. PdoExtension->DeadmeatRecord.LineNumber
  822. );
  823. return DeviceNotExist;
  824. }
  825. }
  826. #if 0 //NEC_98
  827. if (deviceType == DeviceIsAtapi) {
  828. //
  829. // reset device type to determine WD-Mode or ATAPI.
  830. //
  831. deviceType = DeviceUnknown;
  832. }
  833. if (deviceType == DeviceUnknown) {
  834. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  835. ataPassThroughData->IdeReg.bCommandReg = IDE_COMMAND_ATAPI_RESET;
  836. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_ENUM_PROBING;
  837. status = IssueSyncAtaPassThroughSafe (
  838. FdoExtension,
  839. PdoExtension,
  840. ataPassThroughData,
  841. FALSE,
  842. FALSE,
  843. 15,
  844. mustSucceed
  845. );
  846. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  847. signatureLow = ataPassThroughData->IdeReg.bCylLowReg;
  848. signatureHigh = ataPassThroughData->IdeReg.bCylHighReg;
  849. if (signatureLow == 0x14 && signatureHigh == 0xEB) {
  850. deviceType = DeviceIsAtapi;
  851. } else {
  852. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice - ata %x status after soft reset %x\n",PdoExtension->TargetId, statusByte1));
  853. if (statusByte1 & IDE_STATUS_ERROR) {
  854. deviceType = DeviceIsAta;
  855. } else {
  856. //
  857. // Device is WD-Mode cd-rom.
  858. //
  859. deviceType = DeviceIsAtapi;
  860. SETMASK (FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId], DFLAGS_WD_MODE);
  861. }
  862. }
  863. }
  864. #endif //NEC_98
  865. }
  866. #if ENABLE_ATAPI_VERIFIER
  867. if (!Is98LegacyIde(cmdRegBase)) {
  868. //
  869. // simulate device change
  870. //
  871. if (deviceType == DeviceIsAta) {
  872. deviceType = DeviceIsAtapi;
  873. } else if (deviceType == DeviceIsAtapi) {
  874. deviceType = DeviceIsAta;
  875. }
  876. }
  877. #endif
  878. //
  879. // command to issue
  880. //
  881. RtlZeroMemory (&identifyCommand, sizeof (identifyCommand));
  882. if (deviceType == DeviceNotExist) {
  883. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  884. PdoExtension->DeadmeatRecord.LineNumber
  885. );
  886. return DeviceNotExist;
  887. } else if (deviceType == DeviceIsAta) {
  888. identifyCommand[0].bCommandReg = IDE_COMMAND_IDENTIFY;
  889. identifyCommand[0].bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED | ATA_PTFLAGS_ENUM_PROBING;
  890. identifyCommand[1].bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
  891. identifyCommand[1].bReserved = ATA_PTFLAGS_ENUM_PROBING;
  892. } else {
  893. identifyCommand[0].bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
  894. identifyCommand[0].bReserved = ATA_PTFLAGS_ENUM_PROBING;
  895. identifyCommand[1].bCommandReg = IDE_COMMAND_IDENTIFY;
  896. identifyCommand[1].bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED | ATA_PTFLAGS_ENUM_PROBING;
  897. }
  898. //
  899. // IDE HACK
  900. //
  901. // If we are talking to a non-existing device, the
  902. // status register value may be unstable.
  903. // Reading it a few time seems to stablize it.
  904. //
  905. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  906. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  907. //
  908. // Repeat 10 times
  909. //
  910. ataPassThroughData->IdeReg.bSectorCountReg = 10;
  911. LogBusScanStartTimer(&tickCount);
  912. status = IssueSyncAtaPassThroughSafe (
  913. FdoExtension,
  914. PdoExtension,
  915. ataPassThroughData,
  916. FALSE,
  917. FALSE,
  918. 3,
  919. MustSucceed
  920. );
  921. timeDiff = LogBusScanStopTimer(&tickCount);
  922. DebugPrint((DBG_SPECIAL,
  923. "DetectDevice: Hack for device %d at %x took %u ms\n",
  924. PdoExtension->TargetId,
  925. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  926. timeDiff
  927. ));
  928. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  929. if (Is98LegacyIde(cmdRegBase)) {
  930. UCHAR driveHeadReg;
  931. driveHeadReg = ataPassThroughData->IdeReg.bDriveHeadReg;
  932. if (driveHeadReg != ((PdoExtension->TargetId & 0x1) << 4 | 0xA0)) {
  933. //
  934. // Bad controller.
  935. //
  936. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  937. PdoExtension->DeadmeatRecord.LineNumber
  938. );
  939. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  940. ataPassThroughData->IdeReg
  941. );
  942. return DeviceNotExist;
  943. }
  944. //
  945. // There are some H/W as follow...
  946. //
  947. if ((statusByte1 & 0xe8) == 0xa8) {
  948. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  949. PdoExtension->DeadmeatRecord.LineNumber
  950. );
  951. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  952. ataPassThroughData->IdeReg
  953. );
  954. return DeviceNotExist;
  955. }
  956. }
  957. if (statusByte1 == 0xff) {
  958. //
  959. // nothing here
  960. //
  961. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  962. PdoExtension->DeadmeatRecord.LineNumber
  963. );
  964. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  965. ataPassThroughData->IdeReg
  966. );
  967. return DeviceNotExist;
  968. }
  969. //
  970. // If the statusByte1 is 80 then try a reset
  971. //
  972. if (statusByte1 & IDE_STATUS_BUSY) {
  973. //
  974. // look like it is hung, try reset to bring it back
  975. //
  976. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  977. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_BUS_RESET;
  978. LogBusScanStartTimer(&tickCount);
  979. status = IssueSyncAtaPassThroughSafe(
  980. FdoExtension,
  981. PdoExtension,
  982. ataPassThroughData,
  983. FALSE,
  984. FALSE,
  985. 30,
  986. MustSucceed
  987. );
  988. timeDiff = LogBusScanStopTimer(&tickCount);
  989. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[0], timeDiff);
  990. DebugPrint((DBG_SPECIAL,
  991. "DtectDevice: Reset device %d ata %x took %u ms\n",
  992. PdoExtension->TargetId,
  993. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  994. timeDiff
  995. ));
  996. }
  997. LogBusScanStartTimer(&tickCount);
  998. retryCount = 0;
  999. for (i=0; i<2; i++) {
  1000. BOOLEAN ataIdentify;
  1001. ataIdentify = identifyCommand[i].bCommandReg == IDE_COMMAND_IDENTIFY ? TRUE : FALSE;
  1002. if (ataIdentify) {
  1003. //
  1004. // IDE HACK
  1005. //
  1006. // If we are talking to a non-existing device, the
  1007. // status register value may be unstable.
  1008. // Reading it a few time seems to stablize it.
  1009. //
  1010. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  1011. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  1012. //
  1013. // Repeat 10 times
  1014. //
  1015. ataPassThroughData->IdeReg.bSectorCountReg = 10;
  1016. status = IssueSyncAtaPassThroughSafe(
  1017. FdoExtension,
  1018. PdoExtension,
  1019. ataPassThroughData,
  1020. FALSE,
  1021. FALSE,
  1022. 3,
  1023. MustSucceed
  1024. );
  1025. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  1026. //
  1027. // a real ATA device should never return this
  1028. //
  1029. if ((statusByte1 == 0x00) ||
  1030. (statusByte1 == 0x01)) {
  1031. //
  1032. // nothing here
  1033. //
  1034. continue;
  1035. }
  1036. deviceType = DeviceIsAta;
  1037. if (Is98LegacyIde(cmdRegBase)) {
  1038. UCHAR systemPortAData;
  1039. //
  1040. // dip-switch 2 read.
  1041. //
  1042. systemPortAData = IdePortInPortByte( (PUCHAR)SYSTEM_PORT_A );
  1043. DebugPrint((DBG_BUSSCAN, "atapi:AtapiFindNewDevices - ide dip switch %x\n",systemPortAData));
  1044. if (!(systemPortAData & 0x20)) {
  1045. //
  1046. // Internal-hd(ide) has been disabled with system-menu.
  1047. //
  1048. deviceType = DeviceNotExist;
  1049. break;
  1050. }
  1051. }
  1052. } else {
  1053. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  1054. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  1055. status = IssueSyncAtaPassThroughSafe (
  1056. FdoExtension,
  1057. PdoExtension,
  1058. ataPassThroughData,
  1059. FALSE,
  1060. FALSE,
  1061. 3,
  1062. MustSucceed
  1063. );
  1064. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  1065. deviceType = DeviceIsAtapi;
  1066. }
  1067. if ((statusByte1 == 0xff) ||
  1068. (statusByte1 == 0xfe)) {
  1069. //
  1070. // nothing here
  1071. //
  1072. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1073. PdoExtension->DeadmeatRecord.LineNumber
  1074. );
  1075. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1076. ataPassThroughData->IdeReg
  1077. );
  1078. deviceType = DeviceNotExist;
  1079. break;
  1080. }
  1081. //
  1082. // build the ata pass through the id data command
  1083. //
  1084. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  1085. ataPassThroughData->DataBufferSize = sizeof (*IdentifyData);
  1086. RtlMoveMemory (&ataPassThroughData->IdeReg, identifyCommand + i, sizeof(ataPassThroughData->IdeReg));
  1087. ASSERT(timeoutValue);
  1088. //
  1089. // Issue an id data command to the device
  1090. //
  1091. // some device (Kingston PCMCIA Datapak (non-flash)) takes a long time to response. we
  1092. // can possibly timeout even an device exists.
  1093. //
  1094. // we have to make a compromise here. We want to detect slow devices without causing
  1095. // many systems to boot slow.
  1096. //
  1097. // here is the logic:
  1098. //
  1099. // Since we are here (IsChannelEmpty() == FALSE), we are guessing we have at least
  1100. // one device attached and it is a master device. It should be ok to allow longer
  1101. // timeout when sending ID data to the master. We should never timeout unless
  1102. // the channel has only a slave device.
  1103. //
  1104. // Yes, we will not detect slow slave device for now. If anyone complain, we will
  1105. // fix it.
  1106. //
  1107. // You can never win as long as we have broken ATA devices!
  1108. //
  1109. status = IssueSyncAtaPassThroughSafe (
  1110. FdoExtension,
  1111. PdoExtension,
  1112. ataPassThroughData,
  1113. TRUE,
  1114. FALSE,
  1115. timeoutValue,
  1116. MustSucceed
  1117. );
  1118. //(PdoExtension->TargetId & 0x1)==0 ? 10 : 1,
  1119. if (NT_SUCCESS(status)) {
  1120. if (!(ataPassThroughData->IdeReg.bCommandReg & IDE_STATUS_ERROR)) {
  1121. DebugPrint ((DBG_BUSSCAN, "IdePort: Found a child on 0x%x target 0x%x\n", cmdRegBase->RegistersBaseAddress, PdoExtension->TargetId));
  1122. foundIt = TRUE;
  1123. if (ataIdentify) {
  1124. IdePortFudgeAtaIdentifyData(
  1125. (PIDENTIFY_DATA) ataPassThroughData->DataBuffer
  1126. );
  1127. }
  1128. break;
  1129. } else {
  1130. DebugPrint ((DBG_BUSSCAN, "AtapiDetectDevice:Command %x, 0x%x target 0x%x failed 0x%x with status 0x%x\n",
  1131. i,
  1132. cmdRegBase->RegistersBaseAddress,
  1133. PdoExtension->TargetId,
  1134. identifyCommand[i].bCommandReg,
  1135. ataPassThroughData->IdeReg.bCommandReg
  1136. ));
  1137. }
  1138. } else {
  1139. DebugPrint ((DBG_BUSSCAN, "AtapiDetectDevice:The irp with command %x, 0x%x target 0x%x failed 0x%x with status 0x%x\n",
  1140. i,
  1141. cmdRegBase->RegistersBaseAddress,
  1142. PdoExtension->TargetId,
  1143. identifyCommand[i].bCommandReg,
  1144. status
  1145. ));
  1146. deviceType = DeviceNotExist;
  1147. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1148. PdoExtension->DeadmeatRecord.LineNumber
  1149. );
  1150. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1151. ataPassThroughData->IdeReg
  1152. );
  1153. if ((FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId] & DFLAGS_DEVICE_PRESENT) &&
  1154. !(FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId] & DFLAGS_ATAPI_DEVICE) &&
  1155. (retryCount < 2)) {
  1156. //
  1157. // BAD BAD BAD device
  1158. //
  1159. // SAMSUNG WU32543A (2.54GB)
  1160. //
  1161. // when it does a few UDMA transfers, it kind of forgets
  1162. // how to do ATA identify data so it looks like the device
  1163. // is gone.
  1164. //
  1165. // we better try harder to make sure if it is really gone
  1166. // we will do that by issuing a hard reset and try identify
  1167. // data again.
  1168. //
  1169. if (identifyCommand[i].bCommandReg == IDE_COMMAND_IDENTIFY) {
  1170. //
  1171. // ask for an "inline" hard reset before issuing identify command
  1172. //
  1173. identifyCommand[i].bReserved |= ATA_PTFLAGS_INLINE_HARD_RESET;
  1174. //
  1175. // redo the last command
  1176. //
  1177. i -= 1;
  1178. resetController = TRUE;
  1179. retryCount++;
  1180. }
  1181. } else {
  1182. if (status == STATUS_IO_TIMEOUT) {
  1183. //
  1184. // looks like there is no device there
  1185. // update the registry with a low timeout value if
  1186. // this is the slave device.
  1187. //
  1188. if ((PdoExtension->TargetId & 0x1) &&
  1189. defaultTimeout) {
  1190. //
  1191. // Use the timeout value of 1s for the next boot.
  1192. //
  1193. DebugPrint((1,
  1194. "Updating the registry with 1s value for device %d\n",
  1195. PdoExtension->TargetId
  1196. ));
  1197. IdePortSaveDeviceParameter(
  1198. FdoExtension,
  1199. IdePortRegistryDeviceTimeout[PdoExtension->TargetId],
  1200. 1
  1201. );
  1202. }
  1203. break;
  1204. }
  1205. }
  1206. }
  1207. //
  1208. // try the next command
  1209. //
  1210. }
  1211. timeDiff = LogBusScanStopTimer(&tickCount);
  1212. DebugPrint((DBG_SPECIAL,
  1213. "DetectDevice: Identify Data for device %d at %x took %u ms\n",
  1214. PdoExtension->TargetId,
  1215. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1216. timeDiff
  1217. ));
  1218. //
  1219. // save for the next boot
  1220. //
  1221. IdePortSaveDeviceParameter(
  1222. FdoExtension,
  1223. IdePortRegistryDeviceTypeName[PdoExtension->TargetId],
  1224. deviceType == DeviceNotExist? DeviceUnknown : deviceType
  1225. );
  1226. if (foundIt) {
  1227. RtlMoveMemory (IdentifyData, ataPassThroughData->DataBuffer, sizeof (*IdentifyData));
  1228. #if DBG
  1229. {
  1230. ULONG i;
  1231. UCHAR string[41];
  1232. for (i=0; i<8; i+=2) {
  1233. string[i] = IdentifyData->FirmwareRevision[i + 1];
  1234. string[i + 1] = IdentifyData->FirmwareRevision[i];
  1235. }
  1236. string[i] = 0;
  1237. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: firmware version: %s\n", string));
  1238. for (i=0; i<40; i+=2) {
  1239. string[i] = IdentifyData->ModelNumber[i + 1];
  1240. string[i + 1] = IdentifyData->ModelNumber[i];
  1241. }
  1242. string[i] = 0;
  1243. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: model number: %s\n", string));
  1244. for (i=0; i<20; i+=2) {
  1245. string[i] = IdentifyData->SerialNumber[i + 1];
  1246. string[i + 1] = IdentifyData->SerialNumber[i];
  1247. }
  1248. string[i] = 0;
  1249. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: serial number: %s\n", string));
  1250. }
  1251. #endif // DBG
  1252. } else {
  1253. deviceType = DeviceNotExist;
  1254. }
  1255. if (deviceType == DeviceNotExist) {
  1256. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1257. PdoExtension->DeadmeatRecord.LineNumber
  1258. );
  1259. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1260. ataPassThroughData->IdeReg
  1261. );
  1262. }
  1263. return deviceType;
  1264. }
  1265. NTSTATUS
  1266. IdePortSelectCHS (
  1267. IN OUT PFDO_EXTENSION FdoExtension,
  1268. IN ULONG Device,
  1269. IN PIDENTIFY_DATA IdentifyData
  1270. )
  1271. {
  1272. IN PHW_DEVICE_EXTENSION HwDeviceExtension;
  1273. BOOLEAN skipSetParameters = FALSE;
  1274. //
  1275. // Code is paged until locked down.
  1276. //
  1277. PAGED_CODE();
  1278. #ifdef ALLOC_PRAGMA
  1279. ASSERT(IdePAGESCANLockCount > 0);
  1280. #endif
  1281. ASSERT(FdoExtension);
  1282. ASSERT(IdentifyData);
  1283. HwDeviceExtension = FdoExtension->HwDeviceExtension;
  1284. ASSERT (HwDeviceExtension);
  1285. ASSERT(Device < HwDeviceExtension->MaxIdeDevice);
  1286. // LBA???
  1287. // We set the LBA flag in AnalyzeDeviceCapabilities.
  1288. //
  1289. if (!((HwDeviceExtension->DeviceFlags[Device] & DFLAGS_DEVICE_PRESENT) &&
  1290. (!(HwDeviceExtension->DeviceFlags[Device] & DFLAGS_ATAPI_DEVICE)))) {
  1291. return STATUS_SUCCESS;
  1292. }
  1293. if (!Is98LegacyIde(&HwDeviceExtension->BaseIoAddress1) &&
  1294. (((IdentifyData->NumberOfCurrentCylinders *
  1295. IdentifyData->NumberOfCurrentHeads *
  1296. IdentifyData->CurrentSectorsPerTrack) <
  1297. (IdentifyData->NumCylinders *
  1298. IdentifyData->NumHeads *
  1299. IdentifyData->NumSectorsPerTrack)) || // discover a larger drive
  1300. (IdentifyData->MajorRevision == 0) ||
  1301. ((IdentifyData->NumberOfCurrentCylinders == 0) ||
  1302. (IdentifyData->NumberOfCurrentHeads == 0) ||
  1303. (IdentifyData->CurrentSectorsPerTrack == 0))) ) {
  1304. HwDeviceExtension->NumberOfCylinders[Device] = IdentifyData->NumCylinders;
  1305. HwDeviceExtension->NumberOfHeads[Device] = IdentifyData->NumHeads;
  1306. HwDeviceExtension->SectorsPerTrack[Device] = IdentifyData->NumSectorsPerTrack;
  1307. } else {
  1308. HwDeviceExtension->NumberOfCylinders[Device] = IdentifyData->NumberOfCurrentCylinders;
  1309. HwDeviceExtension->NumberOfHeads[Device] = IdentifyData->NumberOfCurrentHeads;
  1310. HwDeviceExtension->SectorsPerTrack[Device] = IdentifyData->CurrentSectorsPerTrack;
  1311. }
  1312. if ((IdentifyData->NumCylinders != IdentifyData->NumberOfCurrentCylinders) ||
  1313. (IdentifyData->NumHeads != IdentifyData->NumberOfCurrentHeads) ||
  1314. (IdentifyData->NumSectorsPerTrack != IdentifyData->CurrentSectorsPerTrack)) {
  1315. DebugPrint ((
  1316. DBG_ALWAYS,
  1317. "0x%x device %d current CHS (%x,%x,%x) differs from default CHS (%x,%x,%x)\n",
  1318. HwDeviceExtension->BaseIoAddress1.RegistersBaseAddress,
  1319. Device,
  1320. IdentifyData->NumberOfCurrentCylinders,
  1321. IdentifyData->NumberOfCurrentHeads,
  1322. IdentifyData->CurrentSectorsPerTrack,
  1323. IdentifyData->NumCylinders,
  1324. IdentifyData->NumHeads,
  1325. IdentifyData->NumSectorsPerTrack
  1326. ));
  1327. }
  1328. //
  1329. // This hideous hack is to deal with ESDI devices that return
  1330. // garbage geometry in the IDENTIFY data.
  1331. // This is ONLY for the crashdump environment as
  1332. // these are ESDI devices.
  1333. //
  1334. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1335. 0x35 &&
  1336. HwDeviceExtension->NumberOfHeads[Device] ==
  1337. 0x07) {
  1338. DebugPrint((DBG_ALWAYS,
  1339. "FindDevices: Found nasty Compaq ESDI!\n"));
  1340. //
  1341. // Change these values to something reasonable.
  1342. //
  1343. HwDeviceExtension->SectorsPerTrack[Device] =
  1344. 0x34;
  1345. HwDeviceExtension->NumberOfHeads[Device] =
  1346. 0x0E;
  1347. }
  1348. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1349. 0x35 &&
  1350. HwDeviceExtension->NumberOfHeads[Device] ==
  1351. 0x0F) {
  1352. DebugPrint((DBG_ALWAYS,
  1353. "FindDevices: Found nasty Compaq ESDI!\n"));
  1354. //
  1355. // Change these values to something reasonable.
  1356. //
  1357. HwDeviceExtension->SectorsPerTrack[Device] =
  1358. 0x34;
  1359. HwDeviceExtension->NumberOfHeads[Device] =
  1360. 0x0F;
  1361. }
  1362. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1363. 0x36 &&
  1364. HwDeviceExtension->NumberOfHeads[Device] ==
  1365. 0x07) {
  1366. DebugPrint((DBG_ALWAYS,
  1367. "FindDevices: Found nasty UltraStor ESDI!\n"));
  1368. //
  1369. // Change these values to something reasonable.
  1370. //
  1371. HwDeviceExtension->SectorsPerTrack[Device] =
  1372. 0x3F;
  1373. HwDeviceExtension->NumberOfHeads[Device] =
  1374. 0x10;
  1375. skipSetParameters = TRUE;
  1376. }
  1377. if (Is98LegacyIde(&HwDeviceExtension->BaseIoAddress1)) {
  1378. skipSetParameters = TRUE;
  1379. }
  1380. if (!skipSetParameters) {
  1381. PIDE_REGISTERS_1 baseIoAddress1 = &HwDeviceExtension->BaseIoAddress1;
  1382. PIDE_REGISTERS_2 baseIoAddress2 = &HwDeviceExtension->BaseIoAddress2;
  1383. UCHAR statusByte;
  1384. DebugPrintTickCount (FindDeviceTimer, 0);
  1385. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1386. //
  1387. // Select the device.
  1388. //
  1389. SelectIdeDevice(baseIoAddress1, Device, 0);
  1390. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1391. WaitOnBusy(baseIoAddress1,statusByte);
  1392. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1393. if (statusByte & IDE_STATUS_BUSY) {
  1394. ULONG waitCount = 20000;
  1395. DebugPrintTickCount (FindDeviceTimer, 0);
  1396. //
  1397. // Reset the device.
  1398. //
  1399. DebugPrint((2,
  1400. "FindDevices: Resetting controller before SetDriveParameters.\n"));
  1401. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1402. IdeHardReset (
  1403. baseIoAddress1,
  1404. baseIoAddress2,
  1405. FALSE,
  1406. TRUE
  1407. );
  1408. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1409. DebugPrintTickCount (FindDeviceTimer, 0);
  1410. }
  1411. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1412. WaitOnBusy(baseIoAddress1,statusByte);
  1413. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1414. DebugPrintTickCount (FindDeviceTimer, 0);
  1415. DebugPrint((2,
  1416. "FindDevices: Status before SetDriveParameters: (%x) (%x)\n",
  1417. statusByte,
  1418. IdePortInPortByte (baseIoAddress1->DriveSelect)));
  1419. //
  1420. // Use the IDENTIFY data to set drive parameters.
  1421. //
  1422. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1423. if (!SetDriveParameters(HwDeviceExtension,Device,TRUE)) {
  1424. DebugPrint((0,
  1425. "IdePortFixUpCHS: Set drive parameters for device %d failed\n",
  1426. Device));
  1427. //
  1428. // Don't use this device as writes could cause corruption.
  1429. //
  1430. HwDeviceExtension->DeviceFlags[Device] = 0;
  1431. }
  1432. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1433. }
  1434. return STATUS_SUCCESS;
  1435. }
  1436. NTSTATUS
  1437. IdePortScanBus (
  1438. IN OUT PFDO_EXTENSION FdoExtension
  1439. )
  1440. /**++
  1441. Routine Description:
  1442. Scans the IDE bus (channel) for devices. It also configures the detected devices.
  1443. The "safe" routines used in the procedure are not thread-safe, they use pre-allocated
  1444. memory. The important steps in the enumeration of a channel are:
  1445. 1. Detect the devices on the channel
  1446. 2. Stop all the device queues
  1447. 3. Determine and set the transfer modes and the other flags
  1448. 4. Start all the device queues
  1449. 5. IssueInquiry
  1450. Arguments:
  1451. FdoExtension: Functional device extension
  1452. Return Value:
  1453. STATUS_SUCCESS : if the operation succeeded
  1454. Failure status : if the operation fails
  1455. --**/
  1456. {
  1457. NTSTATUS status;
  1458. IDE_PATH_ID pathId;
  1459. ULONG target;
  1460. ULONG lun;
  1461. PPDO_EXTENSION pdoExtension;
  1462. PHW_DEVICE_EXTENSION hwDeviceExtension;
  1463. PIDEDRIVER_EXTENSION ideDriverExtension;
  1464. INQUIRYDATA InquiryData;
  1465. IDENTIFY_DATA identifyData[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1466. ULONG idDatacheckSum[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1467. SPECIAL_ACTION_FLAG specialAction[MAX_IDE_TARGETID*MAX_IDE_LINE];
  1468. IDE_DEVICETYPE deviceType[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1469. BOOLEAN mustBePio[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1470. BOOLEAN pioByDefault[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1471. UCHAR flushCommand[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1472. BOOLEAN removableMedia[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1473. BOOLEAN isLs120[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1474. BOOLEAN noPowerDown[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1475. BOOLEAN isSameDevice[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1476. ULONG lastKnownGoodTimingMode[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1477. ULONG savedTransferMode[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1478. PULONG enableBigLba;
  1479. ULONG numSlot=0;
  1480. ULONG numPdoChildren;
  1481. UCHAR targetModelNum[MAX_MODELNUM_SIZE+sizeof('\0')]; //extra bytes for '\0'
  1482. HANDLE pageScanCodePageHandle;
  1483. BOOLEAN newPdo;
  1484. BOOLEAN check4EmptyChannel;
  1485. BOOLEAN emptyChannel;
  1486. BOOLEAN mustSucceed=TRUE;
  1487. KIRQL currentIrql;
  1488. BOOLEAN inSetup;
  1489. PULONG waitOnPowerUp;
  1490. LARGE_INTEGER tickCount;
  1491. ULONG timeDiff;
  1492. LARGE_INTEGER totalDeviceDetectionTime;
  1493. totalDeviceDetectionTime.QuadPart = 0;
  1494. //
  1495. // This macro is used in IdePortScanBus
  1496. //
  1497. #define RefLuExt(pdoExtension, fdoExtension, pathId, removedOk, newPdo) {\
  1498. pdoExtension = RefLogicalUnitExtensionWithTag( \
  1499. fdoExtension, \
  1500. (UCHAR) pathId.b.Path, \
  1501. (UCHAR) pathId.b.TargetId, \
  1502. (UCHAR) pathId.b.Lun, \
  1503. removedOk, \
  1504. IdePortScanBus \
  1505. ); \
  1506. if (pdoExtension == NULL) { \
  1507. pdoExtension = AllocatePdoWithTag( \
  1508. fdoExtension, \
  1509. pathId, \
  1510. IdePortScanBus \
  1511. ); \
  1512. newPdo = TRUE; \
  1513. } \
  1514. }
  1515. //
  1516. // This macro is used in IdePortScanBus
  1517. //
  1518. #define UnRefLuExt(pdoExtension, fdoExtension, sync, callIoDeleteDevice, newPdo) { \
  1519. if (newPdo) { \
  1520. FreePdoWithTag( \
  1521. pdoExtension, \
  1522. sync, \
  1523. callIoDeleteDevice, \
  1524. IdePortScanBus \
  1525. ); \
  1526. } else { \
  1527. UnrefLogicalUnitExtensionWithTag ( \
  1528. fdoExtension, \
  1529. pdoExtension, \
  1530. IdePortScanBus \
  1531. ); \
  1532. } \
  1533. }
  1534. //
  1535. // Before getting in to this critical region, we must lock down
  1536. // all the code and data because we may have stopped the paging
  1537. // device!
  1538. //
  1539. // lock down all code that belongs to PAGESCAN
  1540. //
  1541. #ifdef ALLOC_PRAGMA
  1542. pageScanCodePageHandle = MmLockPagableCodeSection(
  1543. IdePortScanBus
  1544. );
  1545. InterlockedIncrement(&IdePAGESCANLockCount);
  1546. #endif
  1547. ASSERT(FdoExtension);
  1548. ASSERT(FdoExtension->PreAllocEnumStruct);
  1549. hwDeviceExtension = FdoExtension->HwDeviceExtension;
  1550. if (FdoExtension->InterruptObject == NULL) {
  1551. //
  1552. // we are started with no irq. it means
  1553. // we have no children. it is ok to poke
  1554. // at the ports directly
  1555. //
  1556. if (IdePortChannelEmpty (&hwDeviceExtension->BaseIoAddress1,
  1557. &hwDeviceExtension->BaseIoAddress2,
  1558. hwDeviceExtension->MaxIdeDevice) == FALSE) {
  1559. //
  1560. // this channel is started with out an irq
  1561. // it was because the channel looked empty
  1562. // but, now it doesn't look empty. we need
  1563. // to restart with an irq resource
  1564. //
  1565. if (FdoExtension->RequestProperResourceInterface) {
  1566. FdoExtension->RequestProperResourceInterface (FdoExtension->AttacheePdo);
  1567. }
  1568. else {
  1569. DebugPrint((DBG_ALWAYS,
  1570. "No interface to request resources. Probably a pcmcia parent\n"));
  1571. }
  1572. }
  1573. goto done;
  1574. }
  1575. DebugPrint ((
  1576. DBG_BUSSCAN,
  1577. "IdePort: scan bus 0x%x\n",
  1578. FdoExtension->IdeResource.TranslatedCommandBaseAddress
  1579. ));
  1580. inSetup = IdePortInSetup(FdoExtension);
  1581. DebugPrint((DBG_BUSSCAN,
  1582. "ATAPI: insetup = 0x%x\n",
  1583. inSetup? 1: 0
  1584. ));
  1585. waitOnPowerUp = NULL;
  1586. IdePortGetParameterFromServiceSubKey (
  1587. FdoExtension->DriverObject,
  1588. L"WaitOnBusyOnPowerUp",
  1589. REG_DWORD,
  1590. TRUE,
  1591. (PVOID) &waitOnPowerUp,
  1592. 0
  1593. );
  1594. FdoExtension->WaitOnPowerUp = PtrToUlong(waitOnPowerUp);
  1595. check4EmptyChannel = FALSE;
  1596. FdoExtension->DeviceChanged = FALSE;
  1597. pathId.l = 0;
  1598. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  1599. pathId.b.TargetId = target;
  1600. pathId.b.Lun = 0;
  1601. newPdo = FALSE;
  1602. mustBePio[target] = FALSE;
  1603. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  1604. if (!newPdo && (pdoExtension->PdoState & PDOS_DEADMEAT)) {
  1605. //
  1606. // device marked dead already
  1607. //
  1608. UnrefLogicalUnitExtensionWithTag (
  1609. FdoExtension,
  1610. pdoExtension,
  1611. IdePortScanBus
  1612. );
  1613. ASSERT (FALSE);
  1614. pdoExtension = NULL;
  1615. }
  1616. if (!pdoExtension) {
  1617. DebugPrint ((DBG_ALWAYS,
  1618. "ATAPI: IdePortScanBus() is unable to get pdo (%d,%d,%d)\n",
  1619. pathId.b.Path,
  1620. pathId.b.TargetId,
  1621. pathId.b.Lun));
  1622. deviceType[target] = DeviceNotExist;
  1623. continue;
  1624. }
  1625. if (!check4EmptyChannel) {
  1626. ULONG i;
  1627. NTSTATUS status;
  1628. UCHAR statusByte1;
  1629. ATA_PASS_THROUGH ataPassThroughData;
  1630. check4EmptyChannel = TRUE;
  1631. //
  1632. // make sure the channel is not empty
  1633. //
  1634. RtlZeroMemory (&ataPassThroughData, sizeof (ataPassThroughData));
  1635. ataPassThroughData.IdeReg.bReserved = ATA_PTFLAGS_EMPTY_CHANNEL_TEST;
  1636. LogBusScanStartTimer(&tickCount);
  1637. status = IssueSyncAtaPassThroughSafe(
  1638. FdoExtension,
  1639. pdoExtension,
  1640. &ataPassThroughData,
  1641. FALSE,
  1642. FALSE,
  1643. 30,
  1644. TRUE
  1645. );
  1646. if (NT_SUCCESS(status)) {
  1647. emptyChannel = TRUE;
  1648. } else {
  1649. emptyChannel = FALSE;
  1650. }
  1651. timeDiff = LogBusScanStopTimer(&tickCount);
  1652. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[1], timeDiff);
  1653. DebugPrint((DBG_SPECIAL,
  1654. "BusScan: Empty Channel check for fdoe %x took %u ms\n",
  1655. FdoExtension,
  1656. timeDiff
  1657. ));
  1658. }
  1659. LogBusScanStartTimer(&tickCount);
  1660. if (!emptyChannel) {
  1661. deviceType[target] = AtapiDetectDevice (FdoExtension, pdoExtension,
  1662. identifyData + target, TRUE);
  1663. if (deviceType[target] != DeviceNotExist) {
  1664. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_DEVICE_PRESENT);
  1665. //
  1666. // Check for special action requests for the device
  1667. //
  1668. GetTargetModelId((identifyData+target), targetModelNum);
  1669. specialAction[target] = IdeFindSpecialDevice(targetModelNum, NULL);
  1670. if (specialAction[target] == setFlagSonyMemoryStick ) {
  1671. ULONG i;
  1672. // SonyMemoryStick device.
  1673. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_SONY_MEMORYSTICK);
  1674. //
  1675. // Truncate the hardware id, so that the size of
  1676. // the memory stick is not included in it.
  1677. //
  1678. for (i=strlen("MEMORYSTICK");i<sizeof((identifyData+target)->ModelNumber);i++) {
  1679. (identifyData+target)->ModelNumber[i+1]='\0';
  1680. }
  1681. }
  1682. }
  1683. else {
  1684. DebugPrint((DBG_BUSSCAN, "Didn't detect the device %d\n", target));
  1685. }
  1686. } else {
  1687. DebugPrint((DBG_SPECIAL,
  1688. "BusScan: IdeDevicePresent %x detected no device %d\n",
  1689. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1690. target
  1691. ));
  1692. //
  1693. // invalidate the last boot configuration
  1694. //
  1695. IdePortSaveDeviceParameter(
  1696. FdoExtension,
  1697. IdePortRegistryDeviceTypeName[pdoExtension->TargetId],
  1698. DeviceUnknown
  1699. );
  1700. deviceType[target] = DeviceNotExist;
  1701. }
  1702. ASSERT (deviceType[target] <= DeviceNotExist);
  1703. timeDiff = LogBusScanStopTimer(&tickCount);
  1704. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[2+target], timeDiff);
  1705. DebugPrint((DBG_SPECIAL,
  1706. "BusScan: Detect device %d for %x took %u ms\n",
  1707. target,
  1708. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1709. timeDiff
  1710. ));
  1711. totalDeviceDetectionTime.QuadPart += timeDiff;
  1712. ASSERT (deviceType[target] <= DeviceNotExist);
  1713. ASSERT (deviceType[target] != DeviceUnknown);
  1714. ASSERT (pdoExtension->TargetId == target);
  1715. if (deviceType[target] != DeviceNotExist) {
  1716. if (target & 1) {
  1717. if (deviceType[(LONG) target - 1] != DeviceNotExist) {
  1718. if (IdePortSlaveIsGhost (
  1719. FdoExtension,
  1720. identifyData + target - 1,
  1721. identifyData + target - 0)) {
  1722. //
  1723. // remove the slave device
  1724. //
  1725. deviceType[target] = DeviceNotExist;
  1726. }
  1727. }
  1728. }
  1729. }
  1730. ASSERT (deviceType[target] <= DeviceNotExist);
  1731. if (deviceType[target] == DeviceNotExist) {
  1732. CLRMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_IDENTIFY_VALID);
  1733. if (FdoExtension->HwDeviceExtension->DeviceFlags[target] & DFLAGS_DEVICE_PRESENT) {
  1734. IDE_PATH_ID pathId;
  1735. PPDO_EXTENSION pdoExtension;
  1736. //
  1737. // device went away
  1738. //
  1739. FdoExtension->DeviceChanged = TRUE;
  1740. //
  1741. // mark all PDOs for the missing device DEADMEAT
  1742. //
  1743. pathId.l = 0;
  1744. pathId.b.TargetId = target;
  1745. while (pdoExtension = NextLogUnitExtensionWithTag(
  1746. FdoExtension,
  1747. &pathId,
  1748. TRUE,
  1749. (PVOID) (~(ULONG_PTR)IdePortScanBus)
  1750. )) {
  1751. if (pdoExtension->TargetId == target) {
  1752. DebugPrint((DBG_BUSSCAN, "Enum Failed for target=%d, PDOe=0x%x\n",
  1753. target, pdoExtension));
  1754. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1755. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT);
  1756. IdeLogDeadMeatReason( pdoExtension->DeadmeatRecord.Reason,
  1757. enumFailed;
  1758. );
  1759. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1760. UnrefPdoWithTag (pdoExtension, (PVOID) (~(ULONG_PTR)IdePortScanBus));
  1761. } else {
  1762. UnrefPdoWithTag (pdoExtension, (PVOID) (~(ULONG_PTR)IdePortScanBus));
  1763. break;
  1764. }
  1765. }
  1766. }
  1767. } else {
  1768. idDatacheckSum[target] = IdePortSimpleCheckSum (
  1769. 0,
  1770. identifyData[target].ModelNumber,
  1771. sizeof(identifyData[target].ModelNumber)
  1772. );
  1773. idDatacheckSum[target] += IdePortSimpleCheckSum (
  1774. idDatacheckSum[target],
  1775. identifyData[target].SerialNumber,
  1776. sizeof(identifyData[target].SerialNumber)
  1777. );
  1778. idDatacheckSum[target] += IdePortSimpleCheckSum (
  1779. idDatacheckSum[target],
  1780. identifyData[target].FirmwareRevision,
  1781. sizeof(identifyData[target].FirmwareRevision)
  1782. );
  1783. if (newPdo) {
  1784. //
  1785. // new device
  1786. //
  1787. FdoExtension->DeviceChanged = TRUE;
  1788. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Found a new device. pdoe = x%x\n", pdoExtension));
  1789. } else {
  1790. #ifdef ENABLE_ATAPI_VERIFIER
  1791. idDatacheckSum[target] += ViIdeFakeDeviceChange(FdoExtension, target);
  1792. #endif //ENABLE_ATAPI_VERIFIER
  1793. if (idDatacheckSum[target] != pdoExtension->IdentifyDataCheckSum) {
  1794. FdoExtension->DeviceChanged = TRUE;
  1795. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: bad bad bad user. a device is replaced by a different device. pdoe = x%x\n", pdoExtension));
  1796. //
  1797. // mark the old device deadmeat
  1798. //
  1799. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1800. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT | PDOS_NEED_RESCAN);
  1801. IdeLogDeadMeatReason( pdoExtension->DeadmeatRecord.Reason,
  1802. replacedByUser;
  1803. );
  1804. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1805. //
  1806. // pretend we have seen the new device.
  1807. // we will re-enum when the old one is removed.
  1808. //
  1809. deviceType[target] = DeviceNotExist;
  1810. }
  1811. }
  1812. }
  1813. ASSERT (deviceType[target] <= DeviceNotExist);
  1814. if (deviceType[target] != DeviceNotExist) {
  1815. ULONG savedIdDataCheckSum;
  1816. mustBePio[target] = IdePortMustBePio (
  1817. FdoExtension,
  1818. identifyData + target
  1819. );
  1820. pioByDefault[target] = IdePortPioByDefaultDevice (
  1821. FdoExtension,
  1822. identifyData + target
  1823. );
  1824. ASSERT (deviceType[target] <= DeviceNotExist);
  1825. LogBusScanStartTimer(&tickCount);
  1826. flushCommand[target] = IDE_COMMAND_NO_FLUSH;
  1827. //
  1828. // we need this only for ata devices
  1829. //
  1830. if (deviceType[target] != DeviceIsAtapi) {
  1831. flushCommand[target] = IdePortGetFlushCommand (
  1832. FdoExtension,
  1833. pdoExtension,
  1834. identifyData + target
  1835. );
  1836. }
  1837. timeDiff = LogBusScanStopTimer(&tickCount);
  1838. DebugPrint((DBG_SPECIAL,
  1839. "BusScan: Flush command for device %d at %x took %u ms\n",
  1840. target,
  1841. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1842. timeDiff
  1843. ));
  1844. ASSERT (deviceType[target] <= DeviceNotExist);
  1845. removableMedia[target] = IdePortDeviceHasNonRemovableMedia (
  1846. FdoExtension,
  1847. identifyData + target
  1848. );
  1849. ASSERT (deviceType[target] <= DeviceNotExist);
  1850. isLs120[target] = IdePortDeviceIsLs120 (
  1851. FdoExtension,
  1852. identifyData + target
  1853. );
  1854. ASSERT (deviceType[target] <= DeviceNotExist);
  1855. noPowerDown[target] = IdePortNoPowerDown (
  1856. FdoExtension,
  1857. identifyData + target
  1858. );
  1859. ASSERT (deviceType[target] <= DeviceNotExist);
  1860. //
  1861. // init. the default value to an abnormal #.
  1862. //
  1863. FdoExtension->UserChoiceTransferMode[target] = 0x12345678;
  1864. IdePortGetDeviceParameter(
  1865. FdoExtension,
  1866. IdePortRegistryUserDeviceTimingModeAllowedName[target],
  1867. FdoExtension->UserChoiceTransferMode + target
  1868. );
  1869. if (FdoExtension->UserChoiceTransferMode[target] == 0x12345678) {
  1870. //
  1871. // This value is used to decide whether a user choice was indicated
  1872. // or not. This helps us to set the transfer mode to a default value
  1873. // if the user doesn't choose a particular transfer mode. Otherwise we
  1874. // honour the user choice.
  1875. //
  1876. FdoExtension->UserChoiceTransferMode[target] = UNINITIALIZED_TRANSFER_MODE;
  1877. //
  1878. // we know the register doesn't have what we are looking for
  1879. // set the default atapi-override setting to a value
  1880. // that will force pio only on atapi device
  1881. //
  1882. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = PIO_SUPPORT;
  1883. } else {
  1884. //
  1885. // user acutally picked the transfer mode settings.
  1886. // set the default atapi-override setting to a value (-1)
  1887. // that will not affect the user choice.
  1888. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = MAXULONG;
  1889. }
  1890. //
  1891. // get the previous mode
  1892. //
  1893. IdePortGetDeviceParameter(
  1894. FdoExtension,
  1895. IdePortRegistryDeviceTimingModeName[target],
  1896. savedTransferMode+target
  1897. );
  1898. savedIdDataCheckSum = 0;
  1899. IdePortGetDeviceParameter(
  1900. FdoExtension,
  1901. IdePortRegistryIdentifyDataChecksum[target],
  1902. &savedIdDataCheckSum
  1903. );
  1904. ASSERT (deviceType[target] <= DeviceNotExist);
  1905. //
  1906. // figure out what transfer mode we can use
  1907. //
  1908. if (savedIdDataCheckSum == idDatacheckSum[target]) {
  1909. //
  1910. // same device. if we program the same transfer mode then
  1911. // we can skip the DMA test
  1912. //
  1913. isSameDevice[target] = TRUE;
  1914. //
  1915. // it is the same device, use
  1916. // the lastKnownGoodTimingMode
  1917. // in the registry
  1918. //
  1919. lastKnownGoodTimingMode[target] = MAXULONG;
  1920. IdePortGetDeviceParameter(
  1921. FdoExtension,
  1922. IdePortRegistryDeviceTimingModeAllowedName[target],
  1923. lastKnownGoodTimingMode + target
  1924. );
  1925. } else {
  1926. isSameDevice[target] = FALSE;
  1927. lastKnownGoodTimingMode[target] = MAXULONG;
  1928. }
  1929. ASSERT (deviceType[target] <= DeviceNotExist);
  1930. FdoExtension->TimingModeAllowed[target] =
  1931. lastKnownGoodTimingMode[target] &
  1932. FdoExtension->UserChoiceTransferMode[target];
  1933. //
  1934. // TransferModeMask is initially 0.
  1935. //
  1936. FdoExtension->TimingModeAllowed[target] &= ~(hwDeviceExtension->
  1937. DeviceParameters[target].TransferModeMask);
  1938. if (pdoExtension->CrcErrorCount >= PDO_UDMA_CRC_ERROR_LIMIT) {
  1939. //
  1940. //Reset the error count
  1941. //
  1942. pdoExtension->CrcErrorCount =0;
  1943. }
  1944. DebugPrint ((DBG_XFERMODE, "TMAllowed=%x, TMMask=%x, UserChoice=%x\n",
  1945. FdoExtension->TimingModeAllowed[target],
  1946. hwDeviceExtension->DeviceParameters[target].TransferModeMask,
  1947. FdoExtension->UserChoiceTransferMode[target]));
  1948. ASSERT (deviceType[target] <= DeviceNotExist);
  1949. }
  1950. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  1951. pdoExtension = NULL;
  1952. }
  1953. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  1954. if (FdoExtension->BusScanTime == 0) {
  1955. FdoExtension->BusScanTime = totalDeviceDetectionTime.LowPart;
  1956. }
  1957. #endif // IDE_MEASURE_BUSSCAN_SPEED
  1958. #ifdef ENABLE_48BIT_LBA
  1959. //
  1960. // Enable big lba support by default
  1961. //
  1962. FdoExtension->EnableBigLba = 1;
  1963. #endif
  1964. // if (!deviceChanged && !DBG) {
  1965. //
  1966. // //
  1967. // // didn't find anything different than before
  1968. // //
  1969. // return STATUS_SUCCESS;
  1970. // }
  1971. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: detect a change of device...re-initializing\n"));
  1972. // ISSUE: check if device got removed!!!
  1973. //
  1974. // Begin of a critial region
  1975. // must stop all children, do the stuff, and restart all children
  1976. //
  1977. //
  1978. // cycle through all children and stop their device queue
  1979. //
  1980. LogBusScanStartTimer(&tickCount);
  1981. pathId.l = 0;
  1982. numPdoChildren = 0;
  1983. status = STATUS_SUCCESS;
  1984. while (pdoExtension = NextLogUnitExtensionWithTag(
  1985. FdoExtension,
  1986. &pathId,
  1987. TRUE,
  1988. IdePortScanBus
  1989. )) {
  1990. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: stopping pdo 0x%x\n", pdoExtension));
  1991. status = DeviceStopDeviceQueueSafe (pdoExtension, PDOS_QUEUE_FROZEN_BY_PARENT, TRUE);
  1992. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: stopped pdo 0x%x\n", pdoExtension));
  1993. UnrefLogicalUnitExtensionWithTag (
  1994. FdoExtension,
  1995. pdoExtension,
  1996. IdePortScanBus
  1997. );
  1998. numPdoChildren++;
  1999. if (!NT_SUCCESS(status)) {
  2000. break;
  2001. }
  2002. }
  2003. if (NT_SUCCESS(status)) {
  2004. BOOLEAN foundAtLeastOneIdeDevice = FALSE;
  2005. BOOLEAN useDma;
  2006. IDE_PATH_ID pathId;
  2007. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: all children are stoped\n"));
  2008. pathId.l = 0;
  2009. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  2010. ASSERT (deviceType[target] <= DeviceNotExist);
  2011. if (deviceType[target] != DeviceNotExist) {
  2012. pathId.b.TargetId = target;
  2013. newPdo = FALSE;
  2014. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  2015. if (!pdoExtension) {
  2016. continue;
  2017. }
  2018. ASSERT (pdoExtension);
  2019. foundAtLeastOneIdeDevice = TRUE;
  2020. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_DEVICE_PRESENT);
  2021. if (deviceType[target] == DeviceIsAtapi) {
  2022. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_ATAPI_DEVICE);
  2023. useDma=FALSE;
  2024. //
  2025. // skip the dvd test, if ModeSense command is not to be
  2026. // sent to the device or if we are in setup
  2027. //
  2028. if (inSetup) {
  2029. mustBePio[target] = TRUE;
  2030. } else if ((specialAction[target] != skipModeSense) &&
  2031. (!pioByDefault[target])) {
  2032. useDma = IdePortDmaCdromDrive(FdoExtension,
  2033. pdoExtension,
  2034. TRUE
  2035. );
  2036. }
  2037. //
  2038. // Don't force PIO if we have seen this before. If it was doing PIO
  2039. // TimingModeAllowed would reflect that.
  2040. // Set UserChoiceForAtapi to 0xffffffff
  2041. // This won't anyway affect the user choice
  2042. //
  2043. if ( useDma) {
  2044. DebugPrint((DBG_BUSSCAN,
  2045. "IdePortScanBus: USE DMA FOR target %d\n",
  2046. target
  2047. ));
  2048. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = MAXULONG;
  2049. }
  2050. FdoExtension->TimingModeAllowed[target] &=
  2051. FdoExtension->UserChoiceTransferModeForAtapiDevice[target];
  2052. }
  2053. //
  2054. // allow LS-120 Format Command
  2055. //
  2056. if (isLs120[target]) {
  2057. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_LS120_FORMAT);
  2058. }
  2059. RtlMoveMemory (
  2060. hwDeviceExtension->IdentifyData + target,
  2061. identifyData + target,
  2062. sizeof (IDENTIFY_DATA)
  2063. );
  2064. //
  2065. // Always re-use identify data
  2066. // This will get cleared if it is a removable media
  2067. // The queue is stopped. Now I can safely set this flag.
  2068. //
  2069. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_IDENTIFY_VALID);
  2070. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling InitHwExtWithIdentify\n"));
  2071. //
  2072. // IdentifyValid flag should be cleared, if it is a removable media
  2073. //
  2074. InitHwExtWithIdentify(
  2075. hwDeviceExtension,
  2076. target,
  2077. (UCHAR) (deviceType[target] == DeviceIsAtapi ? IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY),
  2078. hwDeviceExtension->IdentifyData + target,
  2079. removableMedia[target]
  2080. );
  2081. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling IdePortSelectCHS\n"));
  2082. IdePortSelectCHS (
  2083. FdoExtension,
  2084. target,
  2085. identifyData + target
  2086. );
  2087. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: back from IdePortSelectCHS\n"));
  2088. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  2089. } else {
  2090. hwDeviceExtension->DeviceFlags[target] = 0;
  2091. }
  2092. }
  2093. if (foundAtLeastOneIdeDevice) {
  2094. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AnalyzeDeviceCapabilities\n"));
  2095. //
  2096. // could move this out of the critial region
  2097. //
  2098. AnalyzeDeviceCapabilities (
  2099. FdoExtension,
  2100. mustBePio
  2101. );
  2102. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AtapiSelectTransferMode\n"));
  2103. //
  2104. // could move this out of the critial region
  2105. //
  2106. AtapiSyncSelectTransferMode (
  2107. FdoExtension,
  2108. hwDeviceExtension,
  2109. FdoExtension->TimingModeAllowed
  2110. );
  2111. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AtapiHwInitialize\n"));
  2112. AtapiHwInitialize (
  2113. FdoExtension->HwDeviceExtension,
  2114. flushCommand
  2115. );
  2116. }
  2117. } else {
  2118. //
  2119. // unable to stop all children, so force an buscheck to try again
  2120. //
  2121. // IoInvalidateDeviceRelations (
  2122. // FdoExtension->AttacheePdo,
  2123. // BusRelations
  2124. // );
  2125. }
  2126. //
  2127. // cycle through all children and restart their device queue
  2128. //
  2129. pathId.l = 0;
  2130. numPdoChildren = 0;
  2131. while (pdoExtension = NextLogUnitExtensionWithTag(
  2132. FdoExtension,
  2133. &pathId,
  2134. TRUE,
  2135. IdePortScanBus
  2136. )) {
  2137. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: re-start pdo 0x%x\n", pdoExtension));
  2138. DeviceStartDeviceQueue (pdoExtension, PDOS_QUEUE_FROZEN_BY_PARENT);
  2139. UnrefLogicalUnitExtensionWithTag (
  2140. FdoExtension,
  2141. pdoExtension,
  2142. IdePortScanBus
  2143. );
  2144. numPdoChildren++;
  2145. }
  2146. timeDiff = LogBusScanStopTimer(&tickCount);
  2147. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[4], timeDiff);
  2148. DebugPrint((DBG_SPECIAL,
  2149. "BusScan : Critical section %x took %u ms\n",
  2150. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2151. timeDiff
  2152. ));
  2153. if (NT_SUCCESS(status)) {
  2154. //
  2155. // second stage scanning
  2156. //
  2157. pathId.l = 0;
  2158. LogBusScanStartTimer(&tickCount);
  2159. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  2160. if (deviceType[target] == DeviceNotExist) {
  2161. continue;
  2162. }
  2163. pathId.b.TargetId = target;
  2164. for (lun = 0; lun < FdoExtension->MaxLuCount; lun++) {
  2165. LARGE_INTEGER tempTickCount;
  2166. pathId.b.Lun = lun;
  2167. newPdo = FALSE;
  2168. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  2169. if (!pdoExtension) {
  2170. continue;
  2171. }
  2172. ASSERT (pdoExtension);
  2173. if (lun == 0) {
  2174. #if defined (ALWAYS_VERIFY_DMA)
  2175. #undef ALWAYS_VERIFY_DMA
  2176. #define ALWAYS_VERIFY_DMA TRUE
  2177. #else
  2178. #define ALWAYS_VERIFY_DMA FALSE
  2179. #endif
  2180. ASSERT (ALL_MODE_SUPPORT != MAXULONG);
  2181. if ((FdoExtension->HwDeviceExtension->
  2182. DeviceParameters[target].TransferModeSelected & DMA_SUPPORT) ||
  2183. ALWAYS_VERIFY_DMA) {
  2184. ULONG mode = FdoExtension->HwDeviceExtension->
  2185. DeviceParameters[target].TransferModeSelected;
  2186. //
  2187. // if lastKnownGoodTimingMode is MAX_ULONG, it means
  2188. // we have never seen this device before and the user
  2189. // hasn't said anything about what dma mode to use.
  2190. //
  2191. // we have chosen to use dma because all the software
  2192. // detectable parameters (identify dma, pci config data)
  2193. // looks good for DMA.
  2194. //
  2195. // the only thing that can stop us from using DMA now
  2196. // is bad device. before we go on, do a little test
  2197. // to verify dma is ok
  2198. //
  2199. // could re-use the inquiry data obtained here.
  2200. //
  2201. //
  2202. // skip the test if we have already seen the device
  2203. //
  2204. LogBusScanStartTimer(&tempTickCount);
  2205. if (isSameDevice[target] &&
  2206. mode == savedTransferMode[target]) {
  2207. DebugPrint((DBG_BUSSCAN,
  2208. "Skip dma test for %d\n", target));
  2209. } else {
  2210. IdePortVerifyDma (
  2211. pdoExtension,
  2212. deviceType[target]
  2213. );
  2214. }
  2215. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2216. DebugPrint((DBG_SPECIAL,
  2217. "ScanBus: VerifyDma for %x device %d took %u ms\n",
  2218. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2219. target,
  2220. timeDiff
  2221. ));
  2222. }
  2223. //
  2224. // Initialize numSlot to 0
  2225. //
  2226. numSlot=0;
  2227. //
  2228. // If this is in the bad cd-rom drive list, then don't
  2229. // send these Mode Sense command. The drive might lock up.
  2230. //
  2231. LogBusScanStartTimer(&tempTickCount);
  2232. if (specialAction[target] != skipModeSense) {
  2233. //
  2234. // Non-CD device
  2235. //
  2236. numSlot = IdePortQueryNonCdNumLun (
  2237. FdoExtension,
  2238. pdoExtension,
  2239. FALSE
  2240. );
  2241. } else {
  2242. DebugPrint((DBG_BUSSCAN, "Skip modesense\n"));
  2243. }
  2244. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2245. DebugPrint((DBG_SPECIAL,
  2246. "ScanBus: Initialize Luns for %x device %d took %u ms\n",
  2247. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2248. target,
  2249. timeDiff
  2250. ));
  2251. AtapiHwInitializeMultiLun (
  2252. FdoExtension->HwDeviceExtension,
  2253. pdoExtension->TargetId,
  2254. numSlot
  2255. );
  2256. }
  2257. if (pdoExtension) {
  2258. LogBusScanStartTimer(&tempTickCount);
  2259. status = IssueInquirySafe(FdoExtension, pdoExtension, &InquiryData, TRUE);
  2260. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2261. DebugPrint((DBG_SPECIAL,
  2262. "ScanBus: Inquiry %x for Lun %d device %d took %u ms\n",
  2263. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2264. lun,
  2265. target,
  2266. timeDiff
  2267. ));
  2268. if (NT_SUCCESS(status) || (status == STATUS_DATA_OVERRUN)) {
  2269. DeviceInitDeviceType (
  2270. pdoExtension,
  2271. &InquiryData
  2272. );
  2273. //
  2274. // Init Ids String for PnP Query ID
  2275. //
  2276. DeviceInitIdStrings (
  2277. pdoExtension,
  2278. deviceType[target],
  2279. &InquiryData,
  2280. identifyData + target
  2281. );
  2282. //
  2283. // Clear rescan flag. Since this LogicalUnit will not be freed,
  2284. // the IOCTL_SCSI_MINIPORT requests can safely attach.
  2285. //
  2286. CLRMASK (pdoExtension->LuFlags, PD_RESCAN_ACTIVE);
  2287. DebugPrint((DBG_BUSSCAN,"IdePortScanBus: Found device at "));
  2288. DebugPrint((DBG_BUSSCAN," Bus %d", pdoExtension->PathId));
  2289. DebugPrint((DBG_BUSSCAN," Target Id %d", pdoExtension->TargetId));
  2290. DebugPrint((DBG_BUSSCAN," LUN %d\n", pdoExtension->Lun));
  2291. if (noPowerDown[target] ||
  2292. (pdoExtension->ScsiDeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE)) {
  2293. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  2294. SETMASK (pdoExtension->PdoState, PDOS_NO_POWER_DOWN);
  2295. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  2296. }
  2297. pdoExtension->IdentifyDataCheckSum = idDatacheckSum[target];
  2298. //
  2299. // done using the current logical unit extension
  2300. //
  2301. UnrefLogicalUnitExtensionWithTag (
  2302. FdoExtension,
  2303. pdoExtension,
  2304. IdePortScanBus
  2305. );
  2306. pdoExtension = NULL;
  2307. }
  2308. } else {
  2309. ASSERT (pdoExtension);
  2310. DebugPrint ((DBG_ALWAYS, "IdePort: unable to create new pdo\n"));
  2311. }
  2312. if (pdoExtension) {
  2313. if (!newPdo) {
  2314. DebugPrint((DBG_BUSSCAN, "IdePortScanBus: pdoe 0x%x is missing. (physically removed)\n", pdoExtension));
  2315. }
  2316. //
  2317. // get the pdo states
  2318. //
  2319. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  2320. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT);
  2321. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  2322. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  2323. pdoExtension = NULL;
  2324. }
  2325. }
  2326. }
  2327. //
  2328. // Get all PDOs ready
  2329. //
  2330. pathId.l = 0;
  2331. while (pdoExtension = NextLogUnitExtensionWithTag(
  2332. FdoExtension,
  2333. &pathId,
  2334. FALSE,
  2335. IdePortScanBus
  2336. )) {
  2337. //
  2338. // PO Idle Timer
  2339. //
  2340. DeviceRegisterIdleDetection (
  2341. pdoExtension,
  2342. DEVICE_DEFAULT_IDLE_TIMEOUT,
  2343. DEVICE_DEFAULT_IDLE_TIMEOUT
  2344. );
  2345. CLRMASK (pdoExtension->DeviceObject->Flags, DO_DEVICE_INITIALIZING);
  2346. UnrefLogicalUnitExtensionWithTag (
  2347. FdoExtension,
  2348. pdoExtension,
  2349. IdePortScanBus
  2350. );
  2351. }
  2352. //
  2353. // Update the device map.
  2354. //
  2355. ideDriverExtension = IoGetDriverObjectExtension(
  2356. FdoExtension->DriverObject,
  2357. DRIVER_OBJECT_EXTENSION_ID
  2358. );
  2359. IdeBuildDeviceMap(FdoExtension, &ideDriverExtension->RegistryPath);
  2360. }
  2361. timeDiff = LogBusScanStopTimer(&tickCount);
  2362. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[5], timeDiff);
  2363. DebugPrint((DBG_SPECIAL,
  2364. "BusScan: Last Stage scanning for %x took %u ms\n",
  2365. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2366. timeDiff
  2367. ));
  2368. //
  2369. // save current transfer mode setting in the registry
  2370. //
  2371. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  2372. ULONG mode;
  2373. pdoExtension = RefLogicalUnitExtensionWithTag(
  2374. FdoExtension,
  2375. 0,
  2376. (UCHAR) target,
  2377. 0,
  2378. TRUE,
  2379. IdePortScanBus
  2380. );
  2381. if (pdoExtension) {
  2382. mode = FdoExtension->HwDeviceExtension->DeviceParameters[target].TransferModeSelected;
  2383. if (pdoExtension->DmaTransferTimeoutCount >= PDO_DMA_TIMEOUT_LIMIT) {
  2384. mode &= PIO_SUPPORT;
  2385. lastKnownGoodTimingMode[target] &= PIO_SUPPORT;
  2386. }
  2387. UnrefLogicalUnitExtensionWithTag (
  2388. FdoExtension,
  2389. pdoExtension,
  2390. IdePortScanBus
  2391. );
  2392. IdePortSaveDeviceParameter(
  2393. FdoExtension,
  2394. IdePortRegistryDeviceTimingModeName[target],
  2395. mode
  2396. );
  2397. IdePortSaveDeviceParameter(
  2398. FdoExtension,
  2399. IdePortRegistryDeviceTimingModeAllowedName[target],
  2400. lastKnownGoodTimingMode[target]
  2401. );
  2402. IdePortSaveDeviceParameter(
  2403. FdoExtension,
  2404. IdePortRegistryIdentifyDataChecksum[target],
  2405. idDatacheckSum[target]
  2406. );
  2407. } else {
  2408. IdePortSaveDeviceParameter(
  2409. FdoExtension,
  2410. IdePortRegistryDeviceTimingModeName[target],
  2411. 0
  2412. );
  2413. }
  2414. }
  2415. done:
  2416. //
  2417. // unlock BUSSCAN code pages
  2418. //
  2419. #ifdef ALLOC_PRAGMA
  2420. InterlockedDecrement(&IdePAGESCANLockCount);
  2421. MmUnlockPagableImageSection(
  2422. pageScanCodePageHandle
  2423. );
  2424. #endif
  2425. return STATUS_SUCCESS;
  2426. }
  2427. BOOLEAN
  2428. IdePreAllocEnumStructs (
  2429. IN PFDO_EXTENSION FdoExtension
  2430. )
  2431. /**++
  2432. Routine Description:
  2433. Pre-Allocates Memory for structures used during enumertion. This is not protected by a lock.
  2434. Thus if multiple threads cannot use the structures at the same time. Any routine using these
  2435. structures should be aware of this fact.
  2436. Arguments:
  2437. FdoExtension : Functional Device Extension
  2438. Return Value:
  2439. TRUE: if allocations succeeded.
  2440. FALSE: if any of the allocations failed
  2441. --**/
  2442. {
  2443. PENUMERATION_STRUCT enumStruct;
  2444. PIRP irp1;
  2445. ULONG deviceRelationsSize;
  2446. PULONG DataBuffer;
  2447. ULONG currsize=0;
  2448. PIDE_WORK_ITEM_CONTEXT workItemContext;
  2449. PAGED_CODE();
  2450. //
  2451. // Lock
  2452. //
  2453. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 1, 0) == 0);
  2454. if (FdoExtension->PreAllocEnumStruct) {
  2455. //
  2456. // Unlock
  2457. //
  2458. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2459. return TRUE;
  2460. }
  2461. enumStruct = ExAllocatePool(NonPagedPool, sizeof(ENUMERATION_STRUCT));
  2462. if (enumStruct == NULL) {
  2463. //
  2464. // Unlock
  2465. //
  2466. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2467. ASSERT(FdoExtension->EnumStructLock == 0);
  2468. return FALSE;
  2469. }
  2470. currsize += sizeof(ENUMERATION_STRUCT);
  2471. RtlZeroMemory(enumStruct, sizeof(ENUMERATION_STRUCT));
  2472. //
  2473. // Allocate ATaPassThru context
  2474. //
  2475. enumStruct->Context = ExAllocatePool(NonPagedPool, sizeof (ATA_PASSTHROUGH_CONTEXT));
  2476. if (enumStruct->Context == NULL) {
  2477. goto getout;
  2478. }
  2479. currsize += sizeof(ATA_PASSTHROUGH_CONTEXT);
  2480. //
  2481. // Allocate the WorkItemContext for the enumeration
  2482. //
  2483. ASSERT(enumStruct->EnumWorkItemContext == NULL);
  2484. enumStruct->EnumWorkItemContext = ExAllocatePool (NonPagedPool,
  2485. sizeof(IDE_WORK_ITEM_CONTEXT)
  2486. );
  2487. if (enumStruct->EnumWorkItemContext == NULL) {
  2488. goto getout;
  2489. }
  2490. currsize += sizeof(IDE_WORK_ITEM_CONTEXT);
  2491. //
  2492. // Allocate the WorkItem
  2493. //
  2494. workItemContext = (PIDE_WORK_ITEM_CONTEXT) (enumStruct->EnumWorkItemContext);
  2495. workItemContext->WorkItem = IoAllocateWorkItem(FdoExtension->DeviceObject);
  2496. if (workItemContext->WorkItem == NULL) {
  2497. goto getout;
  2498. }
  2499. //
  2500. // StopQueu Context, used to stop the device queue
  2501. //
  2502. enumStruct->StopQContext = ExAllocatePool(NonPagedPool, sizeof (PDO_STOP_QUEUE_CONTEXT));
  2503. if (enumStruct->StopQContext == NULL) {
  2504. goto getout;
  2505. }
  2506. currsize += sizeof(PDO_STOP_QUEUE_CONTEXT);
  2507. //
  2508. // Sense Info buffer
  2509. //
  2510. enumStruct->SenseInfoBuffer = ExAllocatePool( NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
  2511. if (enumStruct->SenseInfoBuffer == NULL) {
  2512. goto getout;
  2513. }
  2514. currsize += SENSE_BUFFER_SIZE;
  2515. //
  2516. // Srb to send pass thru requests
  2517. //
  2518. enumStruct->Srb = ExAllocatePool (NonPagedPool, sizeof (SCSI_REQUEST_BLOCK));
  2519. if (enumStruct->Srb == NULL) {
  2520. goto getout;
  2521. }
  2522. currsize += sizeof(SCSI_REQUEST_BLOCK);
  2523. //
  2524. // irp for pass thru requests
  2525. //
  2526. irp1 = IoAllocateIrp (
  2527. (CCHAR) (PREALLOC_STACK_LOCATIONS),
  2528. FALSE
  2529. );
  2530. if (irp1 == NULL) {
  2531. goto getout;
  2532. }
  2533. enumStruct->Irp1 = irp1;
  2534. //
  2535. // Data buffer to hold inquiry data or Identify data
  2536. //
  2537. enumStruct->DataBufferSize = sizeof(ATA_PASS_THROUGH)+INQUIRYDATABUFFERSIZE+
  2538. sizeof(IDENTIFY_DATA);
  2539. currsize += enumStruct->DataBufferSize;
  2540. DataBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
  2541. enumStruct->DataBufferSize);
  2542. if (DataBuffer == NULL) {
  2543. enumStruct->DataBufferSize=0;
  2544. goto getout;
  2545. }
  2546. enumStruct->DataBuffer = DataBuffer;
  2547. enumStruct->MdlAddress = IoAllocateMdl( DataBuffer,
  2548. enumStruct->DataBufferSize,
  2549. FALSE,
  2550. FALSE,
  2551. (PIRP) NULL );
  2552. if (enumStruct->MdlAddress == NULL) {
  2553. goto getout;
  2554. }
  2555. MmBuildMdlForNonPagedPool(enumStruct->MdlAddress);
  2556. FdoExtension->PreAllocEnumStruct=enumStruct;
  2557. DebugPrint((DBG_BUSSCAN, "BusScan: TOTAL PRE_ALLOCED MEM=%x\n", currsize));
  2558. //
  2559. // Unlock
  2560. //
  2561. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2562. return TRUE;
  2563. getout:
  2564. //
  2565. // Some allocations failed. Free the already allocated ones.
  2566. //
  2567. IdeFreeEnumStructs(enumStruct);
  2568. FdoExtension->PreAllocEnumStruct=NULL;
  2569. //
  2570. // Unlock
  2571. //
  2572. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2573. ASSERT(FALSE);
  2574. return FALSE;
  2575. }
  2576. VOID
  2577. IdeFreeEnumStructs(
  2578. PENUMERATION_STRUCT enumStruct
  2579. )
  2580. /**++
  2581. Routine Description:
  2582. Frees the pre-allocated memory.
  2583. Arguments
  2584. Pointer to the Enumeration Structure that is to be freed
  2585. Return Value:
  2586. None
  2587. --**/
  2588. {
  2589. PAGED_CODE();
  2590. if (enumStruct != NULL) {
  2591. if (enumStruct->Context) {
  2592. ExFreePool (enumStruct->Context);
  2593. }
  2594. if (enumStruct->SenseInfoBuffer) {
  2595. ExFreePool (enumStruct->SenseInfoBuffer);
  2596. }
  2597. if (enumStruct->Srb) {
  2598. ExFreePool(enumStruct->Srb);
  2599. }
  2600. if (enumStruct->StopQContext) {
  2601. ExFreePool(enumStruct->StopQContext);
  2602. }
  2603. if (enumStruct->DataBuffer) {
  2604. ExFreePool(enumStruct->DataBuffer);
  2605. }
  2606. if (enumStruct->Irp1) {
  2607. IoFreeIrp(enumStruct->Irp1);
  2608. }
  2609. if (enumStruct->MdlAddress) {
  2610. ExFreePool(enumStruct->MdlAddress);
  2611. }
  2612. if (enumStruct->EnumWorkItemContext) {
  2613. PIDE_WORK_ITEM_CONTEXT workItemContext = (PIDE_WORK_ITEM_CONTEXT)enumStruct->
  2614. EnumWorkItemContext;
  2615. if (workItemContext->WorkItem) {
  2616. IoFreeWorkItem(workItemContext->WorkItem);
  2617. }
  2618. ExFreePool (enumStruct->EnumWorkItemContext);
  2619. }
  2620. ExFreePool(enumStruct);
  2621. enumStruct = NULL;
  2622. }
  2623. }