PageRenderTime 74ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 2ms

/drivers/storage/ide/uniata/id_ata.cpp

https://bitbucket.org/arty/arty-newcc-reactos
C++ | 9575 lines | 6997 code | 1343 blank | 1235 comment | 1413 complexity | a9c6a1e31e8b6930e2482b6edb54b0e8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*++
  2. Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
  3. Module Name:
  4. id_ata.cpp
  5. Abstract:
  6. This is the miniport driver for ATA/ATAPI IDE controllers
  7. with Busmaster DMA and Serial ATA support
  8. Author:
  9. Alexander A. Telyatnikov (Alter)
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  14. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  15. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  16. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. Revision History:
  24. The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
  25. Mike Glass (MGlass)
  26. Chuck Park (ChuckP)
  27. Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
  28. S?ren Schmidt, Copyright (c) 1998-2007
  29. All parts of code are greatly changed/updated by
  30. Alter, Copyright (c) 2002-2007:
  31. 1. Internal command queueing/reordering
  32. 2. Drive identification
  33. 3. Support for 2 _independent_ channels in a single PCI device
  34. 4. Smart host<->drive transfer rate slowdown (for bad cable)
  35. 5. W2k support (binary compatibility)
  36. 6. HDD hot swap under NT4
  37. 7. XP support (binary compatibility)
  38. 8. Serial ATA (SATA/SATA2) support
  39. 9. NT 3.51 support (binary compatibility)
  40. etc. (See todo.txt)
  41. --*/
  42. #include "stdafx.h"
  43. #ifndef UNIATA_CORE
  44. static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
  45. static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR " \n";
  46. UNICODE_STRING SavedRegPath;
  47. WCHAR SavedRegPathBuffer[256];
  48. #endif //UNIATA_CORE
  49. UCHAR AtaCommands48[256];
  50. UCHAR AtaCommandFlags[256];
  51. ULONG SkipRaids = 1;
  52. ULONG ForceSimplex = 0;
  53. LONGLONG g_Perf = 0;
  54. ULONG g_PerfDt = 0;
  55. #ifdef _DEBUG
  56. ULONG g_LogToDisplay = 0;
  57. #endif //_DEBUG
  58. ULONG g_WaitBusyInISR = 1;
  59. ULONG g_opt_WaitBusyCount = 200; // 20000
  60. ULONG g_opt_WaitBusyDelay = 10; // 150
  61. ULONG g_opt_WaitDrqDelay = 10; // 100
  62. BOOLEAN g_opt_AtapiSendDisableIntr = 1; // 0
  63. BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
  64. ULONG g_opt_VirtualMachine = 0; // Auto
  65. BOOLEAN InDriverEntry = TRUE;
  66. BOOLEAN g_opt_Verbose = 0;
  67. BOOLEAN WinVer_WDM_Model = FALSE;
  68. //UCHAR EnableDma = FALSE;
  69. //UCHAR EnableReorder = FALSE;
  70. UCHAR g_foo = 0;
  71. BOOLEAN
  72. NTAPI
  73. AtapiResetController__(
  74. IN PVOID HwDeviceExtension,
  75. IN ULONG PathId,
  76. IN UCHAR CompleteType
  77. );
  78. VOID
  79. NTAPI
  80. AtapiHwInitialize__(
  81. IN PHW_DEVICE_EXTENSION deviceExtension,
  82. IN ULONG lChannel
  83. );
  84. #define RESET_COMPLETE_CURRENT 0x00
  85. #define RESET_COMPLETE_ALL 0x01
  86. #define RESET_COMPLETE_NONE 0x02
  87. #ifndef UNIATA_CORE
  88. VOID
  89. NTAPI
  90. AtapiCallBack_X(
  91. IN PVOID HwDeviceExtension
  92. );
  93. #ifdef UNIATA_USE_XXableInterrupts
  94. #define RETTYPE_XXableInterrupts BOOLEAN
  95. #define RETVAL_XXableInterrupts TRUE
  96. #else
  97. #define RETTYPE_XXableInterrupts VOID
  98. #define RETVAL_XXableInterrupts
  99. #endif
  100. RETTYPE_XXableInterrupts
  101. NTAPI
  102. AtapiInterruptDpc(
  103. IN PVOID HwDeviceExtension
  104. );
  105. RETTYPE_XXableInterrupts
  106. NTAPI
  107. AtapiEnableInterrupts__(
  108. IN PVOID HwDeviceExtension
  109. );
  110. VOID
  111. NTAPI
  112. AtapiQueueTimerDpc(
  113. IN PVOID HwDeviceExtension,
  114. IN ULONG lChannel,
  115. IN PHW_TIMER HwScsiTimer,
  116. IN ULONG MiniportTimerValue
  117. );
  118. SCSI_ADAPTER_CONTROL_STATUS
  119. NTAPI
  120. AtapiAdapterControl(
  121. IN PVOID HwDeviceExtension,
  122. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  123. IN PVOID Parameters
  124. );
  125. #endif //UNIATA_CORE
  126. #ifndef UNIATA_CORE
  127. BOOLEAN
  128. NTAPI
  129. AtapiRegGetStringParameterValue(
  130. IN PWSTR RegistryPath,
  131. IN PWSTR Name,
  132. IN PWCHAR Str,
  133. IN ULONG MaxLen
  134. )
  135. {
  136. #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
  137. NTSTATUS status;
  138. RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
  139. UNICODE_STRING ustr;
  140. ustr.Buffer = Str;
  141. ustr.Length =
  142. ustr.MaximumLength = (USHORT)MaxLen;
  143. RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
  144. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  145. parameters[0].Name = Name;
  146. parameters[0].EntryContext = &ustr;
  147. parameters[0].DefaultType = REG_SZ;
  148. parameters[0].DefaultData = Str;
  149. parameters[0].DefaultLength = MaxLen;
  150. status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
  151. RegistryPath, parameters, NULL, NULL);
  152. if(!NT_SUCCESS(status))
  153. return FALSE;
  154. return TRUE;
  155. #undef ITEMS_TO_QUERY
  156. } // end AtapiRegGetStringParameterValue()
  157. #endif //UNIATA_CORE
  158. VOID
  159. DDKFASTAPI
  160. UniataNanoSleep(
  161. ULONG nano
  162. )
  163. {
  164. LONGLONG t;
  165. LARGE_INTEGER t0;
  166. #ifdef NAVO_TEST
  167. return;
  168. #endif //NAVO_TEST
  169. if(!nano || !g_Perf || !g_PerfDt)
  170. return;
  171. t = (g_Perf * nano) / g_PerfDt / 1000;
  172. if(!t) {
  173. t = 1;
  174. }
  175. do {
  176. KeQuerySystemTime(&t0);
  177. t--;
  178. } while(t);
  179. } // end UniataNanoSleep()
  180. #define AtapiWritePortN_template(_type, _Type, sz) \
  181. VOID \
  182. DDKFASTAPI \
  183. AtapiWritePort##sz( \
  184. IN PHW_CHANNEL chan, \
  185. IN ULONGIO_PTR _port, \
  186. IN _type data \
  187. ) \
  188. { \
  189. PIORES res; \
  190. if(_port >= IDX_MAX_REG) { \
  191. res = (PIORES)(_port); \
  192. } else \
  193. if(chan) { \
  194. res = &chan->RegTranslation[_port]; \
  195. } else { \
  196. KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
  197. return; \
  198. } \
  199. if(res->Proc) { \
  200. } else \
  201. if(!res->MemIo) { \
  202. ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
  203. } else { \
  204. /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
  205. ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
  206. } \
  207. return; \
  208. }
  209. AtapiWritePortN_template(ULONG, Ulong, 4);
  210. AtapiWritePortN_template(USHORT, Ushort, 2);
  211. AtapiWritePortN_template(UCHAR, Uchar, 1);
  212. #define AtapiWritePortExN_template(_type, _Type, sz) \
  213. VOID \
  214. DDKFASTAPI \
  215. AtapiWritePortEx##sz( \
  216. IN PHW_CHANNEL chan, \
  217. IN ULONGIO_PTR _port, \
  218. IN ULONG offs, \
  219. IN _type data \
  220. ) \
  221. { \
  222. PIORES res; \
  223. if(_port >= IDX_MAX_REG) { \
  224. res = (PIORES)(_port); \
  225. } else \
  226. if(chan) { \
  227. res = &chan->RegTranslation[_port]; \
  228. } else { \
  229. KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
  230. return; \
  231. } \
  232. if(res->Proc) { \
  233. } else \
  234. if(!res->MemIo) { \
  235. ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
  236. } else { \
  237. /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
  238. ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
  239. } \
  240. return; \
  241. }
  242. AtapiWritePortExN_template(ULONG, Ulong, 4);
  243. //AtapiWritePortExN_template(USHORT, Ushort, 2);
  244. AtapiWritePortExN_template(UCHAR, Uchar, 1);
  245. #define AtapiReadPortN_template(_type, _Type, sz) \
  246. _type \
  247. DDKFASTAPI \
  248. AtapiReadPort##sz( \
  249. IN PHW_CHANNEL chan, \
  250. IN ULONGIO_PTR _port \
  251. ) \
  252. { \
  253. PIORES res; \
  254. if(_port >= IDX_MAX_REG) { \
  255. res = (PIORES)(_port); \
  256. } else \
  257. if(chan) { \
  258. res = &chan->RegTranslation[_port]; \
  259. } else { \
  260. KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
  261. return (_type)(-1); \
  262. } \
  263. if(res->Proc) { \
  264. return 0; \
  265. } else \
  266. if(!res->MemIo) { \
  267. /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
  268. return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
  269. } else { \
  270. /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
  271. return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
  272. } \
  273. }
  274. AtapiReadPortN_template(ULONG, Ulong, 4);
  275. AtapiReadPortN_template(USHORT, Ushort, 2);
  276. AtapiReadPortN_template(UCHAR, Uchar, 1);
  277. #define AtapiReadPortExN_template(_type, _Type, sz) \
  278. _type \
  279. DDKFASTAPI \
  280. AtapiReadPortEx##sz( \
  281. IN PHW_CHANNEL chan, \
  282. IN ULONGIO_PTR _port, \
  283. IN ULONG offs \
  284. ) \
  285. { \
  286. PIORES res; \
  287. if(_port >= IDX_MAX_REG) { \
  288. res = (PIORES)(_port); \
  289. } else \
  290. if(chan) { \
  291. res = &chan->RegTranslation[_port]; \
  292. } else { \
  293. KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
  294. return (_type)(-1); \
  295. } \
  296. if(res->Proc) { \
  297. return 0; \
  298. } else \
  299. if(!res->MemIo) { \
  300. return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
  301. } else { \
  302. /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
  303. return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
  304. } \
  305. }
  306. AtapiReadPortExN_template(ULONG, Ulong, 4);
  307. //AtapiReadPortExN_template(USHORT, Ushort, 2);
  308. AtapiReadPortExN_template(UCHAR, Uchar, 1);
  309. #define AtapiReadPortBufferN_template(_type, _Type, sz) \
  310. VOID \
  311. DDKFASTAPI \
  312. AtapiReadBuffer##sz( \
  313. IN PHW_CHANNEL chan, \
  314. IN ULONGIO_PTR _port, \
  315. IN PVOID Buffer, \
  316. IN ULONG Count, \
  317. IN ULONG Timing \
  318. ) \
  319. { \
  320. PIORES res; \
  321. \
  322. if(Timing) { \
  323. while(Count) { \
  324. (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
  325. Count--; \
  326. Buffer = ((_type*)Buffer)+1; \
  327. UniataNanoSleep(Timing); \
  328. } \
  329. return; \
  330. } \
  331. \
  332. if(_port >= IDX_MAX_REG) { \
  333. res = (PIORES)(_port); \
  334. } else \
  335. if(chan) { \
  336. res = &chan->RegTranslation[_port]; \
  337. } else { \
  338. KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
  339. return; \
  340. } \
  341. if(!res->MemIo) { \
  342. /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
  343. ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
  344. return; \
  345. } \
  346. while(Count) { \
  347. (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
  348. Count--; \
  349. Buffer = ((_type*)Buffer)+1; \
  350. } \
  351. return; \
  352. }
  353. #define AtapiWritePortBufferN_template(_type, _Type, sz) \
  354. VOID \
  355. DDKFASTAPI \
  356. AtapiWriteBuffer##sz( \
  357. IN PHW_CHANNEL chan, \
  358. IN ULONGIO_PTR _port, \
  359. IN PVOID Buffer, \
  360. IN ULONG Count, \
  361. IN ULONG Timing \
  362. ) \
  363. { \
  364. PIORES res; \
  365. \
  366. if(Timing) { \
  367. while(Count) { \
  368. AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
  369. Buffer = ((_type*)Buffer)+1; \
  370. Count--; \
  371. UniataNanoSleep(Timing); \
  372. } \
  373. return; \
  374. } \
  375. \
  376. if(_port >= IDX_MAX_REG) { \
  377. res = (PIORES)(_port); \
  378. } else \
  379. if(chan) { \
  380. res = &chan->RegTranslation[_port]; \
  381. } else { \
  382. KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
  383. return; \
  384. } \
  385. if(!res->MemIo) { \
  386. /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
  387. ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
  388. return; \
  389. } \
  390. while(Count) { \
  391. ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
  392. Count--; \
  393. Buffer = ((_type*)Buffer)+1; \
  394. } \
  395. return; \
  396. }
  397. AtapiWritePortBufferN_template(ULONG, Ulong, 4);
  398. AtapiWritePortBufferN_template(USHORT, Ushort, 2);
  399. AtapiReadPortBufferN_template(ULONG, Ulong, 4);
  400. AtapiReadPortBufferN_template(USHORT, Ushort, 2);
  401. UCHAR
  402. DDKFASTAPI
  403. AtapiSuckPort2(
  404. IN PHW_CHANNEL chan
  405. )
  406. {
  407. UCHAR statusByte;
  408. ULONG i;
  409. WaitOnBusyLong(chan);
  410. for (i = 0; i < 0x10000; i++) {
  411. GetStatus(chan, statusByte);
  412. if (statusByte & IDE_STATUS_DRQ) {
  413. // Suck out any remaining bytes and throw away.
  414. AtapiReadPort2(chan, IDX_IO1_i_Data);
  415. } else {
  416. break;
  417. }
  418. }
  419. if(i) {
  420. KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
  421. }
  422. return statusByte;
  423. } // AtapiSuckPort2()
  424. UCHAR
  425. DDKFASTAPI
  426. WaitOnBusy(
  427. IN PHW_CHANNEL chan
  428. )
  429. {
  430. ULONG i;
  431. UCHAR Status;
  432. for (i=0; i<200; i++) {
  433. GetStatus(chan, Status);
  434. if (Status & IDE_STATUS_BUSY) {
  435. AtapiStallExecution(10);
  436. continue;
  437. } else {
  438. break;
  439. }
  440. }
  441. return Status;
  442. } // end WaitOnBusy()
  443. UCHAR
  444. DDKFASTAPI
  445. WaitOnBusyLong(
  446. IN PHW_CHANNEL chan
  447. )
  448. {
  449. ULONG i;
  450. UCHAR Status;
  451. Status = WaitOnBusy(chan);
  452. if(!(Status & IDE_STATUS_BUSY))
  453. return Status;
  454. for (i=0; i<2000; i++) {
  455. GetStatus(chan, Status);
  456. if (Status & IDE_STATUS_BUSY) {
  457. AtapiStallExecution(250);
  458. continue;
  459. } else {
  460. break;
  461. }
  462. }
  463. return Status;
  464. } // end WaitOnBusyLong()
  465. UCHAR
  466. DDKFASTAPI
  467. WaitOnBaseBusy(
  468. IN PHW_CHANNEL chan
  469. )
  470. {
  471. ULONG i;
  472. UCHAR Status = 0xff;
  473. for (i=0; i<g_opt_WaitBusyCount; i++) {
  474. GetBaseStatus(chan, Status);
  475. if (Status & IDE_STATUS_BUSY) {
  476. AtapiStallExecution(g_opt_WaitBusyDelay);
  477. continue;
  478. } else {
  479. break;
  480. }
  481. }
  482. return Status;
  483. } // end WaitOnBaseBusy()
  484. UCHAR
  485. DDKFASTAPI
  486. WaitOnBaseBusyLong(
  487. IN PHW_CHANNEL chan
  488. )
  489. {
  490. ULONG i;
  491. UCHAR Status;
  492. Status = WaitOnBaseBusy(chan);
  493. if(!(Status & IDE_STATUS_BUSY))
  494. return Status;
  495. for (i=0; i<2000; i++) {
  496. GetBaseStatus(chan, Status);
  497. if (Status & IDE_STATUS_BUSY) {
  498. AtapiStallExecution(250);
  499. continue;
  500. } else {
  501. break;
  502. }
  503. }
  504. return Status;
  505. } // end WaitOnBaseBusyLong()
  506. UCHAR
  507. DDKFASTAPI
  508. UniataIsIdle(
  509. IN struct _HW_DEVICE_EXTENSION* deviceExtension,
  510. IN UCHAR Status
  511. )
  512. {
  513. UCHAR Status2;
  514. if(Status == 0xff) {
  515. return 0xff;
  516. }
  517. if(Status & IDE_STATUS_BUSY) {
  518. return Status;
  519. }
  520. // if(deviceExtension->HwFlags & UNIATA_SATA) {
  521. if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
  522. if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
  523. return Status;
  524. }
  525. } else {
  526. Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
  527. if ((Status & IDE_STATUS_BUSY) ||
  528. (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
  529. return Status;
  530. }
  531. }
  532. return IDE_STATUS_IDLE;
  533. } // end UniataIsIdle()
  534. UCHAR
  535. DDKFASTAPI
  536. WaitForIdleLong(
  537. IN PHW_CHANNEL chan
  538. )
  539. {
  540. ULONG i;
  541. UCHAR Status;
  542. UCHAR Status2;
  543. for (i=0; i<20000; i++) {
  544. GetStatus(chan, Status);
  545. Status2 = UniataIsIdle(chan->DeviceExtension, Status);
  546. if(Status2 == 0xff) {
  547. // no drive ?
  548. break;
  549. } else
  550. if(Status2 & IDE_STATUS_BUSY) {
  551. AtapiStallExecution(10);
  552. continue;
  553. } else {
  554. break;
  555. }
  556. }
  557. return Status;
  558. } // end WaitForIdleLong()
  559. UCHAR
  560. DDKFASTAPI
  561. WaitForDrq(
  562. IN PHW_CHANNEL chan
  563. )
  564. {
  565. ULONG i;
  566. UCHAR Status;
  567. for (i=0; i<1000; i++) {
  568. GetStatus(chan, Status);
  569. if (Status & IDE_STATUS_BUSY) {
  570. AtapiStallExecution(g_opt_WaitDrqDelay);
  571. } else if (Status & IDE_STATUS_DRQ) {
  572. break;
  573. } else {
  574. AtapiStallExecution(g_opt_WaitDrqDelay*2);
  575. }
  576. }
  577. return Status;
  578. } // end WaitForDrq()
  579. UCHAR
  580. DDKFASTAPI
  581. WaitShortForDrq(
  582. IN PHW_CHANNEL chan
  583. )
  584. {
  585. ULONG i;
  586. UCHAR Status;
  587. for (i=0; i<2; i++) {
  588. GetStatus(chan, Status);
  589. if (Status & IDE_STATUS_BUSY) {
  590. AtapiStallExecution(g_opt_WaitDrqDelay);
  591. } else if (Status & IDE_STATUS_DRQ) {
  592. break;
  593. } else {
  594. AtapiStallExecution(g_opt_WaitDrqDelay);
  595. }
  596. }
  597. return Status;
  598. } // end WaitShortForDrq()
  599. VOID
  600. DDKFASTAPI
  601. AtapiSoftReset(
  602. IN PHW_CHANNEL chan,
  603. ULONG DeviceNumber
  604. )
  605. {
  606. //ULONG c = chan->lChannel;
  607. ULONG i = 30 * 1000;
  608. UCHAR dma_status = 0;
  609. KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
  610. UCHAR statusByte2;
  611. if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
  612. UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
  613. return;
  614. }
  615. GetBaseStatus(chan, statusByte2);
  616. KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
  617. SelectDrive(chan, DeviceNumber);
  618. AtapiStallExecution(500);
  619. AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
  620. // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
  621. // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
  622. // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
  623. // implementation. (which is around 1 second)
  624. while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
  625. i--)
  626. {
  627. AtapiStallExecution(30);
  628. }
  629. SelectDrive(chan, DeviceNumber);
  630. WaitOnBusy(chan);
  631. GetBaseStatus(chan, statusByte2);
  632. AtapiStallExecution(500);
  633. GetBaseStatus(chan, statusByte2);
  634. if(chan && chan->DeviceExtension) {
  635. dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
  636. KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
  637. } else {
  638. KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
  639. }
  640. if(dma_status & BM_STATUS_INTR) {
  641. // bullshit, we have DMA interrupt, but had never initiate DMA operation
  642. KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
  643. AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
  644. GetBaseStatus(chan, statusByte2);
  645. }
  646. if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
  647. UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
  648. /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
  649. UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
  650. }*/
  651. }
  652. return;
  653. } // end AtapiSoftReset()
  654. /*
  655. Send command to device.
  656. Translate to 48-Lba form if required
  657. */
  658. UCHAR
  659. NTAPI
  660. AtaCommand48(
  661. IN PHW_DEVICE_EXTENSION deviceExtension,
  662. IN ULONG DeviceNumber,
  663. IN ULONG lChannel,
  664. IN UCHAR command,
  665. IN ULONGLONG lba,
  666. IN USHORT count,
  667. IN USHORT feature,
  668. IN ULONG flags
  669. )
  670. {
  671. PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
  672. UCHAR statusByte;
  673. ULONG i;
  674. PUCHAR plba;
  675. KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
  676. deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
  677. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  678. PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
  679. KdPrint3((" (ahci)\n"));
  680. RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
  681. if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
  682. &(AHCI_CMD->cfis[0]),
  683. command,
  684. lba,
  685. count,
  686. feature,
  687. ATA_IMMEDIATE
  688. )) {
  689. return 0xff;
  690. }
  691. if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
  692. KdPrint2((" timeout\n"));
  693. return 0xff;
  694. }
  695. return IDE_STATUS_IDLE;
  696. }
  697. SelectDrive(chan, DeviceNumber);
  698. statusByte = WaitOnBusy(chan);
  699. /* ready to issue command ? */
  700. if (statusByte & IDE_STATUS_BUSY) {
  701. KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
  702. return statusByte;
  703. }
  704. // !!! We should not check ERROR condition here
  705. // ERROR bit may be asserted durring previous operation
  706. // and not cleared after SELECT
  707. //>>>>>> NV: 2006/08/03
  708. if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
  709. CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
  710. KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
  711. return IDE_STATUS_ERROR;
  712. //return SRB_STATUS_ERROR;
  713. }
  714. //<<<<<< NV: 2006/08/03
  715. /* only use 48bit addressing if needed because of the overhead */
  716. if (UniAta_need_lba48(command, lba, count,
  717. chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
  718. KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber ));
  719. /* translate command into 48bit version */
  720. if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
  721. command = AtaCommands48[command];
  722. } else {
  723. KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
  724. return (UCHAR)-1;
  725. }
  726. chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
  727. plba = (PUCHAR)&lba;
  728. AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)(feature>>8));
  729. AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
  730. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)(count>>8));
  731. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
  732. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
  733. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
  734. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
  735. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
  736. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
  737. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
  738. //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
  739. AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
  740. } else {
  741. plba = (PUCHAR)&lba; //ktp
  742. chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
  743. //if(feature ||
  744. // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
  745. AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
  746. //}
  747. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
  748. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]);
  749. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]);
  750. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
  751. if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
  752. //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
  753. AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
  754. } else {
  755. //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
  756. AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
  757. }
  758. }
  759. // write command code to device
  760. AtapiWritePort1(chan, IDX_IO1_o_Command, command);
  761. switch (flags) {
  762. case ATA_WAIT_INTR:
  763. // caller requested wait for interrupt
  764. for(i=0;i<4;i++) {
  765. WaitOnBusy(chan);
  766. statusByte = WaitForDrq(chan);
  767. if (statusByte & IDE_STATUS_DRQ)
  768. break;
  769. AtapiStallExecution(500);
  770. KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
  771. }
  772. return statusByte;
  773. case ATA_WAIT_IDLE:
  774. // caller requested wait for entering Wait state
  775. for (i=0; i<30 * 1000; i++) {
  776. GetStatus(chan, statusByte);
  777. statusByte = UniataIsIdle(deviceExtension, statusByte);
  778. if(statusByte == 0xff) {
  779. // no drive ?
  780. break;
  781. } else
  782. if(statusByte & IDE_STATUS_ERROR) {
  783. break;
  784. } else
  785. if(statusByte & IDE_STATUS_BUSY) {
  786. AtapiStallExecution(100);
  787. continue;
  788. } else
  789. if(statusByte == IDE_STATUS_IDLE) {
  790. break;
  791. } else {
  792. //if(deviceExtension->HwFlags & UNIATA_SATA) {
  793. if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  794. break;
  795. }
  796. AtapiStallExecution(100);
  797. }
  798. }
  799. //statusByte |= IDE_STATUS_BUSY;
  800. break;
  801. case ATA_WAIT_READY:
  802. statusByte = WaitOnBusyLong(chan);
  803. break;
  804. case ATA_WAIT_BASE_READY:
  805. statusByte = WaitOnBaseBusyLong(chan);
  806. break;
  807. case ATA_IMMEDIATE:
  808. GetStatus(chan, statusByte);
  809. if (statusByte & IDE_STATUS_ERROR) {
  810. KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
  811. if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
  812. break;
  813. }
  814. KdPrint2((PRINT_PREFIX " try to continue\n"));
  815. statusByte &= ~IDE_STATUS_ERROR;
  816. }
  817. chan->ExpectingInterrupt = TRUE;
  818. // !!!!!
  819. InterlockedExchange(&(chan->CheckIntr),
  820. CHECK_INTR_IDLE);
  821. statusByte = 0;
  822. break;
  823. }
  824. KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
  825. return statusByte;
  826. } // end AtaCommand48()
  827. /*
  828. Send command to device.
  829. This is simply wrapper for AtaCommand48()
  830. */
  831. UCHAR
  832. NTAPI
  833. AtaCommand(
  834. IN PHW_DEVICE_EXTENSION deviceExtension,
  835. IN ULONG DeviceNumber,
  836. IN ULONG lChannel,
  837. IN UCHAR command,
  838. IN USHORT cylinder,
  839. IN UCHAR head,
  840. IN UCHAR sector,
  841. IN UCHAR count,
  842. IN UCHAR feature,
  843. IN ULONG flags
  844. )
  845. {
  846. if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
  847. return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  848. command,
  849. (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
  850. count, feature, flags);
  851. } else {
  852. PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
  853. PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
  854. KdPrint3(("AtaCommand(ahci)\n"));
  855. RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
  856. if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
  857. &(AHCI_CMD->cfis[0]),
  858. command,
  859. (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
  860. count,
  861. feature,
  862. ATA_IMMEDIATE
  863. )) {
  864. return 0xff;
  865. }
  866. if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
  867. KdPrint2((" timeout\n"));
  868. return 0xff;
  869. }
  870. return IDE_STATUS_IDLE;
  871. }
  872. } // end AtaCommand()
  873. LONG
  874. NTAPI
  875. AtaPio2Mode(LONG pio)
  876. {
  877. switch (pio) {
  878. default: return ATA_PIO;
  879. case 0: return ATA_PIO0;
  880. case 1: return ATA_PIO1;
  881. case 2: return ATA_PIO2;
  882. case 3: return ATA_PIO3;
  883. case 4: return ATA_PIO4;
  884. case 5: return ATA_PIO5;
  885. }
  886. } // end AtaPio2Mode()
  887. LONG
  888. NTAPI
  889. AtaPioMode(PIDENTIFY_DATA2 ident)
  890. {
  891. if (ident->PioTimingsValid) {
  892. if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
  893. return 5;
  894. if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
  895. return 4;
  896. if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
  897. return 3;
  898. }
  899. if (ident->PioCycleTimingMode == 2)
  900. return 2;
  901. if (ident->PioCycleTimingMode == 1)
  902. return 1;
  903. if (ident->PioCycleTimingMode == 0)
  904. return 0;
  905. return -1;
  906. } // end AtaPioMode()
  907. LONG
  908. NTAPI
  909. AtaWmode(PIDENTIFY_DATA2 ident)
  910. {
  911. if (ident->MultiWordDMASupport & 0x04)
  912. return 2;
  913. if (ident->MultiWordDMASupport & 0x02)
  914. return 1;
  915. if (ident->MultiWordDMASupport & 0x01)
  916. return 0;
  917. return -1;
  918. } // end AtaWmode()
  919. LONG
  920. NTAPI
  921. AtaUmode(PIDENTIFY_DATA2 ident)
  922. {
  923. if (!ident->UdmaModesValid)
  924. return -1;
  925. if (ident->UltraDMASupport & 0x40)
  926. return 6;
  927. if (ident->UltraDMASupport & 0x20)
  928. return 5;
  929. if (ident->UltraDMASupport & 0x10)
  930. return 4;
  931. if (ident->UltraDMASupport & 0x08)
  932. return 3;
  933. if (ident->UltraDMASupport & 0x04)
  934. return 2;
  935. if (ident->UltraDMASupport & 0x02)
  936. return 1;
  937. if (ident->UltraDMASupport & 0x01)
  938. return 0;
  939. return -1;
  940. } // end AtaUmode()
  941. #ifndef UNIATA_CORE
  942. VOID
  943. NTAPI
  944. AtapiTimerDpc(
  945. IN PVOID HwDeviceExtension
  946. )
  947. {
  948. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  949. PHW_TIMER HwScsiTimer;
  950. LARGE_INTEGER time;
  951. ULONG MiniportTimerValue;
  952. BOOLEAN recall = FALSE;
  953. ULONG lChannel;
  954. PHW_CHANNEL chan;
  955. KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
  956. lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
  957. if(lChannel == CHAN_NOT_SPECIFIED) {
  958. KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
  959. return;
  960. }
  961. chan = &deviceExtension->chan[lChannel];
  962. while(TRUE) {
  963. HwScsiTimer = chan->HwScsiTimer;
  964. chan->HwScsiTimer = NULL;
  965. deviceExtension->FirstDpcChan = chan->NextDpcChan;
  966. if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
  967. recall = TRUE;
  968. }
  969. HwScsiTimer(HwDeviceExtension);
  970. chan->NextDpcChan = CHAN_NOT_SPECIFIED;
  971. lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
  972. if(lChannel == CHAN_NOT_SPECIFIED) {
  973. KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
  974. deviceExtension->FirstDpcChan =
  975. deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
  976. return;
  977. }
  978. KeQuerySystemTime(&time);
  979. KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
  980. chan = &deviceExtension->chan[lChannel];
  981. if(time.QuadPart >= chan->DpcTime - 10) {
  982. // call now
  983. KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
  984. (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
  985. continue;
  986. }
  987. break;
  988. }
  989. if(recall) {
  990. deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
  991. MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
  992. if(!MiniportTimerValue)
  993. MiniportTimerValue = 1;
  994. KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
  995. ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
  996. AtapiTimerDpc,
  997. MiniportTimerValue
  998. );
  999. }
  1000. return;
  1001. } // end AtapiTimerDpc()
  1002. /*
  1003. Wrapper for ScsiPort, that implements smart Dpc
  1004. queueing. We need it to allow parallel functioning
  1005. of IDE channles with shared interrupt. Standard Dpc mechanism
  1006. cancels previous Dpc request (if any), but we need Dpc queue.
  1007. */
  1008. VOID
  1009. NTAPI
  1010. AtapiQueueTimerDpc(
  1011. IN PVOID HwDeviceExtension,
  1012. IN ULONG lChannel,
  1013. IN PHW_TIMER HwScsiTimer,
  1014. IN ULONG MiniportTimerValue
  1015. )
  1016. {
  1017. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  1018. LARGE_INTEGER time;
  1019. LARGE_INTEGER time2;
  1020. ULONG i;
  1021. PHW_CHANNEL prev_chan;
  1022. PHW_CHANNEL chan;
  1023. // BOOLEAN UseRequestTimerCall = TRUE;
  1024. KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
  1025. KeQuerySystemTime(&time);
  1026. time2 = time;
  1027. KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
  1028. time.QuadPart += MiniportTimerValue*10;
  1029. KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
  1030. KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
  1031. i = deviceExtension->FirstDpcChan;
  1032. chan = prev_chan = NULL;
  1033. while(i != CHAN_NOT_SPECIFIED) {
  1034. prev_chan = chan;
  1035. chan = &deviceExtension->chan[i];
  1036. if(chan->DpcTime > time.QuadPart) {
  1037. break;
  1038. }
  1039. i = chan->NextDpcChan;
  1040. }
  1041. chan = &deviceExtension->chan[lChannel];
  1042. if(!prev_chan) {
  1043. deviceExtension->FirstDpcChan = lChannel;
  1044. } else {
  1045. prev_chan->NextDpcChan = lChannel;
  1046. }
  1047. chan->NextDpcChan = i;
  1048. chan->HwScsiTimer = HwScsiTimer;
  1049. chan->DpcTime = time.QuadPart;
  1050. KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
  1051. if(time.QuadPart <= time2.QuadPart) {
  1052. MiniportTimerValue = 1;
  1053. } else {
  1054. MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
  1055. }
  1056. KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
  1057. ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
  1058. AtapiTimerDpc,
  1059. MiniportTimerValue);
  1060. } // end AtapiQueueTimerDpc()
  1061. #endif //UNIATA_CORE
  1062. VOID
  1063. NTAPI
  1064. UniataDumpATARegs(
  1065. IN PHW_CHANNEL chan
  1066. )
  1067. {
  1068. ULONG j;
  1069. UCHAR statusByteAlt;
  1070. GetStatus(chan, statusByteAlt);
  1071. KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
  1072. for(j=1; j<IDX_IO1_SZ; j++) {
  1073. statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
  1074. KdPrint2((PRINT_PREFIX
  1075. " Reg_%#x (%#x) = %#x\n",
  1076. j,
  1077. chan->RegTranslation[IDX_IO1+j].Addr,
  1078. statusByteAlt));
  1079. }
  1080. for(j=0; j<IDX_BM_IO_SZ-1; j++) {
  1081. statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
  1082. KdPrint2((PRINT_PREFIX
  1083. " BM_%#x (%#x) = %#x\n",
  1084. j,
  1085. chan->RegTranslation[IDX_BM_IO+j].Addr,
  1086. statusByteAlt));
  1087. }
  1088. return;
  1089. } // end UniataDumpATARegs()
  1090. /*++
  1091. Routine Description:
  1092. Issue IDENTIFY command to a device.
  1093. Arguments:
  1094. HwDeviceExtension - HBA miniport driver's adapter data storage
  1095. DeviceNumber - Indicates which device.
  1096. Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
  1097. Return Value:
  1098. TRUE if all goes well.
  1099. --*/
  1100. BOOLEAN
  1101. NTAPI
  1102. IssueIdentify(
  1103. IN PVOID HwDeviceExtension,
  1104. IN ULONG DeviceNumber,
  1105. IN ULONG lChannel,
  1106. IN UCHAR Command,
  1107. IN BOOLEAN NoSetup
  1108. )
  1109. {
  1110. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  1111. PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
  1112. ULONG waitCount = 50000;
  1113. ULONG j;
  1114. UCHAR statusByte;
  1115. UCHAR statusByte2;
  1116. UCHAR signatureLow,
  1117. signatureHigh;
  1118. BOOLEAN atapiDev = FALSE;
  1119. PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
  1120. if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
  1121. if(chan->PmLunMap & (1 << DeviceNumber)) {
  1122. // OK
  1123. } else {
  1124. KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
  1125. return FALSE;
  1126. }
  1127. } else
  1128. if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
  1129. KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
  1130. return FALSE;
  1131. }
  1132. if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
  1133. KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
  1134. return FALSE;
  1135. }
  1136. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  1137. statusByte = WaitOnBusyLong(chan);
  1138. } else {
  1139. SelectDrive(chan, DeviceNumber);
  1140. AtapiStallExecution(10);
  1141. statusByte = WaitOnBusyLong(chan);
  1142. // Check that the status register makes sense.
  1143. GetBaseStatus(chan, statusByte2);
  1144. UniataDumpATARegs(chan);
  1145. }
  1146. if (Command == IDE_COMMAND_IDENTIFY) {
  1147. // Mask status byte ERROR bits.
  1148. statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
  1149. KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
  1150. // Check if register value is reasonable.
  1151. if(statusByte != IDE_STATUS_IDLE) {
  1152. // No reset here !!!
  1153. KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
  1154. //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
  1155. if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  1156. SelectDrive(chan, DeviceNumber);
  1157. WaitOnBusyLong(chan);
  1158. signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  1159. signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  1160. if (signatureLow == ATAPI_MAGIC_LSB &&
  1161. signatureHigh == ATAPI_MAGIC_MSB) {
  1162. // Device is Atapi.
  1163. KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
  1164. return FALSE;
  1165. }
  1166. // We really should wait up to 31 seconds
  1167. // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
  1168. // (30 seconds for device 1)
  1169. do {
  1170. // Wait for Busy to drop.
  1171. AtapiStallExecution(100);
  1172. GetStatus(chan, statusByte);
  1173. } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
  1174. GetBaseStatus(chan, statusByte2);
  1175. SelectDrive(chan, DeviceNumber);
  1176. } else {
  1177. GetBaseStatus(chan, statusByte2);
  1178. }
  1179. // Another check for signature, to deal with one model Atapi that doesn't assert signature after
  1180. // a soft reset.
  1181. signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  1182. signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  1183. if (signatureLow == ATAPI_MAGIC_LSB &&
  1184. signatureHigh == ATAPI_MAGIC_MSB) {
  1185. KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
  1186. // Device is Atapi.
  1187. return FALSE;
  1188. }
  1189. statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
  1190. if (statusByte != IDE_STATUS_IDLE) {
  1191. // Give up on this.
  1192. KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
  1193. return FALSE;
  1194. }
  1195. }
  1196. } else {
  1197. KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
  1198. //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
  1199. if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  1200. statusByte = WaitForIdleLong(chan);
  1201. KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
  1202. }
  1203. atapiDev = TRUE;
  1204. }
  1205. // if(deviceExtension->HwFlags & UNIATA_SATA) {
  1206. if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  1207. j = 4; // skip old-style checks
  1208. } else {
  1209. j = 0;
  1210. }
  1211. for (; j < 4*2; j++) {
  1212. // Send IDENTIFY command.
  1213. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, 0, 0, 0, (j >= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR);
  1214. // Clear interrupt
  1215. if (statusByte & IDE_STATUS_DRQ) {
  1216. // Read status to acknowledge any interrupts generated.
  1217. KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
  1218. GetBaseStatus(chan, statusByte);
  1219. // One last check for Atapi.
  1220. if (Command == IDE_COMMAND_IDENTIFY) {
  1221. signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  1222. signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  1223. if (signatureLow == ATAPI_MAGIC_LSB &&
  1224. signatureHigh == ATAPI_MAGIC_MSB) {
  1225. KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
  1226. // Device is Atapi.
  1227. return FALSE;
  1228. }
  1229. }
  1230. break;
  1231. } else {
  1232. KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
  1233. if (Command == IDE_COMMAND_IDENTIFY) {
  1234. // Check the signature. If DRQ didn't come up it's likely Atapi.
  1235. signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  1236. signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  1237. if (signatureLow == ATAPI_MAGIC_LSB &&
  1238. signatureHigh == ATAPI_MAGIC_MSB) {
  1239. // Device is Atapi.
  1240. KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
  1241. return FALSE;
  1242. }
  1243. } else {
  1244. if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
  1245. KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
  1246. break;
  1247. }
  1248. }
  1249. // Device didn't respond correctly. It will be given one more chances.
  1250. KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
  1251. statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
  1252. GetBaseStatus(chan, statusByte);
  1253. AtapiSoftReset(chan,DeviceNumber);
  1254. AtapiDisableInterrupts(deviceExtension, lChannel);
  1255. AtapiEnableInterrupts(deviceExtension, lChannel);
  1256. GetBaseStatus(chan, statusByte);
  1257. //GetStatus(chan, statusByte);
  1258. KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
  1259. }
  1260. }
  1261. // Check for error on really stupid master devices that assert random
  1262. // patterns of bits in the status register at the slave address.
  1263. if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
  1264. KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
  1265. return FALSE;
  1266. }
  1267. KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
  1268. // Suck out 256 words. After waiting for one model that asserts busy
  1269. // after receiving the Packet Identify command.
  1270. statusByte = WaitForDrq(chan);
  1271. statusByte = WaitOnBusyLong(chan);
  1272. KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
  1273. if (!(statusByte & IDE_STATUS_DRQ)) {
  1274. KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
  1275. GetBaseStatus(chan, statusByte);
  1276. return FALSE;
  1277. }
  1278. GetBaseStatus(chan, statusByte);
  1279. KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
  1280. if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
  1281. KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
  1282. #if 0
  1283. USHORT w;
  1284. ULONG i;
  1285. // ATI/SII chipsets with memory-mapped IO hangs when
  1286. // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
  1287. // Unfortunately, I don't know yet how to workaround it except the way you see below.
  1288. KdPrint2((PRINT_PREFIX
  1289. " IO_%#x (%#x), %s:\n",
  1290. IDX_IO1_i_Data,
  1291. chan->RegTranslation[IDX_IO1_i_Data].Addr,
  1292. chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
  1293. for(i=0; i<256; i++) {
  1294. /*
  1295. KdPrint2((PRINT_PREFIX
  1296. " IO_%#x (%#x):\n",
  1297. IDX_IO1_i_Data,
  1298. chan->RegTranslation[IDX_IO1_i_Data].Addr));
  1299. */
  1300. w = AtapiReadPort2(chan, IDX_IO1_i_Data);
  1301. KdPrint2((PRINT_PREFIX
  1302. " %x\n", w));
  1303. AtapiStallExecution(1);
  1304. ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
  1305. }
  1306. #else
  1307. ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
  1308. #endif
  1309. // Work around for some IDE and one model Atapi that will present more than
  1310. // 256 bytes for the Identify data.
  1311. KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
  1312. statusByte = AtapiSuckPort2(chan);
  1313. } else {
  1314. KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
  1315. ReadBuffer2(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
  1316. }
  1317. KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
  1318. statusByte = WaitForDrq(chan);
  1319. KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
  1320. GetBaseStatus(chan, statusByte);
  1321. KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
  1322. if(NoSetup) {
  1323. KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
  1324. return TRUE;
  1325. }
  1326. KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
  1327. KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
  1328. KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
  1329. KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
  1330. if(deviceExtension->FullIdentifyData.PioTimingsValid) {
  1331. KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
  1332. }
  1333. KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
  1334. KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
  1335. if(deviceExtension->FullIdentifyData.UdmaModesValid) {
  1336. KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
  1337. }
  1338. KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
  1339. // Check out a few capabilities / limitations of the device.
  1340. if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
  1341. // Determine if this drive supports the MSN functions.
  1342. KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
  1343. DeviceNumber,
  1344. deviceExtension->FullIdentifyData.RemovableStatus));
  1345. LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
  1346. }
  1347. if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
  1348. // Determine max. block transfer for this device.
  1349. LunExt->MaximumBlockXfer =
  1350. (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
  1351. }
  1352. LunExt->NumOfSectors = 0;
  1353. if (Command == IDE_COMMAND_IDENTIFY) {
  1354. ULONGLONG NumOfSectors=0;
  1355. ULONGLONG NativeNumOfSectors=0;
  1356. ULONGLONG cylinders=0;
  1357. ULONGLONG tmp_cylinders=0;
  1358. // Read very-old-style drive geometry
  1359. KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
  1360. deviceExtension->FullIdentifyData.NumberOfCylinders,
  1361. deviceExtension->FullIdentifyData.NumberOfHeads,
  1362. deviceExtension->FullIdentifyData.SectorsPerTrack
  1363. ));
  1364. NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
  1365. deviceExtension->FullIdentifyData.NumberOfHeads *
  1366. deviceExtension->FullIdentifyData.SectorsPerTrack;
  1367. KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
  1368. // Check for HDDs > 8Gb
  1369. if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
  1370. /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
  1371. (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
  1372. KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
  1373. cylinders =
  1374. (deviceExtension->FullIdentifyData.UserAddressableSectors /
  1375. (deviceExtension->FullIdentifyData.NumberOfHeads *
  1376. deviceExtension->FullIdentifyData.SectorsPerTrack));
  1377. KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
  1378. NumOfSectors = cylinders *
  1379. deviceExtension->FullIdentifyData.NumberOfHeads *
  1380. deviceExtension->FullIdentifyData.SectorsPerTrack;
  1381. KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
  1382. } else {
  1383. }
  1384. // Check for LBA mode
  1385. KdPrint2((PRINT_PREFIX "Suppo…

Large files files are truncated, but you can click here to view the full file