PageRenderTime 58ms CodeModel.GetById 18ms 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
  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 "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
  1386. KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
  1387. KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
  1388. if ( deviceExtension->FullIdentifyData.SupportLba
  1389. ||
  1390. (deviceExtension->FullIdentifyData.MajorRevision &&
  1391. /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
  1392. deviceExtension->FullIdentifyData.UserAddressableSectors)) {
  1393. KdPrint2((PRINT_PREFIX "LBA mode\n"));
  1394. LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
  1395. } else {
  1396. KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
  1397. LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
  1398. goto skip_lba_staff;
  1399. }
  1400. // Check for LBA48 support
  1401. if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
  1402. if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
  1403. deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
  1404. (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
  1405. ) {
  1406. KdPrint2((PRINT_PREFIX "LBA48\n"));
  1407. cylinders =
  1408. (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
  1409. (deviceExtension->FullIdentifyData.NumberOfHeads *
  1410. deviceExtension->FullIdentifyData.SectorsPerTrack));
  1411. KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
  1412. NativeNumOfSectors = cylinders *
  1413. deviceExtension->FullIdentifyData.NumberOfHeads *
  1414. deviceExtension->FullIdentifyData.SectorsPerTrack;
  1415. KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
  1416. if(NativeNumOfSectors > NumOfSectors) {
  1417. KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
  1418. NumOfSectors = NativeNumOfSectors;
  1419. }
  1420. }
  1421. // Check drive capacity report for LBA48-capable drives.
  1422. if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
  1423. ULONG hNativeNumOfSectors;
  1424. KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
  1425. statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  1426. IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
  1427. if(!(statusByte & IDE_STATUS_ERROR)) {
  1428. NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
  1429. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
  1430. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
  1431. AtapiWritePort1(chan, IDX_IO2_o_Control,
  1432. IDE_DC_USE_HOB );
  1433. KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
  1434. NativeNumOfSectors |=
  1435. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
  1436. hNativeNumOfSectors=
  1437. (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
  1438. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
  1439. ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
  1440. KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
  1441. // Some drives report LBA48 capability while has capacity below 128Gb
  1442. // Probably they support large block-counters.
  1443. // But the problem is that some of them reports higher part of Max LBA equal to lower part.
  1444. // Here we check this
  1445. if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
  1446. KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
  1447. statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  1448. IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
  1449. if(!(statusByte & IDE_STATUS_ERROR)) {
  1450. NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
  1451. ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) |
  1452. ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) |
  1453. ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) |
  1454. ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
  1455. ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
  1456. ;
  1457. }
  1458. if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
  1459. KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
  1460. NativeNumOfSectors = 0;
  1461. }
  1462. }
  1463. if(NumOfSectors <= ATA_MAX_LBA28 &&
  1464. NativeNumOfSectors > NumOfSectors) {
  1465. KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
  1466. KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
  1467. statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  1468. IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
  1469. if(!(statusByte & IDE_STATUS_ERROR)) {
  1470. NumOfSectors = NativeNumOfSectors;
  1471. }
  1472. }
  1473. }
  1474. }
  1475. if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
  1476. // check for native LBA size
  1477. // some drives report ~32Gb in Identify Block
  1478. KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
  1479. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
  1480. 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
  1481. if(!(statusByte & IDE_STATUS_ERROR)) {
  1482. NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
  1483. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
  1484. ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
  1485. (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
  1486. KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
  1487. if(NativeNumOfSectors > NumOfSectors) {
  1488. KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
  1489. KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
  1490. statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  1491. IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
  1492. if(!(statusByte & IDE_STATUS_ERROR)) {
  1493. NumOfSectors = NativeNumOfSectors;
  1494. }
  1495. }
  1496. }
  1497. }
  1498. } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
  1499. // fill IdentifyData with bogus geometry
  1500. KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
  1501. tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
  1502. deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
  1503. KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
  1504. if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
  1505. // ok, we can keep original values
  1506. if(LunExt->opt_GeomType == GEOM_AUTO) {
  1507. LunExt->opt_GeomType = GEOM_ORIG;
  1508. }
  1509. } else {
  1510. tmp_cylinders = NumOfSectors / (255*63);
  1511. if(tmp_cylinders < 0xffff) {
  1512. // we can use generic values for H/S for generic geometry approach
  1513. if(LunExt->opt_GeomType == GEOM_AUTO) {
  1514. LunExt->opt_GeomType = GEOM_STD;
  1515. }
  1516. } else {
  1517. // we should use UNIATA geometry approach
  1518. if(LunExt->opt_GeomType == GEOM_AUTO) {
  1519. LunExt->opt_GeomType = GEOM_UNIATA;
  1520. }
  1521. }
  1522. }
  1523. KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
  1524. if(LunExt->opt_GeomType == GEOM_STD) {
  1525. deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
  1526. deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
  1527. deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
  1528. deviceExtension->FullIdentifyData.NumberOfHeads = 255;
  1529. cylinders = NumOfSectors / (255*63);
  1530. KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
  1531. } else
  1532. if(LunExt->opt_GeomType == GEOM_UNIATA) {
  1533. while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
  1534. cylinders /= 2;
  1535. KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
  1536. deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
  1537. deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
  1538. }
  1539. while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
  1540. cylinders /= 2;
  1541. KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
  1542. deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
  1543. deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
  1544. }
  1545. while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
  1546. cylinders /= 2;
  1547. KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
  1548. deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
  1549. deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
  1550. }
  1551. while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
  1552. cylinders /= 2;
  1553. KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
  1554. deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
  1555. deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
  1556. }
  1557. KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
  1558. deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
  1559. deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
  1560. }
  1561. if(!cylinders) {
  1562. KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
  1563. cylinders = tmp_cylinders;
  1564. }
  1565. deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
  1566. deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
  1567. skip_lba_staff:
  1568. KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
  1569. deviceExtension->FullIdentifyData.NumberOfCylinders,
  1570. deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
  1571. ));
  1572. KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
  1573. deviceExtension->FullIdentifyData.NumberOfHeads,
  1574. deviceExtension->FullIdentifyData.NumberOfCurrentHeads
  1575. ));
  1576. KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
  1577. deviceExtension->FullIdentifyData.SectorsPerTrack,
  1578. deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
  1579. ));
  1580. if(NumOfSectors)
  1581. LunExt->NumOfSectors = NumOfSectors;
  1582. /* if(deviceExtension->FullIdentifyData.MajorRevision &&
  1583. deviceExtension->FullIdentifyData.DoubleWordIo) {
  1584. LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
  1585. }*/
  1586. }
  1587. ScsiPortMoveMemory(&LunExt->IdentifyData,
  1588. &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
  1589. InitBadBlocks(LunExt);
  1590. if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
  1591. (Command != IDE_COMMAND_IDENTIFY)) {
  1592. // This device interrupts with the assertion of DRQ after receiving
  1593. // Atapi Packet Command
  1594. LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
  1595. KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
  1596. } else {
  1597. KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
  1598. }
  1599. if(Command != IDE_COMMAND_IDENTIFY) {
  1600. // ATAPI branch
  1601. if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
  1602. // This is a tape.
  1603. LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
  1604. KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
  1605. } else
  1606. if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
  1607. LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
  1608. KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
  1609. // set CD default costs
  1610. LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_CD;
  1611. LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
  1612. LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
  1613. statusByte = WaitForDrq(chan);
  1614. } else {
  1615. KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
  1616. LunExt->IdentifyData.DeviceType));
  1617. }
  1618. } else {
  1619. KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
  1620. }
  1621. GetBaseStatus(chan, statusByte);
  1622. KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
  1623. return TRUE;
  1624. } // end IssueIdentify()
  1625. /*++
  1626. Routine Description:
  1627. Set drive parameters using the IDENTIFY data.
  1628. Arguments:
  1629. HwDeviceExtension - HBA miniport driver's adapter data storage
  1630. DeviceNumber - Indicates which device.
  1631. Return Value:
  1632. TRUE if all goes well.
  1633. --*/
  1634. BOOLEAN
  1635. NTAPI
  1636. SetDriveParameters(
  1637. IN PVOID HwDeviceExtension,
  1638. IN ULONG DeviceNumber,
  1639. IN ULONG lChannel
  1640. )
  1641. {
  1642. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  1643. PIDENTIFY_DATA2 identifyData;
  1644. PHW_LU_EXTENSION LunExt;
  1645. // ULONG i;
  1646. UCHAR statusByte;
  1647. UCHAR errorByte;
  1648. LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
  1649. identifyData = &(LunExt->IdentifyData);
  1650. if(LunExt->DeviceFlags &
  1651. (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
  1652. return TRUE;
  1653. KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
  1654. KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
  1655. // Send SET PARAMETER command.
  1656. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
  1657. IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
  1658. (identifyData->NumberOfHeads - 1), 0,
  1659. (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
  1660. statusByte = UniataIsIdle(deviceExtension, statusByte);
  1661. if(statusByte & IDE_STATUS_ERROR) {
  1662. errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
  1663. KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
  1664. errorByte, statusByte));
  1665. return FALSE;
  1666. }
  1667. if(statusByte == IDE_STATUS_IDLE) {
  1668. return TRUE;
  1669. }
  1670. return FALSE;
  1671. } // end SetDriveParameters()
  1672. VOID
  1673. NTAPI
  1674. UniataForgetDevice(
  1675. PHW_LU_EXTENSION LunExt
  1676. )
  1677. {
  1678. LunExt->DeviceFlags &= DFLAGS_HIDDEN;
  1679. } // end UniataForgetDevice()
  1680. /*++
  1681. Routine Description:
  1682. Reset IDE controller and/or Atapi device.
  1683. Arguments:
  1684. HwDeviceExtension - HBA miniport driver's adapter data storage
  1685. Return Value:
  1686. Nothing.
  1687. --*/
  1688. BOOLEAN
  1689. NTAPI
  1690. AtapiResetController(
  1691. IN PVOID HwDeviceExtension,
  1692. IN ULONG PathId
  1693. )
  1694. {
  1695. KdPrint2((PRINT_PREFIX "AtapiResetController()\n"));
  1696. return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
  1697. } // end AtapiResetController()
  1698. BOOLEAN
  1699. NTAPI
  1700. AtapiResetController__(
  1701. IN PVOID HwDeviceExtension,
  1702. IN ULONG PathId,
  1703. IN BOOLEAN CompleteType
  1704. )
  1705. {
  1706. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  1707. ULONG numberChannels = deviceExtension->NumberChannels;
  1708. PHW_CHANNEL chan = NULL;
  1709. ULONG i,j;
  1710. ULONG MaxLuns;
  1711. UCHAR statusByte;
  1712. PSCSI_REQUEST_BLOCK CurSrb;
  1713. ULONG ChannelCtrlFlags;
  1714. UCHAR dma_status = 0;
  1715. ULONG slotNumber = deviceExtension->slotNumber;
  1716. ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
  1717. ULONG VendorID = deviceExtension->DevID & 0xffff;
  1718. #ifdef _DEBUG
  1719. ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
  1720. #endif
  1721. //ULONG RevID = deviceExtension->RevID;
  1722. ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
  1723. //UCHAR tmp8;
  1724. UCHAR tmp16;
  1725. KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
  1726. if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
  1727. // we shall reset both channels on SimplexOnly devices,
  1728. // It's not worth doing so on normal controllers
  1729. j = PathId;
  1730. numberChannels = min(j+1, deviceExtension->NumberChannels);
  1731. } else {
  1732. j=0;
  1733. numberChannels = deviceExtension->NumberChannels;
  1734. }
  1735. for (; j < numberChannels; j++) {
  1736. KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j));
  1737. chan = &deviceExtension->chan[j];
  1738. KdPrint2((PRINT_PREFIX " CompleteType %#x\n", CompleteType));
  1739. //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
  1740. MaxLuns = chan->NumberLuns;
  1741. if(CompleteType != RESET_COMPLETE_NONE) {
  1742. #ifndef UNIATA_CORE
  1743. while((CurSrb = UniataGetCurRequest(chan))) {
  1744. PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
  1745. KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x\n", CurSrb));
  1746. // Check and see if we are processing an internal srb
  1747. if (AtaReq->OriginalSrb) {
  1748. KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
  1749. AtaReq->Srb = AtaReq->OriginalSrb;
  1750. AtaReq->OriginalSrb = NULL;
  1751. // NOTE: internal SRB doesn't get to SRB queue !!!
  1752. CurSrb = AtaReq->Srb;
  1753. }
  1754. // Remove current request from queue
  1755. UniataRemoveRequest(chan, CurSrb);
  1756. // Check if request is in progress.
  1757. ASSERT(AtaReq->Srb == CurSrb);
  1758. if (CurSrb) {
  1759. // Complete outstanding request with SRB_STATUS_BUS_RESET.
  1760. UCHAR PathId = CurSrb->PathId;
  1761. UCHAR TargetId = CurSrb->TargetId;
  1762. UCHAR Lun = CurSrb->Lun;
  1763. CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
  1764. CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  1765. if (CurSrb->SenseInfoBuffer) {
  1766. PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
  1767. senseBuffer->ErrorCode = 0x70;
  1768. senseBuffer->Valid = 1;
  1769. senseBuffer->AdditionalSenseLength = 0xb;
  1770. if(CompleteType == RESET_COMPLETE_ALL) {
  1771. KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
  1772. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  1773. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
  1774. senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
  1775. } else {
  1776. KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
  1777. senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
  1778. senseBuffer->AdditionalSenseCode = 0;
  1779. senseBuffer->AdditionalSenseCodeQualifier = 0;
  1780. }
  1781. }
  1782. // Clear request tracking fields.
  1783. AtaReq->WordsLeft = 0;
  1784. AtaReq->DataBuffer = NULL;
  1785. AtaReq->TransferLength = 0;
  1786. ScsiPortNotification(RequestComplete,
  1787. deviceExtension,
  1788. CurSrb);
  1789. // Indicate ready for next request.
  1790. ScsiPortNotification(NextLuRequest,
  1791. deviceExtension,
  1792. PathId,
  1793. TargetId,
  1794. Lun);
  1795. }
  1796. if(CompleteType != RESET_COMPLETE_ALL)
  1797. break;
  1798. } // end while()
  1799. #endif //UNIATA_CORE
  1800. } // end if (!CompleteType != RESET_COMPLETE_NONE)
  1801. // Save control flags
  1802. ChannelCtrlFlags = chan->ChannelCtrlFlags;
  1803. // Clear expecting interrupt flag.
  1804. chan->ExpectingInterrupt = FALSE;
  1805. chan->RDP = FALSE;
  1806. chan->ChannelCtrlFlags = 0;
  1807. InterlockedExchange(&(chan->CheckIntr),
  1808. CHECK_INTR_IDLE);
  1809. // Reset controller
  1810. if(ChipFlags & UNIATA_AHCI) {
  1811. KdPrint2((PRINT_PREFIX " AHCI path\n"));
  1812. UniataAhciReset(HwDeviceExtension, j);
  1813. } else {
  1814. KdPrint2((PRINT_PREFIX " ATA path\n"));
  1815. KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
  1816. AtapiDisableInterrupts(deviceExtension, j);
  1817. KdPrint2((PRINT_PREFIX " done\n"));
  1818. switch(VendorID) {
  1819. case ATA_INTEL_ID: {
  1820. ULONG mask;
  1821. ULONG timeout;
  1822. if(!(ChipFlags & UNIATA_SATA))
  1823. goto default_reset;
  1824. if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
  1825. goto default_reset;
  1826. }
  1827. #if 0
  1828. /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
  1829. if(ChipFlags & UNIATA_AHCI) {
  1830. mask = 0x0005 << j;
  1831. } else {
  1832. /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
  1833. GetPciConfig1(0x90, tmp8);
  1834. if(tmp8 & 0x04) {
  1835. mask = 0x0003;
  1836. } else {
  1837. mask = 0x0001 << j;
  1838. }
  1839. }
  1840. #else
  1841. mask = 1 << chan->lun[0]->SATA_lun_map;
  1842. if (MaxLuns > 1) {
  1843. mask |= (1 << chan->lun[1]->SATA_lun_map);
  1844. }
  1845. #endif
  1846. ChangePciConfig2(0x92, a & ~mask);
  1847. AtapiStallExecution(10);
  1848. ChangePciConfig2(0x92, a | mask);
  1849. timeout = 100;
  1850. /* Wait up to 1 sec for "connect well". */
  1851. if (ChipFlags & (I6CH | I6CH2))
  1852. mask = mask << 8;
  1853. else
  1854. mask = mask << 4;
  1855. while (timeout--) {
  1856. AtapiStallExecution(10000);
  1857. GetPciConfig2(0x92, tmp16);
  1858. if ((tmp16 & mask) == mask) {
  1859. AtapiStallExecution(10000);
  1860. break;
  1861. }
  1862. }
  1863. break; }
  1864. case ATA_SIS_ID:
  1865. case ATA_NVIDIA_ID: {
  1866. KdPrint2((PRINT_PREFIX " SIS/nVidia\n"));
  1867. if(!(ChipFlags & UNIATA_SATA))
  1868. goto default_reset;
  1869. break; }
  1870. case ATA_SILICON_IMAGE_ID: {
  1871. ULONG offset;
  1872. ULONG Channel = deviceExtension->Channel + j;
  1873. if(!(ChipFlags & UNIATA_SATA))
  1874. goto default_reset;
  1875. offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
  1876. /* disable PHY state change interrupt */
  1877. AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
  1878. UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
  1879. /* reset controller part for this channel */
  1880. AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
  1881. AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
  1882. AtapiStallExecution(1000);
  1883. AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
  1884. AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
  1885. break; }
  1886. case ATA_PROMISE_ID: {
  1887. break; }
  1888. default:
  1889. if(ChipFlags & UNIATA_SATA) {
  1890. KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
  1891. UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
  1892. }
  1893. default_reset:
  1894. KdPrint2((PRINT_PREFIX " send reset\n"));
  1895. AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
  1896. IDE_DC_RESET_CONTROLLER );
  1897. KdPrint2((PRINT_PREFIX " wait a little\n"));
  1898. AtapiStallExecution(10000);
  1899. // Disable interrupts
  1900. KdPrint2((PRINT_PREFIX " disable intr\n"));
  1901. AtapiDisableInterrupts(deviceExtension, j);
  1902. AtapiStallExecution(100);
  1903. KdPrint2((PRINT_PREFIX " re-enable intr\n"));
  1904. AtapiEnableInterrupts(deviceExtension, j);
  1905. KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
  1906. AtapiStallExecution(100000);
  1907. KdPrint2((PRINT_PREFIX " done\n"));
  1908. break;
  1909. } // end switch()
  1910. //if(!(ChipFlags & UNIATA_SATA)) {}
  1911. if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
  1912. // Reset DMA engine if active
  1913. KdPrint2((PRINT_PREFIX " check DMA engine\n"));
  1914. dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
  1915. KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
  1916. if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
  1917. (dma_status & BM_STATUS_INTR)) {
  1918. AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
  1919. }
  1920. }
  1921. } // ATA vs AHCI
  1922. // all these shall be performed inside AtapiHwInitialize__() ?
  1923. #if 1
  1924. KdPrint2((PRINT_PREFIX " process connected devices\n"));
  1925. // Do special processing for ATAPI and IDE disk devices.
  1926. for (i = 0; i < MaxLuns; i++) {
  1927. // Check if device present.
  1928. if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  1929. if(ChipFlags & UNIATA_AHCI) {
  1930. // everything is done in UniataAhciReset()
  1931. KdPrint2((PRINT_PREFIX " device have gone\n"));
  1932. continue;
  1933. }
  1934. #ifdef NAVO_TEST
  1935. continue;
  1936. #else //NAVO_TEST
  1937. //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
  1938. if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
  1939. continue;
  1940. }
  1941. if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
  1942. continue;
  1943. }
  1944. } else {
  1945. if(ChipFlags & UNIATA_AHCI) {
  1946. // everything is done in UniataAhciReset()
  1947. KdPrint2((PRINT_PREFIX " found some device\n"));
  1948. if(!IssueIdentify(HwDeviceExtension,
  1949. i, j,
  1950. (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ?
  1951. IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
  1952. FALSE)) {
  1953. KdPrint2((PRINT_PREFIX " identify failed !\n"));
  1954. UniataForgetDevice(chan->lun[i]);
  1955. }
  1956. continue;
  1957. }
  1958. if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
  1959. KdPrint2((PRINT_PREFIX " device have gone\n"));
  1960. UniataForgetDevice(chan->lun[i]);
  1961. }
  1962. #endif //NAVO_TEST
  1963. }
  1964. SelectDrive(chan, i);
  1965. AtapiStallExecution(10);
  1966. statusByte = WaitOnBusyLong(chan);
  1967. statusByte = UniataIsIdle(deviceExtension, statusByte);
  1968. if(statusByte == 0xff) {
  1969. KdPrint2((PRINT_PREFIX
  1970. "no drive, status %#x\n",
  1971. statusByte));
  1972. UniataForgetDevice(chan->lun[i]);
  1973. } else
  1974. // Check for ATAPI disk.
  1975. if (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  1976. // Issue soft reset and issue identify.
  1977. GetStatus(chan, statusByte);
  1978. KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
  1979. statusByte));
  1980. AtapiDisableInterrupts(deviceExtension, j);
  1981. AtapiSoftReset(chan, i);
  1982. AtapiEnableInterrupts(deviceExtension, j);
  1983. GetStatus(chan, statusByte);
  1984. if(statusByte == IDE_STATUS_SUCCESS) {
  1985. IssueIdentify(HwDeviceExtension,
  1986. i, j,
  1987. IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
  1988. } else {
  1989. KdPrint2((PRINT_PREFIX
  1990. "AtapiResetController: Status after soft reset %#x\n",
  1991. statusByte));
  1992. }
  1993. GetBaseStatus(chan, statusByte);
  1994. } else {
  1995. // Issue identify and reinit after channel reset.
  1996. if (statusByte != IDE_STATUS_IDLE &&
  1997. statusByte != IDE_STATUS_SUCCESS &&
  1998. statusByte != IDE_STATUS_DRDY) {
  1999. // result2 = FALSE;
  2000. KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
  2001. } else
  2002. if(!IssueIdentify(HwDeviceExtension,
  2003. i, j,
  2004. IDE_COMMAND_IDENTIFY, FALSE)) {
  2005. // result2 = FALSE;
  2006. KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
  2007. } else
  2008. // Set disk geometry parameters.
  2009. if (!SetDriveParameters(HwDeviceExtension, i, j)) {
  2010. KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
  2011. }
  2012. GetBaseStatus(chan, statusByte);
  2013. }
  2014. // force DMA mode reinit
  2015. chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
  2016. }
  2017. #endif //0
  2018. // Enable interrupts, note, the we can have here recursive disable
  2019. AtapiStallExecution(10);
  2020. KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
  2021. j,
  2022. chan->DisableIntr));
  2023. AtapiEnableInterrupts(deviceExtension, j);
  2024. // Call the HwInitialize routine to setup multi-block.
  2025. AtapiHwInitialize__(deviceExtension, j);
  2026. } // for(channel)
  2027. ScsiPortNotification(NextRequest, deviceExtension, NULL);
  2028. return TRUE;
  2029. } // end AtapiResetController__()
  2030. /*++
  2031. Routine Description:
  2032. This routine maps ATAPI and IDE errors to specific SRB statuses.
  2033. Arguments:
  2034. HwDeviceExtension - HBA miniport driver's adapter data storage
  2035. Srb - IO request packet
  2036. Return Value:
  2037. SRB status
  2038. --*/
  2039. ULONG
  2040. NTAPI
  2041. MapError(
  2042. IN PVOID HwDeviceExtension,
  2043. IN PSCSI_REQUEST_BLOCK Srb
  2044. )
  2045. {
  2046. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  2047. ULONG lChannel = GET_CHANNEL(Srb);
  2048. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  2049. // ULONG i;
  2050. UCHAR errorByte;
  2051. UCHAR srbStatus = SRB_STATUS_SUCCESS;
  2052. UCHAR scsiStatus;
  2053. ULONG DeviceNumber = GET_CDEV(Srb);
  2054. PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
  2055. // Read the error register.
  2056. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  2057. KdPrint2((PRINT_PREFIX
  2058. "MapError: Error register is %#x\n",
  2059. errorByte));
  2060. if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  2061. switch (errorByte >> 4) {
  2062. case SCSI_SENSE_NO_SENSE:
  2063. KdPrint2((PRINT_PREFIX
  2064. "ATAPI: No sense information\n"));
  2065. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2066. srbStatus = SRB_STATUS_ERROR;
  2067. break;
  2068. case SCSI_SENSE_RECOVERED_ERROR:
  2069. KdPrint2((PRINT_PREFIX
  2070. "ATAPI: Recovered error\n"));
  2071. scsiStatus = 0;
  2072. srbStatus = SRB_STATUS_SUCCESS;
  2073. break;
  2074. case SCSI_SENSE_NOT_READY:
  2075. KdPrint2((PRINT_PREFIX
  2076. "ATAPI: Device not ready\n"));
  2077. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2078. srbStatus = SRB_STATUS_ERROR;
  2079. break;
  2080. case SCSI_SENSE_MEDIUM_ERROR:
  2081. KdPrint2((PRINT_PREFIX
  2082. "ATAPI: Media error\n"));
  2083. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2084. srbStatus = SRB_STATUS_ERROR;
  2085. break;
  2086. case SCSI_SENSE_HARDWARE_ERROR:
  2087. KdPrint2((PRINT_PREFIX
  2088. "ATAPI: Hardware error\n"));
  2089. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2090. srbStatus = SRB_STATUS_ERROR;
  2091. break;
  2092. case SCSI_SENSE_ILLEGAL_REQUEST:
  2093. KdPrint2((PRINT_PREFIX
  2094. "ATAPI: Illegal request\n"));
  2095. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2096. srbStatus = SRB_STATUS_ERROR;
  2097. break;
  2098. case SCSI_SENSE_UNIT_ATTENTION:
  2099. KdPrint2((PRINT_PREFIX
  2100. "ATAPI: Unit attention\n"));
  2101. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2102. srbStatus = SRB_STATUS_ERROR;
  2103. break;
  2104. case SCSI_SENSE_DATA_PROTECT:
  2105. KdPrint2((PRINT_PREFIX
  2106. "ATAPI: Data protect\n"));
  2107. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2108. srbStatus = SRB_STATUS_ERROR;
  2109. break;
  2110. case SCSI_SENSE_BLANK_CHECK:
  2111. KdPrint2((PRINT_PREFIX
  2112. "ATAPI: Blank check\n"));
  2113. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2114. srbStatus = SRB_STATUS_ERROR;
  2115. break;
  2116. case SCSI_SENSE_ABORTED_COMMAND:
  2117. KdPrint2((PRINT_PREFIX
  2118. "Atapi: Command Aborted\n"));
  2119. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2120. srbStatus = SRB_STATUS_ERROR;
  2121. break;
  2122. default:
  2123. KdPrint2((PRINT_PREFIX
  2124. "ATAPI: Invalid sense information\n"));
  2125. scsiStatus = 0;
  2126. srbStatus = SRB_STATUS_ERROR;
  2127. break;
  2128. }
  2129. } else {
  2130. scsiStatus = 0;
  2131. // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
  2132. chan->ReturningMediaStatus = errorByte;
  2133. if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
  2134. KdPrint2((PRINT_PREFIX
  2135. "IDE: Media change\n"));
  2136. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2137. srbStatus = SRB_STATUS_ERROR;
  2138. if (Srb->SenseInfoBuffer) {
  2139. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2140. senseBuffer->ErrorCode = 0x70;
  2141. senseBuffer->Valid = 1;
  2142. senseBuffer->AdditionalSenseLength = 0xb;
  2143. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  2144. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  2145. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2146. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2147. }
  2148. } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
  2149. KdPrint2((PRINT_PREFIX
  2150. "IDE: Command abort\n"));
  2151. srbStatus = SRB_STATUS_ABORTED;
  2152. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2153. if (Srb->SenseInfoBuffer) {
  2154. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2155. senseBuffer->ErrorCode = 0x70;
  2156. senseBuffer->Valid = 1;
  2157. senseBuffer->AdditionalSenseLength = 0xb;
  2158. senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
  2159. senseBuffer->AdditionalSenseCode = 0;
  2160. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2161. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2162. }
  2163. LunExt->ErrorCount++;
  2164. } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
  2165. KdPrint2((PRINT_PREFIX
  2166. "IDE: End of media\n"));
  2167. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2168. srbStatus = SRB_STATUS_ERROR;
  2169. if (Srb->SenseInfoBuffer) {
  2170. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2171. senseBuffer->ErrorCode = 0x70;
  2172. senseBuffer->Valid = 1;
  2173. senseBuffer->AdditionalSenseLength = 0xb;
  2174. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  2175. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
  2176. senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
  2177. senseBuffer->EndOfMedia = 1;
  2178. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2179. }
  2180. if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
  2181. LunExt->ErrorCount++;
  2182. }
  2183. } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
  2184. KdPrint2((PRINT_PREFIX
  2185. "IDE: Illegal length\n"));
  2186. srbStatus = SRB_STATUS_INVALID_REQUEST;
  2187. if (Srb->SenseInfoBuffer) {
  2188. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2189. senseBuffer->ErrorCode = 0x70;
  2190. senseBuffer->Valid = 1;
  2191. senseBuffer->AdditionalSenseLength = 0xb;
  2192. senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
  2193. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE;
  2194. senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
  2195. senseBuffer->IncorrectLength = 1;
  2196. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2197. }
  2198. } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
  2199. KdPrint2((PRINT_PREFIX
  2200. "IDE: Bad block\n"));
  2201. srbStatus = SRB_STATUS_ERROR;
  2202. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2203. if (Srb->SenseInfoBuffer) {
  2204. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2205. senseBuffer->ErrorCode = 0x70;
  2206. senseBuffer->Valid = 1;
  2207. senseBuffer->AdditionalSenseLength = 0xb;
  2208. senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
  2209. senseBuffer->AdditionalSenseCode = 0;
  2210. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2211. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2212. }
  2213. } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
  2214. KdPrint2((PRINT_PREFIX
  2215. "IDE: Id not found\n"));
  2216. srbStatus = SRB_STATUS_ERROR;
  2217. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2218. if (Srb->SenseInfoBuffer) {
  2219. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2220. senseBuffer->ErrorCode = 0x70;
  2221. senseBuffer->Valid = 1;
  2222. senseBuffer->AdditionalSenseLength = 0xb;
  2223. senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
  2224. senseBuffer->AdditionalSenseCode = 0;
  2225. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2226. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2227. }
  2228. LunExt->ErrorCount++;
  2229. } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
  2230. KdPrint2((PRINT_PREFIX
  2231. "IDE: Media change\n"));
  2232. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2233. srbStatus = SRB_STATUS_ERROR;
  2234. if (Srb->SenseInfoBuffer) {
  2235. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2236. senseBuffer->ErrorCode = 0x70;
  2237. senseBuffer->Valid = 1;
  2238. senseBuffer->AdditionalSenseLength = 0xb;
  2239. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  2240. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  2241. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2242. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2243. }
  2244. } else if (errorByte & IDE_ERROR_DATA_ERROR) {
  2245. KdPrint2((PRINT_PREFIX
  2246. "IDE: Data error\n"));
  2247. scsiStatus = SCSISTAT_CHECK_CONDITION;
  2248. srbStatus = SRB_STATUS_ERROR;
  2249. if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
  2250. LunExt->ErrorCount++;
  2251. }
  2252. // Build sense buffer
  2253. if (Srb->SenseInfoBuffer) {
  2254. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  2255. senseBuffer->ErrorCode = 0x70;
  2256. senseBuffer->Valid = 1;
  2257. senseBuffer->AdditionalSenseLength = 0xb;
  2258. senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
  2259. senseBuffer->AdditionalSenseCode = 0;
  2260. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2261. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2262. }
  2263. }
  2264. if (LunExt->ErrorCount >= MAX_ERRORS) {
  2265. // deviceExtension->DWordIO = FALSE;
  2266. KdPrint2((PRINT_PREFIX
  2267. "MapError: ErrorCount >= MAX_ERRORS\n"));
  2268. LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
  2269. LunExt->MaximumBlockXfer = 0;
  2270. BrutePoint();
  2271. KdPrint2((PRINT_PREFIX
  2272. "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
  2273. // Log the error.
  2274. KdPrint2((PRINT_PREFIX
  2275. "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
  2276. HwDeviceExtension,
  2277. Srb,
  2278. Srb->PathId,
  2279. Srb->TargetId,
  2280. Srb->Lun,
  2281. SP_BAD_FW_WARNING,
  2282. 4
  2283. ));
  2284. ScsiPortLogError( HwDeviceExtension,
  2285. Srb,
  2286. Srb->PathId,
  2287. Srb->TargetId,
  2288. Srb->Lun,
  2289. SP_BAD_FW_WARNING,
  2290. 4);
  2291. // Reprogram to not use Multi-sector.
  2292. UCHAR statusByte;
  2293. if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
  2294. !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
  2295. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
  2296. // Check for errors. Reset the value to 0 (disable MultiBlock) if the
  2297. // command was aborted.
  2298. if (statusByte & IDE_STATUS_ERROR) {
  2299. // Read the error register.
  2300. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  2301. KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
  2302. statusByte,
  2303. errorByte));
  2304. // Adjust the devExt. value, if necessary.
  2305. LunExt->MaximumBlockXfer = 0;
  2306. BrutePoint();
  2307. }
  2308. }
  2309. }
  2310. }
  2311. // Set SCSI status to indicate a check condition.
  2312. Srb->ScsiStatus = scsiStatus;
  2313. return srbStatus;
  2314. } // end MapError()
  2315. /*++
  2316. Routine Description:
  2317. Arguments:
  2318. HwDeviceExtension - HBA miniport driver's adapter data storage
  2319. Return Value:
  2320. TRUE - if initialization successful.
  2321. FALSE - if initialization unsuccessful.
  2322. --*/
  2323. BOOLEAN
  2324. NTAPI
  2325. AtapiHwInitialize(
  2326. IN PVOID HwDeviceExtension
  2327. )
  2328. {
  2329. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  2330. ULONG numberChannels = deviceExtension->NumberChannels;
  2331. ULONG c;
  2332. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
  2333. if(WinVer_WDM_Model) {
  2334. AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
  2335. }
  2336. /* do extra chipset specific setups */
  2337. AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
  2338. /*
  2339. if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
  2340. KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
  2341. BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
  2342. }
  2343. */
  2344. for (c = 0; c < numberChannels; c++) {
  2345. AtapiHwInitialize__(deviceExtension, c);
  2346. }
  2347. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
  2348. return TRUE;
  2349. } // end AtapiHwInitialize()
  2350. VOID
  2351. NTAPI
  2352. AtapiHwInitialize__(
  2353. IN PHW_DEVICE_EXTENSION deviceExtension,
  2354. IN ULONG lChannel
  2355. )
  2356. {
  2357. ULONG i;
  2358. UCHAR statusByte, errorByte;
  2359. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  2360. PHW_LU_EXTENSION LunExt;
  2361. // ULONG tmp32;
  2362. ULONG PreferedMode = 0xffffffff;
  2363. AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
  2364. FindDevices(deviceExtension, 0, lChannel);
  2365. for (i = 0; i < chan->NumberLuns; i++) {
  2366. KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
  2367. LunExt = chan->lun[i];
  2368. // skip empty slots
  2369. if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  2370. continue;
  2371. }
  2372. AtapiDisableInterrupts(deviceExtension, lChannel);
  2373. AtapiStallExecution(1);
  2374. if (!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
  2375. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
  2376. // Enable media status notification
  2377. IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
  2378. // If supported, setup Multi-block transfers.
  2379. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2380. IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
  2381. LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
  2382. // Check for errors. Reset the value to 0 (disable MultiBlock) if the
  2383. // command was aborted.
  2384. if (statusByte & IDE_STATUS_ERROR) {
  2385. // Read the error register.
  2386. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  2387. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
  2388. statusByte,
  2389. errorByte));
  2390. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2391. IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
  2392. LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
  2393. if (statusByte & IDE_STATUS_ERROR) {
  2394. // Read the error register.
  2395. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  2396. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
  2397. statusByte,
  2398. errorByte));
  2399. }
  2400. // Adjust the devExt. value, if necessary.
  2401. LunExt->MaximumBlockXfer = 0;
  2402. } else {
  2403. KdPrint2((PRINT_PREFIX
  2404. "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
  2405. i,
  2406. LunExt->MaximumBlockXfer));
  2407. }
  2408. if(LunExt->IdentifyData.MajorRevision) {
  2409. if(LunExt->opt_ReadCacheEnable) {
  2410. KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
  2411. // If supported, setup read/write cacheing
  2412. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2413. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  2414. 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
  2415. // Check for errors.
  2416. if (statusByte & IDE_STATUS_ERROR) {
  2417. KdPrint2((PRINT_PREFIX
  2418. "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
  2419. i));
  2420. LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
  2421. } else {
  2422. LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
  2423. }
  2424. } else {
  2425. KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
  2426. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2427. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  2428. 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
  2429. LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
  2430. }
  2431. if(LunExt->opt_WriteCacheEnable) {
  2432. KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
  2433. // If supported & allowed, setup write cacheing
  2434. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2435. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  2436. 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
  2437. // Check for errors.
  2438. if (statusByte & IDE_STATUS_ERROR) {
  2439. KdPrint2((PRINT_PREFIX
  2440. "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
  2441. i));
  2442. LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
  2443. } else {
  2444. LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
  2445. }
  2446. } else {
  2447. KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
  2448. statusByte = AtaCommand(deviceExtension, i, lChannel,
  2449. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  2450. 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
  2451. LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
  2452. }
  2453. }
  2454. } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
  2455. ULONG j;
  2456. BOOLEAN isSanyo = FALSE;
  2457. CCHAR vendorId[26];
  2458. KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
  2459. // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
  2460. for (j = 0; j < 26; j += 2) {
  2461. // Build a buffer based on the identify data.
  2462. MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
  2463. }
  2464. if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
  2465. // Inquiry string for older model had a '-', newer is '_'
  2466. if (vendorId[12] == 'C') {
  2467. // Torisan changer. Set the bit. This will be used in several places
  2468. // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
  2469. LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
  2470. LunExt->DiscsPresent = 3;
  2471. isSanyo = TRUE;
  2472. }
  2473. }
  2474. }
  2475. PreferedMode = LunExt->opt_MaxTransferMode;
  2476. if(PreferedMode == 0xffffffff) {
  2477. KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
  2478. PreferedMode = chan->MaxTransferMode;
  2479. }
  2480. if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
  2481. KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
  2482. PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
  2483. }
  2484. KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
  2485. LunExt->OrigTransferMode =
  2486. LunExt->LimitedTransferMode =
  2487. LunExt->TransferMode =
  2488. (CHAR)PreferedMode;
  2489. AtapiDmaInit__(deviceExtension, LunExt);
  2490. LunExt->OrigTransferMode =
  2491. LunExt->LimitedTransferMode =
  2492. LunExt->TransferMode;
  2493. KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
  2494. // We need to get our device ready for action before
  2495. // returning from this function
  2496. // According to the atapi spec 2.5 or 2.6, an atapi device
  2497. // clears its status BSY bit when it is ready for atapi commands.
  2498. // However, some devices (Panasonic SQ-TC500N) are still
  2499. // not ready even when the status BSY is clear. They don't react
  2500. // to atapi commands.
  2501. //
  2502. // Since there is really no other indication that tells us
  2503. // the drive is really ready for action. We are going to check BSY
  2504. // is clear and then just wait for an arbitrary amount of time!
  2505. //
  2506. if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  2507. ULONG waitCount;
  2508. // have to get out of the loop sometime!
  2509. // 10000 * 100us = 1000,000us = 1000ms = 1s
  2510. waitCount = 10000;
  2511. GetStatus(chan, statusByte);
  2512. while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
  2513. KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x\n)", statusByte));
  2514. // Wait for Busy to drop.
  2515. AtapiStallExecution(100);
  2516. GetStatus(chan, statusByte);
  2517. waitCount--;
  2518. }
  2519. // 5000 * 100us = 500,000us = 500ms = 0.5s
  2520. waitCount = 5000;
  2521. do {
  2522. AtapiStallExecution(100);
  2523. } while (waitCount--);
  2524. }
  2525. GetBaseStatus(chan, statusByte);
  2526. AtapiEnableInterrupts(deviceExtension, lChannel);
  2527. AtapiStallExecution(10);
  2528. }
  2529. return;
  2530. } // end AtapiHwInitialize()
  2531. #ifndef UNIATA_CORE
  2532. VOID
  2533. NTAPI
  2534. AtapiHwInitializeChanger(
  2535. IN PVOID HwDeviceExtension,
  2536. IN PSCSI_REQUEST_BLOCK Srb,
  2537. IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
  2538. {
  2539. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  2540. ULONG lChannel = GET_CHANNEL(Srb);
  2541. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  2542. ULONG DeviceNumber = GET_CDEV(Srb);
  2543. PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
  2544. if (MechanismStatus) {
  2545. LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
  2546. if (LunExt->DiscsPresent > 1) {
  2547. LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
  2548. }
  2549. }
  2550. return;
  2551. } // end AtapiHwInitializeChanger()
  2552. /*++
  2553. Routine Description:
  2554. This routine will parse the string for a match on the keyword, then
  2555. calculate the value for the keyword and return it to the caller.
  2556. Arguments:
  2557. String - The ASCII string to parse.
  2558. KeyWord - The keyword for the value desired.
  2559. Return Values:
  2560. Zero if value not found
  2561. Value converted from ASCII to binary.
  2562. --*/
  2563. ULONG
  2564. NTAPI
  2565. AtapiParseArgumentString(
  2566. IN PCCH String,
  2567. IN PCCH KeyWord
  2568. )
  2569. {
  2570. PCCH cptr;
  2571. PCCH kptr;
  2572. ULONG value;
  2573. ULONG stringLength = 0;
  2574. ULONG keyWordLength = 0;
  2575. ULONG index;
  2576. if (!String) {
  2577. return 0;
  2578. }
  2579. if (!KeyWord) {
  2580. return 0;
  2581. }
  2582. // Calculate the string length and lower case all characters.
  2583. cptr = String;
  2584. while (*cptr++) {
  2585. stringLength++;
  2586. }
  2587. // Calculate the keyword length.
  2588. kptr = KeyWord;
  2589. while (*kptr++) {
  2590. keyWordLength++;
  2591. }
  2592. if (keyWordLength > stringLength) {
  2593. // Can't possibly have a match.
  2594. return 0;
  2595. }
  2596. // Now setup and start the compare.
  2597. cptr = String;
  2598. ContinueSearch:
  2599. // The input string may start with white space. Skip it.
  2600. while (*cptr == ' ' || *cptr == '\t') {
  2601. cptr++;
  2602. }
  2603. if (*cptr == '\0') {
  2604. // end of string.
  2605. return 0;
  2606. }
  2607. kptr = KeyWord;
  2608. while ((*cptr == *kptr) ||
  2609. (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
  2610. (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
  2611. cptr++;
  2612. kptr++;
  2613. if (*cptr == '\0') {
  2614. // end of string
  2615. return 0;
  2616. }
  2617. }
  2618. if (*kptr == '\0') {
  2619. // May have a match backup and check for blank or equals.
  2620. while (*cptr == ' ' || *cptr == '\t') {
  2621. cptr++;
  2622. }
  2623. // Found a match. Make sure there is an equals.
  2624. if (*cptr != '=') {
  2625. // Not a match so move to the next semicolon.
  2626. while (*cptr) {
  2627. if (*cptr++ == ';') {
  2628. goto ContinueSearch;
  2629. }
  2630. }
  2631. return 0;
  2632. }
  2633. // Skip the equals sign.
  2634. cptr++;
  2635. // Skip white space.
  2636. while ((*cptr == ' ') || (*cptr == '\t')) {
  2637. cptr++;
  2638. }
  2639. if (*cptr == '\0') {
  2640. // Early end of string, return not found
  2641. return 0;
  2642. }
  2643. if (*cptr == ';') {
  2644. // This isn't it either.
  2645. cptr++;
  2646. goto ContinueSearch;
  2647. }
  2648. value = 0;
  2649. if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
  2650. // Value is in Hex. Skip the "0x"
  2651. cptr += 2;
  2652. for (index = 0; *(cptr + index); index++) {
  2653. if (*(cptr + index) == ' ' ||
  2654. *(cptr + index) == '\t' ||
  2655. *(cptr + index) == ';') {
  2656. break;
  2657. }
  2658. if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
  2659. value = (16 * value) + (*(cptr + index) - '0');
  2660. } else {
  2661. if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
  2662. value = (16 * value) + (*(cptr + index) - 'a' + 10);
  2663. } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
  2664. value = (16 * value) + (*(cptr + index) - 'A' + 10);
  2665. } else {
  2666. // Syntax error, return not found.
  2667. return 0;
  2668. }
  2669. }
  2670. }
  2671. } else {
  2672. // Value is in Decimal.
  2673. for (index = 0; *(cptr + index); index++) {
  2674. if (*(cptr + index) == ' ' ||
  2675. *(cptr + index) == '\t' ||
  2676. *(cptr + index) == ';') {
  2677. break;
  2678. }
  2679. if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
  2680. value = (10 * value) + (*(cptr + index) - '0');
  2681. } else {
  2682. // Syntax error return not found.
  2683. return 0;
  2684. }
  2685. }
  2686. }
  2687. return value;
  2688. } else {
  2689. // Not a match check for ';' to continue search.
  2690. while (*cptr) {
  2691. if (*cptr++ == ';') {
  2692. goto ContinueSearch;
  2693. }
  2694. }
  2695. return 0;
  2696. }
  2697. } // end AtapiParseArgumentString()_
  2698. /*
  2699. Timer callback
  2700. */
  2701. VOID
  2702. NTAPI
  2703. AtapiCallBack__(
  2704. IN PVOID HwDeviceExtension,
  2705. IN UCHAR lChannel
  2706. )
  2707. {
  2708. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  2709. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  2710. ULONG c, _c;
  2711. PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
  2712. UCHAR statusByte;
  2713. KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
  2714. // If the last command was DSC restrictive, see if it's set. If so, the device is
  2715. // ready for a new request. Otherwise, reset the timer and come back to here later.
  2716. // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
  2717. // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
  2718. // we shall have no problem with interrupt handler.
  2719. if (!srb || chan->ExpectingInterrupt) {
  2720. KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
  2721. chan->DpcState = DPC_STATE_TIMER;
  2722. if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
  2723. InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
  2724. KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
  2725. }
  2726. goto ReturnCallback;
  2727. }
  2728. #ifdef DBG
  2729. if (!IS_RDP((srb->Cdb[0]))) {
  2730. KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
  2731. }
  2732. #endif
  2733. if(!(chan->RDP)) {
  2734. goto ReturnEnableIntr;
  2735. }
  2736. GetStatus(chan, statusByte);
  2737. if (statusByte & IDE_STATUS_DSC) {
  2738. UCHAR PathId = srb->PathId;
  2739. UCHAR TargetId = srb->TargetId;
  2740. UCHAR Lun = srb->Lun;
  2741. KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
  2742. AtapiDmaDBSync(chan, srb);
  2743. UniataRemoveRequest(chan, srb);
  2744. ScsiPortNotification(RequestComplete, deviceExtension, srb);
  2745. // Clear current SRB.
  2746. if(!deviceExtension->simplexOnly) {
  2747. srb = UniataGetCurRequest(chan);
  2748. } else {
  2749. srb = NULL;
  2750. }
  2751. chan->RDP = FALSE;
  2752. // Ask for next request.
  2753. ScsiPortNotification(NextLuRequest,
  2754. deviceExtension,
  2755. PathId,
  2756. TargetId,
  2757. Lun);
  2758. ScsiPortNotification(NextRequest, deviceExtension, NULL);
  2759. if(srb) {
  2760. AtapiStartIo__(HwDeviceExtension, srb, FALSE);
  2761. }
  2762. } else {
  2763. KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
  2764. srb->Cdb[0]));
  2765. AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
  2766. AtapiCallBack_X,
  2767. 1000);
  2768. goto ReturnCallback;
  2769. }
  2770. ReturnEnableIntr:
  2771. if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
  2772. KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
  2773. //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  2774. #ifdef UNIATA_USE_XXableInterrupts
  2775. chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
  2776. // must be called on DISPATCH_LEVEL
  2777. ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
  2778. AtapiEnableInterrupts__);
  2779. #else
  2780. AtapiEnableInterrupts(HwDeviceExtension, lChannel);
  2781. InterlockedExchange(&(chan->CheckIntr),
  2782. CHECK_INTR_IDLE);
  2783. // Will raise IRQL to DIRQL
  2784. AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
  2785. AtapiEnableInterrupts__,
  2786. 1);
  2787. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
  2788. #endif // UNIATA_USE_XXableInterrupts
  2789. } else {
  2790. //ASSERT(!deviceExtension->simplexOnly);
  2791. }
  2792. ReturnCallback:
  2793. // Check other channel
  2794. // In simplex mode no interrupts must appear on other channels
  2795. for(_c=0; _c<deviceExtension->NumberChannels-1; _c++) {
  2796. c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
  2797. chan = &(deviceExtension->chan[c]);
  2798. if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
  2799. CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
  2800. CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED)
  2801. {
  2802. //ASSERT(!deviceExtension->simplexOnly);
  2803. chan->DpcState = DPC_STATE_ISR;
  2804. if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
  2805. InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
  2806. }
  2807. }
  2808. }
  2809. KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
  2810. return;
  2811. } // end AtapiCallBack__()
  2812. VOID
  2813. NTAPI
  2814. AtapiCallBack_X(
  2815. IN PVOID HwDeviceExtension
  2816. )
  2817. {
  2818. AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
  2819. }
  2820. #endif //UNIATA_CORE
  2821. /*++
  2822. Routine Description:
  2823. This is the interrupt service routine for ATAPI IDE miniport driver.
  2824. Arguments:
  2825. HwDeviceExtension - HBA miniport driver's adapter data storage
  2826. Return Value:
  2827. TRUE if expecting an interrupt.
  2828. --*/
  2829. BOOLEAN
  2830. NTAPI
  2831. AtapiInterrupt(
  2832. IN PVOID HwDeviceExtension
  2833. )
  2834. {
  2835. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  2836. ULONG c, _c;
  2837. BOOLEAN status = FALSE;
  2838. ULONG c_state;
  2839. ULONG i_res = 0;
  2840. ULONG pass;
  2841. BOOLEAN checked[AHCI_MAX_PORT];
  2842. ULONG hIS;
  2843. KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
  2844. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  2845. hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
  2846. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
  2847. if(!hIS) {
  2848. return FALSE;
  2849. }
  2850. }
  2851. for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
  2852. checked[_c] = FALSE;
  2853. }
  2854. // fc =
  2855. for(pass=0; pass<2; pass++) {
  2856. for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
  2857. c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
  2858. if(checked[c])
  2859. continue;
  2860. // check non-empty and expecting interrupt channels first
  2861. if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
  2862. continue;
  2863. checked[c] = TRUE;
  2864. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
  2865. if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
  2866. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
  2867. continue;
  2868. }
  2869. // lock channel. Wait, while 2nd ISR checks interrupt on this channel
  2870. do {
  2871. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
  2872. // c_state = deviceExtension->chan[c].CheckIntr;
  2873. // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
  2874. // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
  2875. // }
  2876. c_state =
  2877. (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
  2878. CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
  2879. CRNT_ILK_TYPE CHECK_INTR_DETECTED);
  2880. if(c_state == CHECK_INTR_IDLE) {
  2881. // c_state = deviceExtension->chan[c].CheckIntr;
  2882. // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
  2883. // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
  2884. // }
  2885. c_state =
  2886. (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
  2887. CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
  2888. CRNT_ILK_TYPE CHECK_INTR_IDLE);
  2889. }
  2890. } while(c_state == CHECK_INTR_CHECK);
  2891. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
  2892. // check if already serviced
  2893. if(c_state == CHECK_INTR_ACTIVE) {
  2894. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
  2895. continue;
  2896. }
  2897. if((c_state == CHECK_INTR_DETECTED) ||
  2898. (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
  2899. if(i_res == INTERRUPT_REASON_UNEXPECTED) {
  2900. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
  2901. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  2902. return TRUE;
  2903. }
  2904. // disable interrupts on other channel of legacy mode
  2905. // ISA-bridged onboard controller
  2906. if(deviceExtension->simplexOnly /*||
  2907. ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
  2908. AtapiDisableInterrupts(deviceExtension, !c);
  2909. }
  2910. deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
  2911. if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
  2912. deviceExtension->LastInterruptedChannel = (UCHAR)c;
  2913. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
  2914. status = TRUE;
  2915. } else {
  2916. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
  2917. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  2918. }
  2919. // re-enable interrupts on other channel
  2920. if(deviceExtension->simplexOnly /*||
  2921. ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
  2922. AtapiEnableInterrupts(deviceExtension, !c);
  2923. }
  2924. } else {
  2925. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
  2926. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  2927. }
  2928. }
  2929. }
  2930. KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
  2931. if(status) {
  2932. deviceExtension->FirstChannelToCheck++;
  2933. if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
  2934. deviceExtension->FirstChannelToCheck = 0;
  2935. }
  2936. return status;
  2937. } // end AtapiInterrupt()
  2938. //ULONG i2c = 0;
  2939. #ifndef UNIATA_CORE
  2940. BOOLEAN
  2941. NTAPI
  2942. AtapiInterrupt2(
  2943. IN PKINTERRUPT Interrupt,
  2944. IN PVOID Isr2HwDeviceExtension
  2945. )
  2946. {
  2947. PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
  2948. PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
  2949. ULONG c;
  2950. BOOLEAN status = FALSE;
  2951. ULONG c_count = 0;
  2952. ULONG i_res;
  2953. ULONG hIS;
  2954. // we should never get here for ISA/MCA
  2955. if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
  2956. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
  2957. return FALSE;
  2958. }
  2959. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  2960. hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
  2961. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
  2962. if(!hIS) {
  2963. return FALSE;
  2964. }
  2965. }
  2966. for(c=0; c<deviceExtension->NumberChannels; c++) {
  2967. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
  2968. if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
  2969. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
  2970. continue;
  2971. }
  2972. if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
  2973. CRNT_ILK_TYPE CHECK_INTR_CHECK,
  2974. CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE)
  2975. {
  2976. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
  2977. // hunt on unexpected intr (Some devices generate double interrupts,
  2978. // some controllers (at least CMD649) interrupt twice with small delay.
  2979. // If interrupts are disabled, they queue interrupt and re-issue it later,
  2980. // when we do not expect it.
  2981. continue;
  2982. }
  2983. c_count++;
  2984. if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
  2985. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
  2986. if(i_res == INTERRUPT_REASON_UNEXPECTED) {
  2987. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
  2988. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  2989. return TRUE;
  2990. }
  2991. status = TRUE;
  2992. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
  2993. } else {
  2994. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  2995. }
  2996. }
  2997. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
  2998. if(status && (c_count != deviceExtension->NumberChannels)) {
  2999. // there is an active ISR/DPC for one channel, but
  3000. // we have an interrupt from another one
  3001. // Lets inform current ISR/DPC about new interrupt
  3002. InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
  3003. } else {
  3004. status = FALSE;
  3005. }
  3006. KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
  3007. return status;
  3008. } // end AtapiInterrupt2()
  3009. RETTYPE_XXableInterrupts
  3010. NTAPI
  3011. AtapiInterruptDpc(
  3012. IN PVOID HwDeviceExtension
  3013. )
  3014. {
  3015. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3016. ULONG c;
  3017. for(c=0; c<deviceExtension->NumberChannels; c++) {
  3018. KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
  3019. if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
  3020. if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
  3021. CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
  3022. CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED)
  3023. {
  3024. continue;
  3025. }
  3026. } else {
  3027. deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
  3028. }
  3029. /*
  3030. if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
  3031. AtapiDisableInterrupts(deviceExtension, lChannel);
  3032. }
  3033. */
  3034. deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
  3035. if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
  3036. InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
  3037. }
  3038. }
  3039. return RETVAL_XXableInterrupts;
  3040. } // end AtapiInterruptDpc()
  3041. RETTYPE_XXableInterrupts
  3042. NTAPI
  3043. AtapiEnableInterrupts__(
  3044. IN PVOID HwDeviceExtension
  3045. )
  3046. {
  3047. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3048. KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
  3049. ULONG c;
  3050. PHW_CHANNEL chan = NULL;
  3051. for(c=0; c<deviceExtension->NumberChannels; c++) {
  3052. KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
  3053. chan = &(deviceExtension->chan[c]);
  3054. if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
  3055. // enable intrs on requested channel
  3056. chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
  3057. AtapiEnableInterrupts(HwDeviceExtension, c);
  3058. InterlockedExchange(&(chan->CheckIntr),
  3059. CHECK_INTR_IDLE);
  3060. // check if current or other channel(s) interrupted
  3061. //AtapiInterrupt(HwDeviceExtension);
  3062. if(deviceExtension->simplexOnly) {
  3063. break;
  3064. }
  3065. } else {
  3066. // check if other channel(s) interrupted
  3067. // must do nothing in simplex mode
  3068. if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
  3069. CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
  3070. CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
  3071. continue;
  3072. }
  3073. //ASSERT(!deviceExtension->simplexOnly);
  3074. chan->DpcState = DPC_STATE_ISR;
  3075. if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
  3076. InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
  3077. }
  3078. }
  3079. }
  3080. // In simplex mode next command must be sent to device here
  3081. if(deviceExtension->simplexOnly && chan) {
  3082. PSCSI_REQUEST_BLOCK srb;
  3083. chan = UniataGetNextChannel(chan);
  3084. if(chan) {
  3085. srb = UniataGetCurRequest(chan);
  3086. } else {
  3087. srb = NULL;
  3088. }
  3089. if(srb) {
  3090. AtapiStartIo__(HwDeviceExtension, srb, FALSE);
  3091. }
  3092. }
  3093. return RETVAL_XXableInterrupts;
  3094. } // end AtapiEnableInterrupts__()
  3095. #endif //UNIATA_CORE
  3096. VOID
  3097. NTAPI
  3098. AtapiEnableInterrupts(
  3099. IN PVOID HwDeviceExtension,
  3100. IN ULONG c
  3101. )
  3102. {
  3103. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3104. PHW_CHANNEL chan;
  3105. if(c >= deviceExtension->NumberChannels) {
  3106. KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
  3107. return;
  3108. }
  3109. chan = &(deviceExtension->chan[c]);
  3110. KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
  3111. if(!InterlockedDecrement(&chan->DisableIntr)) {
  3112. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  3113. UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
  3114. } else {
  3115. AtapiWritePort1(chan, IDX_IO2_o_Control,
  3116. IDE_DC_A_4BIT );
  3117. }
  3118. chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
  3119. } else {
  3120. AtapiWritePort1(chan, IDX_IO2_o_Control,
  3121. IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
  3122. }
  3123. return;
  3124. } // end AtapiEnableInterrupts()
  3125. VOID
  3126. NTAPI
  3127. AtapiDisableInterrupts(
  3128. IN PVOID HwDeviceExtension,
  3129. IN ULONG c
  3130. )
  3131. {
  3132. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3133. PHW_CHANNEL chan;
  3134. if(c >= deviceExtension->NumberChannels) {
  3135. KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
  3136. return;
  3137. }
  3138. chan = &(deviceExtension->chan[c]);
  3139. KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
  3140. // mark channel as busy
  3141. if(InterlockedIncrement(&chan->DisableIntr)) {
  3142. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  3143. UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
  3144. (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
  3145. ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
  3146. ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
  3147. ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
  3148. ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
  3149. );
  3150. } else {
  3151. AtapiWritePort1(chan, IDX_IO2_o_Control,
  3152. IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
  3153. }
  3154. chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
  3155. }
  3156. return;
  3157. } // end AtapiDisableInterrupts()
  3158. /*
  3159. Check hardware for interrupt state
  3160. */
  3161. BOOLEAN
  3162. NTAPI
  3163. AtapiCheckInterrupt__(
  3164. IN PVOID HwDeviceExtension,
  3165. IN UCHAR c // logical channel
  3166. )
  3167. {
  3168. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3169. PHW_CHANNEL chan = &(deviceExtension->chan[c]);
  3170. PHW_LU_EXTENSION LunExt;
  3171. ULONG VendorID = deviceExtension->DevID & 0xffff;
  3172. ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
  3173. ULONG status;
  3174. ULONG pr_status = 0;
  3175. UCHAR dma_status = 0;
  3176. UCHAR reg8 = 0;
  3177. ULONG reg32 = 0;
  3178. UCHAR statusByte;
  3179. ULONG slotNumber = deviceExtension->slotNumber;
  3180. ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
  3181. ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
  3182. UCHAR Channel;
  3183. UCHAR lChannel;
  3184. BOOLEAN DmaTransfer = FALSE;
  3185. BOOLEAN OurInterrupt = FALSE;
  3186. // ULONG k;
  3187. UCHAR interruptReason;
  3188. BOOLEAN EarlyIntr = FALSE;
  3189. KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
  3190. lChannel = c;
  3191. Channel = (UCHAR)(deviceExtension->Channel + lChannel);
  3192. if((ChipFlags & UNIATA_AHCI) &&
  3193. UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  3194. OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1);
  3195. return OurInterrupt;
  3196. }
  3197. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
  3198. DmaTransfer = TRUE;
  3199. KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
  3200. deviceExtension->Channel + c, c));
  3201. } else {
  3202. KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
  3203. deviceExtension->Channel + c, c));
  3204. dma_status = GetDmaStatus(deviceExtension, lChannel);
  3205. KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
  3206. }
  3207. // do controller-specific interrupt servicing staff
  3208. if(deviceExtension->UnknownDev) {
  3209. KdPrint2((PRINT_PREFIX " UnknownDev\n"));
  3210. goto check_unknown;
  3211. }
  3212. // Attention !
  3213. // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
  3214. // Such behavior was observed with Intel ICH-xxx chips
  3215. // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
  3216. switch(VendorID) {
  3217. case ATA_PROMISE_ID: {
  3218. switch(ChipType) {
  3219. case PROLD:
  3220. case PRNEW:
  3221. status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
  3222. if (!DmaTransfer)
  3223. break;
  3224. if (!(status &
  3225. ((Channel) ? 0x00004000 : 0x00000400))) {
  3226. KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n"));
  3227. return INTERRUPT_REASON_IGNORE;
  3228. }
  3229. break;
  3230. case PRTX:
  3231. AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
  3232. status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
  3233. if (!DmaTransfer)
  3234. break;
  3235. if(!(status & 0x20)) {
  3236. KdPrint2((PRINT_PREFIX " Promise tx unexpected\n"));
  3237. return INTERRUPT_REASON_IGNORE;
  3238. }
  3239. break;
  3240. case PRMIO:
  3241. status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
  3242. if(ChipFlags & PRSATA) {
  3243. pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
  3244. AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
  3245. }
  3246. if(pr_status & (0x11 << Channel)) {
  3247. // TODO: reset channel
  3248. KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
  3249. return INTERRUPT_REASON_IGNORE;
  3250. }
  3251. if(!(status & (0x01 << Channel))) {
  3252. KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
  3253. return INTERRUPT_REASON_IGNORE;
  3254. }
  3255. AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
  3256. break;
  3257. }
  3258. break; }
  3259. case ATA_NVIDIA_ID: {
  3260. if(!(ChipFlags & UNIATA_SATA))
  3261. break;
  3262. KdPrint2((PRINT_PREFIX "NVIDIA\n"));
  3263. ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
  3264. ULONG shift = Channel << ((ChipFlags & NVQ) ? 4 : 2);
  3265. /* get and clear interrupt status */
  3266. if(ChipFlags & NVQ) {
  3267. pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
  3268. AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
  3269. } else {
  3270. pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
  3271. AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
  3272. }
  3273. KdPrint2((PRINT_PREFIX " pr_status %x\n", pr_status));
  3274. /* check for and handle connect events */
  3275. if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
  3276. UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
  3277. }
  3278. /* check for and handle disconnect events */
  3279. if((pr_status & (0x08UL << shift)) &&
  3280. !((pr_status & (0x04UL << shift) &&
  3281. UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
  3282. UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
  3283. }
  3284. /* do we have any device action ? */
  3285. if(!(pr_status & (0x01UL << shift))) {
  3286. KdPrint2((PRINT_PREFIX " nVidia unexpected\n"));
  3287. if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
  3288. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3289. } else {
  3290. return INTERRUPT_REASON_IGNORE;
  3291. }
  3292. }
  3293. break; }
  3294. case ATA_ATI_ID:
  3295. KdPrint2((PRINT_PREFIX "ATI\n"));
  3296. if(ChipType == SIIMIO) {
  3297. // fall to SiI
  3298. } else {
  3299. break;
  3300. }
  3301. case ATA_SILICON_IMAGE_ID:
  3302. if(ChipType == SIIMIO) {
  3303. reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
  3304. KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32));
  3305. if(reg32 == 0xffffffff) {
  3306. KdPrint2((PRINT_PREFIX " Sii mio unexpected\n"));
  3307. return INTERRUPT_REASON_IGNORE;
  3308. }
  3309. if(!(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_DMA_COMPLETE | BM_DS0_SII_IRQ | BM_DS0_SII_DMA_ENABLE | BM_DS0_SII_DMA_ERROR))) {
  3310. KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n"));
  3311. return INTERRUPT_REASON_IGNORE;
  3312. }
  3313. if(ChipFlags & UNIATA_SATA) {
  3314. if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
  3315. /* SIEN doesn't mask SATA IRQs on some 3112s. Those
  3316. * controllers continue to assert IRQ as long as
  3317. * SError bits are pending. Clear SError immediately.
  3318. */
  3319. if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
  3320. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3321. }
  3322. }
  3323. }
  3324. if (!DmaTransfer)
  3325. break;
  3326. if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
  3327. KdPrint2((PRINT_PREFIX " Sii mio unexpected (3)\n"));
  3328. return OurInterrupt;
  3329. }
  3330. AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
  3331. goto skip_dma_stat_check;
  3332. } else {
  3333. if(!(deviceExtension->HwFlags & SIIINTR))
  3334. break;
  3335. GetPciConfig1(0x71, reg8);
  3336. KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8));
  3337. if (!(reg8 &
  3338. (Channel ? 0x08 : 0x04))) {
  3339. return INTERRUPT_REASON_IGNORE;
  3340. }
  3341. if (!DmaTransfer) {
  3342. KdPrint2((PRINT_PREFIX " cmd our\n"));
  3343. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3344. }
  3345. SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
  3346. }
  3347. break;
  3348. case ATA_ACARD_ID:
  3349. if (!DmaTransfer)
  3350. break;
  3351. //dma_status = GetDmaStatus(deviceExtension, lChannel);
  3352. if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
  3353. KdPrint2((PRINT_PREFIX " Acard unexpected\n"));
  3354. return INTERRUPT_REASON_IGNORE;
  3355. }
  3356. AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
  3357. AtapiStallExecution(1);
  3358. AtapiWritePort1(chan, IDX_BM_Command,
  3359. AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
  3360. goto skip_dma_stat_check;
  3361. case ATA_INTEL_ID:
  3362. if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  3363. if(ChipFlags & UNIATA_AHCI) {
  3364. // Do nothing here
  3365. } else
  3366. if(ChipFlags & UNIATA_SATA) {
  3367. if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
  3368. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3369. }
  3370. if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
  3371. if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
  3372. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3373. }
  3374. }
  3375. }
  3376. }
  3377. break;
  3378. default:
  3379. if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
  3380. if(ChipFlags & UNIATA_AHCI) {
  3381. // Do nothing here
  3382. } else
  3383. if(ChipFlags & UNIATA_SATA) {
  3384. if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
  3385. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3386. }
  3387. }
  3388. }
  3389. }
  3390. check_unknown:
  3391. KdPrint2((PRINT_PREFIX " perform generic check\n"));
  3392. if (DmaTransfer) {
  3393. if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
  3394. KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
  3395. if(dma_status & BM_STATUS_ERR) {
  3396. KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n"));
  3397. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3398. } else {
  3399. KdPrint2((PRINT_PREFIX " getting status...\n"));
  3400. GetStatus(chan, statusByte);
  3401. KdPrint2((PRINT_PREFIX " status %#x\n", statusByte));
  3402. if(statusByte & IDE_STATUS_ERROR) {
  3403. KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte));
  3404. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3405. } else {
  3406. return INTERRUPT_REASON_IGNORE;
  3407. }
  3408. }
  3409. }
  3410. } else {
  3411. if(dma_status & BM_STATUS_INTR) {
  3412. // bullshit, we have DMA interrupt, but had never initiate DMA operation
  3413. KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n"));
  3414. AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
  3415. // catch it !
  3416. OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
  3417. }
  3418. }
  3419. skip_dma_stat_check:
  3420. if(!(ChipFlags & UNIATA_SATA)) {
  3421. AtapiStallExecution(1);
  3422. }
  3423. LunExt = chan->lun[chan->cur_cdev];
  3424. /* if drive is busy it didn't interrupt */
  3425. /* the exception is DCS + BSY state of ATAPI devices */
  3426. KdPrint2((PRINT_PREFIX " getting status...\n"));
  3427. GetStatus(chan, statusByte);
  3428. if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  3429. KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte));
  3430. } else {
  3431. KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte));
  3432. }
  3433. if (statusByte == 0xff) {
  3434. // interrupt from empty controller ?
  3435. } else
  3436. if (statusByte & IDE_STATUS_BUSY) {
  3437. if(!chan->ExpectingInterrupt) {
  3438. KdPrint3((PRINT_PREFIX " unexpected intr + BUSY\n"));
  3439. return OurInterrupt;
  3440. }
  3441. if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  3442. KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
  3443. } else {
  3444. KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n"));
  3445. return INTERRUPT_REASON_IGNORE;
  3446. }
  3447. if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
  3448. KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n"));
  3449. return INTERRUPT_REASON_IGNORE;
  3450. }
  3451. if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
  3452. KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n"));
  3453. return INTERRUPT_REASON_IGNORE;
  3454. }
  3455. EarlyIntr = TRUE;
  3456. if(dma_status & BM_STATUS_INTR) {
  3457. KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n"));
  3458. /* clear interrupt and get status */
  3459. GetBaseStatus(chan, statusByte);
  3460. KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte));
  3461. return INTERRUPT_REASON_OUR;
  3462. }
  3463. if(g_WaitBusyInISR) {
  3464. GetStatus(chan, statusByte);
  3465. KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
  3466. reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
  3467. KdPrint2((PRINT_PREFIX " Error reg (%#x)\n", reg8));
  3468. if (!(statusByte & IDE_STATUS_BUSY)) {
  3469. KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
  3470. }
  3471. if (statusByte & IDE_STATUS_BUSY) {
  3472. KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n"));
  3473. return INTERRUPT_REASON_IGNORE;
  3474. }
  3475. }
  3476. }
  3477. /* clear interrupt and get status */
  3478. GetBaseStatus(chan, statusByte);
  3479. KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte));
  3480. if (statusByte == 0xff) {
  3481. // interrupt from empty controller ?
  3482. } else
  3483. if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
  3484. KdPrint2((PRINT_PREFIX " no DRQ/DRDY set\n"));
  3485. return OurInterrupt;
  3486. }
  3487. #ifndef UNIATA_PIO_ONLY
  3488. if(DmaTransfer) {
  3489. if(!EarlyIntr || g_WaitBusyInISR) {
  3490. dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
  3491. } else {
  3492. PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
  3493. PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
  3494. //ASSERT(AtaReq);
  3495. KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
  3496. if(AtaReq) {
  3497. AtaReq->ReqState = REQ_STATE_EARLY_INTR;
  3498. }
  3499. }
  3500. }
  3501. #endif //
  3502. if (!(chan->ExpectingInterrupt)) {
  3503. KdPrint2((PRINT_PREFIX " Unexpected interrupt.\n"));
  3504. if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  3505. KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
  3506. } else {
  3507. KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt));
  3508. return OurInterrupt;
  3509. }
  3510. interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
  3511. KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
  3512. return OurInterrupt;
  3513. }
  3514. //ASSERT(!chan->queue_depth || chan->cur_req);
  3515. KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
  3516. return INTERRUPT_REASON_OUR;
  3517. } // end AtapiCheckInterrupt__()
  3518. BOOLEAN
  3519. NTAPI
  3520. AtapiInterrupt__(
  3521. IN PVOID HwDeviceExtension,
  3522. IN UCHAR c
  3523. )
  3524. {
  3525. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  3526. PHW_CHANNEL chan = &(deviceExtension->chan[c]);
  3527. // Get current Srb
  3528. PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
  3529. PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
  3530. ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
  3531. ULONG status = SRB_STATUS_SUCCESS;
  3532. UCHAR dma_status = 0;
  3533. ULONG i;
  3534. ULONG k;
  3535. UCHAR statusByte = 0,interruptReason;
  3536. BOOLEAN atapiDev = FALSE;
  3537. UCHAR Channel;
  3538. UCHAR lChannel;
  3539. UCHAR DeviceNumber;
  3540. BOOLEAN DmaTransfer = FALSE;
  3541. UCHAR error = 0;
  3542. ULONG TimerValue = 1000;
  3543. #ifdef UNIATA_USE_XXableInterrupts
  3544. BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
  3545. #else
  3546. BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
  3547. #endif // UNIATA_USE_XXableInterrupts
  3548. BOOLEAN UseDpc = deviceExtension->UseDpc;
  3549. // BOOLEAN RestoreUseDpc = FALSE;
  3550. BOOLEAN DataOverrun = FALSE;
  3551. BOOLEAN NoStartIo = TRUE;
  3552. KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
  3553. if(InDpc) {
  3554. KdPrint2((PRINT_PREFIX " InDpc = TRUE\n"));
  3555. //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
  3556. }
  3557. UCHAR PathId;
  3558. UCHAR TargetId;
  3559. UCHAR Lun;
  3560. UCHAR OldReqState = REQ_STATE_NONE;
  3561. //ULONG ldev;
  3562. PHW_LU_EXTENSION LunExt;
  3563. lChannel = c;
  3564. Channel = (UCHAR)(deviceExtension->Channel + lChannel);
  3565. KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
  3566. if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
  3567. (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ) {
  3568. DmaTransfer = TRUE;
  3569. KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n"));
  3570. }
  3571. if (srb) {
  3572. PathId = srb->PathId;
  3573. TargetId = srb->TargetId;
  3574. Lun = srb->Lun;
  3575. } else {
  3576. PathId = (UCHAR)c;
  3577. TargetId =
  3578. Lun = 0;
  3579. goto enqueue_next_req;
  3580. }
  3581. //ldev = GET_LDEV2(PathId, TargetId, Lun);
  3582. DeviceNumber = (UCHAR)(TargetId);
  3583. LunExt = chan->lun[DeviceNumber];
  3584. atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
  3585. KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
  3586. // check if we are in ISR DPC
  3587. if(InDpc) {
  3588. KdPrint2((PRINT_PREFIX " InDpc -> CTRFLAGS_INTR_DISABLED\n"));
  3589. goto ServiceInterrupt;
  3590. }
  3591. if (DmaTransfer) {
  3592. dma_status = GetDmaStatus(deviceExtension, lChannel);
  3593. }
  3594. if (!(chan->ExpectingInterrupt)) {
  3595. KdPrint2((PRINT_PREFIX " Unexpected interrupt for this channel.\n"));
  3596. return FALSE;
  3597. }
  3598. // change request state
  3599. if(AtaReq) {
  3600. OldReqState = AtaReq->ReqState;
  3601. AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
  3602. KdPrint2((PRINT_PREFIX " OldReqState = %x\n", OldReqState));
  3603. }
  3604. // We don't want using DPC for fast operations, like
  3605. // DMA completion, sending CDB, short ATAPI transfers, etc.
  3606. // !!!! BUT !!!!
  3607. // We MUST use DPC, because of interprocessor synchronization
  3608. // on multiprocessor platforms
  3609. if(DmaTransfer)
  3610. goto ServiceInterrupt;
  3611. switch(OldReqState) {
  3612. case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
  3613. KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n"));
  3614. case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
  3615. case REQ_STATE_DPC_WAIT_BUSY0:
  3616. case REQ_STATE_DPC_WAIT_BUSY1:
  3617. KdPrint2((PRINT_PREFIX " continue service interrupt\n"));
  3618. goto ServiceInterrupt;
  3619. case REQ_STATE_ATAPI_DO_NOTHING_INTR:
  3620. KdPrint2((PRINT_PREFIX " do nothing on interrupt\n"));
  3621. return TRUE;
  3622. }
  3623. if(!DmaTransfer && !atapiDev) {
  3624. KdPrint2((PRINT_PREFIX " service PIO HDD\n"));
  3625. UseDpc = FALSE;
  3626. }
  3627. #ifndef UNIATA_CORE
  3628. if(!UseDpc)
  3629. goto ServiceInterrupt;
  3630. #ifdef UNIATA_USE_XXableInterrupts
  3631. if(InDpc) {
  3632. KdPrint2((PRINT_PREFIX " Unexpected InDpc\n"));
  3633. ASSERT(FALSE);
  3634. // shall never get here
  3635. TimerValue = 1;
  3636. goto CallTimerDpc;
  3637. }
  3638. KdPrint2((PRINT_PREFIX " this is direct DPC call on DRQL\n"));
  3639. if(AtaReq) {
  3640. AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
  3641. KdPrint2((PRINT_PREFIX " ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
  3642. } else {
  3643. KdPrint2((PRINT_PREFIX " DPC without AtaReq!!!\n"));
  3644. }
  3645. #else
  3646. KdPrint2((PRINT_PREFIX "call service interrupt\n"));
  3647. goto ServiceInterrupt;
  3648. #endif // UNIATA_USE_XXableInterrupts
  3649. PostToDpc:
  3650. // Attention !!!
  3651. // AtapiInterruptDpc() is called on DISPATCH_LEVEL
  3652. // We always get here when are called from timer callback, which is invoked on DRQL.
  3653. // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
  3654. KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
  3655. // disable interrupts for this channel,
  3656. // but avoid recursion and double-disable
  3657. if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
  3658. AtapiDisableInterrupts(deviceExtension, lChannel);
  3659. }
  3660. // go to ISR DPC
  3661. chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
  3662. #ifdef UNIATA_USE_XXableInterrupts
  3663. // Will lower IRQL to DISPATCH_LEVEL
  3664. ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
  3665. /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
  3666. KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
  3667. #else
  3668. // Will raise IRQL to DIRQL
  3669. AtapiQueueTimerDpc(HwDeviceExtension, c,
  3670. AtapiInterruptDpc,
  3671. TimerValue);
  3672. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
  3673. #endif // UNIATA_USE_XXableInterrupts
  3674. return TRUE;
  3675. #ifndef UNIATA_CORE
  3676. CallTimerDpc:
  3677. AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
  3678. CallTimerDpc2:
  3679. // Will raise IRQL to DIRQL
  3680. AtapiQueueTimerDpc(HwDeviceExtension, c,
  3681. AtapiCallBack_X,
  3682. TimerValue);
  3683. return TRUE;
  3684. #endif //UNIATA_CORE
  3685. ServiceInterrupt:
  3686. if(AtaReq && InDpc) {
  3687. switch(AtaReq->ReqState) {
  3688. case REQ_STATE_DPC_WAIT_DRQ0:
  3689. goto PIO_wait_DRQ0;
  3690. case REQ_STATE_DPC_WAIT_BUSY:
  3691. goto PIO_wait_busy;
  3692. case REQ_STATE_DPC_WAIT_DRQ:
  3693. goto PIO_wait_DRQ;
  3694. case REQ_STATE_DPC_WAIT_DRQ_ERR:
  3695. goto continue_err;
  3696. case REQ_STATE_DPC_WAIT_BUSY0:
  3697. case REQ_STATE_DPC_WAIT_BUSY1:
  3698. // continue normal execution
  3699. break;
  3700. }
  3701. }
  3702. #else
  3703. ServiceInterrupt:
  3704. #endif //UNIATA_CORE
  3705. /*
  3706. // make additional delay for old devices (if we are not in DPC)
  3707. if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
  3708. &&
  3709. !InDpc &&
  3710. !atapiDev &&
  3711. !(deviceExtension->HwFlags & UNIATA_SATA)
  3712. ) {
  3713. KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
  3714. AtapiStallExecution(10);
  3715. }
  3716. */
  3717. /* clear interrupt and get status */
  3718. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  3719. UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
  3720. statusByte = (UCHAR)(AtaReq->ahci.in_status & 0xff);
  3721. } else {
  3722. GetBaseStatus(chan, statusByte);
  3723. }
  3724. if(atapiDev) {
  3725. KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
  3726. } else {
  3727. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
  3728. }
  3729. if(!UseDpc) {
  3730. KdPrint2((PRINT_PREFIX " operate like in DPC\n"));
  3731. InDpc = TRUE;
  3732. }
  3733. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  3734. KdPrint3((PRINT_PREFIX " AHCI branch\n"));
  3735. } else
  3736. if (!atapiDev) {
  3737. // IDE
  3738. if (statusByte & IDE_STATUS_BUSY) {
  3739. if (deviceExtension->DriverMustPoll) {
  3740. // Crashdump is polling and we got caught with busy asserted.
  3741. // Just go away, and we will be polled again shortly.
  3742. KdPrint2((PRINT_PREFIX " Hit BUSY while polling during crashdump.\n"));
  3743. goto ReturnEnableIntr;
  3744. }
  3745. try_dpc_wait:
  3746. // Ensure BUSY is non-asserted.
  3747. // make a very small idle before falling to DPC
  3748. k = (InDpc && UseDpc) ? 1000 : 2;
  3749. for (i = 0; i < k; i++) {
  3750. GetBaseStatus(chan, statusByte);
  3751. if (!(statusByte & IDE_STATUS_BUSY)) {
  3752. break;
  3753. }
  3754. AtapiStallExecution(10);
  3755. }
  3756. if (!InDpc && UseDpc && i == 2) {
  3757. KdPrint2((PRINT_PREFIX " BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
  3758. TimerValue = 50;
  3759. AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
  3760. #ifndef UNIATA_CORE
  3761. goto PostToDpc;
  3762. #else //UNIATA_CORE
  3763. AtapiStallExecution(TimerValue);
  3764. goto ServiceInterrupt;
  3765. #endif //UNIATA_CORE
  3766. } else
  3767. if (InDpc && i == k) {
  3768. // reset the controller.
  3769. KdPrint2((PRINT_PREFIX
  3770. " Resetting due to BUSY on entry - %#x.\n",
  3771. statusByte));
  3772. goto IntrPrepareResetController;
  3773. }
  3774. }
  3775. } else {
  3776. // ATAPI
  3777. if(!LunExt->IdentifyData.MajorRevision &&
  3778. InDpc &&
  3779. !atapiDev &&
  3780. !(deviceExtension->HwFlags & UNIATA_SATA)
  3781. ) {
  3782. KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
  3783. AtapiStallExecution(10);
  3784. }
  3785. if (statusByte & IDE_STATUS_BUSY) {
  3786. //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
  3787. KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting\n"));
  3788. for(k=20; k; k--) {
  3789. GetStatus(chan, statusByte);
  3790. KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
  3791. KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
  3792. AtapiReadPort1(chan, IDX_IO1_i_Error)));
  3793. if (!(statusByte & IDE_STATUS_BUSY)) {
  3794. KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
  3795. break;
  3796. }
  3797. if(k <= 18) {
  3798. KdPrint3((PRINT_PREFIX " too long wait -> DPC\n"));
  3799. if(!InDpc) {
  3800. KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n"));
  3801. TimerValue = 100;
  3802. AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
  3803. } else {
  3804. KdPrint2((PRINT_PREFIX " too long wait: DPC -> DPC\n"));
  3805. TimerValue = 1000;
  3806. AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
  3807. }
  3808. #ifndef UNIATA_CORE
  3809. goto CallTimerDpc2;
  3810. #else //UNIATA_CORE
  3811. AtapiStallExecution(TimerValue);
  3812. #endif //UNIATA_CORE
  3813. }
  3814. AtapiStallExecution(10);
  3815. }
  3816. if (statusByte & IDE_STATUS_BUSY) {
  3817. KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n"));
  3818. goto try_dpc_wait;
  3819. }
  3820. }
  3821. }
  3822. if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
  3823. switch(OldReqState) {
  3824. case REQ_STATE_EARLY_INTR:
  3825. case REQ_STATE_DPC_WAIT_BUSY0:
  3826. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
  3827. KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
  3828. dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
  3829. }
  3830. break;
  3831. }
  3832. }
  3833. //retry_check:
  3834. // Check for error conditions.
  3835. if ((statusByte & IDE_STATUS_ERROR) ||
  3836. (dma_status & BM_STATUS_ERR)) {
  3837. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  3838. error = (UCHAR)((AtaReq->ahci.in_status >> 8) && 0xff);
  3839. } else {
  3840. error = AtapiReadPort1(chan, IDX_IO1_i_Error);
  3841. }
  3842. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
  3843. /*
  3844. if(error & IDE_STATUS_CORRECTED_ERROR) {
  3845. KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
  3846. statusByte &= ~IDE_STATUS_ERROR;
  3847. goto retry_check;
  3848. }
  3849. */
  3850. if(AtaReq) {
  3851. KdPrint2((PRINT_PREFIX " Bad Lba %#I64x\n", AtaReq->lba));
  3852. } else {
  3853. KdPrint2((PRINT_PREFIX " Bad Lba unknown\n"));
  3854. }
  3855. if(!atapiDev) {
  3856. KdPrint2((PRINT_PREFIX " wait 100 ready after IDE error\n"));
  3857. AtapiStallExecution(100);
  3858. } else {
  3859. KdPrint2((PRINT_PREFIX " wait 10 ready after ATAPI error\n"));
  3860. AtapiStallExecution(10);
  3861. }
  3862. continue_err:
  3863. KdPrint3((PRINT_PREFIX " Intr on DRQ %x\n",
  3864. LunExt->DeviceFlags & DFLAGS_INT_DRQ));
  3865. for (k = atapiDev ? 0 : 200; k; k--) {
  3866. GetStatus(chan, statusByte);
  3867. if (!(statusByte & IDE_STATUS_DRQ)) {
  3868. AtapiStallExecution(50);
  3869. } else {
  3870. break;
  3871. }
  3872. }
  3873. if (!atapiDev) {
  3874. /* if this is a UDMA CRC error, reinject request */
  3875. AtaReq->retry++;
  3876. if(AtaReq->retry < MAX_RETRIES) {
  3877. #ifdef IO_STATISTICS
  3878. chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
  3879. #endif //IO_STATISTICS
  3880. if(DmaTransfer /*&&
  3881. (error & IDE_ERROR_ICRC)*/) {
  3882. if(AtaReq->retry < MAX_RETRIES) {
  3883. //fallback_pio:
  3884. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  3885. AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
  3886. // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
  3887. AtaReq->ReqState = REQ_STATE_QUEUED;
  3888. goto reenqueue_req;
  3889. }
  3890. } else {
  3891. if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
  3892. AtaReq->retry++;
  3893. }
  3894. KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
  3895. }
  3896. }
  3897. } else {
  3898. interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
  3899. KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
  3900. if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
  3901. ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
  3902. if(AtaReq->retry < MAX_RETRIES) {
  3903. //fallback_pio:
  3904. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  3905. AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
  3906. // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
  3907. AtaReq->ReqState = REQ_STATE_QUEUED;
  3908. goto reenqueue_req;
  3909. }
  3910. } else {
  3911. if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
  3912. AtaReq->retry++;
  3913. }
  3914. KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
  3915. }
  3916. }
  3917. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
  3918. if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
  3919. // Fail this request.
  3920. status = SRB_STATUS_ERROR;
  3921. goto CompleteRequest;
  3922. } else {
  3923. KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n"));
  3924. }
  3925. } else
  3926. if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
  3927. KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
  3928. deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
  3929. } else
  3930. if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
  3931. #ifdef IO_STATISTICS
  3932. KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
  3933. KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
  3934. AtaReq->retry,
  3935. chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
  3936. chan->lun[DeviceNumber]->BlockIoCount
  3937. ));
  3938. chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
  3939. if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
  3940. (deviceExtension->HwFlags & UNIATA_NO80CHK)
  3941. ) {
  3942. #else
  3943. if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
  3944. #endif //IO_STATISTICS
  3945. KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
  3946. deviceExtension->lun[DeviceNumber].LimitedTransferMode =
  3947. deviceExtension->lun[DeviceNumber].TransferMode;
  3948. }
  3949. }
  3950. #ifdef IO_STATISTICS
  3951. if(AtaReq->bcount) {
  3952. // we need stats for Read/Write operations
  3953. chan->lun[DeviceNumber]->BlockIoCount++;
  3954. }
  3955. chan->lun[DeviceNumber]->IoCount++;
  3956. #endif //IO_STATISTICS
  3957. continue_PIO:
  3958. // check reason for this interrupt.
  3959. if (atapiDev) {
  3960. KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
  3961. // ATAPI branch
  3962. interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
  3963. KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
  3964. if(DmaTransfer) {
  3965. wordsThisInterrupt = DEV_BSIZE/2*512;
  3966. } else {
  3967. wordsThisInterrupt = DEV_BSIZE/2;
  3968. }
  3969. } else {
  3970. // ATA branch
  3971. if(DmaTransfer) {
  3972. // simulate DRQ for DMA transfers
  3973. statusByte |= IDE_STATUS_DRQ;
  3974. }
  3975. if (statusByte & IDE_STATUS_DRQ) {
  3976. if(DmaTransfer) {
  3977. wordsThisInterrupt = DEV_BSIZE/2*512;
  3978. } else
  3979. if (LunExt->MaximumBlockXfer) {
  3980. wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
  3981. }
  3982. if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  3983. interruptReason = 0x2;
  3984. } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  3985. interruptReason = 0x0;
  3986. } else {
  3987. status = SRB_STATUS_ERROR;
  3988. goto CompleteRequest;
  3989. }
  3990. } else if (statusByte & IDE_STATUS_BUSY) {
  3991. //AtapiEnableInterrupts(deviceExtension, lChannel);
  3992. KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
  3993. return FALSE;
  3994. } else {
  3995. if (AtaReq->WordsLeft) {
  3996. // Funky behaviour seen with PCI IDE (not all, just one).
  3997. PIO_wait_DRQ0:
  3998. // The ISR hits with DRQ low, but comes up later.
  3999. for (k = 0; k < 5000; k++) {
  4000. GetStatus(chan, statusByte);
  4001. if (statusByte & IDE_STATUS_DRQ) {
  4002. break;
  4003. }
  4004. if(!InDpc) {
  4005. // goto DPC
  4006. AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
  4007. TimerValue = 100;
  4008. KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
  4009. #ifndef UNIATA_CORE
  4010. goto PostToDpc;
  4011. #else //UNIATA_CORE
  4012. AtapiStallExecution(TimerValue);
  4013. goto ServiceInterrupt;
  4014. #endif //UNIATA_CORE
  4015. }
  4016. AtapiStallExecution(100);
  4017. }
  4018. if (k == 5000) {
  4019. // reset the controller.
  4020. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
  4021. statusByte));
  4022. IntrPrepareResetController:
  4023. AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
  4024. goto ReturnEnableIntr;
  4025. } else {
  4026. interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;
  4027. }
  4028. } else {
  4029. // Command complete - verify, write, or the SMART enable/disable.
  4030. // Also get_media_status
  4031. interruptReason = 0x3;
  4032. }
  4033. }
  4034. }
  4035. KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
  4036. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  4037. KdPrint2((PRINT_PREFIX " AHCI path\n"));
  4038. goto ReturnEnableIntr;
  4039. } else
  4040. if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
  4041. // Write the packet.
  4042. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
  4043. // Send CDB to device.
  4044. WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
  4045. AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
  4046. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
  4047. KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
  4048. AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
  4049. }
  4050. goto ReturnEnableIntr;
  4051. } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
  4052. // Write the data.
  4053. if (atapiDev) {
  4054. // Pick up bytes to transfer and convert to words.
  4055. wordCount =
  4056. AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
  4057. wordCount |=
  4058. AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
  4059. // Covert bytes to words.
  4060. wordCount >>= 1;
  4061. KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
  4062. if (wordCount != AtaReq->WordsLeft) {
  4063. KdPrint2((PRINT_PREFIX
  4064. "AtapiInterrupt: %d words requested; %d words xferred\n",
  4065. AtaReq->WordsLeft,
  4066. wordCount));
  4067. }
  4068. // Verify this makes sense.
  4069. if (wordCount > AtaReq->WordsLeft) {
  4070. wordCount = AtaReq->WordsLeft;
  4071. KdPrint2((PRINT_PREFIX
  4072. "AtapiInterrupt: Write underrun\n"));
  4073. DataOverrun = TRUE;
  4074. }
  4075. } else {
  4076. // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
  4077. if (AtaReq->WordsLeft < wordsThisInterrupt) {
  4078. // Transfer only words requested.
  4079. wordCount = AtaReq->WordsLeft;
  4080. } else {
  4081. // Transfer next block.
  4082. wordCount = wordsThisInterrupt;
  4083. }
  4084. }
  4085. if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
  4086. //ASSERT(AtaReq->WordsLeft == wordCount);
  4087. AtaReq->WordsLeft = 0;
  4088. status = SRB_STATUS_SUCCESS;
  4089. chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
  4090. goto CompleteRequest;
  4091. }
  4092. // Ensure that this is a write command.
  4093. if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  4094. KdPrint2((PRINT_PREFIX
  4095. "AtapiInterrupt: Write interrupt\n"));
  4096. statusByte = WaitOnBusy(chan);
  4097. if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
  4098. WriteBuffer(chan,
  4099. AtaReq->DataBuffer,
  4100. wordCount,
  4101. UniataGetPioTiming(LunExt));
  4102. } else {
  4103. WriteBuffer2(chan,
  4104. (PULONG)(AtaReq->DataBuffer),
  4105. wordCount / 2,
  4106. UniataGetPioTiming(LunExt));
  4107. }
  4108. } else {
  4109. KdPrint3((PRINT_PREFIX
  4110. "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
  4111. interruptReason,
  4112. srb));
  4113. // Fail this request.
  4114. status = SRB_STATUS_ERROR;
  4115. goto CompleteRequest;
  4116. }
  4117. // Advance data buffer pointer and bytes left.
  4118. AtaReq->DataBuffer += wordCount;
  4119. AtaReq->WordsLeft -= wordCount;
  4120. if (atapiDev) {
  4121. AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
  4122. }
  4123. goto ReturnEnableIntr;
  4124. } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
  4125. if (atapiDev) {
  4126. // Pick up bytes to transfer and convert to words.
  4127. wordCount =
  4128. AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
  4129. (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
  4130. // Covert bytes to words.
  4131. wordCount /= 2;
  4132. KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
  4133. if (wordCount != AtaReq->WordsLeft) {
  4134. KdPrint2((PRINT_PREFIX
  4135. "AtapiInterrupt: %d words requested; %d words xferred\n",
  4136. AtaReq->WordsLeft,
  4137. wordCount));
  4138. }
  4139. // Verify this makes sense.
  4140. if (wordCount > AtaReq->WordsLeft) {
  4141. wordCount = AtaReq->WordsLeft;
  4142. DataOverrun = TRUE;
  4143. }
  4144. } else {
  4145. // Check if words left is at least 256.
  4146. if (AtaReq->WordsLeft < wordsThisInterrupt) {
  4147. // Transfer only words requested.
  4148. wordCount = AtaReq->WordsLeft;
  4149. } else {
  4150. // Transfer next block.
  4151. wordCount = wordsThisInterrupt;
  4152. }
  4153. }
  4154. if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
  4155. //ASSERT(AtaReq->WordsLeft == wordCount);
  4156. AtaReq->WordsLeft = 0;
  4157. status = SRB_STATUS_SUCCESS;
  4158. chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
  4159. goto CompleteRequest;
  4160. }
  4161. // Ensure that this is a read command.
  4162. if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  4163. /* KdPrint2((
  4164. "AtapiInterrupt: Read interrupt\n"));*/
  4165. statusByte = WaitOnBusy(chan);
  4166. if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
  4167. KdPrint2((PRINT_PREFIX
  4168. "IdeIntr: Read %#x words\n", wordCount));
  4169. ReadBuffer(chan,
  4170. AtaReq->DataBuffer,
  4171. wordCount,
  4172. UniataGetPioTiming(LunExt));
  4173. KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
  4174. //KdDump(AtaReq->DataBuffer, wordCount*2);
  4175. if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
  4176. KdDump(AtaReq->DataBuffer, wordCount*2);
  4177. }
  4178. GetStatus(chan, statusByte);
  4179. KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
  4180. if(DataOverrun) {
  4181. KdPrint2((PRINT_PREFIX " DataOverrun\n"));
  4182. AtapiSuckPort2(chan);
  4183. }
  4184. } else {
  4185. KdPrint2((PRINT_PREFIX
  4186. "IdeIntr: Read %#x Dwords\n", wordCount/2));
  4187. ReadBuffer2(chan,
  4188. (PULONG)(AtaReq->DataBuffer),
  4189. wordCount / 2,
  4190. UniataGetPioTiming(LunExt));
  4191. }
  4192. } else {
  4193. KdPrint3((PRINT_PREFIX
  4194. "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
  4195. interruptReason,
  4196. srb));
  4197. // Fail this request.
  4198. status = SRB_STATUS_ERROR;
  4199. goto CompleteRequest;
  4200. }
  4201. // Advance data buffer pointer and bytes left.
  4202. AtaReq->DataBuffer += wordCount;
  4203. AtaReq->WordsLeft -= wordCount;
  4204. // Check for read command complete.
  4205. if (AtaReq->WordsLeft == 0) {
  4206. KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
  4207. if (atapiDev) {
  4208. // Work around to make many atapi devices return correct sector size
  4209. // of 2048. Also certain devices will have sector count == 0x00, check
  4210. // for that also.
  4211. if ((srb->Cdb[0] == SCSIOP_READ_CAPACITY) &&
  4212. (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
  4213. AtaReq->DataBuffer -= wordCount;
  4214. if (AtaReq->DataBuffer[0] == 0x00) {
  4215. *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
  4216. }
  4217. *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
  4218. AtaReq->DataBuffer += wordCount;
  4219. }
  4220. } else {
  4221. /*
  4222. // Completion for IDE drives.
  4223. if (AtaReq->WordsLeft) {
  4224. status = SRB_STATUS_DATA_OVERRUN;
  4225. } else {
  4226. status = SRB_STATUS_SUCCESS;
  4227. }
  4228. goto CompleteRequest;
  4229. */
  4230. status = SRB_STATUS_SUCCESS;
  4231. goto CompleteRequest;
  4232. }
  4233. } else {
  4234. if (atapiDev) {
  4235. AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
  4236. }
  4237. }
  4238. goto ReturnEnableIntr;
  4239. } else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) {
  4240. KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
  4241. // Command complete.
  4242. if(DmaTransfer) {
  4243. KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
  4244. AtaReq->WordsLeft = 0;
  4245. }
  4246. if (AtaReq->WordsLeft) {
  4247. status = SRB_STATUS_DATA_OVERRUN;
  4248. } else {
  4249. status = SRB_STATUS_SUCCESS;
  4250. }
  4251. #ifdef UNIATA_DUMP_ATAPI
  4252. if(srb &&
  4253. srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  4254. UCHAR ScsiCommand;
  4255. PCDB Cdb;
  4256. PCHAR CdbData;
  4257. PCHAR ModeSelectData;
  4258. ULONG CdbDataLen;
  4259. PSCSI_REQUEST_BLOCK Srb = srb;
  4260. Cdb = (PCDB)(Srb->Cdb);
  4261. ScsiCommand = Cdb->CDB6.OperationCode;
  4262. CdbData = (PCHAR)(Srb->DataBuffer);
  4263. CdbDataLen = Srb->DataTransferLength;
  4264. if(CdbDataLen > 0x1000) {
  4265. CdbDataLen = 0x1000;
  4266. }
  4267. KdPrint(("--\n"));
  4268. KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
  4269. KdPrint2(("P:T:D=%d:%d:%d\n",
  4270. Srb->PathId,
  4271. Srb->TargetId,
  4272. Srb->Lun));
  4273. KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
  4274. KdDump(Cdb, 16);
  4275. if(ScsiCommand == SCSIOP_MODE_SENSE) {
  4276. KdPrint(("ModeSense 6\n"));
  4277. PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
  4278. ModeSelectData = CdbData+4;
  4279. KdDump(CdbData, CdbDataLen);
  4280. } else
  4281. if(ScsiCommand == SCSIOP_MODE_SENSE10) {
  4282. KdPrint(("ModeSense 10\n"));
  4283. PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
  4284. ModeSelectData = CdbData+8;
  4285. KdDump(CdbData, CdbDataLen);
  4286. } else {
  4287. if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  4288. KdPrint(("Read buffer from device:\n"));
  4289. KdDump(CdbData, CdbDataLen);
  4290. }
  4291. }
  4292. KdPrint(("--\n"));
  4293. }
  4294. #endif //UNIATA_DUMP_ATAPI
  4295. CompleteRequest:
  4296. KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest\n"));
  4297. // Check and see if we are processing our secret (mechanism status/request sense) srb
  4298. if (AtaReq->OriginalSrb) {
  4299. ULONG srbStatus;
  4300. KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
  4301. if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
  4302. KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
  4303. if (status == SRB_STATUS_SUCCESS) {
  4304. // Bingo!!
  4305. AtapiHwInitializeChanger (HwDeviceExtension,
  4306. srb,
  4307. (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
  4308. // Get ready to issue the original srb
  4309. srb = AtaReq->Srb = AtaReq->OriginalSrb;
  4310. AtaReq->OriginalSrb = NULL;
  4311. } else {
  4312. // failed! Get the sense key and maybe try again
  4313. srb = AtaReq->Srb = BuildRequestSenseSrb (
  4314. HwDeviceExtension,
  4315. AtaReq->OriginalSrb);
  4316. }
  4317. /*
  4318. // do not enable interrupts in DPC, do not waste time, do it now!
  4319. if(UseDpc && chan->DisableIntr) {
  4320. AtapiEnableInterrupts(HwDeviceExtension, c);
  4321. UseDpc = FALSE;
  4322. RestoreUseDpc = TRUE;
  4323. }
  4324. */
  4325. srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
  4326. KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
  4327. if (srbStatus == SRB_STATUS_PENDING) {
  4328. KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
  4329. goto ReturnEnableIntr;
  4330. }
  4331. /*
  4332. if(RestoreUseDpc) {
  4333. // restore state on error
  4334. UseDpc = TRUE;
  4335. AtapiDisableInterrupts(HwDeviceExtension, c);
  4336. }
  4337. */
  4338. } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
  4339. PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
  4340. KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
  4341. if (status == SRB_STATUS_DATA_OVERRUN) {
  4342. // Check to see if we at least get mininum number of bytes
  4343. if ((srb->DataTransferLength - AtaReq->WordsLeft) >
  4344. (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
  4345. status = SRB_STATUS_SUCCESS;
  4346. }
  4347. }
  4348. if (status == SRB_STATUS_SUCCESS) {
  4349. #ifndef UNIATA_CORE
  4350. if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
  4351. chan->MechStatusRetryCount) {
  4352. // The sense key doesn't say the last request is illegal, so try again
  4353. chan->MechStatusRetryCount--;
  4354. srb = AtaReq->Srb = BuildMechanismStatusSrb (
  4355. HwDeviceExtension,
  4356. AtaReq->OriginalSrb);
  4357. } else {
  4358. // last request was illegal. No point trying again
  4359. AtapiHwInitializeChanger (HwDeviceExtension,
  4360. srb,
  4361. (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
  4362. // Get ready to issue the original srb
  4363. srb = AtaReq->Srb = AtaReq->OriginalSrb;
  4364. AtaReq->OriginalSrb = NULL;
  4365. }
  4366. #endif //UNIATA_CORE
  4367. /*
  4368. // do not enable interrupts in DPC, do not waste time, do it now!
  4369. if(UseDpc && chan->DisableIntr) {
  4370. AtapiEnableInterrupts(HwDeviceExtension, c);
  4371. UseDpc = FALSE;
  4372. RestoreUseDpc = TRUE;
  4373. }
  4374. */
  4375. srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
  4376. KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
  4377. if (srbStatus == SRB_STATUS_PENDING) {
  4378. KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
  4379. goto ReturnEnableIntr;
  4380. }
  4381. /*
  4382. if(RestoreUseDpc) {
  4383. // restore state on error
  4384. UseDpc = TRUE;
  4385. AtapiDisableInterrupts(HwDeviceExtension, c);
  4386. }
  4387. */
  4388. }
  4389. }
  4390. // If we get here, it means AtapiSendCommand() has failed
  4391. // Can't recover. Pretend the original srb has failed and complete it.
  4392. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
  4393. if (AtaReq->OriginalSrb) {
  4394. KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
  4395. AtapiHwInitializeChanger (HwDeviceExtension,
  4396. srb,
  4397. (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
  4398. srb = AtaReq->Srb = AtaReq->OriginalSrb;
  4399. AtaReq->OriginalSrb = NULL;
  4400. }
  4401. KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
  4402. // fake an error and read no data
  4403. status = SRB_STATUS_ERROR;
  4404. srb->ScsiStatus = 0;
  4405. AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
  4406. AtaReq->WordsLeft = srb->DataTransferLength;
  4407. chan->RDP = FALSE;
  4408. } else if (status == SRB_STATUS_ERROR) {
  4409. // Map error to specific SRB status and handle request sense.
  4410. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
  4411. status = MapError(deviceExtension,
  4412. srb);
  4413. chan->RDP = FALSE;
  4414. } else if(!DmaTransfer) {
  4415. KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
  4416. // Command complete.
  4417. PIO_wait_busy:
  4418. KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
  4419. // Wait for busy to drop.
  4420. for (i = 0; i < 5*30; i++) {
  4421. GetStatus(chan, statusByte);
  4422. if (!(statusByte & IDE_STATUS_BUSY)) {
  4423. break;
  4424. }
  4425. if(!InDpc) {
  4426. // goto DPC
  4427. AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
  4428. TimerValue = 200;
  4429. KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
  4430. #ifndef UNIATA_CORE
  4431. goto PostToDpc;
  4432. #else //UNIATA_CORE
  4433. AtapiStallExecution(TimerValue);
  4434. goto ServiceInterrupt;
  4435. #endif //UNIATA_CORE
  4436. }
  4437. AtapiStallExecution(100);
  4438. }
  4439. if (i == 5*30) {
  4440. // reset the controller.
  4441. KdPrint2((PRINT_PREFIX
  4442. "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
  4443. statusByte));
  4444. goto IntrPrepareResetController;
  4445. }
  4446. // Check to see if DRQ is still up.
  4447. if(statusByte & IDE_STATUS_DRQ) {
  4448. KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
  4449. if(srb) {
  4450. if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  4451. KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
  4452. } else {
  4453. KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
  4454. }
  4455. } else {
  4456. KdPrint2((PRINT_PREFIX "srb NULL\n"));
  4457. }
  4458. if(AtaReq) {
  4459. KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
  4460. } else {
  4461. KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
  4462. }
  4463. if(AtaReq && AtaReq->WordsLeft /*&&
  4464. !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
  4465. KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
  4466. goto continue_PIO;
  4467. }
  4468. }
  4469. //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
  4470. //if ((statusByte & IDE_STATUS_DRQ)) {}
  4471. if((statusByte & IDE_STATUS_DRQ) &&
  4472. (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
  4473. PIO_wait_DRQ:
  4474. KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
  4475. for (i = 0; i < 200; i++) {
  4476. GetStatus(chan, statusByte);
  4477. if (!(statusByte & IDE_STATUS_DRQ)) {
  4478. break;
  4479. }
  4480. if(!InDpc) {
  4481. // goto DPC
  4482. KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
  4483. AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
  4484. TimerValue = 100;
  4485. #ifndef UNIATA_CORE
  4486. goto PostToDpc;
  4487. #else //UNIATA_CORE
  4488. AtapiStallExecution(TimerValue);
  4489. goto ServiceInterrupt;
  4490. #endif //UNIATA_CORE
  4491. }
  4492. AtapiStallExecution(100);
  4493. }
  4494. if (i == 200) {
  4495. // reset the controller.
  4496. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
  4497. statusByte));
  4498. goto IntrPrepareResetController;
  4499. }
  4500. }
  4501. if(atapiDev) {
  4502. KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
  4503. AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
  4504. //KdDump(srb->DataBuffer, srb->DataTransferLength);
  4505. }
  4506. if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
  4507. KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
  4508. }
  4509. }
  4510. // Clear interrupt expecting flag.
  4511. chan->ExpectingInterrupt = FALSE;
  4512. InterlockedExchange(&(chan->CheckIntr),
  4513. CHECK_INTR_IDLE);
  4514. // Sanity check that there is a current request.
  4515. if(srb != NULL) {
  4516. // Set status in SRB.
  4517. srb->SrbStatus = (UCHAR)status;
  4518. // Check for underflow.
  4519. if(AtaReq->WordsLeft) {
  4520. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
  4521. // Subtract out residual words and update if filemark hit,
  4522. // setmark hit , end of data, end of media...
  4523. if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
  4524. if (status == SRB_STATUS_DATA_OVERRUN) {
  4525. srb->DataTransferLength -= AtaReq->WordsLeft*2;
  4526. } else {
  4527. srb->DataTransferLength = 0;
  4528. }
  4529. } else {
  4530. srb->DataTransferLength -= AtaReq->WordsLeft*2;
  4531. }
  4532. }
  4533. if(status == SRB_STATUS_SUCCESS) {
  4534. AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
  4535. if(!atapiDev &&
  4536. AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
  4537. KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
  4538. AtaReq->WordsTransfered*2, AtaReq->TransferLength));
  4539. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  4540. AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
  4541. goto reenqueue_req;
  4542. } else {
  4543. KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n",
  4544. AtaReq->WordsTransfered*2, AtaReq->TransferLength));
  4545. }
  4546. }
  4547. if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
  4548. CompleteRDP:
  4549. // Indicate command complete.
  4550. if (!(chan->RDP)) {
  4551. KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
  4552. IntrCompleteReq:
  4553. if (status == SRB_STATUS_SUCCESS &&
  4554. srb->SenseInfoBuffer &&
  4555. srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
  4556. PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
  4557. KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
  4558. senseBuffer->ErrorCode = 0;
  4559. senseBuffer->Valid = 1;
  4560. senseBuffer->AdditionalSenseLength = 0xb;
  4561. senseBuffer->SenseKey = 0;
  4562. senseBuffer->AdditionalSenseCode = 0;
  4563. senseBuffer->AdditionalSenseCodeQualifier = 0;
  4564. srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  4565. }
  4566. AtapiDmaDBSync(chan, srb);
  4567. KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
  4568. UniataRemoveRequest(chan, srb);
  4569. KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
  4570. ScsiPortNotification(RequestComplete,
  4571. deviceExtension,
  4572. srb);
  4573. }
  4574. } else {
  4575. KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
  4576. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4577. if (status != SRB_STATUS_SUCCESS) {
  4578. error = AtapiReadPort1(chan, IDX_IO1_i_Error);
  4579. KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
  4580. }
  4581. // Build the SMART status block depending upon the completion status.
  4582. cmdOutParameters->cBufferSize = wordCount;
  4583. cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
  4584. cmdOutParameters->DriverStatus.bIDEError = error;
  4585. // If the sub-command is return smart status, jam the value from cylinder low and high, into the
  4586. // data buffer.
  4587. if (chan->SmartCommand == RETURN_SMART_STATUS) {
  4588. cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
  4589. cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
  4590. cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
  4591. cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
  4592. cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
  4593. cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
  4594. cmdOutParameters->bBuffer[6] = SMART_CMD;
  4595. cmdOutParameters->cBufferSize = 8;
  4596. }
  4597. // Indicate command complete.
  4598. goto IntrCompleteReq;
  4599. }
  4600. } else {
  4601. KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
  4602. }
  4603. if (chan->RDP) {
  4604. // Check DSC
  4605. for (i = 0; i < 5; i++) {
  4606. GetStatus(chan, statusByte);
  4607. if(!(statusByte & IDE_STATUS_BUSY)) {
  4608. KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
  4609. chan->RDP = FALSE;
  4610. goto CompleteRDP;
  4611. } else
  4612. if (statusByte & IDE_STATUS_DSC) {
  4613. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
  4614. chan->RDP = FALSE;
  4615. goto CompleteRDP;
  4616. }
  4617. AtapiStallExecution(50);
  4618. }
  4619. }
  4620. // RDP can be cleared since previous check
  4621. if (chan->RDP) {
  4622. KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
  4623. TimerValue = 2000;
  4624. #ifndef UNIATA_CORE
  4625. goto CallTimerDpc;
  4626. #else //UNIATA_CORE
  4627. AtapiStallExecution(TimerValue);
  4628. goto ServiceInterrupt;
  4629. #endif //UNIATA_CORE
  4630. }
  4631. // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  4632. enqueue_next_req:
  4633. // Get next request
  4634. srb = UniataGetCurRequest(chan);
  4635. reenqueue_req:
  4636. #ifndef UNIATA_CORE
  4637. KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
  4638. if(!srb) {
  4639. ScsiPortNotification(NextRequest,
  4640. deviceExtension,
  4641. NULL);
  4642. } else {
  4643. ScsiPortNotification(NextLuRequest,
  4644. deviceExtension,
  4645. PathId,
  4646. TargetId,
  4647. Lun);
  4648. // in simplex mode next command must NOT be sent here
  4649. if(!deviceExtension->simplexOnly) {
  4650. AtapiStartIo__(HwDeviceExtension, srb, FALSE);
  4651. }
  4652. }
  4653. // Try to get SRB fron any non-empty queue (later)
  4654. if(deviceExtension->simplexOnly) {
  4655. NoStartIo = FALSE;
  4656. }
  4657. #endif //UNIATA_CORE
  4658. goto ReturnEnableIntr;
  4659. } else {
  4660. // Unexpected int. Catch it
  4661. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
  4662. interruptReason,
  4663. statusByte));
  4664. }
  4665. ReturnEnableIntr:
  4666. KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
  4667. if(UseDpc) {
  4668. if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
  4669. KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
  4670. #ifdef UNIATA_USE_XXableInterrupts
  4671. //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  4672. chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
  4673. // must be called on DISPATCH_LEVEL
  4674. ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
  4675. AtapiEnableInterrupts__);
  4676. #else
  4677. AtapiEnableInterrupts(HwDeviceExtension, c);
  4678. InterlockedExchange(&(chan->CheckIntr),
  4679. CHECK_INTR_IDLE);
  4680. // Will raise IRQL to DIRQL
  4681. #ifndef UNIATA_CORE
  4682. AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
  4683. AtapiEnableInterrupts__,
  4684. 1);
  4685. #endif // UNIATA_CORE
  4686. KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
  4687. #endif // UNIATA_USE_XXableInterrupts
  4688. }
  4689. }
  4690. InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
  4691. // in simplex mode next command must be sent here if
  4692. // DPC is not used
  4693. KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
  4694. #ifndef UNIATA_CORE
  4695. if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
  4696. chan = UniataGetNextChannel(chan);
  4697. if(chan) {
  4698. srb = UniataGetCurRequest(chan);
  4699. } else {
  4700. srb = NULL;
  4701. }
  4702. KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
  4703. if(srb) {
  4704. AtapiStartIo__(HwDeviceExtension, srb, FALSE);
  4705. }
  4706. }
  4707. #endif //UNIATA_CORE
  4708. return TRUE;
  4709. } // end AtapiInterrupt__()
  4710. #ifndef UNIATA_CORE
  4711. /*++
  4712. Routine Description:
  4713. This routine handles SMART enable, disable, read attributes and threshold commands.
  4714. Arguments:
  4715. HwDeviceExtension - HBA miniport driver's adapter data storage
  4716. Srb - IO request packet
  4717. Return Value:
  4718. SRB status
  4719. --*/
  4720. ULONG
  4721. NTAPI
  4722. IdeSendSmartCommand(
  4723. IN PVOID HwDeviceExtension,
  4724. IN PSCSI_REQUEST_BLOCK Srb
  4725. )
  4726. {
  4727. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  4728. ULONG c = GET_CHANNEL(Srb);
  4729. PHW_CHANNEL chan = &(deviceExtension->chan[c]);
  4730. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  4731. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4732. SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4733. PIDEREGS regs = &cmdInParameters.irDriveRegs;
  4734. // ULONG i;
  4735. UCHAR statusByte,targetId;
  4736. if (regs->bCommandReg != SMART_CMD) {
  4737. KdPrint2((PRINT_PREFIX
  4738. "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
  4739. return SRB_STATUS_INVALID_REQUEST;
  4740. }
  4741. targetId = cmdInParameters.bDriveNumber;
  4742. //TODO optimize this check
  4743. if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
  4744. (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
  4745. return SRB_STATUS_SELECTION_TIMEOUT;
  4746. }
  4747. chan->SmartCommand = regs->bFeaturesReg;
  4748. // Determine which of the commands to carry out.
  4749. switch(regs->bFeaturesReg) {
  4750. case READ_ATTRIBUTES:
  4751. case READ_THRESHOLDS:
  4752. statusByte = WaitOnBusy(chan);
  4753. if (statusByte & IDE_STATUS_BUSY) {
  4754. KdPrint2((PRINT_PREFIX
  4755. "IdeSendSmartCommand: Returning BUSY status\n"));
  4756. return SRB_STATUS_BUSY;
  4757. }
  4758. // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
  4759. RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
  4760. // Set data buffer pointer and words left.
  4761. AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
  4762. AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
  4763. statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
  4764. regs->bCommandReg,
  4765. (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
  4766. 0,
  4767. regs->bSectorNumberReg,
  4768. regs->bSectorCountReg,
  4769. regs->bFeaturesReg,
  4770. ATA_IMMEDIATE);
  4771. if(!(statusByte & IDE_STATUS_ERROR)) {
  4772. // Wait for interrupt.
  4773. return SRB_STATUS_PENDING;
  4774. }
  4775. return SRB_STATUS_ERROR;
  4776. case ENABLE_SMART:
  4777. case DISABLE_SMART:
  4778. case RETURN_SMART_STATUS:
  4779. case ENABLE_DISABLE_AUTOSAVE:
  4780. case EXECUTE_OFFLINE_DIAGS:
  4781. case SAVE_ATTRIBUTE_VALUES:
  4782. statusByte = WaitOnBusy(chan);
  4783. if (statusByte & IDE_STATUS_BUSY) {
  4784. KdPrint2((PRINT_PREFIX
  4785. "IdeSendSmartCommand: Returning BUSY status\n"));
  4786. return SRB_STATUS_BUSY;
  4787. }
  4788. // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
  4789. RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
  4790. // Set data buffer pointer and indicate no data transfer.
  4791. AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
  4792. AtaReq->WordsLeft = 0;
  4793. statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
  4794. regs->bCommandReg,
  4795. (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
  4796. 0,
  4797. regs->bSectorNumberReg,
  4798. regs->bSectorCountReg,
  4799. regs->bFeaturesReg,
  4800. ATA_IMMEDIATE);
  4801. if(!(statusByte & IDE_STATUS_ERROR)) {
  4802. // Wait for interrupt.
  4803. return SRB_STATUS_PENDING;
  4804. }
  4805. return SRB_STATUS_ERROR;
  4806. } // end switch(regs->bFeaturesReg)
  4807. return SRB_STATUS_INVALID_REQUEST;
  4808. } // end IdeSendSmartCommand()
  4809. #endif //UNIATA_CORE
  4810. ULONGLONG
  4811. NTAPI
  4812. UniAtaCalculateLBARegs(
  4813. PHW_LU_EXTENSION LunExt,
  4814. ULONG startingSector,
  4815. PULONG max_bcount
  4816. )
  4817. {
  4818. UCHAR drvSelect,sectorNumber;
  4819. USHORT cylinder;
  4820. ULONG tmp;
  4821. if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
  4822. if(LunExt->LimitedTransferMode >= ATA_DMA) {
  4823. if(LunExt->DeviceExtension) {
  4824. (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
  4825. }
  4826. }
  4827. return startingSector;
  4828. }
  4829. tmp = LunExt->IdentifyData.SectorsPerTrack *
  4830. LunExt->IdentifyData.NumberOfHeads;
  4831. if(!tmp) {
  4832. KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
  4833. cylinder = 0;
  4834. drvSelect = 0;
  4835. sectorNumber = 1;
  4836. (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
  4837. } else {
  4838. cylinder = (USHORT)(startingSector / tmp);
  4839. drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
  4840. sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
  4841. (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
  4842. KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
  4843. cylinder, drvSelect, sectorNumber, (*max_bcount)));
  4844. }
  4845. (*max_bcount) = 0;
  4846. return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
  4847. } // end UniAtaCalculateLBARegs()
  4848. ULONGLONG
  4849. NTAPI
  4850. UniAtaCalculateLBARegsBack(
  4851. PHW_LU_EXTENSION LunExt,
  4852. ULONGLONG lba
  4853. )
  4854. {
  4855. ULONG drvSelect,sectorNumber;
  4856. ULONG cylinder;
  4857. ULONG tmp;
  4858. if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
  4859. return lba;
  4860. }
  4861. tmp = LunExt->IdentifyData.SectorsPerTrack *
  4862. LunExt->IdentifyData.NumberOfHeads;
  4863. cylinder = (USHORT)((lba >> 8) & 0xffff);
  4864. drvSelect = (UCHAR)((lba >> 24) & 0xf);
  4865. sectorNumber = (UCHAR)(lba & 0xff);
  4866. lba = sectorNumber-1 +
  4867. (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
  4868. (cylinder*tmp);
  4869. return lba;
  4870. } // end UniAtaCalculateLBARegsBack()
  4871. /*++
  4872. Routine Description:
  4873. This routine handles IDE read and writes.
  4874. Arguments:
  4875. HwDeviceExtension - HBA miniport driver's adapter data storage
  4876. Srb - IO request packet
  4877. Return Value:
  4878. SRB status
  4879. --*/
  4880. ULONG
  4881. NTAPI
  4882. IdeReadWrite(
  4883. IN PVOID HwDeviceExtension,
  4884. IN PSCSI_REQUEST_BLOCK Srb,
  4885. IN ULONG CmdAction
  4886. )
  4887. {
  4888. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  4889. UCHAR lChannel = GET_CHANNEL(Srb);
  4890. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  4891. PHW_LU_EXTENSION LunExt;
  4892. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  4893. //ULONG ldev = GET_LDEV(Srb);
  4894. UCHAR DeviceNumber = GET_CDEV(Srb);;
  4895. ULONG startingSector;
  4896. ULONG max_bcount;
  4897. ULONG wordCount = 0;
  4898. UCHAR statusByte,statusByte2;
  4899. UCHAR cmd;
  4900. ULONGLONG lba;
  4901. BOOLEAN use_dma = FALSE;
  4902. ULONG fis_size;
  4903. AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
  4904. LunExt = chan->lun[DeviceNumber];
  4905. if((CmdAction & CMD_ACTION_PREPARE) &&
  4906. (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
  4907. if(LunExt->opt_ReadOnly &&
  4908. (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
  4909. if(LunExt->opt_ReadOnly == 1) {
  4910. KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
  4911. return SRB_STATUS_ERROR;
  4912. } else {
  4913. KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
  4914. return SRB_STATUS_SUCCESS;
  4915. }
  4916. }
  4917. // Set data buffer pointer and words left.
  4918. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  4919. if(AtaReq->WordsTransfered) {
  4920. AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
  4921. startingSector = (ULONG)(UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
  4922. AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
  4923. KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
  4924. startingSector,
  4925. AtaReq->TransferLength/2,
  4926. AtaReq->WordsTransfered,
  4927. AtaReq->bcount));
  4928. } else {
  4929. AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
  4930. AtaReq->TransferLength = Srb->DataTransferLength;
  4931. // Set up 1st block.
  4932. MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
  4933. MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
  4934. KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
  4935. startingSector,
  4936. AtaReq->TransferLength/2,
  4937. AtaReq->bcount));
  4938. }
  4939. lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
  4940. if(max_bcount) {
  4941. AtaReq->bcount = min(AtaReq->bcount, max_bcount);
  4942. }
  4943. AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
  4944. AtaReq->bcount * DEV_BSIZE) / 2;
  4945. KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
  4946. startingSector,
  4947. AtaReq->WordsLeft,
  4948. AtaReq->bcount));
  4949. AtaReq->lba = lba;
  4950. // assume best case here
  4951. // we cannot reinit Dma until previous request is completed
  4952. if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
  4953. use_dma = TRUE;
  4954. // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
  4955. if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
  4956. (PUCHAR)(AtaReq->DataBuffer),
  4957. AtaReq->bcount * DEV_BSIZE)) {
  4958. use_dma = FALSE;
  4959. }
  4960. }
  4961. if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
  4962. UniataAhciSetupCmdPtr(AtaReq);
  4963. KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
  4964. RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
  4965. fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
  4966. &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
  4967. (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : /*IDE_COMMAND_WRITE_DMA*/ IDE_COMMAND_READ_DMA,
  4968. lba,
  4969. (USHORT)(AtaReq->bcount),
  4970. 0,
  4971. ATA_IMMEDIATE
  4972. );
  4973. if(!fis_size) {
  4974. KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
  4975. return SRB_STATUS_ERROR;
  4976. }
  4977. AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
  4978. /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
  4979. (fis_size / sizeof(ULONG)) |
  4980. (DeviceNumber << 12));
  4981. KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
  4982. }
  4983. AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
  4984. } else { // exec_only
  4985. KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
  4986. lba = AtaReq->lba;
  4987. if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
  4988. use_dma = TRUE;
  4989. }
  4990. }
  4991. if(!(CmdAction & CMD_ACTION_EXEC)) {
  4992. return SRB_STATUS_PENDING;
  4993. }
  4994. // if this is queued request, reinit DMA and check
  4995. // if DMA mode is still available
  4996. AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
  4997. if (/*EnableDma &&*/
  4998. (LunExt->TransferMode >= ATA_DMA)) {
  4999. use_dma = TRUE;
  5000. } else {
  5001. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5002. use_dma = FALSE;
  5003. }
  5004. // Check if write request.
  5005. if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  5006. // Prepare read command.
  5007. if(use_dma) {
  5008. cmd = IDE_COMMAND_READ_DMA;
  5009. } else
  5010. if(LunExt->MaximumBlockXfer) {
  5011. cmd = IDE_COMMAND_READ_MULTIPLE;
  5012. } else {
  5013. cmd = IDE_COMMAND_READ;
  5014. }
  5015. } else {
  5016. // Prepare write command.
  5017. if (use_dma) {
  5018. wordCount = AtaReq->bcount*DEV_BSIZE/2;
  5019. cmd = IDE_COMMAND_WRITE_DMA;
  5020. } else
  5021. if (LunExt->MaximumBlockXfer) {
  5022. wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
  5023. if (AtaReq->WordsLeft < wordCount) {
  5024. // Transfer only words requested.
  5025. wordCount = AtaReq->WordsLeft;
  5026. }
  5027. cmd = IDE_COMMAND_WRITE_MULTIPLE;
  5028. } else {
  5029. wordCount = DEV_BSIZE/2;
  5030. cmd = IDE_COMMAND_WRITE;
  5031. }
  5032. }
  5033. // Send IO command.
  5034. KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
  5035. ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
  5036. if(use_dma) {
  5037. chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
  5038. } else {
  5039. chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
  5040. }
  5041. if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
  5042. //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
  5043. UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
  5044. return SRB_STATUS_PENDING;
  5045. }
  5046. if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
  5047. use_dma) {
  5048. statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  5049. cmd, lba,
  5050. (USHORT)(AtaReq->bcount),
  5051. // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
  5052. 0, ATA_IMMEDIATE);
  5053. if(statusByte2 != 0xff) {
  5054. GetStatus(chan, statusByte2);
  5055. }
  5056. if(statusByte2 & IDE_STATUS_ERROR) {
  5057. statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  5058. KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
  5059. return SRB_STATUS_ERROR;
  5060. }
  5061. if(use_dma) {
  5062. AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
  5063. }
  5064. return SRB_STATUS_PENDING;
  5065. }
  5066. statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
  5067. cmd, lba,
  5068. (USHORT)(AtaReq->bcount),
  5069. // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
  5070. 0, ATA_WAIT_INTR);
  5071. if (!(statusByte & IDE_STATUS_DRQ) ||
  5072. statusByte == 0xff) {
  5073. if(statusByte == 0xff) {
  5074. KdPrint2((PRINT_PREFIX
  5075. "IdeReadWrite: error sending command (%#x)\n",
  5076. statusByte));
  5077. } else {
  5078. KdPrint2((PRINT_PREFIX
  5079. "IdeReadWrite: DRQ never asserted (%#x)\n",
  5080. statusByte));
  5081. }
  5082. AtaReq->WordsLeft = 0;
  5083. // Clear interrupt expecting flag.
  5084. chan->ExpectingInterrupt = FALSE;
  5085. InterlockedExchange(&(chan->CheckIntr),
  5086. CHECK_INTR_IDLE);
  5087. // Clear current SRB.
  5088. UniataRemoveRequest(chan, Srb);
  5089. return (statusByte == 0xff) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
  5090. }
  5091. chan->ExpectingInterrupt = TRUE;
  5092. InterlockedExchange(&(chan->CheckIntr),
  5093. CHECK_INTR_IDLE);
  5094. // Write next DEV_BSIZE/2*N words.
  5095. if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
  5096. KdPrint2((PRINT_PREFIX
  5097. "IdeReadWrite: Write %#x words\n", wordCount));
  5098. WriteBuffer(chan,
  5099. AtaReq->DataBuffer,
  5100. wordCount,
  5101. UniataGetPioTiming(LunExt));
  5102. } else {
  5103. KdPrint2((PRINT_PREFIX
  5104. "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
  5105. WriteBuffer2(chan,
  5106. (PULONG)(AtaReq->DataBuffer),
  5107. wordCount / 2,
  5108. UniataGetPioTiming(LunExt));
  5109. }
  5110. // Adjust buffer address and words left count.
  5111. AtaReq->WordsLeft -= wordCount;
  5112. AtaReq->DataBuffer += wordCount;
  5113. // Wait for interrupt.
  5114. return SRB_STATUS_PENDING;
  5115. } // end IdeReadWrite()
  5116. #ifndef UNIATA_CORE
  5117. /*++
  5118. Routine Description:
  5119. This routine handles IDE Verify.
  5120. Arguments:
  5121. HwDeviceExtension - HBA miniport driver's adapter data storage
  5122. Srb - IO request packet
  5123. `
  5124. Return Value:
  5125. SRB status
  5126. --*/
  5127. ULONG
  5128. NTAPI
  5129. IdeVerify(
  5130. IN PVOID HwDeviceExtension,
  5131. IN PSCSI_REQUEST_BLOCK Srb
  5132. )
  5133. {
  5134. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  5135. UCHAR lChannel = GET_CHANNEL(Srb);
  5136. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  5137. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  5138. PHW_LU_EXTENSION LunExt;
  5139. //ULONG ldev = GET_LDEV(Srb);
  5140. ULONG DeviceNumber = GET_CDEV(Srb);
  5141. UCHAR statusByte;
  5142. ULONG startingSector;
  5143. ULONG max_bcount;
  5144. ULONG sectors;
  5145. ULONG endSector;
  5146. USHORT sectorCount;
  5147. ULONGLONG lba;
  5148. LunExt = chan->lun[DeviceNumber];
  5149. // Drive has these number sectors.
  5150. if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
  5151. sectors = LunExt->IdentifyData.SectorsPerTrack *
  5152. LunExt->IdentifyData.NumberOfHeads *
  5153. LunExt->IdentifyData.NumberOfCylinders;
  5154. }
  5155. KdPrint2((PRINT_PREFIX
  5156. "IdeVerify: Total sectors %#x\n",
  5157. sectors));
  5158. // Get starting sector number from CDB.
  5159. MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
  5160. MOV_DW_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
  5161. KdPrint2((PRINT_PREFIX
  5162. "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
  5163. startingSector,
  5164. sectorCount));
  5165. endSector = startingSector + sectorCount;
  5166. KdPrint2((PRINT_PREFIX
  5167. "IdeVerify: Ending sector %#x\n",
  5168. endSector));
  5169. if (endSector > sectors) {
  5170. // Too big, round down.
  5171. KdPrint2((PRINT_PREFIX
  5172. "IdeVerify: Truncating request to %#x blocks\n",
  5173. sectors - startingSector - 1));
  5174. sectorCount = (USHORT)(sectors - startingSector - 1);
  5175. } else {
  5176. // Set up sector count register. Round up to next block.
  5177. if (sectorCount > 0xFF) {
  5178. sectorCount = (USHORT)0xFF;
  5179. }
  5180. }
  5181. // Set data buffer pointer and words left.
  5182. AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
  5183. AtaReq->WordsLeft = Srb->DataTransferLength / 2;
  5184. // Indicate expecting an interrupt.
  5185. InterlockedExchange(&(chan->CheckIntr),
  5186. CHECK_INTR_IDLE);
  5187. lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
  5188. statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
  5189. IDE_COMMAND_VERIFY, lba,
  5190. sectorCount,
  5191. 0, ATA_IMMEDIATE);
  5192. if(!(statusByte & IDE_STATUS_ERROR)) {
  5193. // Wait for interrupt.
  5194. return SRB_STATUS_PENDING;
  5195. }
  5196. return SRB_STATUS_ERROR;
  5197. } // end IdeVerify()
  5198. #endif //UNIATA_CORE
  5199. /*++
  5200. Routine Description:
  5201. Send ATAPI packet command to device.
  5202. Arguments:
  5203. HwDeviceExtension - HBA miniport driver's adapter data storage
  5204. Srb - IO request packet
  5205. Return Value:
  5206. --*/
  5207. ULONG
  5208. NTAPI
  5209. AtapiSendCommand(
  5210. IN PVOID HwDeviceExtension,
  5211. IN PSCSI_REQUEST_BLOCK Srb,
  5212. IN ULONG CmdAction
  5213. )
  5214. {
  5215. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  5216. UCHAR lChannel = GET_CHANNEL(Srb);
  5217. PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
  5218. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  5219. PHW_LU_EXTENSION LunExt;
  5220. //ULONG ldev = GET_LDEV(Srb);
  5221. ULONG DeviceNumber = GET_CDEV(Srb);
  5222. ULONG i;
  5223. ULONG flags;
  5224. UCHAR statusByte,byteCountLow,byteCountHigh;
  5225. BOOLEAN use_dma = FALSE;
  5226. BOOLEAN dma_reinited = FALSE;
  5227. BOOLEAN retried = FALSE;
  5228. ULONG fis_size;
  5229. LunExt = chan->lun[DeviceNumber];
  5230. KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
  5231. if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
  5232. AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
  5233. #ifdef UNIATA_DUMP_ATAPI
  5234. if(CmdAction & CMD_ACTION_PREPARE) {
  5235. UCHAR ScsiCommand;
  5236. PCDB Cdb;
  5237. PCHAR CdbData;
  5238. PCHAR ModeSelectData;
  5239. ULONG CdbDataLen;
  5240. Cdb = (PCDB)(Srb->Cdb);
  5241. ScsiCommand = Cdb->CDB6.OperationCode;
  5242. CdbData = (PCHAR)(Srb->DataBuffer);
  5243. CdbDataLen = Srb->DataTransferLength;
  5244. if(CdbDataLen > 0x1000) {
  5245. CdbDataLen = 0x1000;
  5246. }
  5247. KdPrint(("--\n"));
  5248. KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
  5249. KdPrint2(("P:T:D=%d:%d:%d\n",
  5250. Srb->PathId,
  5251. Srb->TargetId,
  5252. Srb->Lun));
  5253. KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
  5254. KdDump(Cdb, 16);
  5255. if(ScsiCommand == SCSIOP_WRITE_CD) {
  5256. KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
  5257. Cdb->WRITE_CD.LBA[0],
  5258. Cdb->WRITE_CD.LBA[1],
  5259. Cdb->WRITE_CD.LBA[2],
  5260. Cdb->WRITE_CD.LBA[3]
  5261. ));
  5262. } else
  5263. if(ScsiCommand == SCSIOP_WRITE12) {
  5264. KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
  5265. Cdb->CDB12READWRITE.LBA[0],
  5266. Cdb->CDB12READWRITE.LBA[1],
  5267. Cdb->CDB12READWRITE.LBA[2],
  5268. Cdb->CDB12READWRITE.LBA[3]
  5269. ));
  5270. } else
  5271. if(ScsiCommand == SCSIOP_MODE_SELECT) {
  5272. KdPrint(("ModeSelect 6\n"));
  5273. PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
  5274. ModeSelectData = CdbData+4;
  5275. KdDump(CdbData, CdbDataLen);
  5276. } else
  5277. if(ScsiCommand == SCSIOP_MODE_SELECT10) {
  5278. KdPrint(("ModeSelect 10\n"));
  5279. PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
  5280. ModeSelectData = CdbData+8;
  5281. KdDump(CdbData, CdbDataLen);
  5282. } else {
  5283. if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  5284. KdPrint(("Send buffer to device:\n"));
  5285. KdDump(CdbData, CdbDataLen);
  5286. }
  5287. }
  5288. KdPrint(("--\n"));
  5289. }
  5290. #endif //UNIATA_DUMP_ATAPI
  5291. if(CmdAction == CMD_ACTION_PREPARE) {
  5292. KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE\n"));
  5293. switch (Srb->Cdb[0]) {
  5294. case SCSIOP_READ:
  5295. case SCSIOP_WRITE:
  5296. case SCSIOP_READ12:
  5297. case SCSIOP_WRITE12:
  5298. // all right
  5299. break;
  5300. default:
  5301. KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
  5302. return SRB_STATUS_BUSY;
  5303. }
  5304. //
  5305. if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
  5306. !AtaReq->OriginalSrb) {
  5307. KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
  5308. return SRB_STATUS_BUSY;
  5309. }
  5310. }
  5311. if((CmdAction & CMD_ACTION_PREPARE) &&
  5312. (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
  5313. KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb->Cdb[0]));
  5314. // Set data buffer pointer and words left.
  5315. AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
  5316. AtaReq->WordsLeft = Srb->DataTransferLength / 2;
  5317. AtaReq->TransferLength = Srb->DataTransferLength;
  5318. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5319. // check if reorderable
  5320. switch(Srb->Cdb[0]) {
  5321. case SCSIOP_READ12:
  5322. case SCSIOP_WRITE12:
  5323. MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
  5324. goto GetLba;
  5325. case SCSIOP_READ:
  5326. case SCSIOP_WRITE:
  5327. MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
  5328. GetLba:
  5329. MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA);
  5330. AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
  5331. AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
  5332. AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_WRITE12) ?
  5333. REQ_FLAG_WRITE : REQ_FLAG_READ;
  5334. break;
  5335. }
  5336. // check if DMA read/write
  5337. if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
  5338. KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
  5339. } else
  5340. if(AtaReq->TransferLength) {
  5341. // try use DMA
  5342. switch(Srb->Cdb[0]) {
  5343. case SCSIOP_WRITE:
  5344. case SCSIOP_WRITE12:
  5345. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
  5346. break;
  5347. /* FALLTHROUGH */
  5348. case SCSIOP_READ:
  5349. case SCSIOP_READ12:
  5350. if(deviceExtension->opt_AtapiDmaReadWrite) {
  5351. call_dma_setup:
  5352. if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
  5353. (PUCHAR)(AtaReq->DataBuffer),
  5354. Srb->DataTransferLength
  5355. /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
  5356. )) {
  5357. KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
  5358. use_dma = TRUE;
  5359. }
  5360. }
  5361. break;
  5362. case SCSIOP_READ_CD:
  5363. if(deviceExtension->opt_AtapiDmaRawRead)
  5364. goto call_dma_setup;
  5365. break;
  5366. default:
  5367. if(deviceExtension->opt_AtapiDmaControlCmd) {
  5368. if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  5369. // read operation
  5370. use_dma = TRUE;
  5371. } else {
  5372. // write operation
  5373. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
  5374. KdPrint2((PRINT_PREFIX "dma RO\n"));
  5375. use_dma = FALSE;
  5376. } else {
  5377. use_dma = TRUE;
  5378. }
  5379. }
  5380. }
  5381. break;
  5382. }
  5383. // try setup DMA
  5384. if(use_dma) {
  5385. if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
  5386. (PUCHAR)(AtaReq->DataBuffer),
  5387. Srb->DataTransferLength)) {
  5388. KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
  5389. use_dma = FALSE;
  5390. } else {
  5391. KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
  5392. }
  5393. }
  5394. } else {
  5395. KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
  5396. }
  5397. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  5398. UniataAhciSetupCmdPtr(AtaReq);
  5399. KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
  5400. RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
  5401. RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16);
  5402. fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
  5403. &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
  5404. IDE_COMMAND_ATAPI_PACKET /* command */,
  5405. 0 /* lba */,
  5406. (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
  5407. use_dma ? ATA_F_DMA : 0/* feature */,
  5408. ATA_IMMEDIATE /* flags */
  5409. );
  5410. if(!fis_size) {
  5411. KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
  5412. return SRB_STATUS_ERROR;
  5413. }
  5414. AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
  5415. /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
  5416. (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) |
  5417. (fis_size / sizeof(ULONG)) |
  5418. (DeviceNumber << 12));
  5419. KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
  5420. }
  5421. } else {
  5422. if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
  5423. // if this is queued request, reinit DMA and check
  5424. // if DMA mode is still available
  5425. KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n"));
  5426. AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
  5427. if (/*EnableDma &&*/
  5428. (LunExt->TransferMode >= ATA_DMA)) {
  5429. KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
  5430. use_dma = TRUE;
  5431. } else {
  5432. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5433. KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
  5434. use_dma = FALSE;
  5435. }
  5436. dma_reinited = TRUE;
  5437. }
  5438. }
  5439. if(!(CmdAction & CMD_ACTION_EXEC)) {
  5440. KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
  5441. return SRB_STATUS_PENDING;
  5442. }
  5443. KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
  5444. if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
  5445. KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
  5446. }
  5447. if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
  5448. KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
  5449. use_dma = FALSE;
  5450. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5451. //AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
  5452. } if(AtaReq->TransferLength) {
  5453. if(!dma_reinited) {
  5454. KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
  5455. AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
  5456. if (/*EnableDma &&*/
  5457. (LunExt->TransferMode >= ATA_DMA)) {
  5458. use_dma = TRUE;
  5459. } else {
  5460. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5461. use_dma = FALSE;
  5462. }
  5463. }
  5464. } else {
  5465. KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
  5466. use_dma = FALSE;
  5467. AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
  5468. if(!deviceExtension->opt_AtapiDmaZeroTransfer) {
  5469. KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
  5470. AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
  5471. }
  5472. }
  5473. KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
  5474. if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
  5475. KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
  5476. }
  5477. KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
  5478. #ifndef UNIATA_CORE
  5479. // We need to know how many platters our atapi cd-rom device might have.
  5480. // Before anyone tries to send a srb to our target for the first time,
  5481. // we must "secretly" send down a separate mechanism status srb in order to
  5482. // initialize our device extension changer data. That's how we know how
  5483. // many platters our target has.
  5484. if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
  5485. !AtaReq->OriginalSrb) {
  5486. ULONG srbStatus;
  5487. KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
  5488. // Set this flag now. If the device hangs on the mech. status
  5489. // command, we will not have the chance to set it.
  5490. LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
  5491. chan->MechStatusRetryCount = 3;
  5492. AtaReq->OriginalSrb = Srb;
  5493. AtaReq->Srb = BuildMechanismStatusSrb (
  5494. HwDeviceExtension,
  5495. Srb);
  5496. KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
  5497. srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
  5498. if (srbStatus == SRB_STATUS_PENDING) {
  5499. KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
  5500. return srbStatus;
  5501. } else {
  5502. AtaReq->Srb = AtaReq->OriginalSrb;
  5503. AtaReq->OriginalSrb = NULL;
  5504. KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
  5505. AtapiHwInitializeChanger (HwDeviceExtension, Srb,
  5506. (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
  5507. // fall out
  5508. }
  5509. }
  5510. #endif //UNIATA_CORE
  5511. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
  5512. Srb->Cdb[0], Srb->TargetId, Srb->Lun));
  5513. // Make sure command is to ATAPI device.
  5514. flags = LunExt->DeviceFlags;
  5515. if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
  5516. if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
  5517. // Indicate no device found at this address.
  5518. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5519. return SRB_STATUS_SELECTION_TIMEOUT;
  5520. }
  5521. } else if(Srb->Lun > 0) {
  5522. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5523. return SRB_STATUS_SELECTION_TIMEOUT;
  5524. }
  5525. if(!(flags & DFLAGS_ATAPI_DEVICE)) {
  5526. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5527. return SRB_STATUS_SELECTION_TIMEOUT;
  5528. }
  5529. retry:
  5530. if(deviceExtension->HwFlags & UNIATA_AHCI) {
  5531. KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
  5532. if(use_dma) {
  5533. chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
  5534. } else {
  5535. chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
  5536. }
  5537. UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
  5538. return SRB_STATUS_PENDING;
  5539. }
  5540. // Select device 0 or 1.
  5541. SelectDrive(chan, DeviceNumber);
  5542. // Verify that controller is ready for next command.
  5543. GetStatus(chan, statusByte);
  5544. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
  5545. if(statusByte == 0xff) {
  5546. KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
  5547. goto make_reset;
  5548. }
  5549. if(statusByte & IDE_STATUS_BUSY) {
  5550. if(statusByte & IDE_STATUS_DSC) {
  5551. KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
  5552. } else {
  5553. KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
  5554. // We have to make reset here, since we are expecting device to be available
  5555. //return SRB_STATUS_BUSY; // this cause queue freeze
  5556. goto make_reset;
  5557. }
  5558. }
  5559. if(statusByte & IDE_STATUS_ERROR) {
  5560. if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
  5561. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
  5562. // Read the error reg. to clear it and fail this request.
  5563. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5564. return MapError(deviceExtension, Srb);
  5565. } else {
  5566. KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte));
  5567. }
  5568. }
  5569. // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
  5570. // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
  5571. if((!(statusByte & IDE_STATUS_DSC)) &&
  5572. (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
  5573. AtapiStallExecution(200);
  5574. KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
  5575. AtaReq->ReqState = REQ_STATE_QUEUED;
  5576. return SRB_STATUS_PENDING;
  5577. }
  5578. if(IS_RDP(Srb->Cdb[0])) {
  5579. chan->RDP = TRUE;
  5580. KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
  5581. } else {
  5582. chan->RDP = FALSE;
  5583. }
  5584. if(statusByte & IDE_STATUS_DRQ) {
  5585. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
  5586. statusByte));
  5587. // Try to drain the data that one preliminary device thinks that it has
  5588. // to transfer. Hopefully this random assertion of DRQ will not be present
  5589. // in production devices.
  5590. for (i = 0; i < 0x10000; i++) {
  5591. GetStatus(chan, statusByte);
  5592. if(statusByte & IDE_STATUS_DRQ) {
  5593. AtapiReadPort2(chan, IDX_IO1_i_Data);
  5594. } else {
  5595. break;
  5596. }
  5597. }
  5598. if (i == 0x10000) {
  5599. make_reset:
  5600. KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
  5601. AtapiDisableInterrupts(deviceExtension, lChannel);
  5602. AtapiSoftReset(chan, DeviceNumber);
  5603. KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
  5604. // Re-initialize Atapi device.
  5605. CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
  5606. /*
  5607. IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
  5608. IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
  5609. */
  5610. // Inform the port driver that the bus has been reset.
  5611. ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
  5612. // Clean up device extension fields that AtapiStartIo won't.
  5613. chan->ExpectingInterrupt = FALSE;
  5614. chan->RDP = FALSE;
  5615. InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
  5616. CHECK_INTR_IDLE);
  5617. AtapiEnableInterrupts(deviceExtension, lChannel);
  5618. /*
  5619. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5620. return SRB_STATUS_BUS_RESET;
  5621. */
  5622. if(!retried) {
  5623. KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
  5624. retried = TRUE;
  5625. goto retry;
  5626. }
  5627. KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
  5628. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5629. return SRB_STATUS_SELECTION_TIMEOUT;
  5630. }
  5631. }
  5632. if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
  5633. // As the cdrom driver sets the LUN field in the cdb, it must be removed.
  5634. Srb->Cdb[1] &= ~0xE0;
  5635. if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
  5636. // Torisan changer. TUR's are overloaded to be platter switches.
  5637. Srb->Cdb[7] = Srb->Lun;
  5638. }
  5639. }
  5640. // SETUP DMA !!!!!
  5641. if(use_dma) {
  5642. chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
  5643. } else {
  5644. chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
  5645. }
  5646. statusByte = WaitOnBusy(chan);
  5647. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
  5648. statusByte));
  5649. AtapiWritePort1(chan, IDX_IO1_o_Feature,
  5650. use_dma ? ATA_F_DMA : 0);
  5651. // Write transfer byte count to registers.
  5652. byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
  5653. byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
  5654. if (Srb->DataTransferLength >= 0x10000) {
  5655. byteCountLow = byteCountHigh = 0xFF;
  5656. }
  5657. AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
  5658. AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
  5659. if (flags & DFLAGS_INT_DRQ) {
  5660. // This device interrupts when ready to receive the packet.
  5661. KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
  5662. statusByte));
  5663. chan->ExpectingInterrupt = TRUE;
  5664. AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
  5665. InterlockedExchange(&(chan->CheckIntr),
  5666. CHECK_INTR_IDLE);
  5667. // Write ATAPI packet command.
  5668. AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
  5669. KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
  5670. return SRB_STATUS_PENDING;
  5671. }
  5672. // This device quickly sets DRQ when ready to receive the packet.
  5673. KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
  5674. statusByte));
  5675. chan->ExpectingInterrupt = TRUE;
  5676. AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
  5677. InterlockedExchange(&(chan->CheckIntr),
  5678. CHECK_INTR_IDLE);
  5679. if(g_opt_AtapiSendDisableIntr) {
  5680. AtapiDisableInterrupts(deviceExtension, lChannel);
  5681. }
  5682. // Write ATAPI packet command.
  5683. AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
  5684. // Wait for DRQ.
  5685. WaitOnBusy(chan);
  5686. statusByte = WaitForDrq(chan);
  5687. // Need to read status register and clear interrupt (if any)
  5688. GetBaseStatus(chan, statusByte);
  5689. if (!(statusByte & IDE_STATUS_DRQ)) {
  5690. if(g_opt_AtapiSendDisableIntr) {
  5691. AtapiEnableInterrupts(deviceExtension, lChannel);
  5692. }
  5693. KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
  5694. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  5695. return SRB_STATUS_ERROR;
  5696. }
  5697. GetStatus(chan, statusByte);
  5698. KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
  5699. // Send CDB to device.
  5700. statusByte = WaitOnBaseBusy(chan);
  5701. // Indicate expecting an interrupt and wait for it.
  5702. chan->ExpectingInterrupt = TRUE;
  5703. InterlockedExchange(&(chan->CheckIntr),
  5704. CHECK_INTR_IDLE);
  5705. AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
  5706. GetBaseStatus(chan, statusByte);
  5707. if(g_opt_AtapiSendDisableIntr) {
  5708. AtapiEnableInterrupts(deviceExtension, lChannel);
  5709. }
  5710. WriteBuffer(chan,
  5711. (PUSHORT)Srb->Cdb,
  5712. 6,
  5713. 0);
  5714. if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
  5715. AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
  5716. }
  5717. KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
  5718. KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
  5719. return SRB_STATUS_PENDING;
  5720. } // end AtapiSendCommand()
  5721. #ifndef UNIATA_CORE
  5722. /*++
  5723. Routine Description:
  5724. Program ATA registers for IDE disk transfer.
  5725. Arguments:
  5726. HwDeviceExtension - ATAPI driver storage.
  5727. Srb - System request block.
  5728. Return Value:
  5729. SRB status (pending if all goes well).
  5730. --*/
  5731. #ifdef _DEBUG
  5732. ULONG check_point = 0;
  5733. #define SetCheckPoint(cp) { check_point = (cp) ; }
  5734. #else
  5735. #define SetCheckPoint(cp)
  5736. #endif
  5737. ULONG
  5738. NTAPI
  5739. IdeSendCommand(
  5740. IN PVOID HwDeviceExtension,
  5741. IN PSCSI_REQUEST_BLOCK Srb,
  5742. IN ULONG CmdAction
  5743. )
  5744. {
  5745. SetCheckPoint(1);
  5746. KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
  5747. SetCheckPoint(2);
  5748. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  5749. SetCheckPoint(3);
  5750. UCHAR lChannel;
  5751. PHW_CHANNEL chan;
  5752. PCDB cdb;
  5753. SetCheckPoint(4);
  5754. UCHAR statusByte,errorByte;
  5755. ULONG status;
  5756. ULONG i;
  5757. PMODE_PARAMETER_HEADER modeData;
  5758. //ULONG ldev;
  5759. ULONG DeviceNumber;
  5760. PATA_REQ AtaReq;
  5761. SetCheckPoint(5);
  5762. //ULONG __ebp__ = 0;
  5763. SetCheckPoint(0x20);
  5764. KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
  5765. /* __asm {
  5766. mov eax,ebp
  5767. mov __ebp__, eax
  5768. }*/
  5769. /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
  5770. __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
  5771. KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
  5772. (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
  5773. KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
  5774. Srb));
  5775. KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
  5776. Srb->SrbExtension));
  5777. KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
  5778. Srb->TargetId));*/
  5779. SetCheckPoint(0x30);
  5780. AtaReq = (PATA_REQ)(Srb->SrbExtension);
  5781. KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
  5782. &AtaReq));
  5783. KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
  5784. AtaReq));
  5785. KdPrint2((PRINT_PREFIX "** --- **\n"));
  5786. lChannel = GET_CHANNEL(Srb);
  5787. chan = &(deviceExtension->chan[lChannel]);
  5788. //ldev = GET_LDEV(Srb);
  5789. DeviceNumber = GET_CDEV(Srb);
  5790. SetCheckPoint(0x40);
  5791. if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
  5792. AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
  5793. if(CmdAction == CMD_ACTION_PREPARE) {
  5794. switch (Srb->Cdb[0]) {
  5795. #ifdef NAVO_TEST
  5796. case SCSIOP_INQUIRY: // now it requires device access
  5797. #endif //NAVO_TEST
  5798. case SCSIOP_READ_CAPACITY:
  5799. case SCSIOP_READ:
  5800. case SCSIOP_WRITE:
  5801. case SCSIOP_REQUEST_SENSE:
  5802. // all right
  5803. KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
  5804. SetCheckPoint(50);
  5805. break;
  5806. default:
  5807. SetCheckPoint(0);
  5808. KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
  5809. return SRB_STATUS_BUSY;
  5810. }
  5811. }
  5812. SetCheckPoint(0x100 | Srb->Cdb[0]);
  5813. switch (Srb->Cdb[0]) {
  5814. case SCSIOP_INQUIRY:
  5815. KdPrint2((PRINT_PREFIX
  5816. "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
  5817. Srb->PathId, Srb->Lun, Srb->TargetId));
  5818. // Filter out all TIDs but 0 and 1 since this is an IDE interface
  5819. // which support up to two devices.
  5820. if ((Srb->Lun != 0) ||
  5821. (Srb->PathId >= deviceExtension->NumberChannels) ||
  5822. (Srb->TargetId > deviceExtension->NumberLuns)) {
  5823. KdPrint2((PRINT_PREFIX
  5824. "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
  5825. // Indicate no device found at this address.
  5826. status = SRB_STATUS_SELECTION_TIMEOUT;
  5827. break;
  5828. } else {
  5829. KdPrint2((PRINT_PREFIX
  5830. "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
  5831. PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
  5832. PIDENTIFY_DATA2 identifyData = &(chan->lun[DeviceNumber]->IdentifyData);
  5833. if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  5834. if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
  5835. KdPrint2((PRINT_PREFIX
  5836. "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
  5837. // Indicate no device found at this address.
  5838. #ifndef NAVO_TEST
  5839. status = SRB_STATUS_SELECTION_TIMEOUT;
  5840. break;
  5841. }
  5842. } else {
  5843. if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
  5844. KdPrint2((PRINT_PREFIX
  5845. "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
  5846. // Indicate no device found at this address.
  5847. UniataForgetDevice(chan->lun[DeviceNumber]);
  5848. #endif //NAVO_TEST
  5849. status = SRB_STATUS_SELECTION_TIMEOUT;
  5850. break;
  5851. }
  5852. }
  5853. // Zero INQUIRY data structure.
  5854. RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
  5855. // Standard IDE interface only supports disks.
  5856. inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
  5857. // Set the removable bit, if applicable.
  5858. if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
  5859. KdPrint2((PRINT_PREFIX
  5860. "RemovableMedia\n"));
  5861. inquiryData->RemovableMedia = 1;
  5862. }
  5863. // Set the Relative Addressing (LBA) bit, if applicable.
  5864. if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
  5865. inquiryData->RelativeAddressing = 1;
  5866. KdPrint2((PRINT_PREFIX
  5867. "RelativeAddressing\n"));
  5868. }
  5869. // Set the CommandQueue bit
  5870. inquiryData->CommandQueue = 1;
  5871. // Fill in vendor identification fields.
  5872. for (i = 0; i < 24; i += 2) {
  5873. MOV_DW_SWP(inquiryData->VendorId[i], ((PUCHAR)identifyData->ModelNumber)[i]);
  5874. }
  5875. /*
  5876. // Initialize unused portion of product id.
  5877. for (i = 0; i < 4; i++) {
  5878. inquiryData->ProductId[12+i] = ' ';
  5879. }
  5880. */
  5881. // Move firmware revision from IDENTIFY data to
  5882. // product revision in INQUIRY data.
  5883. for (i = 0; i < 4; i += 2) {
  5884. MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
  5885. }
  5886. status = SRB_STATUS_SUCCESS;
  5887. }
  5888. break;
  5889. case SCSIOP_MODE_SENSE:
  5890. KdPrint2((PRINT_PREFIX
  5891. "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
  5892. Srb->PathId, Srb->Lun, Srb->TargetId));
  5893. // This is used to determine if the media is write-protected.
  5894. // Since IDE does not support mode sense then we will modify just the portion we need
  5895. // so the higher level driver can determine if media is protected.
  5896. if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
  5897. SelectDrive(chan, DeviceNumber);
  5898. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
  5899. statusByte = WaitOnBusy(chan);
  5900. if (!(statusByte & IDE_STATUS_ERROR)){
  5901. // no error occured return success, media is not protected
  5902. chan->ExpectingInterrupt = FALSE;
  5903. InterlockedExchange(&(chan->CheckIntr),
  5904. CHECK_INTR_IDLE);
  5905. status = SRB_STATUS_SUCCESS;
  5906. } else {
  5907. // error occured, handle it locally, clear interrupt
  5908. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  5909. GetBaseStatus(chan, statusByte);
  5910. chan->ExpectingInterrupt = FALSE;
  5911. InterlockedExchange(&(chan->CheckIntr),
  5912. CHECK_INTR_IDLE);
  5913. status = SRB_STATUS_SUCCESS;
  5914. if (errorByte & IDE_ERROR_DATA_ERROR) {
  5915. //media is write-protected, set bit in mode sense buffer
  5916. modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
  5917. Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
  5918. modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
  5919. }
  5920. }
  5921. status = SRB_STATUS_SUCCESS;
  5922. } else {
  5923. status = SRB_STATUS_INVALID_REQUEST;
  5924. }
  5925. break;
  5926. case SCSIOP_TEST_UNIT_READY:
  5927. KdPrint2((PRINT_PREFIX
  5928. "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
  5929. Srb->PathId, Srb->Lun, Srb->TargetId));
  5930. if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
  5931. // Select device 0 or 1.
  5932. SelectDrive(chan, DeviceNumber);
  5933. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
  5934. // Wait for busy. If media has not changed, return success
  5935. statusByte = WaitOnBusy(chan);
  5936. if (!(statusByte & IDE_STATUS_ERROR)){
  5937. chan->ExpectingInterrupt = FALSE;
  5938. InterlockedExchange(&(chan->CheckIntr),
  5939. CHECK_INTR_IDLE);
  5940. status = SRB_STATUS_SUCCESS;
  5941. } else {
  5942. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  5943. if (errorByte == IDE_ERROR_DATA_ERROR){
  5944. // Special case: If current media is write-protected,
  5945. // the 0xDA command will always fail since the write-protect bit
  5946. // is sticky,so we can ignore this error
  5947. GetBaseStatus(chan, statusByte);
  5948. chan->ExpectingInterrupt = FALSE;
  5949. InterlockedExchange(&(chan->CheckIntr),
  5950. CHECK_INTR_IDLE);
  5951. status = SRB_STATUS_SUCCESS;
  5952. } else {
  5953. // Request sense buffer to be build
  5954. chan->ExpectingInterrupt = TRUE;
  5955. InterlockedExchange(&(chan->CheckIntr),
  5956. CHECK_INTR_IDLE);
  5957. status = SRB_STATUS_PENDING;
  5958. }
  5959. }
  5960. } else {
  5961. status = SRB_STATUS_SUCCESS;
  5962. }
  5963. break;
  5964. case SCSIOP_READ_CAPACITY:
  5965. KdPrint2((PRINT_PREFIX
  5966. "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
  5967. Srb->PathId, Srb->Lun, Srb->TargetId));
  5968. // Claim 512 byte blocks (big-endian).
  5969. //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
  5970. i = DEV_BSIZE;
  5971. MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
  5972. // Calculate last sector.
  5973. if(!(i = (ULONG)chan->lun[DeviceNumber]->NumOfSectors)) {
  5974. i = chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack *
  5975. chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads *
  5976. chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders;
  5977. }
  5978. i--;
  5979. //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
  5980. // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
  5981. // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
  5982. MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
  5983. KdPrint2((PRINT_PREFIX
  5984. "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
  5985. Srb->TargetId,
  5986. chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack,
  5987. chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads,
  5988. chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders));
  5989. status = SRB_STATUS_SUCCESS;
  5990. break;
  5991. case SCSIOP_VERIFY:
  5992. KdPrint2((PRINT_PREFIX
  5993. "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
  5994. Srb->PathId, Srb->Lun, Srb->TargetId));
  5995. status = IdeVerify(HwDeviceExtension,Srb);
  5996. break;
  5997. case SCSIOP_READ:
  5998. case SCSIOP_WRITE:
  5999. KdPrint2((PRINT_PREFIX
  6000. "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
  6001. (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
  6002. Srb->PathId, Srb->Lun, Srb->TargetId));
  6003. AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
  6004. AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
  6005. status = IdeReadWrite(HwDeviceExtension,
  6006. Srb, CmdAction);
  6007. break;
  6008. case SCSIOP_START_STOP_UNIT:
  6009. KdPrint2((PRINT_PREFIX
  6010. "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
  6011. Srb->PathId, Srb->Lun, Srb->TargetId));
  6012. //Determine what type of operation we should perform
  6013. cdb = (PCDB)Srb->Cdb;
  6014. if (cdb->START_STOP.LoadEject == 1){
  6015. statusByte = WaitOnBaseBusy(chan);
  6016. // Eject media,
  6017. // first select device 0 or 1.
  6018. SelectDrive(chan, DeviceNumber);
  6019. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
  6020. }
  6021. status = SRB_STATUS_SUCCESS;
  6022. break;
  6023. case SCSIOP_MEDIUM_REMOVAL:
  6024. cdb = (PCDB)Srb->Cdb;
  6025. statusByte = WaitOnBaseBusy(chan);
  6026. SelectDrive(chan, DeviceNumber);
  6027. if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
  6028. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
  6029. } else {
  6030. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
  6031. }
  6032. status = SRB_STATUS_SUCCESS;
  6033. break;
  6034. // Note: I don't implement this, because NTFS driver too often issues this command
  6035. // It causes awful performance degrade. However, if somebody wants, I will implement
  6036. // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
  6037. #if 0
  6038. case SCSIOP_FLUSH_BUFFER:
  6039. case SCSIOP_SYNCHRONIZE_CACHE:
  6040. SelectDrive(chan, DeviceNumber);
  6041. AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
  6042. status = SRB_STATUS_SUCCESS;
  6043. // status = SRB_STATUS_PENDING;
  6044. statusByte = WaitOnBusy(chan);
  6045. break;
  6046. #endif
  6047. case SCSIOP_REQUEST_SENSE:
  6048. // this function makes sense buffers to report the results
  6049. // of the original GET_MEDIA_STATUS command
  6050. KdPrint2((PRINT_PREFIX
  6051. "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
  6052. Srb->PathId, Srb->Lun, Srb->TargetId));
  6053. if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
  6054. status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
  6055. break;
  6056. }
  6057. status = SRB_STATUS_INVALID_REQUEST;
  6058. break;
  6059. // ATA_PASSTHORUGH
  6060. case SCSIOP_ATA_PASSTHROUGH:
  6061. {
  6062. PIDEREGS_EX regs;
  6063. BOOLEAN use_dma = FALSE;
  6064. ULONG to_lim;
  6065. regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
  6066. lChannel = Srb->TargetId >> 1;
  6067. regs->bDriveHeadReg &= 0x0f;
  6068. regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
  6069. if((regs->bOpFlags & 1) == 0) { // execute ATA command
  6070. KdPrint2((PRINT_PREFIX
  6071. "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
  6072. Srb->PathId, Srb->Lun, Srb->TargetId));
  6073. AtapiDisableInterrupts(deviceExtension, lChannel);
  6074. if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
  6075. if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
  6076. use_dma = TRUE;
  6077. // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
  6078. if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
  6079. (PUCHAR)(Srb->DataBuffer),
  6080. ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
  6081. use_dma = FALSE;
  6082. }
  6083. }
  6084. }
  6085. AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
  6086. AtapiStallExecution(10);
  6087. if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
  6088. AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
  6089. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
  6090. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
  6091. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
  6092. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
  6093. } else {
  6094. AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH);
  6095. AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
  6096. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH);
  6097. AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
  6098. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH);
  6099. AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
  6100. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH);
  6101. AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
  6102. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
  6103. AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
  6104. }
  6105. AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg);
  6106. if(use_dma) {
  6107. GetBaseStatus(chan, statusByte);
  6108. if(statusByte & IDE_STATUS_ERROR) {
  6109. goto passthrough_err;
  6110. }
  6111. AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb);
  6112. }
  6113. ScsiPortStallExecution(1); // wait for busy to be set
  6114. if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
  6115. to_lim = Srb->TimeOutValue;
  6116. } else {
  6117. if(Srb->TimeOutValue <= 2) {
  6118. to_lim = Srb->TimeOutValue*900;
  6119. } else {
  6120. to_lim = (Srb->TimeOutValue*999) - 500;
  6121. }
  6122. }
  6123. for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
  6124. statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
  6125. GetBaseStatus(chan, statusByte);
  6126. if(statusByte & IDE_STATUS_ERROR) {
  6127. break;
  6128. }
  6129. if(!(statusByte & IDE_STATUS_BUSY)) {
  6130. break;
  6131. }
  6132. }
  6133. if(i >= to_lim) {
  6134. //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
  6135. //}
  6136. AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
  6137. goto passthrough_err;
  6138. }
  6139. if(use_dma) {
  6140. AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
  6141. }
  6142. AtapiDmaDone(deviceExtension, (Srb->TargetId & 0x1), lChannel, NULL);
  6143. GetBaseStatus(chan, statusByte);
  6144. if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
  6145. AtapiSuckPort2(chan);
  6146. passthrough_err:
  6147. if (Srb->SenseInfoBuffer) {
  6148. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
  6149. senseBuffer->ErrorCode = 0x70;
  6150. senseBuffer->Valid = 1;
  6151. senseBuffer->AdditionalSenseLength = 0xb;
  6152. senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
  6153. senseBuffer->AdditionalSenseCode = 0;
  6154. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6155. Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
  6156. Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  6157. }
  6158. status = SRB_STATUS_ERROR;
  6159. } else {
  6160. if(!use_dma) {
  6161. if (statusByte & IDE_STATUS_DRQ) {
  6162. if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  6163. ReadBuffer(chan,
  6164. (PUSHORT) Srb->DataBuffer,
  6165. Srb->DataTransferLength / 2,
  6166. 0);
  6167. } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  6168. WriteBuffer(chan,
  6169. (PUSHORT) Srb->DataBuffer,
  6170. Srb->DataTransferLength / 2,
  6171. 0);
  6172. }
  6173. }
  6174. }
  6175. status = SRB_STATUS_SUCCESS;
  6176. }
  6177. AtapiEnableInterrupts(deviceExtension, lChannel);
  6178. } else { // read task register
  6179. regs = (PIDEREGS_EX) Srb->DataBuffer;
  6180. regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
  6181. if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
  6182. regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
  6183. regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
  6184. regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
  6185. regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  6186. regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  6187. } else {
  6188. regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
  6189. regs->bFeaturesRegH = AtapiReadPort1(chan, IDX_IO1_i_Error);
  6190. regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
  6191. regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
  6192. regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
  6193. regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
  6194. regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  6195. regs->bCylLowRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
  6196. regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  6197. regs->bCylHighRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
  6198. }
  6199. regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
  6200. status = SRB_STATUS_SUCCESS;
  6201. }
  6202. break;
  6203. }
  6204. default:
  6205. KdPrint2((PRINT_PREFIX
  6206. "IdeSendCommand: Unsupported command %#x\n",
  6207. Srb->Cdb[0]));
  6208. status = SRB_STATUS_INVALID_REQUEST;
  6209. } // end switch
  6210. if(status == SRB_STATUS_PENDING) {
  6211. KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
  6212. if(CmdAction & CMD_ACTION_EXEC) {
  6213. KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
  6214. AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
  6215. }
  6216. } else {
  6217. KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
  6218. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
  6219. }
  6220. return status;
  6221. } // end IdeSendCommand()
  6222. /*++
  6223. Routine Description:
  6224. Enables disables media status notification
  6225. Arguments:
  6226. HwDeviceExtension - ATAPI driver storage.
  6227. --*/
  6228. VOID
  6229. NTAPI
  6230. IdeMediaStatus(
  6231. BOOLEAN EnableMSN,
  6232. IN PVOID HwDeviceExtension,
  6233. IN ULONG lChannel,
  6234. IN ULONG DeviceNumber
  6235. )
  6236. {
  6237. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  6238. PHW_CHANNEL chan;
  6239. UCHAR statusByte,errorByte;
  6240. chan = &(deviceExtension->chan[lChannel]);
  6241. if (EnableMSN == TRUE){
  6242. // If supported enable Media Status Notification support
  6243. if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
  6244. // enable
  6245. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
  6246. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  6247. 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
  6248. if (statusByte & IDE_STATUS_ERROR) {
  6249. // Read the error register.
  6250. errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
  6251. KdPrint2((PRINT_PREFIX
  6252. "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
  6253. statusByte,
  6254. errorByte));
  6255. } else {
  6256. chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
  6257. KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
  6258. chan->ReturningMediaStatus = 0;
  6259. }
  6260. }
  6261. } else { // end if EnableMSN == TRUE
  6262. // disable if previously enabled
  6263. if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
  6264. statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
  6265. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  6266. 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
  6267. chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
  6268. }
  6269. }
  6270. } // end IdeMediaStatus()
  6271. /*++
  6272. Routine Description:
  6273. Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
  6274. command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
  6275. Arguments:
  6276. HwDeviceExtension - ATAPI driver storage.
  6277. Srb - System request block.
  6278. Return Value:
  6279. SRB status (ALWAYS SUCCESS).
  6280. --*/
  6281. ULONG
  6282. NTAPI
  6283. IdeBuildSenseBuffer(
  6284. IN PVOID HwDeviceExtension,
  6285. IN PSCSI_REQUEST_BLOCK Srb
  6286. )
  6287. {
  6288. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  6289. // ULONG status;
  6290. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
  6291. UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
  6292. if (senseBuffer){
  6293. if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
  6294. senseBuffer->ErrorCode = 0x70;
  6295. senseBuffer->Valid = 1;
  6296. senseBuffer->AdditionalSenseLength = 0xb;
  6297. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  6298. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  6299. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6300. } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
  6301. senseBuffer->ErrorCode = 0x70;
  6302. senseBuffer->Valid = 1;
  6303. senseBuffer->AdditionalSenseLength = 0xb;
  6304. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  6305. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  6306. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6307. } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
  6308. senseBuffer->ErrorCode = 0x70;
  6309. senseBuffer->Valid = 1;
  6310. senseBuffer->AdditionalSenseLength = 0xb;
  6311. senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
  6312. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
  6313. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6314. } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
  6315. senseBuffer->ErrorCode = 0x70;
  6316. senseBuffer->Valid = 1;
  6317. senseBuffer->AdditionalSenseLength = 0xb;
  6318. senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
  6319. senseBuffer->AdditionalSenseCode = 0;
  6320. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6321. }
  6322. return SRB_STATUS_SUCCESS;
  6323. }
  6324. return SRB_STATUS_ERROR;
  6325. }// End of IdeBuildSenseBuffer
  6326. VOID
  6327. NTAPI
  6328. UniataUserDeviceReset(
  6329. PHW_DEVICE_EXTENSION deviceExtension,
  6330. PHW_LU_EXTENSION LunExt,
  6331. ULONG PathId
  6332. )
  6333. {
  6334. ULONG i;
  6335. AtapiDisableInterrupts(deviceExtension, PathId);
  6336. if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  6337. KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
  6338. AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
  6339. } else {
  6340. KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
  6341. AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
  6342. for(i=0; i<deviceExtension->NumberLuns; i++) {
  6343. deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
  6344. }
  6345. }
  6346. LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
  6347. AtapiEnableInterrupts(deviceExtension, PathId);
  6348. return;
  6349. } // end UniataUserDeviceReset()
  6350. BOOLEAN
  6351. NTAPI
  6352. UniataNeedQueueing(
  6353. PHW_DEVICE_EXTENSION deviceExtension,
  6354. PHW_CHANNEL chan,
  6355. BOOLEAN TopLevel
  6356. )
  6357. {
  6358. BOOLEAN PostReq = FALSE;
  6359. if(TopLevel) {
  6360. KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
  6361. if(chan->queue_depth > 0) {
  6362. #if 0
  6363. if(atapiDev &&
  6364. ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
  6365. (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
  6366. KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
  6367. //PostReq = FALSE;
  6368. status = SRB_STATUS_BUSY;
  6369. goto skip_exec;
  6370. } else {
  6371. PostReq = TRUE;
  6372. }
  6373. #else
  6374. PostReq = TRUE;
  6375. #endif
  6376. } else
  6377. if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
  6378. PostReq = TRUE;
  6379. }
  6380. } else {
  6381. KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
  6382. }
  6383. return PostReq;
  6384. } // end UniataNeedQueueing()
  6385. /*++
  6386. Routine Description:
  6387. This routine is called from the SCSI port driver synchronized
  6388. with the kernel to start an IO request.
  6389. Arguments:
  6390. HwDeviceExtension - HBA miniport driver's adapter data storage
  6391. Srb - IO request packet
  6392. Return Value:
  6393. TRUE
  6394. --*/
  6395. BOOLEAN
  6396. NTAPI
  6397. AtapiStartIo(
  6398. IN PVOID HwDeviceExtension,
  6399. IN PSCSI_REQUEST_BLOCK Srb
  6400. )
  6401. {
  6402. return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
  6403. } // end AtapiStartIo()
  6404. BOOLEAN
  6405. NTAPI
  6406. AtapiStartIo__(
  6407. IN PVOID HwDeviceExtension,
  6408. IN PSCSI_REQUEST_BLOCK Srb,
  6409. IN BOOLEAN TopLevel
  6410. )
  6411. {
  6412. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  6413. UCHAR lChannel;
  6414. PHW_CHANNEL chan;
  6415. PHW_LU_EXTENSION LunExt;
  6416. ULONG status;
  6417. //ULONG ldev;
  6418. ULONG DeviceNumber;
  6419. UCHAR PathId;
  6420. UCHAR TargetId;
  6421. UCHAR Lun;
  6422. PATA_REQ AtaReq;
  6423. PSCSI_REQUEST_BLOCK tmpSrb;
  6424. BOOLEAN PostReq = FALSE;
  6425. BOOLEAN atapiDev;
  6426. BOOLEAN commPort = FALSE;
  6427. // deviceExtension->Isr2DevObj must always be NULL for non-PCI
  6428. if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
  6429. KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
  6430. BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
  6431. }
  6432. // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
  6433. /* KeBugCheckEx(0xc000000e,
  6434. (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
  6435. Srb->Function,
  6436. TopLevel, 0x80000001);
  6437. */
  6438. if(TopLevel && Srb && Srb->SrbExtension) {
  6439. KdPrint2((PRINT_PREFIX "TopLevel\n"));
  6440. RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
  6441. }
  6442. do {
  6443. lChannel = GET_CHANNEL(Srb);
  6444. //ldev = GET_LDEV(Srb);
  6445. chan = NULL;
  6446. LunExt = NULL;
  6447. DeviceNumber = GET_CDEV(Srb);
  6448. //ASSERT(deviceExtension);
  6449. //ASSERT(chan);
  6450. KdPrint2((PRINT_PREFIX
  6451. "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
  6452. Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
  6453. KdPrint2((PRINT_PREFIX " VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
  6454. if(lChannel == deviceExtension->NumberChannels &&
  6455. !Srb->Lun && !Srb->TargetId &&
  6456. ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
  6457. (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
  6458. ) {
  6459. KdPrint2((PRINT_PREFIX
  6460. "AtapiStartIo: Communication port\n"));
  6461. if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
  6462. PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
  6463. KdPrint2((PRINT_PREFIX
  6464. " INQUIRY\n"));
  6465. // Zero INQUIRY data structure.
  6466. RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
  6467. inquiryData->DeviceType = COMMUNICATION_DEVICE;
  6468. // Fill in vendor identification fields.
  6469. RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
  6470. status = SRB_STATUS_SUCCESS;
  6471. goto complete_req;
  6472. }
  6473. commPort = TRUE;
  6474. /* Pass IOCTL request down */
  6475. } else
  6476. if(lChannel >= deviceExtension->NumberChannels ||
  6477. Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
  6478. Srb->Lun) {
  6479. if(lChannel >= deviceExtension->NumberChannels) {
  6480. chan = NULL;
  6481. }
  6482. reject_srb:
  6483. //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
  6484. KdPrint3((PRINT_PREFIX
  6485. "AtapiStartIo: SRB rejected\n"));
  6486. // Indicate no device found at this address.
  6487. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
  6488. status = SRB_STATUS_SELECTION_TIMEOUT;
  6489. goto complete_req;
  6490. //}
  6491. }
  6492. if(!commPort) {
  6493. chan = &(deviceExtension->chan[lChannel]);
  6494. LunExt = chan->lun[DeviceNumber];
  6495. if(!LunExt) {
  6496. goto reject_srb;
  6497. }
  6498. atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
  6499. } else {
  6500. atapiDev = FALSE;
  6501. }
  6502. #ifdef _DEBUG
  6503. if(!commPort && !LunExt) {
  6504. #if 0
  6505. PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
  6506. deviceExtension,
  6507. chan, DeviceNumber,
  6508. deviceExtension->NumberChannels);
  6509. PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
  6510. lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
  6511. PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
  6512. Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
  6513. #endif //0
  6514. /*
  6515. int i;
  6516. for(i=0; i<1000; i++) {
  6517. AtapiStallExecution(3*1000);
  6518. }
  6519. */
  6520. goto reject_srb;
  6521. }
  6522. #endif //_DEBUG
  6523. // Determine which function.
  6524. switch (Srb->Function) {
  6525. case SRB_FUNCTION_EXECUTE_SCSI:
  6526. if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  6527. if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
  6528. // let passthrough go
  6529. } else
  6530. if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
  6531. // let INQUIRY go
  6532. } else {
  6533. //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
  6534. KdPrint2((PRINT_PREFIX
  6535. "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
  6536. // Indicate no device found at this address.
  6537. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
  6538. status = SRB_STATUS_SELECTION_TIMEOUT;
  6539. break;
  6540. //}
  6541. }
  6542. }
  6543. /*
  6544. __try {
  6545. if(Srb->DataTransferLength) {
  6546. UCHAR a;
  6547. a = ((PUCHAR)(Srb->DataBuffer))[0];
  6548. g_foo += a;
  6549. }
  6550. } __except(EXCEPTION_EXECUTE_HANDLER) {
  6551. KdPrint3((PRINT_PREFIX
  6552. "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
  6553. // Indicate no device found at this address.
  6554. KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
  6555. status = SRB_STATUS_ERROR;
  6556. KdPrint2((PRINT_PREFIX " *** Exception...\n"));
  6557. ASSERT(FALSE);
  6558. break;
  6559. }
  6560. */
  6561. PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
  6562. if(PostReq) {
  6563. KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
  6564. if (atapiDev &&
  6565. (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
  6566. KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
  6567. status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
  6568. } else {
  6569. KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
  6570. status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
  6571. }
  6572. /*KeBugCheckEx(0xc000000e,
  6573. (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
  6574. Srb->Function,
  6575. status, 0x80000001);*/
  6576. if(status == SRB_STATUS_BUSY)
  6577. status = SRB_STATUS_PENDING;
  6578. // Insert requests AFTER they have been initialized on
  6579. // CMD_ACTION_PREPARE stage
  6580. // we should not check TopLevel here (it is always TRUE)
  6581. //ASSERT(chan->lun[GET_CDEV(Srb)]);
  6582. UniataQueueRequest(chan, Srb);
  6583. KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
  6584. } else {
  6585. // Send command to device.
  6586. KdPrint2((PRINT_PREFIX "Send to device\n"));
  6587. if(TopLevel) {
  6588. KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
  6589. AtaReq = (PATA_REQ)(Srb->SrbExtension);
  6590. KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
  6591. //ASSERT(!AtaReq->Flags);
  6592. //ASSERT(chan->lun[GET_CDEV(Srb)]);
  6593. UniataQueueRequest(chan, Srb);
  6594. // AtaReq = (PATA_REQ)(Srb->SrbExtension);
  6595. //ASSERT(!AtaReq->Flags);
  6596. AtaReq->ReqState = REQ_STATE_QUEUED;
  6597. //ASSERT(!AtaReq->Flags);
  6598. }
  6599. #ifndef NAVO_TEST
  6600. if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  6601. if(!LunExt) {
  6602. goto reject_srb;
  6603. }
  6604. if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
  6605. if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
  6606. if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
  6607. goto reject_srb;
  6608. }
  6609. }
  6610. if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  6611. goto reject_srb;
  6612. }
  6613. } else
  6614. if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
  6615. // allow
  6616. } else {
  6617. goto reject_srb;
  6618. }
  6619. }
  6620. #endif //NAVO_TEST
  6621. if(atapiDev &&
  6622. (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
  6623. KdPrint3((PRINT_PREFIX "Try ATAPI send\n"));
  6624. status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
  6625. } else {
  6626. KdPrint2((PRINT_PREFIX "Try IDE send\n"));
  6627. /* {
  6628. ULONG __ebp__ = 0;
  6629. ULONG __esp__ = 0;
  6630. KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
  6631. __asm {
  6632. mov eax,ebp
  6633. mov __ebp__, eax
  6634. mov eax,esp
  6635. mov __esp__, eax
  6636. }
  6637. KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
  6638. }*/
  6639. status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
  6640. }
  6641. /* KeBugCheckEx(0xc000000e,
  6642. (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
  6643. Srb->Function,
  6644. status, 0x80000002);*/
  6645. }
  6646. //skip_exec:
  6647. TopLevel = FALSE;
  6648. break;
  6649. case SRB_FUNCTION_ABORT_COMMAND:
  6650. tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
  6651. Srb->QueueTag);
  6652. // Verify that SRB to abort is still outstanding.
  6653. if((tmpSrb != Srb->NextSrb) ||
  6654. !chan->queue_depth) {
  6655. KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
  6656. // Complete abort SRB.
  6657. status = SRB_STATUS_ABORT_FAILED;
  6658. break;
  6659. }
  6660. AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
  6661. if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
  6662. if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
  6663. KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
  6664. // Log reset failure.
  6665. KdPrint3((PRINT_PREFIX
  6666. "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
  6667. HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
  6668. ));
  6669. ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
  6670. status = SRB_STATUS_ERROR;
  6671. } else {
  6672. status = SRB_STATUS_SUCCESS;
  6673. }
  6674. } else {
  6675. KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
  6676. if (tmpSrb->SenseInfoBuffer &&
  6677. tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
  6678. PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
  6679. senseBuffer->ErrorCode = 0;
  6680. senseBuffer->Valid = 1;
  6681. senseBuffer->AdditionalSenseLength = 0xb;
  6682. senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
  6683. senseBuffer->AdditionalSenseCode = 0;
  6684. senseBuffer->AdditionalSenseCodeQualifier = 0;
  6685. tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  6686. }
  6687. AtapiDmaDBSync(chan, tmpSrb);
  6688. UniataRemoveRequest(chan, tmpSrb);
  6689. // Indicate command complete.
  6690. ScsiPortNotification(RequestComplete,
  6691. deviceExtension,
  6692. tmpSrb);
  6693. status = SRB_STATUS_SUCCESS;
  6694. }
  6695. break;
  6696. // Abort function indicates that a request timed out.
  6697. // Call reset routine. Card will only be reset if
  6698. // status indicates something is wrong.
  6699. // Fall through to reset code.
  6700. case SRB_FUNCTION_RESET_DEVICE:
  6701. case SRB_FUNCTION_RESET_LOGICAL_UNIT:
  6702. // Reset single device.
  6703. // For now we support only Lun=0
  6704. // Note: reset is immediate command, it cannot be queued since it is usually used to
  6705. // revert not- responding device to operational state
  6706. KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
  6707. UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
  6708. status = SRB_STATUS_SUCCESS;
  6709. break;
  6710. case SRB_FUNCTION_RESET_BUS:
  6711. do_bus_reset:
  6712. // Reset Atapi and SCSI bus.
  6713. // Note: reset is immediate command, it cannot be queued since it is usually used to
  6714. // revert not- responding device to operational state
  6715. KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
  6716. if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
  6717. KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
  6718. // Log reset failure.
  6719. KdPrint3((PRINT_PREFIX
  6720. "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
  6721. HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
  6722. ));
  6723. ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
  6724. status = SRB_STATUS_ERROR;
  6725. } else {
  6726. status = SRB_STATUS_SUCCESS;
  6727. }
  6728. break;
  6729. case SRB_FUNCTION_SHUTDOWN:
  6730. KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
  6731. if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  6732. KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
  6733. } else
  6734. if(atapiDev) {
  6735. // FLUSH ATAPI device - do nothing
  6736. KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
  6737. } else {
  6738. // FLUSH IDE/ATA device
  6739. KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
  6740. AtapiDisableInterrupts(deviceExtension, lChannel);
  6741. status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
  6742. IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
  6743. // If supported & allowed, reset write cacheing
  6744. if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
  6745. // Disable write cache
  6746. status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
  6747. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  6748. 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
  6749. // Check for errors.
  6750. if (status & IDE_STATUS_ERROR) {
  6751. KdPrint2((PRINT_PREFIX
  6752. "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
  6753. DeviceNumber));
  6754. }
  6755. LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
  6756. // Re-enable write cache
  6757. status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
  6758. IDE_COMMAND_SET_FEATURES, 0, 0, 0,
  6759. 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
  6760. // Check for errors.
  6761. if (status & IDE_STATUS_ERROR) {
  6762. KdPrint2((PRINT_PREFIX
  6763. "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
  6764. DeviceNumber));
  6765. LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
  6766. } else {
  6767. LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
  6768. }
  6769. }
  6770. AtapiEnableInterrupts(deviceExtension, lChannel);
  6771. }
  6772. status = SRB_STATUS_SUCCESS;
  6773. break;
  6774. case SRB_FUNCTION_FLUSH:
  6775. KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
  6776. status = SRB_STATUS_SUCCESS;
  6777. break;
  6778. /* case SRB_FUNCTION_SHUTDOWN:
  6779. case SRB_FUNCTION_FLUSH:
  6780. // Flush device's cache.
  6781. KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
  6782. if (chan->CurrentSrb) {
  6783. KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
  6784. Srb->SrbStatus = SRB_STATUS_BUSY;
  6785. ScsiPortNotification(RequestComplete,
  6786. deviceExtension,
  6787. Srb);
  6788. return FALSE;
  6789. }
  6790. if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
  6791. status = SRB_STATUS_SUCCESS;
  6792. } else {
  6793. status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb),
  6794. IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
  6795. if (status & IDE_STATUS_DRQ) {
  6796. status = SRB_STATUS_SUCCESS;
  6797. } else {
  6798. status = SRB_STATUS_SELECTION_TIMEOUT;
  6799. }
  6800. }
  6801. break;*/
  6802. case SRB_FUNCTION_IO_CONTROL: {
  6803. ULONG len;
  6804. KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
  6805. len = Srb->DataTransferLength;
  6806. if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
  6807. switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
  6808. case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
  6809. PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  6810. UCHAR deviceNumber;
  6811. KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
  6812. // Version and revision per SMART 1.03
  6813. versionParameters->bVersion = 1;
  6814. versionParameters->bRevision = 1;
  6815. versionParameters->bReserved = 0;
  6816. // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
  6817. versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
  6818. // This is done because of how the IOCTL_SCSI_MINIPORT
  6819. // determines 'targetid's'. Disk.sys places the real target id value
  6820. // in the DeviceMap field. Once we do some parameter checking, the value passed
  6821. // back to the application will be determined.
  6822. deviceNumber = versionParameters->bIDEDeviceMap;
  6823. if(commPort) {
  6824. KdPrint2((PRINT_PREFIX
  6825. "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
  6826. // Indicate no device found at this address.
  6827. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
  6828. status = SRB_STATUS_SELECTION_TIMEOUT;
  6829. break;
  6830. }
  6831. if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
  6832. atapiDev) {
  6833. status = SRB_STATUS_SELECTION_TIMEOUT;
  6834. break;
  6835. }
  6836. // NOTE: This will only set the bit
  6837. // corresponding to this drive's target id.
  6838. // The bit mask is as follows:
  6839. //
  6840. // -Sec Pri
  6841. // S M S M
  6842. // 3 2 1 0
  6843. if (deviceExtension->NumberChannels == 1) {
  6844. if (chan->PrimaryAddress) {
  6845. deviceNumber = 1 << DeviceNumber;
  6846. } else {
  6847. deviceNumber = 4 << DeviceNumber;
  6848. }
  6849. } else {
  6850. deviceNumber = (1 << DeviceNumber) << lChannel;
  6851. }
  6852. versionParameters->bIDEDeviceMap = deviceNumber;
  6853. status = SRB_STATUS_SUCCESS;
  6854. break;
  6855. }
  6856. case IOCTL_SCSI_MINIPORT_IDENTIFY: {
  6857. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  6858. SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  6859. UCHAR targetId;
  6860. KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
  6861. // Extract the target.
  6862. targetId = cmdInParameters.bDriveNumber;
  6863. KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
  6864. if((targetId >= deviceExtension->NumberChannels*2) ||
  6865. !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
  6866. KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
  6867. status = SRB_STATUS_SELECTION_TIMEOUT;
  6868. break;
  6869. }
  6870. switch(cmdInParameters.irDriveRegs.bCommandReg) {
  6871. case ID_CMD:
  6872. if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
  6873. KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
  6874. status = SRB_STATUS_INVALID_REQUEST;
  6875. break;
  6876. }
  6877. /* FALL THROUGH */
  6878. case ATAPI_ID_CMD:
  6879. if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
  6880. (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
  6881. KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
  6882. status = SRB_STATUS_INVALID_REQUEST;
  6883. break;
  6884. }
  6885. len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
  6886. // Zero the output buffer
  6887. RtlZeroMemory(cmdOutParameters, len);
  6888. /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
  6889. ((PUCHAR)cmdOutParameters)[i] = 0;
  6890. }*/
  6891. // Build status block.
  6892. cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
  6893. cmdOutParameters->DriverStatus.bDriverError = 0;
  6894. cmdOutParameters->DriverStatus.bIDEError = 0;
  6895. // Extract the identify data from the device extension.
  6896. ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData,
  6897. cmdOutParameters->cBufferSize);
  6898. KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
  6899. status = SRB_STATUS_SUCCESS;
  6900. break;
  6901. default:
  6902. KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
  6903. cmdInParameters.irDriveRegs.bCommandReg));
  6904. status = SRB_STATUS_INVALID_REQUEST;
  6905. break;
  6906. }
  6907. break;
  6908. }
  6909. case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
  6910. case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
  6911. case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
  6912. case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
  6913. case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
  6914. case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
  6915. case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
  6916. case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
  6917. if(commPort) {
  6918. KdPrint2((PRINT_PREFIX
  6919. "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
  6920. // Indicate no device found at this address.
  6921. KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
  6922. status = SRB_STATUS_SELECTION_TIMEOUT;
  6923. break;
  6924. }
  6925. PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
  6926. if(PostReq || TopLevel) {
  6927. UniataQueueRequest(chan, Srb);
  6928. AtaReq = (PATA_REQ)(Srb->SrbExtension);
  6929. AtaReq->ReqState = REQ_STATE_QUEUED;
  6930. }
  6931. if(PostReq) {
  6932. KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
  6933. status = SRB_STATUS_PENDING;
  6934. KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
  6935. } else {
  6936. status = IdeSendSmartCommand(HwDeviceExtension,Srb);
  6937. }
  6938. break;
  6939. default :
  6940. KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
  6941. ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
  6942. status = SRB_STATUS_INVALID_REQUEST;
  6943. break;
  6944. }
  6945. } else
  6946. if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
  6947. PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
  6948. //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
  6949. ULONG DeviceNumber = AtaCtl->addr.TargetId;
  6950. BOOLEAN bad_ldev;
  6951. ULONG i;
  6952. //chan = &(deviceExtension->chan[lChannel]);
  6953. if(AtaCtl->addr.Lun ||
  6954. AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
  6955. AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
  6956. chan = NULL;
  6957. bad_ldev = TRUE;
  6958. LunExt = NULL;
  6959. } else {
  6960. bad_ldev = FALSE;
  6961. lChannel = AtaCtl->addr.PathId;
  6962. chan = &(deviceExtension->chan[lChannel]);
  6963. LunExt = chan->lun[DeviceNumber];
  6964. }
  6965. KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
  6966. /* check for valid LUN */
  6967. switch (AtaCtl->hdr.ControlCode) {
  6968. case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
  6969. case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
  6970. // this would be BUS reset
  6971. if(bad_ldev &&
  6972. (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
  6973. AtaCtl->addr.TargetId != 0xff ||
  6974. AtaCtl->addr.Lun != 0
  6975. )) {
  6976. if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
  6977. DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
  6978. lChannel = AtaCtl->addr.PathId;
  6979. chan = &(deviceExtension->chan[lChannel]);
  6980. LunExt = chan->lun[DeviceNumber];
  6981. // OK
  6982. } else {
  6983. goto handle_bad_ldev;
  6984. }
  6985. } else {
  6986. lChannel = AtaCtl->addr.PathId;
  6987. chan = &(deviceExtension->chan[lChannel]);
  6988. }
  6989. break;
  6990. case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
  6991. case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
  6992. case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
  6993. case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
  6994. // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
  6995. if(bad_ldev) {
  6996. handle_bad_ldev:
  6997. KdPrint2((PRINT_PREFIX
  6998. "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
  6999. // Indicate no device found at this address.
  7000. goto reject_srb;
  7001. }
  7002. }
  7003. /* check if queueing is necessary */
  7004. switch (AtaCtl->hdr.ControlCode) {
  7005. case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
  7006. if(!LunExt->nBadBlocks) {
  7007. break;
  7008. }
  7009. goto uata_ctl_queue;
  7010. case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
  7011. if(!AtaCtl->SetMode.ApplyImmediately) {
  7012. break;
  7013. }
  7014. goto uata_ctl_queue;
  7015. case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
  7016. //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
  7017. uata_ctl_queue:
  7018. KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
  7019. PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
  7020. if(PostReq || TopLevel) {
  7021. UniataQueueRequest(chan, Srb);
  7022. AtaReq = (PATA_REQ)(Srb->SrbExtension);
  7023. AtaReq->ReqState = REQ_STATE_QUEUED;
  7024. }
  7025. if(PostReq) {
  7026. KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
  7027. status = SRB_STATUS_PENDING;
  7028. KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
  7029. goto complete_req;
  7030. }
  7031. } // end switch (AtaCtl->hdr.ControlCode)
  7032. /* process request */
  7033. switch (AtaCtl->hdr.ControlCode) {
  7034. case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
  7035. KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
  7036. if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
  7037. KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
  7038. if(AtaCtl->addr.TargetId != 0xff) {
  7039. LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
  7040. } else {
  7041. }
  7042. }
  7043. for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
  7044. AtapiStallExecution(1000 * 1000);
  7045. }
  7046. FindDevices(HwDeviceExtension,
  7047. ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
  7048. ? UNIATA_FIND_DEV_UNHIDE : 0,
  7049. AtaCtl->addr.PathId);
  7050. status = SRB_STATUS_SUCCESS;
  7051. break;
  7052. case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
  7053. KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
  7054. LunExt->DeviceFlags = 0;
  7055. if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
  7056. KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
  7057. LunExt->DeviceFlags |= DFLAGS_HIDDEN;
  7058. }
  7059. for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
  7060. AtapiStallExecution(1000 * 1000);
  7061. }
  7062. status = SRB_STATUS_SUCCESS;
  7063. break;
  7064. }
  7065. case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
  7066. KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
  7067. if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
  7068. LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
  7069. }
  7070. if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
  7071. LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
  7072. if(LunExt->LimitedTransferMode >
  7073. LunExt->OrigTransferMode) {
  7074. // check for incorrect value
  7075. LunExt->LimitedTransferMode =
  7076. LunExt->OrigTransferMode;
  7077. }
  7078. }
  7079. LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
  7080. LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
  7081. if(AtaCtl->SetMode.ApplyImmediately) {
  7082. AtapiDmaInit__(deviceExtension, LunExt);
  7083. }
  7084. /* LunExt->TransferMode =
  7085. LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
  7086. status = SRB_STATUS_SUCCESS;
  7087. break;
  7088. }
  7089. case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
  7090. KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
  7091. AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
  7092. AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
  7093. AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
  7094. status = SRB_STATUS_SUCCESS;
  7095. break;
  7096. }
  7097. case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
  7098. KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
  7099. AtaCtl->Version.Length = sizeof(GETDRVVERSION);
  7100. AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
  7101. AtaCtl->Version.VersionMn = UNIATA_VER_MN;
  7102. AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ;
  7103. AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN;
  7104. status = SRB_STATUS_SUCCESS;
  7105. break;
  7106. }
  7107. case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
  7108. KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
  7109. AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan);
  7110. if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) {
  7111. KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len,
  7112. AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)));
  7113. status = SRB_STATUS_DATA_OVERRUN;
  7114. break;
  7115. }
  7116. AtaCtl->AdapterInfo.DevID = deviceExtension->DevID;
  7117. AtaCtl->AdapterInfo.RevID = deviceExtension->RevID;
  7118. AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
  7119. AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
  7120. AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex;
  7121. AtaCtl->AdapterInfo.Channel = deviceExtension->Channel;
  7122. AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
  7123. AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
  7124. AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/
  7125. AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
  7126. AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev;
  7127. AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
  7128. AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags;
  7129. AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
  7130. AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
  7131. AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
  7132. AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
  7133. AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
  7134. AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
  7135. AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
  7136. if(deviceExtension->FullDevName) {
  7137. strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
  7138. }
  7139. AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
  7140. AtaCtl->AdapterInfo.LunInfoValid = FALSE;
  7141. RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
  7142. status = SRB_STATUS_SUCCESS;
  7143. break;
  7144. }
  7145. case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
  7146. KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
  7147. ForgetBadBlocks(LunExt);
  7148. status = SRB_STATUS_SUCCESS;
  7149. break;
  7150. }
  7151. case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
  7152. KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
  7153. if(bad_ldev) {
  7154. goto do_bus_reset;
  7155. } else {
  7156. UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
  7157. }
  7158. status = SRB_STATUS_SUCCESS;
  7159. break;
  7160. }
  7161. default :
  7162. KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
  7163. AtaCtl->hdr.ControlCode ));
  7164. status = SRB_STATUS_INVALID_REQUEST;
  7165. break;
  7166. }
  7167. } else {
  7168. KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
  7169. ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
  7170. "SCSIDISK", "-UNIATA-"));
  7171. status = SRB_STATUS_INVALID_REQUEST;
  7172. break;
  7173. }
  7174. break;
  7175. } // end SRB_FUNCTION_IO_CONTROL
  7176. default:
  7177. KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
  7178. // Indicate unsupported command.
  7179. status = SRB_STATUS_INVALID_REQUEST;
  7180. // break;
  7181. } // end switch
  7182. complete_req:
  7183. PathId = Srb->PathId;
  7184. TargetId = Srb->TargetId;
  7185. Lun = Srb->Lun;
  7186. if (status != SRB_STATUS_PENDING) {
  7187. KdPrint2((PRINT_PREFIX
  7188. "AtapiStartIo: Srb %#x complete with status %#x\n",
  7189. Srb,
  7190. status));
  7191. // Set status in SRB.
  7192. Srb->SrbStatus = (UCHAR)status;
  7193. AtapiDmaDBSync(chan, Srb);
  7194. UniataRemoveRequest(chan, Srb);
  7195. // Indicate command complete.
  7196. ScsiPortNotification(RequestComplete,
  7197. deviceExtension,
  7198. Srb);
  7199. // Remove current Srb & get next one
  7200. if((Srb = UniataGetCurRequest(chan))) {
  7201. AtaReq = (PATA_REQ)(Srb->SrbExtension);
  7202. if(AtaReq->ReqState > REQ_STATE_QUEUED) {
  7203. // current request is under precessing, thus
  7204. // we should do nothing here
  7205. Srb = NULL;
  7206. }
  7207. }
  7208. if(!chan) {
  7209. //ASSERT(TopLevel);
  7210. }
  7211. }
  7212. KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
  7213. } while (Srb && (status != SRB_STATUS_PENDING));
  7214. KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
  7215. // Indicate ready for next request.
  7216. ScsiPortNotification(NextRequest,
  7217. deviceExtension,
  7218. NULL);
  7219. ScsiPortNotification(NextLuRequest,
  7220. deviceExtension,
  7221. PathId,
  7222. TargetId,
  7223. Lun);
  7224. return TRUE;
  7225. } // end AtapiStartIo__()
  7226. void
  7227. NTAPI
  7228. UniataInitAtaCommands()
  7229. {
  7230. int i;
  7231. UCHAR command;
  7232. UCHAR flags;
  7233. KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
  7234. for(i=0; i<256; i++) {
  7235. flags = 0;
  7236. command = i;
  7237. KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
  7238. switch(command) {
  7239. case IDE_COMMAND_READ_DMA48:
  7240. case IDE_COMMAND_READ_DMA_Q48:
  7241. case IDE_COMMAND_READ_STREAM_DMA48:
  7242. case IDE_COMMAND_READ_STREAM48:
  7243. case IDE_COMMAND_WRITE_DMA48:
  7244. case IDE_COMMAND_WRITE_DMA_Q48:
  7245. case IDE_COMMAND_READ_DMA_Q:
  7246. case IDE_COMMAND_READ_DMA:
  7247. case IDE_COMMAND_WRITE_DMA:
  7248. case IDE_COMMAND_WRITE_DMA_Q:
  7249. case IDE_COMMAND_WRITE_STREAM_DMA48:
  7250. case IDE_COMMAND_WRITE_STREAM48:
  7251. case IDE_COMMAND_WRITE_FUA_DMA48:
  7252. case IDE_COMMAND_WRITE_FUA_DMA_Q48:
  7253. case IDE_COMMAND_READ_LOG_DMA48:
  7254. case IDE_COMMAND_WRITE_LOG_DMA48:
  7255. case IDE_COMMAND_TRUSTED_RCV_DMA:
  7256. case IDE_COMMAND_TRUSTED_SEND_DMA:
  7257. KdPrint2((PRINT_PREFIX "DMA "));
  7258. flags |= ATA_CMD_FLAG_DMA;
  7259. }
  7260. switch(command) {
  7261. case IDE_COMMAND_READ48:
  7262. case IDE_COMMAND_READ_DMA48:
  7263. case IDE_COMMAND_READ_DMA_Q48:
  7264. case IDE_COMMAND_READ_MUL48:
  7265. case IDE_COMMAND_READ_STREAM_DMA48:
  7266. case IDE_COMMAND_READ_STREAM48:
  7267. case IDE_COMMAND_WRITE48:
  7268. case IDE_COMMAND_WRITE_DMA48:
  7269. case IDE_COMMAND_WRITE_DMA_Q48:
  7270. case IDE_COMMAND_WRITE_MUL48:
  7271. case IDE_COMMAND_WRITE_STREAM_DMA48:
  7272. case IDE_COMMAND_WRITE_STREAM48:
  7273. case IDE_COMMAND_WRITE_FUA_DMA48:
  7274. case IDE_COMMAND_WRITE_FUA_DMA_Q48:
  7275. case IDE_COMMAND_WRITE_MUL_FUA48:
  7276. case IDE_COMMAND_FLUSH_CACHE48:
  7277. case IDE_COMMAND_VERIFY48:
  7278. KdPrint2((PRINT_PREFIX "48 "));
  7279. flags |= ATA_CMD_FLAG_48;
  7280. /* FALL THROUGH */
  7281. case IDE_COMMAND_READ:
  7282. case IDE_COMMAND_READ_MULTIPLE:
  7283. case IDE_COMMAND_READ_DMA:
  7284. case IDE_COMMAND_READ_DMA_Q:
  7285. case IDE_COMMAND_WRITE:
  7286. case IDE_COMMAND_WRITE_MULTIPLE:
  7287. case IDE_COMMAND_WRITE_DMA:
  7288. case IDE_COMMAND_WRITE_DMA_Q:
  7289. case IDE_COMMAND_FLUSH_CACHE:
  7290. case IDE_COMMAND_VERIFY:
  7291. KdPrint2((PRINT_PREFIX "LBA "));
  7292. flags |= ATA_CMD_FLAG_LBAIOsupp;
  7293. }
  7294. flags |= ATA_CMD_FLAG_48supp;
  7295. switch (command) {
  7296. case IDE_COMMAND_READ:
  7297. command = IDE_COMMAND_READ48; break;
  7298. case IDE_COMMAND_READ_MULTIPLE:
  7299. command = IDE_COMMAND_READ_MUL48; break;
  7300. case IDE_COMMAND_READ_DMA:
  7301. command = IDE_COMMAND_READ_DMA48; break;
  7302. case IDE_COMMAND_READ_DMA_Q:
  7303. command = IDE_COMMAND_READ_DMA_Q48; break;
  7304. case IDE_COMMAND_WRITE:
  7305. command = IDE_COMMAND_WRITE48; break;
  7306. case IDE_COMMAND_WRITE_MULTIPLE:
  7307. command = IDE_COMMAND_WRITE_MUL48; break;
  7308. case IDE_COMMAND_WRITE_DMA:
  7309. command = IDE_COMMAND_WRITE_DMA48; break;
  7310. case IDE_COMMAND_WRITE_DMA_Q:
  7311. command = IDE_COMMAND_WRITE_DMA_Q48; break;
  7312. case IDE_COMMAND_FLUSH_CACHE:
  7313. command = IDE_COMMAND_FLUSH_CACHE48; break;
  7314. // case IDE_COMMAND_READ_NATIVE_SIZE:
  7315. // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
  7316. case IDE_COMMAND_SET_NATIVE_SIZE:
  7317. command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
  7318. case IDE_COMMAND_VERIFY:
  7319. command = IDE_COMMAND_VERIFY48; break;
  7320. default:
  7321. KdPrint2((PRINT_PREFIX "!28->48 "));
  7322. flags &= ~ATA_CMD_FLAG_48supp;
  7323. }
  7324. KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
  7325. AtaCommands48[i] = command;
  7326. AtaCommandFlags[i] = flags;
  7327. }
  7328. } // end UniataInitAtaCommands()
  7329. /*++
  7330. Routine Description:
  7331. Installable driver initialization entry point for system.
  7332. Arguments:
  7333. Driver Object
  7334. Return Value:
  7335. Status from ScsiPortInitialize()
  7336. --*/
  7337. extern "C"
  7338. ULONG
  7339. NTAPI
  7340. DriverEntry(
  7341. IN PVOID DriverObject,
  7342. IN PVOID Argument2
  7343. )
  7344. {
  7345. HW_INITIALIZATION_DATA_COMMON hwInitializationData;
  7346. ULONG adapterCount;
  7347. ULONG i, c, alt;
  7348. ULONG statusToReturn, newStatus;
  7349. PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
  7350. BOOLEAN ReEnter = FALSE;
  7351. WCHAR a;
  7352. #ifndef USE_REACTOS_DDK
  7353. NTSTATUS status;
  7354. #endif
  7355. PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
  7356. BOOLEAN PrimaryClaimed = FALSE;
  7357. BOOLEAN SecondaryClaimed = FALSE;
  7358. LARGE_INTEGER t0, t1;
  7359. Connect_DbgPrint();
  7360. KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
  7361. a = (WCHAR)strlen(ver_string);
  7362. g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
  7363. if(g_opt_Verbose) {
  7364. _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
  7365. }
  7366. if(!SavedDriverObject) {
  7367. SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
  7368. #ifdef USE_REACTOS_DDK
  7369. KdPrint(("UniATA Init: OS should be ReactOS\n"));
  7370. MajorVersion=0x04;
  7371. MinorVersion=0x01;
  7372. BuildNumber=1;
  7373. #else
  7374. // we are here for the 1st time
  7375. // init CrossNT and get OS version
  7376. if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
  7377. KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
  7378. //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
  7379. return status;
  7380. }
  7381. #endif // USE_REACTOS_DDK
  7382. KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion, MinorVersion, BuildNumber));
  7383. KeQuerySystemTime(&t0);
  7384. do {
  7385. KeQuerySystemTime(&t1);
  7386. } while(t0.QuadPart == t1.QuadPart);
  7387. t0=t1;
  7388. g_Perf=0;
  7389. do {
  7390. KeQuerySystemTime(&t1);
  7391. g_Perf++;
  7392. } while(t0.QuadPart == t1.QuadPart);
  7393. g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
  7394. KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
  7395. } else {
  7396. KdPrint(("UniATA Init: ReEnter\n"));
  7397. ReEnter = TRUE;
  7398. }
  7399. // (re)read bad block list
  7400. InitBadBlocks(NULL);
  7401. if(!ReEnter) {
  7402. // init ATA command translation table
  7403. UniataInitAtaCommands();
  7404. // get registry path to settings
  7405. RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
  7406. SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
  7407. SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
  7408. SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
  7409. RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
  7410. SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
  7411. }
  7412. if(WinVer_Id() >= WinVer_2k) {
  7413. if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
  7414. KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
  7415. WinVer_WDM_Model = TRUE;
  7416. }
  7417. if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
  7418. KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
  7419. WinVer_WDM_Model = TRUE;
  7420. }
  7421. }
  7422. SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
  7423. ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
  7424. #ifdef _DEBUG
  7425. g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
  7426. #endif //_DEBUG
  7427. statusToReturn = 0xffffffff;
  7428. // Zero out structure.
  7429. RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
  7430. // Set size of hwInitializationData.
  7431. hwInitializationData.comm.HwInitializationDataSize =
  7432. sizeof(hwInitializationData.comm) +
  7433. // sizeof(hwInitializationData.nt4) +
  7434. ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
  7435. KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
  7436. // Set entry points.
  7437. hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
  7438. hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
  7439. hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
  7440. hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
  7441. // Specify size of extensions.
  7442. hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  7443. hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
  7444. hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ);
  7445. // Indicate PIO device.
  7446. hwInitializationData.comm.MapBuffers = TRUE;
  7447. // Set PnP-specific API
  7448. if(WinVer_Id() > WinVer_NT) {
  7449. KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
  7450. hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
  7451. KdPrint(("set AtapiAdapterControl() ptr\n"));
  7452. hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
  7453. }
  7454. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
  7455. if(!ReEnter) {
  7456. g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
  7457. if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
  7458. g_opt_VirtualMachine = 0;
  7459. }
  7460. if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
  7461. g_opt_VirtualMachine = VM_VBOX;
  7462. }
  7463. // Pre-scan PCI bus, also check if we are under VM
  7464. UniataEnumBusMasterController(DriverObject, Argument2);
  7465. switch(g_opt_VirtualMachine) {
  7466. case VM_VBOX:
  7467. // adjust options for VirtualBox
  7468. g_opt_WaitBusyCount = 20000;
  7469. g_opt_WaitBusyDelay = 150;
  7470. g_opt_WaitDrqDelay = 100;
  7471. g_opt_AtapiSendDisableIntr = 0;
  7472. g_opt_AtapiDmaRawRead = FALSE;
  7473. break;
  7474. }
  7475. g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
  7476. g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
  7477. g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
  7478. g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
  7479. g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
  7480. }
  7481. // Look for legacy ISA-bridged PCI IDE controller (onboard)
  7482. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
  7483. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
  7484. for (i=0; i <BMListLen; i++) {
  7485. if(!BMList[i].MasterDev) {
  7486. KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
  7487. break;
  7488. }
  7489. if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
  7490. break;
  7491. }
  7492. if(ReEnter) {
  7493. KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
  7494. if(BMList[i].ChanInitOk & 0x03) {
  7495. KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
  7496. statusToReturn =
  7497. newStatus = STATUS_SUCCESS;
  7498. }
  7499. continue;
  7500. }
  7501. BMList[i].AltInitMasterDev = (UCHAR)0xff;
  7502. if(GlobalConfig->AtDiskPrimaryAddressClaimed)
  7503. PrimaryClaimed = TRUE;
  7504. if(GlobalConfig->AtDiskSecondaryAddressClaimed)
  7505. SecondaryClaimed = TRUE;
  7506. if(g_opt_Verbose) {
  7507. _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
  7508. }
  7509. for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
  7510. for(c=0; c<2; c++) {
  7511. if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
  7512. break;
  7513. }
  7514. if(c==0) {
  7515. if(PrimaryClaimed) {
  7516. KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
  7517. continue;
  7518. }
  7519. } else
  7520. if(c==1) {
  7521. if(SecondaryClaimed) {
  7522. KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
  7523. continue;
  7524. }
  7525. }
  7526. if((WinVer_Id() < WinVer_2k)) {
  7527. // do not even try if already claimed
  7528. if(c==0) {
  7529. GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
  7530. } else
  7531. if(c==1) {
  7532. GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
  7533. }
  7534. }
  7535. if(!WinVer_WDM_Model) {
  7536. hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
  7537. } else {
  7538. // in WDM model things are different....
  7539. hwInitializationData.comm.HwFindAdapter = (c == 0) ?
  7540. UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
  7541. }
  7542. hwInitializationData.comm.NumberOfAccessRanges = 6;
  7543. hwInitializationData.comm.AdapterInterfaceType = Isa;
  7544. if(!WinVer_WDM_Model) {
  7545. BMList[i].channel = (UCHAR)c;
  7546. }
  7547. KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
  7548. newStatus = ScsiPortInitialize(DriverObject,
  7549. Argument2,
  7550. &hwInitializationData.comm,
  7551. (PVOID)(i | (alt ? 0x80000000 : 0)));
  7552. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
  7553. if (newStatus < statusToReturn) {
  7554. statusToReturn = newStatus;
  7555. }
  7556. if (newStatus == STATUS_SUCCESS) {
  7557. BMList[i].ChanInitOk |= 0x01 << c;
  7558. /*
  7559. if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
  7560. c = 1; // this will break our for()
  7561. BMList[i].ChanInitOk |= 0x01 << c;
  7562. }
  7563. */
  7564. }
  7565. }
  7566. if(WinVer_Id() >= WinVer_2k) {
  7567. // the following doesn't work under higher OSes
  7568. KdPrint2((PRINT_PREFIX "make still one attempt\n"));
  7569. continue;
  7570. }
  7571. if(BMList[i].ChanInitOk & 0x03) {
  7572. // under NT we receive status immediately, so
  7573. // we can omit alternative init method id STATUS_SUCCESS returned
  7574. KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
  7575. break;
  7576. }
  7577. // if (WinVer_Id() == WinVer_NT) and some error occured
  7578. // try alternative init method
  7579. } // for(alt...)
  7580. #if 0
  7581. if(WinVer_WDM_Model) {
  7582. hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
  7583. hwInitializationData.comm.NumberOfAccessRanges = 5;
  7584. hwInitializationData.comm.AdapterInterfaceType = PCIBus;
  7585. hwInitializationData.comm.VendorId = BMList[i].VendorId;
  7586. hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
  7587. hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
  7588. hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
  7589. //BMList[i].channel = 0/*(UCHAR)c*/;
  7590. KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
  7591. hwInitializationData.comm.VendorId,
  7592. hwInitializationData.comm.DeviceId));
  7593. newStatus = ScsiPortInitialize(DriverObject,
  7594. Argument2,
  7595. &hwInitializationData.comm,
  7596. (PVOID)i);
  7597. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
  7598. }
  7599. #endif //0
  7600. if(g_opt_Verbose) {
  7601. if(BMList[i].ChanInitOk & 0x03) {
  7602. _PrintNtConsole(" OK\n");
  7603. } else {
  7604. _PrintNtConsole(" failed\n");
  7605. }
  7606. }
  7607. }
  7608. /* KeBugCheckEx(0xc000000e,
  7609. (i << 16) | BMList[0].ChanInitOk,
  7610. c,
  7611. newStatus, statusToReturn);*/
  7612. // Look for PCI IDE controller
  7613. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
  7614. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
  7615. for (; i <BMListLen; i++) {
  7616. if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
  7617. break;
  7618. }
  7619. /* if(BMList[i].MasterDev)
  7620. continue;*/
  7621. if(g_opt_Verbose) {
  7622. _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
  7623. BMList[i].VendorId, BMList[i].DeviceId,
  7624. BMList[i].busNumber,
  7625. BMList[i].slotNumber % PCI_MAX_FUNCTION,
  7626. (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
  7627. }
  7628. hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
  7629. hwInitializationData.comm.NumberOfAccessRanges = 6;
  7630. hwInitializationData.comm.AdapterInterfaceType = PCIBus;
  7631. hwInitializationData.comm.VendorId = BMList[i].VendorId;
  7632. hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
  7633. hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
  7634. hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
  7635. BMList[i].channel = 0/*(UCHAR)c*/;
  7636. KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
  7637. hwInitializationData.comm.VendorId,
  7638. hwInitializationData.comm.DeviceId));
  7639. newStatus = ScsiPortInitialize(DriverObject,
  7640. Argument2,
  7641. &hwInitializationData.comm,
  7642. (PVOID)i);
  7643. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
  7644. if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
  7645. // Note: this is actually a BUG in scsiport.sys
  7646. // It stops scanning PCI bus when reaches empty PCI Function inside Slot
  7647. // However, this PCI Slot may have higher non-empty Functions
  7648. // UniATA will perform all staff instead of ScsiPort under NT,
  7649. // but for ReactOS it is better to patch ScsiPort.
  7650. KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
  7651. hwInitializationData.comm.AdapterInterfaceType = Isa;
  7652. newStatus = ScsiPortInitialize(DriverObject,
  7653. Argument2,
  7654. &hwInitializationData.comm,
  7655. (PVOID)(i | 0x80000000));
  7656. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
  7657. }
  7658. if (newStatus < statusToReturn)
  7659. statusToReturn = newStatus;
  7660. if(g_opt_Verbose) {
  7661. if(newStatus == STATUS_SUCCESS) {
  7662. _PrintNtConsole(" OK\n");
  7663. } else {
  7664. _PrintNtConsole(" failed\n");
  7665. }
  7666. }
  7667. }
  7668. /* KeBugCheckEx(0xc000000e,
  7669. i,
  7670. c,
  7671. newStatus, statusToReturn);*/
  7672. // --------------
  7673. hwInitializationData.comm.VendorId = 0;
  7674. hwInitializationData.comm.VendorIdLength = 0;
  7675. hwInitializationData.comm.DeviceId = 0;
  7676. hwInitializationData.comm.DeviceIdLength = 0;
  7677. // The adapter count is used by the find adapter routine to track how
  7678. // which adapter addresses have been tested.
  7679. // Indicate 2 access ranges and reset FindAdapter.
  7680. hwInitializationData.comm.NumberOfAccessRanges = 2;
  7681. hwInitializationData.comm.HwFindAdapter = AtapiFindController;
  7682. if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
  7683. // Indicate ISA bustype.
  7684. hwInitializationData.comm.AdapterInterfaceType = Isa;
  7685. adapterCount = 0;
  7686. // Call initialization for ISA bustype.
  7687. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
  7688. newStatus = ScsiPortInitialize(DriverObject,
  7689. Argument2,
  7690. &hwInitializationData.comm,
  7691. &adapterCount);
  7692. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
  7693. if (newStatus < statusToReturn)
  7694. statusToReturn = newStatus;
  7695. }
  7696. if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
  7697. // Set up for MCA
  7698. KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
  7699. hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
  7700. adapterCount = 0;
  7701. newStatus = ScsiPortInitialize(DriverObject,
  7702. Argument2,
  7703. &hwInitializationData.comm,
  7704. &adapterCount);
  7705. KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
  7706. if (newStatus < statusToReturn)
  7707. statusToReturn = newStatus;
  7708. }
  7709. InDriverEntry = FALSE;
  7710. KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
  7711. return statusToReturn;
  7712. } // end DriverEntry()
  7713. PSCSI_REQUEST_BLOCK
  7714. NTAPI
  7715. BuildMechanismStatusSrb(
  7716. IN PVOID HwDeviceExtension,
  7717. IN PSCSI_REQUEST_BLOCK Srb
  7718. )
  7719. {
  7720. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  7721. PSCSI_REQUEST_BLOCK srb;
  7722. PCDB cdb;
  7723. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  7724. srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
  7725. RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
  7726. srb->PathId = (UCHAR)(Srb->PathId);
  7727. srb->TargetId = (UCHAR)(Srb->TargetId);
  7728. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  7729. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  7730. // Set flags to disable synchronous negociation.
  7731. srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  7732. // Set timeout to 4 seconds.
  7733. srb->TimeOutValue = 4;
  7734. srb->CdbLength = 6;
  7735. srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
  7736. srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
  7737. srb->SrbExtension = AtaReq;
  7738. // Set CDB operation code.
  7739. cdb = (PCDB)srb->Cdb;
  7740. cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
  7741. cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
  7742. return srb;
  7743. } // end BuildMechanismStatusSrb()
  7744. #endif //UNIATA_CORE
  7745. PSCSI_REQUEST_BLOCK
  7746. NTAPI
  7747. BuildRequestSenseSrb (
  7748. IN PVOID HwDeviceExtension,
  7749. IN PSCSI_REQUEST_BLOCK Srb
  7750. )
  7751. {
  7752. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  7753. PSCSI_REQUEST_BLOCK srb;
  7754. PCDB cdb;
  7755. PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
  7756. srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
  7757. RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
  7758. srb->PathId = (UCHAR)(Srb->PathId);
  7759. srb->TargetId = (UCHAR)(Srb->TargetId);
  7760. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  7761. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  7762. // Set flags to disable synchronous negociation.
  7763. srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  7764. // Set timeout to 2 seconds.
  7765. srb->TimeOutValue = 4;
  7766. srb->CdbLength = 6;
  7767. srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
  7768. srb->DataTransferLength = sizeof(SENSE_DATA);
  7769. srb->SrbExtension = AtaReq;
  7770. // Set CDB operation code.
  7771. cdb = (PCDB)srb->Cdb;
  7772. cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
  7773. cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
  7774. return srb;
  7775. } // end BuildRequestSenseSrb()
  7776. #ifndef UNIATA_CORE
  7777. ULONG
  7778. NTAPI
  7779. AtapiRegCheckDevLunValue(
  7780. IN PVOID HwDeviceExtension,
  7781. IN PCWCH NamePrefix,
  7782. IN ULONG chan,
  7783. IN ULONG dev,
  7784. IN PCWSTR Name,
  7785. IN ULONG Default
  7786. )
  7787. {
  7788. WCHAR namex[160];
  7789. ULONG val = Default;
  7790. val = AtapiRegCheckParameterValue(
  7791. HwDeviceExtension, NamePrefix, Name, val);
  7792. if(chan != CHAN_NOT_SPECIFIED) {
  7793. swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
  7794. val = AtapiRegCheckParameterValue(
  7795. HwDeviceExtension, namex, Name, val);
  7796. if(dev != DEVNUM_NOT_SPECIFIED) {
  7797. swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
  7798. val = AtapiRegCheckParameterValue(
  7799. HwDeviceExtension, namex, Name, val);
  7800. }
  7801. }
  7802. return val;
  7803. } // end AtapiRegCheckDevLunValue()
  7804. ULONG
  7805. NTAPI
  7806. EncodeVendorStr(
  7807. OUT PWCHAR Buffer,
  7808. IN PUCHAR Str,
  7809. IN ULONG Length
  7810. )
  7811. {
  7812. ULONG i,j;
  7813. WCHAR a;
  7814. for(i=0, j=0; i<Length; i++, j++) {
  7815. // fix byte-order
  7816. a = Str[i ^ 0x01];
  7817. if(!a) {
  7818. Buffer[j] = 0;
  7819. return j;
  7820. } else
  7821. if(a == ' ') {
  7822. Buffer[j] = '_';
  7823. } else
  7824. if((a == '_') ||
  7825. (a == '#') ||
  7826. (a == '\\') ||
  7827. (a == '\"') ||
  7828. (a == '\'') ||
  7829. (a < ' ') ||
  7830. (a >= 127)) {
  7831. Buffer[j] = '#';
  7832. j++;
  7833. swprintf(Buffer+j, L"%2.2x", a);
  7834. j++;
  7835. } else {
  7836. Buffer[j] = a;
  7837. }
  7838. }
  7839. Buffer[j] = 0;
  7840. return j;
  7841. } // end EncodeVendorStr()
  7842. ULONG
  7843. NTAPI
  7844. AtapiRegCheckDevValue(
  7845. IN PVOID HwDeviceExtension,
  7846. IN ULONG chan,
  7847. IN ULONG dev,
  7848. IN PCWSTR Name,
  7849. IN ULONG Default
  7850. )
  7851. {
  7852. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  7853. // WCHAR name0[11];
  7854. // WCHAR name1[11+4+5];
  7855. // WCHAR name2[11+4+4+10];
  7856. // WCHAR name3[11+4+4+5+20];
  7857. // WCHAR name3[11+4+4+5+20+1];
  7858. WCHAR namex[160];
  7859. WCHAR namev[16];
  7860. WCHAR named[16];
  7861. WCHAR names[20];
  7862. IN ULONG VendorID;
  7863. IN ULONG DeviceID;
  7864. IN ULONG SlotNumber;
  7865. ULONG val = Default;
  7866. KdPrint(( " Parameter %ws\n", Name));
  7867. if(deviceExtension) {
  7868. VendorID = deviceExtension->DevID & 0xffff;
  7869. DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
  7870. SlotNumber = deviceExtension->slotNumber;
  7871. } else {
  7872. VendorID = 0xffff;
  7873. DeviceID = 0xffff;
  7874. SlotNumber = 0xffffffff;
  7875. }
  7876. val = AtapiRegCheckDevLunValue(
  7877. HwDeviceExtension, L"Parameters", chan, dev, Name, val);
  7878. if(deviceExtension) {
  7879. if(deviceExtension->AdapterInterfaceType == PCIBus) {
  7880. // PCI
  7881. swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
  7882. swprintf(namex, L"Parameters%s", namev);
  7883. val = AtapiRegCheckDevLunValue(
  7884. HwDeviceExtension, namex, chan, dev, Name, val);
  7885. swprintf(namev, L"\\Ven_%4.4x", VendorID);
  7886. swprintf(named, L"\\Dev_%4.4x", DeviceID);
  7887. swprintf(names, L"\\Slot_%8.8x", SlotNumber);
  7888. swprintf(namex, L"Parameters%s", namev);
  7889. val = AtapiRegCheckDevLunValue(
  7890. HwDeviceExtension, namex, chan, dev, Name, val);
  7891. swprintf(namex, L"Parameters%s%s", namev, named);
  7892. val = AtapiRegCheckDevLunValue(
  7893. HwDeviceExtension, namex, chan, dev, Name, val);
  7894. swprintf(namex, L"Parameters%s%s%s", namev, named, names);
  7895. val = AtapiRegCheckDevLunValue(
  7896. HwDeviceExtension, namex, chan, dev, Name, val);
  7897. } else
  7898. if(deviceExtension->AdapterInterfaceType == Isa) {
  7899. // Isa
  7900. swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
  7901. swprintf(namex, L"Parameters%s", namev);
  7902. val = AtapiRegCheckDevLunValue(
  7903. HwDeviceExtension, namex, chan, dev, Name, val);
  7904. swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
  7905. swprintf(namex, L"Parameters%s", namev);
  7906. val = AtapiRegCheckDevLunValue(
  7907. HwDeviceExtension, namex, chan, dev, Name, val);
  7908. } else
  7909. if(deviceExtension->AdapterInterfaceType == MicroChannel) {
  7910. // MicroChannel
  7911. swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
  7912. swprintf(namex, L"Parameters%s", namev);
  7913. val = AtapiRegCheckDevLunValue(
  7914. HwDeviceExtension, namex, chan, dev, Name, val);
  7915. swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
  7916. swprintf(namex, L"Parameters%s", namev);
  7917. val = AtapiRegCheckDevLunValue(
  7918. HwDeviceExtension, namex, chan, dev, Name, val);
  7919. }
  7920. }
  7921. KdPrint(( " Parameter %ws = %#x\n", Name, val));
  7922. return val;
  7923. } // end AtapiRegCheckDevValue()
  7924. /*
  7925. The user must specify that Xxx is to run on the platform
  7926. by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
  7927. Services\UniATA\Xxx:REG_DWORD:Zzz.
  7928. The user can override the global setting to enable or disable Xxx on a
  7929. specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
  7930. CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
  7931. If this registry value does not exist or contains the value zero then
  7932. the timer to check for media change does not run.
  7933. Arguments:
  7934. RegistryPath - pointer to the unicode string inside
  7935. ...\CurrentControlSet\Services\UniATA
  7936. DeviceNumber - The number of the HBA device object
  7937. Returns: Registry Key value
  7938. */
  7939. ULONG
  7940. NTAPI
  7941. AtapiRegCheckParameterValue(
  7942. IN PVOID HwDeviceExtension,
  7943. IN PCWSTR PathSuffix,
  7944. IN PCWSTR Name,
  7945. IN ULONG Default
  7946. )
  7947. {
  7948. #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
  7949. // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  7950. NTSTATUS status;
  7951. LONG zero = Default;
  7952. RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
  7953. // LONG tmp = 0;
  7954. LONG doRun = Default;
  7955. PUNICODE_STRING RegistryPath = &SavedRegPath;
  7956. UNICODE_STRING paramPath;
  7957. // <SavedRegPath>\<PathSuffix> -> <Name>
  7958. // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
  7959. // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
  7960. paramPath.Length = 0;
  7961. paramPath.MaximumLength = RegistryPath->Length +
  7962. (wcslen(PathSuffix)+2)*sizeof(WCHAR);
  7963. paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
  7964. if(!paramPath.Buffer) {
  7965. KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
  7966. return Default;
  7967. }
  7968. RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
  7969. RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
  7970. RtlAppendUnicodeToString(&paramPath, L"\\");
  7971. RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
  7972. // Check for the Xxx value.
  7973. RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
  7974. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  7975. parameters[0].Name = REGRTL_STR_PTYPE Name;
  7976. parameters[0].EntryContext = &doRun;
  7977. parameters[0].DefaultType = REG_DWORD;
  7978. parameters[0].DefaultData = &zero;
  7979. parameters[0].DefaultLength = sizeof(ULONG);
  7980. status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
  7981. paramPath.Buffer, parameters, NULL, NULL);
  7982. KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
  7983. ExFreePool(paramPath.Buffer);
  7984. if(!NT_SUCCESS(status)) {
  7985. doRun = Default;
  7986. }
  7987. return doRun;
  7988. #undef ITEMS_TO_QUERY
  7989. } // end AtapiRegCheckParameterValue()
  7990. SCSI_ADAPTER_CONTROL_STATUS
  7991. NTAPI
  7992. AtapiAdapterControl(
  7993. IN PVOID HwDeviceExtension,
  7994. IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
  7995. IN PVOID Parameters
  7996. )
  7997. {
  7998. PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
  7999. PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
  8000. ULONG numberChannels = deviceExtension->NumberChannels;
  8001. ULONG c;
  8002. NTSTATUS status;
  8003. KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
  8004. switch(ControlType) {
  8005. case ScsiQuerySupportedControlTypes: {
  8006. BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
  8007. TRUE, // ScsiQuerySupportedControlTypes
  8008. TRUE, // ScsiStopAdapter
  8009. TRUE, // ScsiRestartAdapter
  8010. FALSE, // ScsiSetBootConfig
  8011. FALSE // ScsiSetRunningConfig
  8012. };
  8013. ULONG lim = ScsiAdapterControlMax;
  8014. ULONG i;
  8015. pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
  8016. if(pControlTypeList->MaxControlType < lim) {
  8017. lim = pControlTypeList->MaxControlType;
  8018. }
  8019. for(i = 0; i < lim; i++) {
  8020. pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
  8021. }
  8022. break;
  8023. }
  8024. case ScsiStopAdapter: {
  8025. KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
  8026. // Shut down all interrupts on the adapter. They'll get re-enabled
  8027. // by the initialization routines.
  8028. for (c = 0; c < numberChannels; c++) {
  8029. AtapiResetController(deviceExtension, c);
  8030. AtapiDisableInterrupts(deviceExtension, c);
  8031. }
  8032. if(deviceExtension->AdapterInterfaceType == PCIBus) {
  8033. // we must never get here for non-PCI
  8034. status = UniataDisconnectIntr2(HwDeviceExtension);
  8035. BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
  8036. }
  8037. break;
  8038. }
  8039. case ScsiRestartAdapter: {
  8040. KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
  8041. // Enable all the interrupts on the adapter while port driver call
  8042. // for power up an HBA that was shut down for power management
  8043. AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
  8044. status = UniataConnectIntr2(HwDeviceExtension);
  8045. for (c = 0; c < numberChannels; c++) {
  8046. AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
  8047. FindDevices(HwDeviceExtension, 0, c);
  8048. AtapiEnableInterrupts(deviceExtension, c);
  8049. AtapiHwInitialize__(deviceExtension, c);
  8050. }
  8051. if(deviceExtension->Isr2DevObj) {
  8052. // we must never get here for non-PCI
  8053. BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
  8054. }
  8055. break;
  8056. }
  8057. default: {
  8058. KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
  8059. return ScsiAdapterControlUnsuccessful;
  8060. }
  8061. }
  8062. return ScsiAdapterControlSuccess;
  8063. } // end AtapiAdapterControl()
  8064. #endif //UNIATA_CORE
  8065. extern "C"
  8066. NTHALAPI
  8067. VOID
  8068. NTAPI
  8069. HalDisplayString (
  8070. PUCHAR String
  8071. );
  8072. extern "C"
  8073. VOID
  8074. _cdecl
  8075. _PrintNtConsole(
  8076. PCCH DebugMessage,
  8077. ...
  8078. )
  8079. {
  8080. int len;
  8081. UCHAR dbg_print_tmp_buff[512];
  8082. // UNICODE_STRING msgBuff;
  8083. va_list ap;
  8084. va_start(ap, DebugMessage);
  8085. len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
  8086. dbg_print_tmp_buff[511] = 0;
  8087. KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
  8088. HalDisplayString(dbg_print_tmp_buff);
  8089. va_end(ap);
  8090. } // end PrintNtConsole()