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

3298 lines
112 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 ENABLE_ATAPI_VERIFIER
  800. if (!Is98LegacyIde(cmdRegBase)) {
  801. //
  802. // simulate device change
  803. //
  804. if (deviceType == DeviceIsAta) {
  805. deviceType = DeviceIsAtapi;
  806. } else if (deviceType == DeviceIsAtapi) {
  807. deviceType = DeviceIsAta;
  808. }
  809. }
  810. #endif
  811. //
  812. // command to issue
  813. //
  814. RtlZeroMemory (identifyCommand, sizeof (identifyCommand));
  815. if (deviceType == DeviceNotExist) {
  816. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  817. PdoExtension->DeadmeatRecord.LineNumber
  818. );
  819. return DeviceNotExist;
  820. } else if (deviceType == DeviceIsAta) {
  821. identifyCommand[0].bCommandReg = IDE_COMMAND_IDENTIFY;
  822. identifyCommand[0].bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED | ATA_PTFLAGS_ENUM_PROBING;
  823. identifyCommand[1].bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
  824. identifyCommand[1].bReserved = ATA_PTFLAGS_ENUM_PROBING;
  825. } else {
  826. identifyCommand[0].bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
  827. identifyCommand[0].bReserved = ATA_PTFLAGS_ENUM_PROBING;
  828. identifyCommand[1].bCommandReg = IDE_COMMAND_IDENTIFY;
  829. identifyCommand[1].bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED | ATA_PTFLAGS_ENUM_PROBING;
  830. }
  831. //
  832. // IDE HACK
  833. //
  834. // If we are talking to a non-existing device, the
  835. // status register value may be unstable.
  836. // Reading it a few time seems to stablize it.
  837. //
  838. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  839. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  840. //
  841. // Repeat 10 times
  842. //
  843. ataPassThroughData->IdeReg.bSectorCountReg = 10;
  844. LogBusScanStartTimer(&tickCount);
  845. status = IssueSyncAtaPassThroughSafe (
  846. FdoExtension,
  847. PdoExtension,
  848. ataPassThroughData,
  849. FALSE,
  850. FALSE,
  851. 3,
  852. MustSucceed
  853. );
  854. timeDiff = LogBusScanStopTimer(&tickCount);
  855. DebugPrint((DBG_SPECIAL,
  856. "DetectDevice: Hack for device %d at %x took %u ms\n",
  857. PdoExtension->TargetId,
  858. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  859. timeDiff
  860. ));
  861. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  862. if (Is98LegacyIde(cmdRegBase)) {
  863. UCHAR driveHeadReg;
  864. driveHeadReg = ataPassThroughData->IdeReg.bDriveHeadReg;
  865. if (driveHeadReg != ((PdoExtension->TargetId & 0x1) << 4 | 0xA0)) {
  866. //
  867. // Bad controller.
  868. //
  869. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  870. PdoExtension->DeadmeatRecord.LineNumber
  871. );
  872. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  873. ataPassThroughData->IdeReg
  874. );
  875. return DeviceNotExist;
  876. }
  877. //
  878. // There are some H/W as follow...
  879. //
  880. if ((statusByte1 & 0xe8) == 0xa8) {
  881. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  882. PdoExtension->DeadmeatRecord.LineNumber
  883. );
  884. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  885. ataPassThroughData->IdeReg
  886. );
  887. return DeviceNotExist;
  888. }
  889. }
  890. if (statusByte1 == 0xff) {
  891. //
  892. // nothing here
  893. //
  894. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  895. PdoExtension->DeadmeatRecord.LineNumber
  896. );
  897. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  898. ataPassThroughData->IdeReg
  899. );
  900. return DeviceNotExist;
  901. }
  902. //
  903. // If the statusByte1 is 80 then try a reset
  904. //
  905. if (statusByte1 & IDE_STATUS_BUSY) {
  906. //
  907. // look like it is hung, try reset to bring it back
  908. //
  909. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  910. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_BUS_RESET;
  911. LogBusScanStartTimer(&tickCount);
  912. status = IssueSyncAtaPassThroughSafe(
  913. FdoExtension,
  914. PdoExtension,
  915. ataPassThroughData,
  916. FALSE,
  917. FALSE,
  918. 30,
  919. MustSucceed
  920. );
  921. timeDiff = LogBusScanStopTimer(&tickCount);
  922. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[0], timeDiff);
  923. DebugPrint((DBG_SPECIAL,
  924. "DtectDevice: Reset device %d ata %x took %u ms\n",
  925. PdoExtension->TargetId,
  926. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  927. timeDiff
  928. ));
  929. }
  930. LogBusScanStartTimer(&tickCount);
  931. retryCount = 0;
  932. for (i=0; i<2; i++) {
  933. BOOLEAN ataIdentify;
  934. ataIdentify = identifyCommand[i].bCommandReg == IDE_COMMAND_IDENTIFY ? TRUE : FALSE;
  935. if (ataIdentify) {
  936. //
  937. // IDE HACK
  938. //
  939. // If we are talking to a non-existing device, the
  940. // status register value may be unstable.
  941. // Reading it a few time seems to stablize it.
  942. //
  943. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  944. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  945. //
  946. // Repeat 10 times
  947. //
  948. ataPassThroughData->IdeReg.bSectorCountReg = 10;
  949. status = IssueSyncAtaPassThroughSafe(
  950. FdoExtension,
  951. PdoExtension,
  952. ataPassThroughData,
  953. FALSE,
  954. FALSE,
  955. 3,
  956. MustSucceed
  957. );
  958. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  959. //
  960. // a real ATA device should never return this
  961. //
  962. if ((statusByte1 == 0x00) ||
  963. (statusByte1 == 0x01)) {
  964. //
  965. // nothing here
  966. //
  967. continue;
  968. }
  969. deviceType = DeviceIsAta;
  970. if (Is98LegacyIde(cmdRegBase)) {
  971. UCHAR systemPortAData;
  972. //
  973. // dip-switch 2 read.
  974. //
  975. systemPortAData = IdePortInPortByte( (PUCHAR)SYSTEM_PORT_A );
  976. DebugPrint((DBG_BUSSCAN, "atapi:AtapiFindNewDevices - ide dip switch %x\n",systemPortAData));
  977. if (!(systemPortAData & 0x20)) {
  978. //
  979. // Internal-hd(ide) has been disabled with system-menu.
  980. //
  981. deviceType = DeviceNotExist;
  982. break;
  983. }
  984. }
  985. } else {
  986. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  987. ataPassThroughData->IdeReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_ENUM_PROBING;
  988. status = IssueSyncAtaPassThroughSafe (
  989. FdoExtension,
  990. PdoExtension,
  991. ataPassThroughData,
  992. FALSE,
  993. FALSE,
  994. 3,
  995. MustSucceed
  996. );
  997. statusByte1 = ataPassThroughData->IdeReg.bCommandReg;
  998. deviceType = DeviceIsAtapi;
  999. }
  1000. if ((statusByte1 == 0xff) ||
  1001. (statusByte1 == 0xfe)) {
  1002. //
  1003. // nothing here
  1004. //
  1005. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1006. PdoExtension->DeadmeatRecord.LineNumber
  1007. );
  1008. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1009. ataPassThroughData->IdeReg
  1010. );
  1011. deviceType = DeviceNotExist;
  1012. break;
  1013. }
  1014. //
  1015. // build the ata pass through the id data command
  1016. //
  1017. RtlZeroMemory (ataPassThroughData, sizeof (*ataPassThroughData));
  1018. ataPassThroughData->DataBufferSize = sizeof (*IdentifyData);
  1019. RtlMoveMemory (&ataPassThroughData->IdeReg, identifyCommand + i, sizeof(ataPassThroughData->IdeReg));
  1020. ASSERT(timeoutValue);
  1021. //
  1022. // Issue an id data command to the device
  1023. //
  1024. // some device (Kingston PCMCIA Datapak (non-flash)) takes a long time to response. we
  1025. // can possibly timeout even an device exists.
  1026. //
  1027. // we have to make a compromise here. We want to detect slow devices without causing
  1028. // many systems to boot slow.
  1029. //
  1030. // here is the logic:
  1031. //
  1032. // Since we are here (IsChannelEmpty() == FALSE), we are guessing we have at least
  1033. // one device attached and it is a master device. It should be ok to allow longer
  1034. // timeout when sending ID data to the master. We should never timeout unless
  1035. // the channel has only a slave device.
  1036. //
  1037. // Yes, we will not detect slow slave device for now. If anyone complain, we will
  1038. // fix it.
  1039. //
  1040. // You can never win as long as we have broken ATA devices!
  1041. //
  1042. status = IssueSyncAtaPassThroughSafe (
  1043. FdoExtension,
  1044. PdoExtension,
  1045. ataPassThroughData,
  1046. TRUE,
  1047. FALSE,
  1048. timeoutValue,
  1049. MustSucceed
  1050. );
  1051. //(PdoExtension->TargetId & 0x1)==0 ? 10 : 1,
  1052. if (NT_SUCCESS(status)) {
  1053. if (!(ataPassThroughData->IdeReg.bCommandReg & IDE_STATUS_ERROR)) {
  1054. DebugPrint ((DBG_BUSSCAN, "IdePort: Found a child on 0x%x target 0x%x\n", cmdRegBase->RegistersBaseAddress, PdoExtension->TargetId));
  1055. foundIt = TRUE;
  1056. if (ataIdentify) {
  1057. IdePortFudgeAtaIdentifyData(
  1058. (PIDENTIFY_DATA) ataPassThroughData->DataBuffer
  1059. );
  1060. }
  1061. break;
  1062. } else {
  1063. DebugPrint ((DBG_BUSSCAN, "AtapiDetectDevice:Command %x, 0x%x target 0x%x failed 0x%x with status 0x%x\n",
  1064. i,
  1065. cmdRegBase->RegistersBaseAddress,
  1066. PdoExtension->TargetId,
  1067. identifyCommand[i].bCommandReg,
  1068. ataPassThroughData->IdeReg.bCommandReg
  1069. ));
  1070. }
  1071. } else {
  1072. DebugPrint ((DBG_BUSSCAN, "AtapiDetectDevice:The irp with command %x, 0x%x target 0x%x failed 0x%x with status 0x%x\n",
  1073. i,
  1074. cmdRegBase->RegistersBaseAddress,
  1075. PdoExtension->TargetId,
  1076. identifyCommand[i].bCommandReg,
  1077. status
  1078. ));
  1079. deviceType = DeviceNotExist;
  1080. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1081. PdoExtension->DeadmeatRecord.LineNumber
  1082. );
  1083. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1084. ataPassThroughData->IdeReg
  1085. );
  1086. if ((FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId] & DFLAGS_DEVICE_PRESENT) &&
  1087. !(FdoExtension->HwDeviceExtension->DeviceFlags[PdoExtension->TargetId] & DFLAGS_ATAPI_DEVICE) &&
  1088. (retryCount < 2)) {
  1089. //
  1090. // BAD BAD BAD device
  1091. //
  1092. // SAMSUNG WU32543A (2.54GB)
  1093. //
  1094. // when it does a few UDMA transfers, it kind of forgets
  1095. // how to do ATA identify data so it looks like the device
  1096. // is gone.
  1097. //
  1098. // we better try harder to make sure if it is really gone
  1099. // we will do that by issuing a hard reset and try identify
  1100. // data again.
  1101. //
  1102. if (identifyCommand[i].bCommandReg == IDE_COMMAND_IDENTIFY) {
  1103. //
  1104. // ask for an "inline" hard reset before issuing identify command
  1105. //
  1106. identifyCommand[i].bReserved |= ATA_PTFLAGS_INLINE_HARD_RESET;
  1107. //
  1108. // redo the last command
  1109. //
  1110. i -= 1;
  1111. resetController = TRUE;
  1112. retryCount++;
  1113. }
  1114. } else {
  1115. if (status == STATUS_IO_TIMEOUT) {
  1116. //
  1117. // looks like there is no device there
  1118. // update the registry with a low timeout value if
  1119. // this is the slave device.
  1120. //
  1121. if ((PdoExtension->TargetId & 0x1) &&
  1122. defaultTimeout) {
  1123. //
  1124. // Use the timeout value of 1s for the next boot.
  1125. //
  1126. DebugPrint((1,
  1127. "Updating the registry with 1s value for device %d\n",
  1128. PdoExtension->TargetId
  1129. ));
  1130. IdePortSaveDeviceParameter(
  1131. FdoExtension,
  1132. IdePortRegistryDeviceTimeout[PdoExtension->TargetId],
  1133. 1
  1134. );
  1135. }
  1136. break;
  1137. }
  1138. }
  1139. }
  1140. //
  1141. // try the next command
  1142. //
  1143. }
  1144. timeDiff = LogBusScanStopTimer(&tickCount);
  1145. DebugPrint((DBG_SPECIAL,
  1146. "DetectDevice: Identify Data for device %d at %x took %u ms\n",
  1147. PdoExtension->TargetId,
  1148. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1149. timeDiff
  1150. ));
  1151. //
  1152. // save for the next boot
  1153. //
  1154. IdePortSaveDeviceParameter(
  1155. FdoExtension,
  1156. IdePortRegistryDeviceTypeName[PdoExtension->TargetId],
  1157. deviceType == DeviceNotExist? DeviceUnknown : deviceType
  1158. );
  1159. if (foundIt) {
  1160. RtlMoveMemory (IdentifyData, ataPassThroughData->DataBuffer, sizeof (*IdentifyData));
  1161. #if DBG
  1162. {
  1163. UCHAR string[41];
  1164. for (i=0; i<8; i+=2) {
  1165. string[i] = IdentifyData->FirmwareRevision[i + 1];
  1166. string[i + 1] = IdentifyData->FirmwareRevision[i];
  1167. }
  1168. string[i] = 0;
  1169. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: firmware version: %s\n", string));
  1170. for (i=0; i<40; i+=2) {
  1171. string[i] = IdentifyData->ModelNumber[i + 1];
  1172. string[i + 1] = IdentifyData->ModelNumber[i];
  1173. }
  1174. string[i] = 0;
  1175. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: model number: %s\n", string));
  1176. for (i=0; i<20; i+=2) {
  1177. string[i] = IdentifyData->SerialNumber[i + 1];
  1178. string[i + 1] = IdentifyData->SerialNumber[i];
  1179. }
  1180. string[i] = 0;
  1181. DebugPrint((DBG_BUSSCAN, "AtapiDetectDevice: serial number: %s\n", string));
  1182. }
  1183. #endif // DBG
  1184. } else {
  1185. deviceType = DeviceNotExist;
  1186. }
  1187. if (deviceType == DeviceNotExist) {
  1188. IdeLogDeadMeatEvent( PdoExtension->DeadmeatRecord.FileName,
  1189. PdoExtension->DeadmeatRecord.LineNumber
  1190. );
  1191. IdeLogDeadMeatTaskFile( PdoExtension->DeadmeatRecord.IdeReg,
  1192. ataPassThroughData->IdeReg
  1193. );
  1194. }
  1195. return deviceType;
  1196. }
  1197. NTSTATUS
  1198. IdePortSelectCHS (
  1199. IN OUT PFDO_EXTENSION FdoExtension,
  1200. IN ULONG Device,
  1201. IN PIDENTIFY_DATA IdentifyData
  1202. )
  1203. {
  1204. IN PHW_DEVICE_EXTENSION HwDeviceExtension;
  1205. BOOLEAN skipSetParameters = FALSE;
  1206. //
  1207. // Code is paged until locked down.
  1208. //
  1209. PAGED_CODE();
  1210. #ifdef ALLOC_PRAGMA
  1211. ASSERT(IdePAGESCANLockCount > 0);
  1212. #endif
  1213. ASSERT(FdoExtension);
  1214. ASSERT(IdentifyData);
  1215. HwDeviceExtension = FdoExtension->HwDeviceExtension;
  1216. ASSERT (HwDeviceExtension);
  1217. ASSERT(Device < HwDeviceExtension->MaxIdeDevice);
  1218. // LBA???
  1219. // We set the LBA flag in AnalyzeDeviceCapabilities.
  1220. //
  1221. if (!((HwDeviceExtension->DeviceFlags[Device] & DFLAGS_DEVICE_PRESENT) &&
  1222. (!(HwDeviceExtension->DeviceFlags[Device] & DFLAGS_ATAPI_DEVICE)))) {
  1223. return STATUS_SUCCESS;
  1224. }
  1225. if (!Is98LegacyIde(&HwDeviceExtension->BaseIoAddress1) &&
  1226. (((IdentifyData->NumberOfCurrentCylinders *
  1227. IdentifyData->NumberOfCurrentHeads *
  1228. IdentifyData->CurrentSectorsPerTrack) <
  1229. (IdentifyData->NumCylinders *
  1230. IdentifyData->NumHeads *
  1231. IdentifyData->NumSectorsPerTrack)) || // discover a larger drive
  1232. (IdentifyData->MajorRevision == 0) ||
  1233. ((IdentifyData->NumberOfCurrentCylinders == 0) ||
  1234. (IdentifyData->NumberOfCurrentHeads == 0) ||
  1235. (IdentifyData->CurrentSectorsPerTrack == 0))) ) {
  1236. HwDeviceExtension->NumberOfCylinders[Device] = IdentifyData->NumCylinders;
  1237. HwDeviceExtension->NumberOfHeads[Device] = IdentifyData->NumHeads;
  1238. HwDeviceExtension->SectorsPerTrack[Device] = IdentifyData->NumSectorsPerTrack;
  1239. } else {
  1240. HwDeviceExtension->NumberOfCylinders[Device] = IdentifyData->NumberOfCurrentCylinders;
  1241. HwDeviceExtension->NumberOfHeads[Device] = IdentifyData->NumberOfCurrentHeads;
  1242. HwDeviceExtension->SectorsPerTrack[Device] = IdentifyData->CurrentSectorsPerTrack;
  1243. }
  1244. if ((IdentifyData->NumCylinders != IdentifyData->NumberOfCurrentCylinders) ||
  1245. (IdentifyData->NumHeads != IdentifyData->NumberOfCurrentHeads) ||
  1246. (IdentifyData->NumSectorsPerTrack != IdentifyData->CurrentSectorsPerTrack)) {
  1247. DebugPrint ((
  1248. DBG_ALWAYS,
  1249. "0x%x device %d current CHS (%x,%x,%x) differs from default CHS (%x,%x,%x)\n",
  1250. HwDeviceExtension->BaseIoAddress1.RegistersBaseAddress,
  1251. Device,
  1252. IdentifyData->NumberOfCurrentCylinders,
  1253. IdentifyData->NumberOfCurrentHeads,
  1254. IdentifyData->CurrentSectorsPerTrack,
  1255. IdentifyData->NumCylinders,
  1256. IdentifyData->NumHeads,
  1257. IdentifyData->NumSectorsPerTrack
  1258. ));
  1259. }
  1260. //
  1261. // This hideous hack is to deal with ESDI devices that return
  1262. // garbage geometry in the IDENTIFY data.
  1263. // This is ONLY for the crashdump environment as
  1264. // these are ESDI devices.
  1265. //
  1266. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1267. 0x35 &&
  1268. HwDeviceExtension->NumberOfHeads[Device] ==
  1269. 0x07) {
  1270. DebugPrint((DBG_ALWAYS,
  1271. "FindDevices: Fix up the geometry for ESDI!\n"));
  1272. //
  1273. // Change these values to something reasonable.
  1274. //
  1275. HwDeviceExtension->SectorsPerTrack[Device] =
  1276. 0x34;
  1277. HwDeviceExtension->NumberOfHeads[Device] =
  1278. 0x0E;
  1279. }
  1280. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1281. 0x35 &&
  1282. HwDeviceExtension->NumberOfHeads[Device] ==
  1283. 0x0F) {
  1284. DebugPrint((DBG_ALWAYS,
  1285. "FindDevices: Fix up the geometry for ESDI!\n"));
  1286. //
  1287. // Change these values to something reasonable.
  1288. //
  1289. HwDeviceExtension->SectorsPerTrack[Device] =
  1290. 0x34;
  1291. HwDeviceExtension->NumberOfHeads[Device] =
  1292. 0x0F;
  1293. }
  1294. if (HwDeviceExtension->SectorsPerTrack[Device] ==
  1295. 0x36 &&
  1296. HwDeviceExtension->NumberOfHeads[Device] ==
  1297. 0x07) {
  1298. DebugPrint((DBG_ALWAYS,
  1299. "FindDevices: Fix up the geometry for ESDI!\n"));
  1300. //
  1301. // Change these values to something reasonable.
  1302. //
  1303. HwDeviceExtension->SectorsPerTrack[Device] =
  1304. 0x3F;
  1305. HwDeviceExtension->NumberOfHeads[Device] =
  1306. 0x10;
  1307. skipSetParameters = TRUE;
  1308. }
  1309. if (Is98LegacyIde(&HwDeviceExtension->BaseIoAddress1)) {
  1310. skipSetParameters = TRUE;
  1311. }
  1312. if (!skipSetParameters) {
  1313. PIDE_REGISTERS_1 baseIoAddress1 = &HwDeviceExtension->BaseIoAddress1;
  1314. PIDE_REGISTERS_2 baseIoAddress2 = &HwDeviceExtension->BaseIoAddress2;
  1315. UCHAR statusByte;
  1316. DebugPrintTickCount (FindDeviceTimer, 0);
  1317. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1318. //
  1319. // Select the device.
  1320. //
  1321. SelectIdeDevice(baseIoAddress1, Device, 0);
  1322. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1323. WaitOnBusy(baseIoAddress1,statusByte);
  1324. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1325. if (statusByte & IDE_STATUS_BUSY) {
  1326. ULONG waitCount = 20000;
  1327. DebugPrintTickCount (FindDeviceTimer, 0);
  1328. //
  1329. // Reset the device.
  1330. //
  1331. DebugPrint((2,
  1332. "FindDevices: Resetting controller before SetDriveParameters.\n"));
  1333. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1334. IdeHardReset (
  1335. baseIoAddress1,
  1336. baseIoAddress2,
  1337. FALSE,
  1338. TRUE
  1339. );
  1340. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1341. DebugPrintTickCount (FindDeviceTimer, 0);
  1342. }
  1343. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1344. WaitOnBusy(baseIoAddress1,statusByte);
  1345. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1346. DebugPrintTickCount (FindDeviceTimer, 0);
  1347. DebugPrint((2,
  1348. "FindDevices: Status before SetDriveParameters: (%x) (%x)\n",
  1349. statusByte,
  1350. IdePortInPortByte (baseIoAddress1->DriveSelect)));
  1351. //
  1352. // Use the IDENTIFY data to set drive parameters.
  1353. //
  1354. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1355. if (!SetDriveParameters(HwDeviceExtension,Device,TRUE)) {
  1356. DebugPrint((0,
  1357. "IdePortFixUpCHS: Set drive parameters for device %d failed\n",
  1358. Device));
  1359. //
  1360. // Don't use this device as writes could cause corruption.
  1361. //
  1362. HwDeviceExtension->DeviceFlags[Device] = 0;
  1363. }
  1364. DebugPrint ((DBG_BUSSCAN, "IdePortSelectCHS: %s %d\n", __FILE__, __LINE__));
  1365. }
  1366. return STATUS_SUCCESS;
  1367. }
  1368. NTSTATUS
  1369. IdePortScanBus (
  1370. IN OUT PFDO_EXTENSION FdoExtension
  1371. )
  1372. /**++
  1373. Routine Description:
  1374. Scans the IDE bus (channel) for devices. It also configures the detected devices.
  1375. The "safe" routines used in the procedure are not thread-safe, they use pre-allocated
  1376. memory. The important steps in the enumeration of a channel are:
  1377. 1. Detect the devices on the channel
  1378. 2. Stop all the device queues
  1379. 3. Determine and set the transfer modes and the other flags
  1380. 4. Start all the device queues
  1381. 5. IssueInquiry
  1382. Arguments:
  1383. FdoExtension: Functional device extension
  1384. Return Value:
  1385. STATUS_SUCCESS : if the operation succeeded
  1386. Failure status : if the operation fails
  1387. --**/
  1388. {
  1389. NTSTATUS status;
  1390. IDE_PATH_ID pathId;
  1391. ULONG target;
  1392. ULONG lun;
  1393. PPDO_EXTENSION pdoExtension;
  1394. PHW_DEVICE_EXTENSION hwDeviceExtension;
  1395. PIDEDRIVER_EXTENSION ideDriverExtension;
  1396. INQUIRYDATA InquiryData;
  1397. IDENTIFY_DATA identifyData[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1398. ULONG idDatacheckSum[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1399. SPECIAL_ACTION_FLAG specialAction[MAX_IDE_TARGETID*MAX_IDE_LINE];
  1400. IDE_DEVICETYPE deviceType[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1401. BOOLEAN mustBePio[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1402. BOOLEAN pioByDefault[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1403. UCHAR flushCommand[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1404. BOOLEAN removableMedia[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1405. BOOLEAN isLs120[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1406. BOOLEAN noPowerDown[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1407. BOOLEAN isSameDevice[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1408. ULONG lastKnownGoodTimingMode[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1409. ULONG savedTransferMode[MAX_IDE_TARGETID * MAX_IDE_LINE];
  1410. PULONG enableBigLba;
  1411. ULONG numSlot=0;
  1412. ULONG numPdoChildren;
  1413. UCHAR targetModelNum[MAX_MODELNUM_SIZE+sizeof('\0')]; //extra bytes for '\0'
  1414. HANDLE pageScanCodePageHandle;
  1415. BOOLEAN newPdo;
  1416. BOOLEAN check4EmptyChannel;
  1417. BOOLEAN emptyChannel;
  1418. BOOLEAN mustSucceed=TRUE;
  1419. KIRQL currentIrql;
  1420. BOOLEAN inSetup;
  1421. PULONG waitOnPowerUp;
  1422. LARGE_INTEGER tickCount;
  1423. ULONG timeDiff;
  1424. LARGE_INTEGER totalDeviceDetectionTime;
  1425. totalDeviceDetectionTime.QuadPart = 0;
  1426. //
  1427. // This macro is used in IdePortScanBus
  1428. //
  1429. #define RefLuExt(pdoExtension, fdoExtension, pathId, removedOk, newPdo) {\
  1430. pdoExtension = RefLogicalUnitExtensionWithTag( \
  1431. fdoExtension, \
  1432. (UCHAR) pathId.b.Path, \
  1433. (UCHAR) pathId.b.TargetId, \
  1434. (UCHAR) pathId.b.Lun, \
  1435. removedOk, \
  1436. IdePortScanBus \
  1437. ); \
  1438. if (pdoExtension == NULL) { \
  1439. pdoExtension = AllocatePdoWithTag( \
  1440. fdoExtension, \
  1441. pathId, \
  1442. IdePortScanBus \
  1443. ); \
  1444. newPdo = TRUE; \
  1445. } \
  1446. }
  1447. //
  1448. // This macro is used in IdePortScanBus
  1449. //
  1450. #define UnRefLuExt(pdoExtension, fdoExtension, sync, callIoDeleteDevice, newPdo) { \
  1451. if (newPdo) { \
  1452. FreePdoWithTag( \
  1453. pdoExtension, \
  1454. sync, \
  1455. callIoDeleteDevice, \
  1456. IdePortScanBus \
  1457. ); \
  1458. } else { \
  1459. UnrefLogicalUnitExtensionWithTag ( \
  1460. fdoExtension, \
  1461. pdoExtension, \
  1462. IdePortScanBus \
  1463. ); \
  1464. } \
  1465. }
  1466. //
  1467. // Before getting in to this critical region, we must lock down
  1468. // all the code and data because we may have stopped the paging
  1469. // device!
  1470. //
  1471. // lock down all code that belongs to PAGESCAN
  1472. //
  1473. #ifdef ALLOC_PRAGMA
  1474. pageScanCodePageHandle = MmLockPagableCodeSection(
  1475. IdePortScanBus
  1476. );
  1477. InterlockedIncrement(&IdePAGESCANLockCount);
  1478. #endif
  1479. ASSERT(FdoExtension);
  1480. ASSERT(FdoExtension->PreAllocEnumStruct);
  1481. hwDeviceExtension = FdoExtension->HwDeviceExtension;
  1482. if (FdoExtension->InterruptObject == NULL) {
  1483. //
  1484. // we are started with no irq. it means
  1485. // we have no children. it is ok to poke
  1486. // at the ports directly
  1487. //
  1488. if (IdePortChannelEmpty (&hwDeviceExtension->BaseIoAddress1,
  1489. &hwDeviceExtension->BaseIoAddress2,
  1490. hwDeviceExtension->MaxIdeDevice) == FALSE) {
  1491. //
  1492. // this channel is started with out an irq
  1493. // it was because the channel looked empty
  1494. // but, now it doesn't look empty. we need
  1495. // to restart with an irq resource
  1496. //
  1497. if (FdoExtension->RequestProperResourceInterface) {
  1498. FdoExtension->RequestProperResourceInterface (FdoExtension->AttacheePdo);
  1499. }
  1500. else {
  1501. DebugPrint((DBG_ALWAYS,
  1502. "No interface to request resources. Probably a pcmcia parent\n"));
  1503. }
  1504. }
  1505. goto done;
  1506. }
  1507. DebugPrint ((
  1508. DBG_BUSSCAN,
  1509. "IdePort: scan bus 0x%x\n",
  1510. FdoExtension->IdeResource.TranslatedCommandBaseAddress
  1511. ));
  1512. inSetup = IdePortInSetup(FdoExtension);
  1513. DebugPrint((DBG_BUSSCAN,
  1514. "ATAPI: insetup = 0x%x\n",
  1515. inSetup? 1: 0
  1516. ));
  1517. waitOnPowerUp = NULL;
  1518. IdePortGetParameterFromServiceSubKey (
  1519. FdoExtension->DriverObject,
  1520. L"WaitOnBusyOnPowerUp",
  1521. REG_DWORD,
  1522. TRUE,
  1523. (PVOID) &waitOnPowerUp,
  1524. 0
  1525. );
  1526. FdoExtension->WaitOnPowerUp = PtrToUlong(waitOnPowerUp);
  1527. check4EmptyChannel = FALSE;
  1528. FdoExtension->DeviceChanged = FALSE;
  1529. pathId.l = 0;
  1530. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  1531. pathId.b.TargetId = target;
  1532. pathId.b.Lun = 0;
  1533. newPdo = FALSE;
  1534. mustBePio[target] = FALSE;
  1535. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  1536. if (!newPdo && (pdoExtension->PdoState & PDOS_DEADMEAT)) {
  1537. //
  1538. // device marked dead already
  1539. //
  1540. UnrefLogicalUnitExtensionWithTag (
  1541. FdoExtension,
  1542. pdoExtension,
  1543. IdePortScanBus
  1544. );
  1545. ASSERT (FALSE);
  1546. pdoExtension = NULL;
  1547. }
  1548. if (!pdoExtension) {
  1549. DebugPrint ((DBG_ALWAYS,
  1550. "ATAPI: IdePortScanBus() is unable to get pdo (%d,%d,%d)\n",
  1551. pathId.b.Path,
  1552. pathId.b.TargetId,
  1553. pathId.b.Lun));
  1554. deviceType[target] = DeviceNotExist;
  1555. continue;
  1556. }
  1557. if (!check4EmptyChannel) {
  1558. ULONG i;
  1559. UCHAR statusByte1;
  1560. ATA_PASS_THROUGH ataPassThroughData;
  1561. check4EmptyChannel = TRUE;
  1562. //
  1563. // make sure the channel is not empty
  1564. //
  1565. RtlZeroMemory (&ataPassThroughData, sizeof (ataPassThroughData));
  1566. ataPassThroughData.IdeReg.bReserved = ATA_PTFLAGS_EMPTY_CHANNEL_TEST;
  1567. LogBusScanStartTimer(&tickCount);
  1568. status = IssueSyncAtaPassThroughSafe(
  1569. FdoExtension,
  1570. pdoExtension,
  1571. &ataPassThroughData,
  1572. FALSE,
  1573. FALSE,
  1574. 30,
  1575. TRUE
  1576. );
  1577. if (NT_SUCCESS(status)) {
  1578. emptyChannel = TRUE;
  1579. } else {
  1580. emptyChannel = FALSE;
  1581. }
  1582. timeDiff = LogBusScanStopTimer(&tickCount);
  1583. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[1], timeDiff);
  1584. DebugPrint((DBG_SPECIAL,
  1585. "BusScan: Empty Channel check for fdoe %x took %u ms\n",
  1586. FdoExtension,
  1587. timeDiff
  1588. ));
  1589. }
  1590. LogBusScanStartTimer(&tickCount);
  1591. if (!emptyChannel) {
  1592. deviceType[target] = AtapiDetectDevice (FdoExtension, pdoExtension,
  1593. identifyData + target, TRUE);
  1594. if (deviceType[target] != DeviceNotExist) {
  1595. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_DEVICE_PRESENT);
  1596. if (deviceType[target] == DeviceIsAtapi) {
  1597. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_ATAPI_DEVICE);
  1598. }
  1599. //
  1600. // Check for special action requests for the device
  1601. //
  1602. GetTargetModelId((identifyData+target), targetModelNum);
  1603. specialAction[target] = IdeFindSpecialDevice(targetModelNum, NULL);
  1604. if (specialAction[target] == setFlagSonyMemoryStick ) {
  1605. ULONG i;
  1606. // SonyMemoryStick device.
  1607. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_SONY_MEMORYSTICK);
  1608. //
  1609. // Truncate the hardware id, so that the size of
  1610. // the memory stick is not included in it.
  1611. //
  1612. for (i=strlen("MEMORYSTICK");i<sizeof((identifyData+target)->ModelNumber);i++) {
  1613. (identifyData+target)->ModelNumber[i+1]='\0';
  1614. }
  1615. }
  1616. }
  1617. else {
  1618. DebugPrint((DBG_BUSSCAN, "Didn't detect the device %d\n", target));
  1619. }
  1620. } else {
  1621. DebugPrint((DBG_SPECIAL,
  1622. "BusScan: IdeDevicePresent %x detected no device %d\n",
  1623. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1624. target
  1625. ));
  1626. //
  1627. // invalidate the last boot configuration
  1628. //
  1629. IdePortSaveDeviceParameter(
  1630. FdoExtension,
  1631. IdePortRegistryDeviceTypeName[pdoExtension->TargetId],
  1632. DeviceUnknown
  1633. );
  1634. deviceType[target] = DeviceNotExist;
  1635. }
  1636. ASSERT (deviceType[target] <= DeviceNotExist);
  1637. timeDiff = LogBusScanStopTimer(&tickCount);
  1638. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[2+target], timeDiff);
  1639. DebugPrint((DBG_SPECIAL,
  1640. "BusScan: Detect device %d for %x took %u ms\n",
  1641. target,
  1642. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1643. timeDiff
  1644. ));
  1645. totalDeviceDetectionTime.QuadPart += timeDiff;
  1646. ASSERT (deviceType[target] <= DeviceNotExist);
  1647. ASSERT (deviceType[target] != DeviceUnknown);
  1648. ASSERT (pdoExtension->TargetId == target);
  1649. if (deviceType[target] != DeviceNotExist) {
  1650. if (target & 1) {
  1651. if (deviceType[(LONG) target - 1] != DeviceNotExist) {
  1652. if (IdePortSlaveIsGhost (
  1653. FdoExtension,
  1654. identifyData + target - 1,
  1655. identifyData + target - 0)) {
  1656. //
  1657. // remove the slave device
  1658. //
  1659. deviceType[target] = DeviceNotExist;
  1660. }
  1661. }
  1662. }
  1663. }
  1664. ASSERT (deviceType[target] <= DeviceNotExist);
  1665. if (deviceType[target] == DeviceNotExist) {
  1666. CLRMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_IDENTIFY_VALID);
  1667. if (FdoExtension->HwDeviceExtension->DeviceFlags[target] & DFLAGS_DEVICE_PRESENT) {
  1668. IDE_PATH_ID tempPathId;
  1669. PPDO_EXTENSION deadPdoExtension;
  1670. //
  1671. // device went away
  1672. //
  1673. FdoExtension->DeviceChanged = TRUE;
  1674. //
  1675. // mark all PDOs for the missing device DEADMEAT
  1676. //
  1677. tempPathId.l = 0;
  1678. tempPathId.b.TargetId = target;
  1679. while (deadPdoExtension = NextLogUnitExtensionWithTag(
  1680. FdoExtension,
  1681. &tempPathId,
  1682. TRUE,
  1683. (PVOID) (~(ULONG_PTR)IdePortScanBus)
  1684. )) {
  1685. if (deadPdoExtension->TargetId == target) {
  1686. DebugPrint((DBG_BUSSCAN, "Enum Failed for target=%d, PDOe=0x%x\n",
  1687. target, deadPdoExtension));
  1688. KeAcquireSpinLock(&deadPdoExtension->PdoSpinLock, &currentIrql);
  1689. SETMASK (deadPdoExtension->PdoState, PDOS_DEADMEAT);
  1690. IdeLogDeadMeatReason( deadPdoExtension->DeadmeatRecord.Reason,
  1691. enumFailed;
  1692. );
  1693. KeReleaseSpinLock(&deadPdoExtension->PdoSpinLock, currentIrql);
  1694. UnrefPdoWithTag (deadPdoExtension, (PVOID) (~(ULONG_PTR)IdePortScanBus));
  1695. } else {
  1696. UnrefPdoWithTag (deadPdoExtension, (PVOID) (~(ULONG_PTR)IdePortScanBus));
  1697. break;
  1698. }
  1699. }
  1700. }
  1701. } else {
  1702. idDatacheckSum[target] = IdePortSimpleCheckSum (
  1703. 0,
  1704. identifyData[target].ModelNumber,
  1705. sizeof(identifyData[target].ModelNumber)
  1706. );
  1707. idDatacheckSum[target] += IdePortSimpleCheckSum (
  1708. idDatacheckSum[target],
  1709. identifyData[target].SerialNumber,
  1710. sizeof(identifyData[target].SerialNumber)
  1711. );
  1712. idDatacheckSum[target] += IdePortSimpleCheckSum (
  1713. idDatacheckSum[target],
  1714. identifyData[target].FirmwareRevision,
  1715. sizeof(identifyData[target].FirmwareRevision)
  1716. );
  1717. if (newPdo) {
  1718. //
  1719. // new device
  1720. //
  1721. FdoExtension->DeviceChanged = TRUE;
  1722. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Found a new device. pdoe = x%x\n", pdoExtension));
  1723. } else {
  1724. #ifdef ENABLE_ATAPI_VERIFIER
  1725. idDatacheckSum[target] += ViIdeFakeDeviceChange(FdoExtension, target);
  1726. #endif //ENABLE_ATAPI_VERIFIER
  1727. if (idDatacheckSum[target] != pdoExtension->IdentifyDataCheckSum) {
  1728. FdoExtension->DeviceChanged = TRUE;
  1729. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: bad bad bad user. a device is replaced by a different device. pdoe = x%x\n", pdoExtension));
  1730. //
  1731. // mark the old device deadmeat
  1732. //
  1733. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  1734. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT | PDOS_NEED_RESCAN);
  1735. IdeLogDeadMeatReason( pdoExtension->DeadmeatRecord.Reason,
  1736. replacedByUser;
  1737. );
  1738. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  1739. //
  1740. // pretend we have seen the new device.
  1741. // we will re-enum when the old one is removed.
  1742. //
  1743. deviceType[target] = DeviceNotExist;
  1744. }
  1745. }
  1746. }
  1747. ASSERT (deviceType[target] <= DeviceNotExist);
  1748. if (deviceType[target] != DeviceNotExist) {
  1749. ULONG savedIdDataCheckSum;
  1750. mustBePio[target] = IdePortMustBePio (
  1751. FdoExtension,
  1752. identifyData + target
  1753. );
  1754. pioByDefault[target] = IdePortPioByDefaultDevice (
  1755. FdoExtension,
  1756. identifyData + target
  1757. );
  1758. ASSERT (deviceType[target] <= DeviceNotExist);
  1759. LogBusScanStartTimer(&tickCount);
  1760. flushCommand[target] = IDE_COMMAND_NO_FLUSH;
  1761. //
  1762. // we need this only for ata devices
  1763. //
  1764. if (deviceType[target] != DeviceIsAtapi) {
  1765. flushCommand[target] = IdePortGetFlushCommand (
  1766. FdoExtension,
  1767. pdoExtension,
  1768. identifyData + target
  1769. );
  1770. }
  1771. timeDiff = LogBusScanStopTimer(&tickCount);
  1772. DebugPrint((DBG_SPECIAL,
  1773. "BusScan: Flush command for device %d at %x took %u ms\n",
  1774. target,
  1775. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  1776. timeDiff
  1777. ));
  1778. ASSERT (deviceType[target] <= DeviceNotExist);
  1779. removableMedia[target] = IdePortDeviceHasNonRemovableMedia (
  1780. FdoExtension,
  1781. identifyData + target
  1782. );
  1783. ASSERT (deviceType[target] <= DeviceNotExist);
  1784. isLs120[target] = IdePortDeviceIsLs120 (
  1785. FdoExtension,
  1786. identifyData + target
  1787. );
  1788. ASSERT (deviceType[target] <= DeviceNotExist);
  1789. noPowerDown[target] = IdePortNoPowerDown (
  1790. FdoExtension,
  1791. identifyData + target
  1792. );
  1793. ASSERT (deviceType[target] <= DeviceNotExist);
  1794. //
  1795. // init. the default value to an abnormal #.
  1796. //
  1797. FdoExtension->UserChoiceTransferMode[target] = 0x12345678;
  1798. IdePortGetDeviceParameter(
  1799. FdoExtension,
  1800. IdePortRegistryUserDeviceTimingModeAllowedName[target],
  1801. FdoExtension->UserChoiceTransferMode + target
  1802. );
  1803. if (FdoExtension->UserChoiceTransferMode[target] == 0x12345678) {
  1804. //
  1805. // This value is used to decide whether a user choice was indicated
  1806. // or not. This helps us to set the transfer mode to a default value
  1807. // if the user doesn't choose a particular transfer mode. Otherwise we
  1808. // honour the user choice.
  1809. //
  1810. FdoExtension->UserChoiceTransferMode[target] = UNINITIALIZED_TRANSFER_MODE;
  1811. //
  1812. // we know the register doesn't have what we are looking for
  1813. // set the default atapi-override setting to a value
  1814. // that will force pio only on atapi device
  1815. //
  1816. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = PIO_SUPPORT;
  1817. } else {
  1818. //
  1819. // user acutally picked the transfer mode settings.
  1820. // set the default atapi-override setting to a value (-1)
  1821. // that will not affect the user choice.
  1822. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = MAXULONG;
  1823. }
  1824. //
  1825. // get the previous mode
  1826. //
  1827. IdePortGetDeviceParameter(
  1828. FdoExtension,
  1829. IdePortRegistryDeviceTimingModeName[target],
  1830. savedTransferMode+target
  1831. );
  1832. savedIdDataCheckSum = 0;
  1833. IdePortGetDeviceParameter(
  1834. FdoExtension,
  1835. IdePortRegistryIdentifyDataChecksum[target],
  1836. &savedIdDataCheckSum
  1837. );
  1838. ASSERT (deviceType[target] <= DeviceNotExist);
  1839. //
  1840. // figure out what transfer mode we can use
  1841. //
  1842. if (savedIdDataCheckSum == idDatacheckSum[target]) {
  1843. //
  1844. // same device. if we program the same transfer mode then
  1845. // we can skip the DMA test
  1846. //
  1847. isSameDevice[target] = TRUE;
  1848. //
  1849. // it is the same device, use
  1850. // the lastKnownGoodTimingMode
  1851. // in the registry
  1852. //
  1853. lastKnownGoodTimingMode[target] = MAXULONG;
  1854. IdePortGetDeviceParameter(
  1855. FdoExtension,
  1856. IdePortRegistryDeviceTimingModeAllowedName[target],
  1857. lastKnownGoodTimingMode + target
  1858. );
  1859. } else {
  1860. isSameDevice[target] = FALSE;
  1861. lastKnownGoodTimingMode[target] = MAXULONG;
  1862. }
  1863. ASSERT (deviceType[target] <= DeviceNotExist);
  1864. FdoExtension->TimingModeAllowed[target] =
  1865. lastKnownGoodTimingMode[target] &
  1866. FdoExtension->UserChoiceTransferMode[target];
  1867. //
  1868. // TransferModeMask is initially 0.
  1869. //
  1870. FdoExtension->TimingModeAllowed[target] &= ~(hwDeviceExtension->
  1871. DeviceParameters[target].TransferModeMask);
  1872. if (pdoExtension->CrcErrorCount >= PDO_UDMA_CRC_ERROR_LIMIT) {
  1873. //
  1874. //Reset the error count
  1875. //
  1876. pdoExtension->CrcErrorCount =0;
  1877. }
  1878. DebugPrint ((DBG_XFERMODE, "TMAllowed=%x, TMMask=%x, UserChoice=%x\n",
  1879. FdoExtension->TimingModeAllowed[target],
  1880. hwDeviceExtension->DeviceParameters[target].TransferModeMask,
  1881. FdoExtension->UserChoiceTransferMode[target]));
  1882. ASSERT (deviceType[target] <= DeviceNotExist);
  1883. }
  1884. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  1885. pdoExtension = NULL;
  1886. }
  1887. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  1888. if (FdoExtension->BusScanTime == 0) {
  1889. FdoExtension->BusScanTime = totalDeviceDetectionTime.LowPart;
  1890. }
  1891. #endif // IDE_MEASURE_BUSSCAN_SPEED
  1892. #ifdef ENABLE_48BIT_LBA
  1893. //
  1894. // enable big lba support by default
  1895. //
  1896. FdoExtension->EnableBigLba = 1;
  1897. #endif
  1898. // if (!deviceChanged && !DBG) {
  1899. //
  1900. // //
  1901. // // didn't find anything different than before
  1902. // //
  1903. // return STATUS_SUCCESS;
  1904. // }
  1905. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: detect a change of device...re-initializing\n"));
  1906. // ISSUE: check if device got removed!!!
  1907. //
  1908. // Begin of a critial region
  1909. // must stop all children, do the stuff, and restart all children
  1910. //
  1911. //
  1912. // cycle through all children and stop their device queue
  1913. //
  1914. LogBusScanStartTimer(&tickCount);
  1915. pathId.l = 0;
  1916. numPdoChildren = 0;
  1917. status = STATUS_SUCCESS;
  1918. while (pdoExtension = NextLogUnitExtensionWithTag(
  1919. FdoExtension,
  1920. &pathId,
  1921. TRUE,
  1922. IdePortScanBus
  1923. )) {
  1924. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: stopping pdo 0x%x\n", pdoExtension));
  1925. status = DeviceStopDeviceQueueSafe (pdoExtension, PDOS_QUEUE_FROZEN_BY_PARENT, TRUE);
  1926. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: stopped pdo 0x%x\n", pdoExtension));
  1927. UnrefLogicalUnitExtensionWithTag (
  1928. FdoExtension,
  1929. pdoExtension,
  1930. IdePortScanBus
  1931. );
  1932. numPdoChildren++;
  1933. if (!NT_SUCCESS(status)) {
  1934. break;
  1935. }
  1936. }
  1937. if (NT_SUCCESS(status)) {
  1938. BOOLEAN foundAtLeastOneIdeDevice = FALSE;
  1939. BOOLEAN useDma;
  1940. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: all children are stoped\n"));
  1941. pathId.l = 0;
  1942. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  1943. ASSERT (deviceType[target] <= DeviceNotExist);
  1944. if (deviceType[target] != DeviceNotExist) {
  1945. pathId.b.TargetId = target;
  1946. newPdo = FALSE;
  1947. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  1948. if (!pdoExtension) {
  1949. continue;
  1950. }
  1951. ASSERT (pdoExtension);
  1952. foundAtLeastOneIdeDevice = TRUE;
  1953. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_DEVICE_PRESENT);
  1954. if (deviceType[target] == DeviceIsAtapi) {
  1955. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_ATAPI_DEVICE);
  1956. useDma=FALSE;
  1957. //
  1958. // skip the dvd test, if ModeSense command is not to be
  1959. // sent to the device or if we are in setup
  1960. //
  1961. if (inSetup) {
  1962. mustBePio[target] = TRUE;
  1963. } else if ((specialAction[target] != skipModeSense) &&
  1964. (!pioByDefault[target])) {
  1965. useDma = IdePortDmaCdromDrive(FdoExtension,
  1966. pdoExtension,
  1967. TRUE
  1968. );
  1969. }
  1970. //
  1971. // Don't force PIO if we have seen this before. If it was doing PIO
  1972. // TimingModeAllowed would reflect that.
  1973. // Set UserChoiceForAtapi to 0xffffffff
  1974. // This won't anyway affect the user choice
  1975. //
  1976. if ( useDma) {
  1977. DebugPrint((DBG_BUSSCAN,
  1978. "IdePortScanBus: USE DMA FOR target %d\n",
  1979. target
  1980. ));
  1981. FdoExtension->UserChoiceTransferModeForAtapiDevice[target] = MAXULONG;
  1982. }
  1983. FdoExtension->TimingModeAllowed[target] &=
  1984. FdoExtension->UserChoiceTransferModeForAtapiDevice[target];
  1985. }
  1986. //
  1987. // allow LS-120 Format Command
  1988. //
  1989. if (isLs120[target]) {
  1990. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_LS120_FORMAT);
  1991. }
  1992. RtlMoveMemory (
  1993. hwDeviceExtension->IdentifyData + target,
  1994. identifyData + target,
  1995. sizeof (IDENTIFY_DATA)
  1996. );
  1997. //
  1998. // Always re-use identify data
  1999. // This will get cleared if it is a removable media
  2000. // The queue is stopped. Now I can safely set this flag.
  2001. //
  2002. SETMASK (hwDeviceExtension->DeviceFlags[target], DFLAGS_IDENTIFY_VALID);
  2003. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling InitHwExtWithIdentify\n"));
  2004. //
  2005. // IdentifyValid flag should be cleared, if it is a removable media
  2006. //
  2007. InitHwExtWithIdentify(
  2008. hwDeviceExtension,
  2009. target,
  2010. (UCHAR) (deviceType[target] == DeviceIsAtapi ? IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY),
  2011. hwDeviceExtension->IdentifyData + target,
  2012. removableMedia[target]
  2013. );
  2014. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling IdePortSelectCHS\n"));
  2015. IdePortSelectCHS (
  2016. FdoExtension,
  2017. target,
  2018. identifyData + target
  2019. );
  2020. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: back from IdePortSelectCHS\n"));
  2021. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  2022. } else {
  2023. hwDeviceExtension->DeviceFlags[target] = 0;
  2024. }
  2025. }
  2026. if (foundAtLeastOneIdeDevice) {
  2027. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AnalyzeDeviceCapabilities\n"));
  2028. //
  2029. // could move this out of the critial region
  2030. //
  2031. AnalyzeDeviceCapabilities (
  2032. FdoExtension,
  2033. mustBePio
  2034. );
  2035. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AtapiSelectTransferMode\n"));
  2036. //
  2037. // could move this out of the critial region
  2038. //
  2039. AtapiSyncSelectTransferMode (
  2040. FdoExtension,
  2041. hwDeviceExtension,
  2042. FdoExtension->TimingModeAllowed
  2043. );
  2044. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: Calling AtapiHwInitialize\n"));
  2045. AtapiHwInitialize (
  2046. FdoExtension->HwDeviceExtension,
  2047. flushCommand
  2048. );
  2049. }
  2050. } else {
  2051. //
  2052. // unable to stop all children, so force an buscheck to try again
  2053. //
  2054. // IoInvalidateDeviceRelations (
  2055. // FdoExtension->AttacheePdo,
  2056. // BusRelations
  2057. // );
  2058. }
  2059. //
  2060. // cycle through all children and restart their device queue
  2061. //
  2062. pathId.l = 0;
  2063. numPdoChildren = 0;
  2064. while (pdoExtension = NextLogUnitExtensionWithTag(
  2065. FdoExtension,
  2066. &pathId,
  2067. TRUE,
  2068. IdePortScanBus
  2069. )) {
  2070. DebugPrint ((DBG_BUSSCAN, "IdePortScanBus: re-start pdo 0x%x\n", pdoExtension));
  2071. DeviceStartDeviceQueue (pdoExtension, PDOS_QUEUE_FROZEN_BY_PARENT);
  2072. UnrefLogicalUnitExtensionWithTag (
  2073. FdoExtension,
  2074. pdoExtension,
  2075. IdePortScanBus
  2076. );
  2077. numPdoChildren++;
  2078. }
  2079. timeDiff = LogBusScanStopTimer(&tickCount);
  2080. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[4], timeDiff);
  2081. DebugPrint((DBG_SPECIAL,
  2082. "BusScan : Critical section %x took %u ms\n",
  2083. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2084. timeDiff
  2085. ));
  2086. if (NT_SUCCESS(status)) {
  2087. //
  2088. // second stage scanning
  2089. //
  2090. pathId.l = 0;
  2091. LogBusScanStartTimer(&tickCount);
  2092. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  2093. if (deviceType[target] == DeviceNotExist) {
  2094. continue;
  2095. }
  2096. pathId.b.TargetId = target;
  2097. for (lun = 0; lun < FdoExtension->MaxLuCount; lun++) {
  2098. LARGE_INTEGER tempTickCount;
  2099. pathId.b.Lun = lun;
  2100. newPdo = FALSE;
  2101. RefLuExt(pdoExtension, FdoExtension, pathId, TRUE, newPdo);
  2102. if (!pdoExtension) {
  2103. continue;
  2104. }
  2105. ASSERT (pdoExtension);
  2106. if (lun == 0) {
  2107. #if defined (ALWAYS_VERIFY_DMA)
  2108. #undef ALWAYS_VERIFY_DMA
  2109. #define ALWAYS_VERIFY_DMA TRUE
  2110. #else
  2111. #define ALWAYS_VERIFY_DMA FALSE
  2112. #endif
  2113. ASSERT (ALL_MODE_SUPPORT != MAXULONG);
  2114. if ((FdoExtension->HwDeviceExtension->
  2115. DeviceParameters[target].TransferModeSelected & DMA_SUPPORT) ||
  2116. ALWAYS_VERIFY_DMA) {
  2117. ULONG mode = FdoExtension->HwDeviceExtension->
  2118. DeviceParameters[target].TransferModeSelected;
  2119. //
  2120. // if lastKnownGoodTimingMode is MAX_ULONG, it means
  2121. // we have never seen this device before and the user
  2122. // hasn't said anything about what dma mode to use.
  2123. //
  2124. // we have chosen to use dma because all the software
  2125. // detectable parameters (identify dma, pci config data)
  2126. // looks good for DMA.
  2127. //
  2128. // the only thing that can stop us from using DMA now
  2129. // is bad device. before we go on, do a little test
  2130. // to verify dma is ok
  2131. //
  2132. // could re-use the inquiry data obtained here.
  2133. //
  2134. //
  2135. // skip the test if we have already seen the device
  2136. //
  2137. LogBusScanStartTimer(&tempTickCount);
  2138. if (isSameDevice[target] &&
  2139. mode == savedTransferMode[target]) {
  2140. DebugPrint((DBG_BUSSCAN,
  2141. "Skip dma test for %d\n", target));
  2142. } else {
  2143. IdePortVerifyDma (
  2144. pdoExtension,
  2145. deviceType[target]
  2146. );
  2147. }
  2148. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2149. DebugPrint((DBG_SPECIAL,
  2150. "ScanBus: VerifyDma for %x device %d took %u ms\n",
  2151. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2152. target,
  2153. timeDiff
  2154. ));
  2155. }
  2156. //
  2157. // Initialize numSlot to 0
  2158. //
  2159. numSlot=0;
  2160. //
  2161. // If this is in the bad cd-rom drive list, then don't
  2162. // send these Mode Sense command. The drive might lock up.
  2163. //
  2164. LogBusScanStartTimer(&tempTickCount);
  2165. if (specialAction[target] != skipModeSense) {
  2166. //
  2167. // Non-CD device
  2168. //
  2169. numSlot = IdePortQueryNonCdNumLun (
  2170. FdoExtension,
  2171. pdoExtension,
  2172. FALSE
  2173. );
  2174. } else {
  2175. DebugPrint((DBG_BUSSCAN, "Skip modesense\n"));
  2176. }
  2177. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2178. DebugPrint((DBG_SPECIAL,
  2179. "ScanBus: Initialize Luns for %x device %d took %u ms\n",
  2180. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2181. target,
  2182. timeDiff
  2183. ));
  2184. AtapiHwInitializeMultiLun (
  2185. FdoExtension->HwDeviceExtension,
  2186. pdoExtension->TargetId,
  2187. numSlot
  2188. );
  2189. }
  2190. if (pdoExtension) {
  2191. LogBusScanStartTimer(&tempTickCount);
  2192. status = IssueInquirySafe(FdoExtension, pdoExtension, &InquiryData, TRUE);
  2193. timeDiff = LogBusScanStopTimer(&tempTickCount);
  2194. DebugPrint((DBG_SPECIAL,
  2195. "ScanBus: Inquiry %x for Lun %d device %d took %u ms\n",
  2196. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2197. lun,
  2198. target,
  2199. timeDiff
  2200. ));
  2201. if (NT_SUCCESS(status) || (status == STATUS_DATA_OVERRUN)) {
  2202. DeviceInitDeviceType (
  2203. pdoExtension,
  2204. &InquiryData
  2205. );
  2206. //
  2207. // Init Ids String for PnP Query ID
  2208. //
  2209. DeviceInitIdStrings (
  2210. pdoExtension,
  2211. deviceType[target],
  2212. &InquiryData,
  2213. identifyData + target
  2214. );
  2215. //
  2216. // Clear rescan flag. Since this LogicalUnit will not be freed,
  2217. // the IOCTL_SCSI_MINIPORT requests can safely attach.
  2218. //
  2219. CLRMASK (pdoExtension->LuFlags, PD_RESCAN_ACTIVE);
  2220. DebugPrint((DBG_BUSSCAN,"IdePortScanBus: Found device at "));
  2221. DebugPrint((DBG_BUSSCAN," Bus %d", pdoExtension->PathId));
  2222. DebugPrint((DBG_BUSSCAN," Target Id %d", pdoExtension->TargetId));
  2223. DebugPrint((DBG_BUSSCAN," LUN %d\n", pdoExtension->Lun));
  2224. if (noPowerDown[target] ||
  2225. (pdoExtension->ScsiDeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE)) {
  2226. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  2227. SETMASK (pdoExtension->PdoState, PDOS_NO_POWER_DOWN);
  2228. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  2229. }
  2230. pdoExtension->IdentifyDataCheckSum = idDatacheckSum[target];
  2231. //
  2232. // done using the current logical unit extension
  2233. //
  2234. UnrefLogicalUnitExtensionWithTag (
  2235. FdoExtension,
  2236. pdoExtension,
  2237. IdePortScanBus
  2238. );
  2239. pdoExtension = NULL;
  2240. }
  2241. } else {
  2242. ASSERT (pdoExtension);
  2243. DebugPrint ((DBG_ALWAYS, "IdePort: unable to create new pdo\n"));
  2244. }
  2245. if (pdoExtension) {
  2246. if (!newPdo) {
  2247. DebugPrint((DBG_BUSSCAN, "IdePortScanBus: pdoe 0x%x is missing. (physically removed)\n", pdoExtension));
  2248. }
  2249. //
  2250. // get the pdo states
  2251. //
  2252. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  2253. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT);
  2254. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  2255. UnRefLuExt(pdoExtension, FdoExtension, TRUE, TRUE, newPdo);
  2256. pdoExtension = NULL;
  2257. }
  2258. }
  2259. }
  2260. //
  2261. // Get all PDOs ready
  2262. //
  2263. pathId.l = 0;
  2264. while (pdoExtension = NextLogUnitExtensionWithTag(
  2265. FdoExtension,
  2266. &pathId,
  2267. FALSE,
  2268. IdePortScanBus
  2269. )) {
  2270. //
  2271. // PO Idle Timer
  2272. //
  2273. DeviceRegisterIdleDetection (
  2274. pdoExtension,
  2275. DEVICE_DEFAULT_IDLE_TIMEOUT,
  2276. DEVICE_DEFAULT_IDLE_TIMEOUT
  2277. );
  2278. CLRMASK (pdoExtension->DeviceObject->Flags, DO_DEVICE_INITIALIZING);
  2279. UnrefLogicalUnitExtensionWithTag (
  2280. FdoExtension,
  2281. pdoExtension,
  2282. IdePortScanBus
  2283. );
  2284. }
  2285. //
  2286. // Update the device map.
  2287. //
  2288. ideDriverExtension = IoGetDriverObjectExtension(
  2289. FdoExtension->DriverObject,
  2290. DRIVER_OBJECT_EXTENSION_ID
  2291. );
  2292. IdeBuildDeviceMap(FdoExtension, &ideDriverExtension->RegistryPath);
  2293. }
  2294. timeDiff = LogBusScanStopTimer(&tickCount);
  2295. LogBusScanTimeDiff(FdoExtension, IdePortBootTimeRegKey[5], timeDiff);
  2296. DebugPrint((DBG_SPECIAL,
  2297. "BusScan: Last Stage scanning for %x took %u ms\n",
  2298. FdoExtension->IdeResource.TranslatedCommandBaseAddress,
  2299. timeDiff
  2300. ));
  2301. //
  2302. // save current transfer mode setting in the registry
  2303. //
  2304. for (target = 0; target < hwDeviceExtension->MaxIdeTargetId; target++) {
  2305. ULONG mode;
  2306. pdoExtension = RefLogicalUnitExtensionWithTag(
  2307. FdoExtension,
  2308. 0,
  2309. (UCHAR) target,
  2310. 0,
  2311. TRUE,
  2312. IdePortScanBus
  2313. );
  2314. if (pdoExtension) {
  2315. mode = FdoExtension->HwDeviceExtension->DeviceParameters[target].TransferModeSelected;
  2316. if (pdoExtension->DmaTransferTimeoutCount >= PDO_DMA_TIMEOUT_LIMIT) {
  2317. mode &= PIO_SUPPORT;
  2318. lastKnownGoodTimingMode[target] &= PIO_SUPPORT;
  2319. }
  2320. UnrefLogicalUnitExtensionWithTag (
  2321. FdoExtension,
  2322. pdoExtension,
  2323. IdePortScanBus
  2324. );
  2325. IdePortSaveDeviceParameter(
  2326. FdoExtension,
  2327. IdePortRegistryDeviceTimingModeName[target],
  2328. mode
  2329. );
  2330. IdePortSaveDeviceParameter(
  2331. FdoExtension,
  2332. IdePortRegistryDeviceTimingModeAllowedName[target],
  2333. lastKnownGoodTimingMode[target]
  2334. );
  2335. IdePortSaveDeviceParameter(
  2336. FdoExtension,
  2337. IdePortRegistryIdentifyDataChecksum[target],
  2338. idDatacheckSum[target]
  2339. );
  2340. } else {
  2341. IdePortSaveDeviceParameter(
  2342. FdoExtension,
  2343. IdePortRegistryDeviceTimingModeName[target],
  2344. 0
  2345. );
  2346. }
  2347. }
  2348. done:
  2349. //
  2350. // unlock BUSSCAN code pages
  2351. //
  2352. #ifdef ALLOC_PRAGMA
  2353. InterlockedDecrement(&IdePAGESCANLockCount);
  2354. MmUnlockPagableImageSection(
  2355. pageScanCodePageHandle
  2356. );
  2357. #endif
  2358. return STATUS_SUCCESS;
  2359. }
  2360. BOOLEAN
  2361. IdePreAllocEnumStructs (
  2362. IN PFDO_EXTENSION FdoExtension
  2363. )
  2364. /**++
  2365. Routine Description:
  2366. Pre-Allocates Memory for structures used during enumertion. This is not protected by a lock.
  2367. Thus if multiple threads cannot use the structures at the same time. Any routine using these
  2368. structures should be aware of this fact.
  2369. Arguments:
  2370. FdoExtension : Functional Device Extension
  2371. Return Value:
  2372. TRUE: if allocations succeeded.
  2373. FALSE: if any of the allocations failed
  2374. --**/
  2375. {
  2376. PENUMERATION_STRUCT enumStruct;
  2377. PIRP irp1;
  2378. ULONG deviceRelationsSize;
  2379. PULONG DataBuffer;
  2380. ULONG currsize=0;
  2381. PIDE_WORK_ITEM_CONTEXT workItemContext;
  2382. PAGED_CODE();
  2383. //
  2384. // Lock
  2385. //
  2386. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 1, 0) == 0);
  2387. if (FdoExtension->PreAllocEnumStruct) {
  2388. //
  2389. // Unlock
  2390. //
  2391. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2392. return TRUE;
  2393. }
  2394. enumStruct = ExAllocatePool(NonPagedPool, sizeof(ENUMERATION_STRUCT));
  2395. if (enumStruct == NULL) {
  2396. //
  2397. // Unlock
  2398. //
  2399. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2400. ASSERT(FdoExtension->EnumStructLock == 0);
  2401. return FALSE;
  2402. }
  2403. currsize += sizeof(ENUMERATION_STRUCT);
  2404. RtlZeroMemory(enumStruct, sizeof(ENUMERATION_STRUCT));
  2405. //
  2406. // Allocate ATaPassThru context
  2407. //
  2408. enumStruct->Context = ExAllocatePool(NonPagedPool, sizeof (ATA_PASSTHROUGH_CONTEXT));
  2409. if (enumStruct->Context == NULL) {
  2410. goto getout;
  2411. }
  2412. currsize += sizeof(ATA_PASSTHROUGH_CONTEXT);
  2413. //
  2414. // Allocate the WorkItemContext for the enumeration
  2415. //
  2416. ASSERT(enumStruct->EnumWorkItemContext == NULL);
  2417. enumStruct->EnumWorkItemContext = ExAllocatePool (NonPagedPool,
  2418. sizeof(IDE_WORK_ITEM_CONTEXT)
  2419. );
  2420. if (enumStruct->EnumWorkItemContext == NULL) {
  2421. goto getout;
  2422. }
  2423. currsize += sizeof(IDE_WORK_ITEM_CONTEXT);
  2424. //
  2425. // Allocate the WorkItem
  2426. //
  2427. workItemContext = (PIDE_WORK_ITEM_CONTEXT) (enumStruct->EnumWorkItemContext);
  2428. workItemContext->WorkItem = IoAllocateWorkItem(FdoExtension->DeviceObject);
  2429. if (workItemContext->WorkItem == NULL) {
  2430. goto getout;
  2431. }
  2432. //
  2433. // StopQueu Context, used to stop the device queue
  2434. //
  2435. enumStruct->StopQContext = ExAllocatePool(NonPagedPool, sizeof (PDO_STOP_QUEUE_CONTEXT));
  2436. if (enumStruct->StopQContext == NULL) {
  2437. goto getout;
  2438. }
  2439. currsize += sizeof(PDO_STOP_QUEUE_CONTEXT);
  2440. //
  2441. // Sense Info buffer
  2442. //
  2443. enumStruct->SenseInfoBuffer = ExAllocatePool( NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
  2444. if (enumStruct->SenseInfoBuffer == NULL) {
  2445. goto getout;
  2446. }
  2447. currsize += SENSE_BUFFER_SIZE;
  2448. //
  2449. // Srb to send pass thru requests
  2450. //
  2451. enumStruct->Srb = ExAllocatePool (NonPagedPool, sizeof (SCSI_REQUEST_BLOCK));
  2452. if (enumStruct->Srb == NULL) {
  2453. goto getout;
  2454. }
  2455. currsize += sizeof(SCSI_REQUEST_BLOCK);
  2456. //
  2457. // irp for pass thru requests
  2458. //
  2459. irp1 = IoAllocateIrp (
  2460. (CCHAR) (PREALLOC_STACK_LOCATIONS),
  2461. FALSE
  2462. );
  2463. if (irp1 == NULL) {
  2464. goto getout;
  2465. }
  2466. enumStruct->Irp1 = irp1;
  2467. //
  2468. // Data buffer to hold inquiry data or Identify data
  2469. //
  2470. enumStruct->DataBufferSize = sizeof(ATA_PASS_THROUGH)+INQUIRYDATABUFFERSIZE+
  2471. sizeof(IDENTIFY_DATA);
  2472. currsize += enumStruct->DataBufferSize;
  2473. DataBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
  2474. enumStruct->DataBufferSize);
  2475. if (DataBuffer == NULL) {
  2476. enumStruct->DataBufferSize=0;
  2477. goto getout;
  2478. }
  2479. enumStruct->DataBuffer = DataBuffer;
  2480. enumStruct->MdlAddress = IoAllocateMdl( DataBuffer,
  2481. enumStruct->DataBufferSize,
  2482. FALSE,
  2483. FALSE,
  2484. (PIRP) NULL );
  2485. if (enumStruct->MdlAddress == NULL) {
  2486. goto getout;
  2487. }
  2488. MmBuildMdlForNonPagedPool(enumStruct->MdlAddress);
  2489. FdoExtension->PreAllocEnumStruct=enumStruct;
  2490. DebugPrint((DBG_BUSSCAN, "BusScan: TOTAL PRE_ALLOCED MEM=%x\n", currsize));
  2491. //
  2492. // Unlock
  2493. //
  2494. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2495. return TRUE;
  2496. getout:
  2497. //
  2498. // Some allocations failed. Free the already allocated ones.
  2499. //
  2500. IdeFreeEnumStructs(enumStruct);
  2501. FdoExtension->PreAllocEnumStruct=NULL;
  2502. //
  2503. // Unlock
  2504. //
  2505. ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
  2506. ASSERT(FALSE);
  2507. return FALSE;
  2508. }
  2509. VOID
  2510. IdeFreeEnumStructs(
  2511. PENUMERATION_STRUCT enumStruct
  2512. )
  2513. /**++
  2514. Routine Description:
  2515. Frees the pre-allocated memory.
  2516. Arguments
  2517. Pointer to the Enumeration Structure that is to be freed
  2518. Return Value:
  2519. None
  2520. --**/
  2521. {
  2522. PAGED_CODE();
  2523. if (enumStruct != NULL) {
  2524. if (enumStruct->Context) {
  2525. ExFreePool (enumStruct->Context);
  2526. }
  2527. if (enumStruct->SenseInfoBuffer) {
  2528. ExFreePool (enumStruct->SenseInfoBuffer);
  2529. }
  2530. if (enumStruct->Srb) {
  2531. ExFreePool(enumStruct->Srb);
  2532. }
  2533. if (enumStruct->StopQContext) {
  2534. ExFreePool(enumStruct->StopQContext);
  2535. }
  2536. if (enumStruct->DataBuffer) {
  2537. ExFreePool(enumStruct->DataBuffer);
  2538. }
  2539. if (enumStruct->Irp1) {
  2540. IoFreeIrp(enumStruct->Irp1);
  2541. }
  2542. if (enumStruct->MdlAddress) {
  2543. ExFreePool(enumStruct->MdlAddress);
  2544. }
  2545. if (enumStruct->EnumWorkItemContext) {
  2546. PIDE_WORK_ITEM_CONTEXT workItemContext = (PIDE_WORK_ITEM_CONTEXT)enumStruct->
  2547. EnumWorkItemContext;
  2548. if (workItemContext->WorkItem) {
  2549. IoFreeWorkItem(workItemContext->WorkItem);
  2550. }
  2551. ExFreePool (enumStruct->EnumWorkItemContext);
  2552. }
  2553. ExFreePool(enumStruct);
  2554. enumStruct = NULL;
  2555. }
  2556. }