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

6618 lines
188 KiB

  1. /*++
  2. Copyright (C) 1993-99 Microsoft Corporation
  3. Module Name:
  4. atapi.c
  5. Abstract:
  6. This is the miniport driver for IDE controllers.
  7. Author:
  8. Mike Glass (MGlass)
  9. Chuck Park (ChuckP)
  10. Joe Dai (joedai)
  11. Environment:
  12. kernel mode only
  13. Notes:
  14. Revision History:
  15. george C.(georgioc) Merged wtih Compaq code to make miniport driver function
  16. with the 120MB floppy drive
  17. Added support for MEDIA STATUS NOTIFICATION
  18. Added support for SCSIOP_START_STOP_UNIT (eject media)
  19. joedai PCI Bus Master IDE Support
  20. ATA Passthrough (temporary solution)
  21. LBA with ATA drive > 8G
  22. PCMCIA IDE support
  23. Native mode support
  24. --*/
  25. #include "ideport.h"
  26. #if DBG
  27. ULONG __DebugForceTimeout = 0;
  28. static ULONG __DebugResetCounter = 0;
  29. #endif // DBG
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text(NONPAGE, InitHwExtWithIdentify)
  32. #endif // ALLOC_PRAGMA
  33. BOOLEAN
  34. IssueIdentify(
  35. PIDE_REGISTERS_1 CmdBaseAddr,
  36. PIDE_REGISTERS_2 CtrlBaseAddr,
  37. IN ULONG DeviceNumber,
  38. IN UCHAR Command,
  39. IN BOOLEAN InterruptOff,
  40. OUT PIDENTIFY_DATA IdentifyData
  41. )
  42. /*++
  43. Routine Description:
  44. Issue IDENTIFY command to a device.
  45. Arguments:
  46. HwDeviceExtension - HBA miniport driver's adapter data storage
  47. DeviceNumber - Indicates which device.
  48. Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
  49. InterruptOff - should leave interrupt disabled
  50. Return Value:
  51. TRUE if all goes well.
  52. --*/
  53. {
  54. ULONG waitCount = 20000;
  55. ULONG i,j;
  56. UCHAR statusByte;
  57. UCHAR signatureLow,
  58. signatureHigh;
  59. IDENTIFY_DATA fullIdentifyData;
  60. RtlZeroMemory (IdentifyData, sizeof (IdentifyData));
  61. //
  62. // Select device 0 or 1.
  63. //
  64. SelectIdeDevice(CmdBaseAddr, DeviceNumber, 0);
  65. //
  66. // Check that the status register makes sense.
  67. //
  68. GetBaseStatus(CmdBaseAddr, statusByte);
  69. if (Command == IDE_COMMAND_IDENTIFY) {
  70. //
  71. // Mask status byte ERROR bits.
  72. //
  73. CLRMASK (statusByte, IDE_STATUS_ERROR | IDE_STATUS_INDEX);
  74. DebugPrint((1,
  75. "IssueIdentify: Checking for IDE. Status (%x)\n",
  76. statusByte));
  77. //
  78. // Check if register value is reasonable.
  79. //
  80. if (statusByte != IDE_STATUS_IDLE) {
  81. //
  82. // Reset the controller.
  83. //
  84. IdeHardReset (
  85. CmdBaseAddr,
  86. CtrlBaseAddr,
  87. InterruptOff,
  88. TRUE
  89. );
  90. SelectIdeDevice(CmdBaseAddr, DeviceNumber, 0);
  91. //
  92. // Another check for signature, to deal with one model Atapi that doesn't assert signature after
  93. // a soft reset.
  94. //
  95. signatureLow = IdePortInPortByte(CmdBaseAddr->CylinderLow);
  96. signatureHigh = IdePortInPortByte(CmdBaseAddr->CylinderHigh);
  97. if (signatureLow == 0x14 && signatureHigh == 0xEB) {
  98. //
  99. // Device is Atapi.
  100. //
  101. return FALSE;
  102. }
  103. if (Is98LegacyIde(CmdBaseAddr)) {
  104. AtapiSoftReset(CmdBaseAddr, CtrlBaseAddr, DeviceNumber, TRUE);
  105. WaitOnBusy(CmdBaseAddr, statusByte);
  106. if (!(statusByte & IDE_STATUS_ERROR)) {
  107. //
  108. // Device is WD-Mode cdrom.
  109. //
  110. return FALSE;
  111. }
  112. }
  113. GetBaseStatus(CmdBaseAddr, statusByte);
  114. CLRMASK (statusByte, IDE_STATUS_INDEX);
  115. if (statusByte != IDE_STATUS_IDLE) {
  116. //
  117. // Give up on this.
  118. //
  119. return FALSE;
  120. }
  121. }
  122. } else {
  123. DebugPrint((1,
  124. "IssueIdentify: Checking for ATAPI. Status (%x)\n",
  125. statusByte));
  126. }
  127. //
  128. // Load CylinderHigh and CylinderLow with number bytes to transfer.
  129. //
  130. IdePortOutPortByte(CmdBaseAddr->CylinderHigh, (0x200 >> 8));
  131. IdePortOutPortByte(CmdBaseAddr->CylinderLow, (0x200 & 0xFF));
  132. for (j = 0; j < 2; j++) {
  133. //
  134. // Send IDENTIFY command.
  135. //
  136. WaitOnBusy(CmdBaseAddr,statusByte);
  137. IdePortOutPortByte(CmdBaseAddr->Command, Command);
  138. WaitOnBusy(CmdBaseAddr,statusByte);
  139. if (statusByte & IDE_STATUS_ERROR) {
  140. continue;
  141. }
  142. //
  143. // Wait for DRQ.
  144. //
  145. for (i = 0; i < 4; i++) {
  146. WaitForDrq(CmdBaseAddr, statusByte);
  147. if (statusByte & IDE_STATUS_DRQ) {
  148. //
  149. // Read status to acknowledge any interrupts generated.
  150. //
  151. GetBaseStatus(CmdBaseAddr, statusByte);
  152. //
  153. // One last check for Atapi.
  154. //
  155. signatureLow = IdePortInPortByte(CmdBaseAddr->CylinderLow);
  156. signatureHigh = IdePortInPortByte(CmdBaseAddr->CylinderHigh);
  157. if (signatureLow == 0x14 && signatureHigh == 0xEB) {
  158. //
  159. // Device is Atapi.
  160. //
  161. return FALSE;
  162. }
  163. break;
  164. }
  165. if (Command == IDE_COMMAND_IDENTIFY) {
  166. //
  167. // Check the signature. If DRQ didn't come up it's likely Atapi.
  168. //
  169. signatureLow = IdePortInPortByte(CmdBaseAddr->CylinderLow);
  170. signatureHigh = IdePortInPortByte(CmdBaseAddr->CylinderHigh);
  171. if (signatureLow == 0x14 && signatureHigh == 0xEB) {
  172. //
  173. // Device is Atapi.
  174. //
  175. return FALSE;
  176. }
  177. if (Is98LegacyIde(CmdBaseAddr)) {
  178. AtapiSoftReset(CmdBaseAddr, CtrlBaseAddr, DeviceNumber, TRUE);
  179. WaitOnBusy(CmdBaseAddr, statusByte);
  180. if (!(statusByte & IDE_STATUS_ERROR)) {
  181. //
  182. // Device is WD-Mode cdrom.
  183. //
  184. return FALSE;
  185. }
  186. }
  187. }
  188. WaitOnBusy(CmdBaseAddr,statusByte);
  189. }
  190. if (i == 4 && j == 0) {
  191. //
  192. // Device didn't respond correctly. It will be given one more chances.
  193. //
  194. DebugPrint((1,
  195. "IssueIdentify: DRQ never asserted (%x). Error reg (%x)\n",
  196. statusByte,
  197. IdePortInPortByte(CmdBaseAddr->Error)));
  198. AtapiSoftReset(CmdBaseAddr, CtrlBaseAddr, DeviceNumber, InterruptOff);
  199. GetStatus(CmdBaseAddr,statusByte);
  200. DebugPrint((1,
  201. "IssueIdentify: Status after soft reset (%x)\n",
  202. statusByte));
  203. } else {
  204. break;
  205. }
  206. }
  207. //
  208. // Check for error on really bad master devices that assert random
  209. // patterns of bits in the status register at the slave address.
  210. //
  211. if (statusByte & IDE_STATUS_ERROR) {
  212. return FALSE;
  213. }
  214. DebugPrint((1,
  215. "IssueIdentify: Status before read words %x\n",
  216. statusByte));
  217. //
  218. // pull out 256 words. After waiting for one model that asserts busy
  219. // after receiving the Packet Identify command.
  220. //
  221. WaitOnBusy(CmdBaseAddr,statusByte);
  222. if (!(statusByte & IDE_STATUS_DRQ)) {
  223. return FALSE;
  224. }
  225. if (Is98LegacyIde(CmdBaseAddr)) {
  226. //
  227. // Delay(10ms) for ATAPI CD-ROM device.
  228. //
  229. if (Command == IDE_COMMAND_ATAPI_IDENTIFY) {
  230. for (i = 0; i < 100; i++) {
  231. KeStallExecutionProcessor(100);
  232. }
  233. }
  234. }
  235. ReadBuffer(CmdBaseAddr,
  236. (PUSHORT)&fullIdentifyData,
  237. sizeof (fullIdentifyData) / 2);
  238. RtlMoveMemory(IdentifyData,&fullIdentifyData,sizeof(*IdentifyData));
  239. WaitOnBusy(CmdBaseAddr,statusByte);
  240. for (i = 0; i < 0x10000; i++) {
  241. GetStatus(CmdBaseAddr,statusByte);
  242. if (statusByte & IDE_STATUS_DRQ) {
  243. //
  244. // pull out any remaining bytes and throw away.
  245. //
  246. READ_PORT_USHORT(CmdBaseAddr->Data);
  247. } else {
  248. break;
  249. }
  250. }
  251. DebugPrint((3,
  252. "IssueIdentify: Status after read words (%x)\n",
  253. statusByte));
  254. return TRUE;
  255. } // end IssueIdentify()
  256. VOID
  257. InitDeviceGeometry(
  258. PHW_DEVICE_EXTENSION HwDeviceExtension,
  259. ULONG Device,
  260. ULONG NumberOfCylinders,
  261. ULONG NumberOfHeads,
  262. ULONG SectorsPerTrack
  263. )
  264. {
  265. ASSERT (HwDeviceExtension);
  266. ASSERT (Device < HwDeviceExtension->MaxIdeDevice);
  267. ASSERT (NumberOfCylinders);
  268. ASSERT (NumberOfHeads);
  269. ASSERT (SectorsPerTrack);
  270. HwDeviceExtension->NumberOfCylinders[Device] = NumberOfCylinders;
  271. HwDeviceExtension->NumberOfHeads[Device] = NumberOfHeads;
  272. HwDeviceExtension->SectorsPerTrack[Device] = SectorsPerTrack;
  273. return;
  274. }
  275. VOID
  276. InitHwExtWithIdentify(
  277. IN PVOID HwDeviceExtension,
  278. IN ULONG DeviceNumber,
  279. IN UCHAR Command,
  280. IN PIDENTIFY_DATA IdentifyData,
  281. IN BOOLEAN RemovableMedia
  282. )
  283. /*++
  284. Routine Description:
  285. Issue IDENTIFY command to a device.
  286. Arguments:
  287. HwDeviceExtension - HBA miniport driver's adapter data storage
  288. DeviceNumber - Indicates which device.
  289. Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
  290. InterruptOff - should leave interrupt disabled
  291. Return Value:
  292. TRUE if all goes well.
  293. --*/
  294. {
  295. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  296. ULONG i,j;
  297. //
  298. // Check out a few capabilities / limitations of the device.
  299. //
  300. if (IdentifyData->MediaStatusNotification == IDENTIFY_MEDIA_STATUS_NOTIFICATION_SUPPORTED) {
  301. //
  302. // Determine if this drive supports the MSN functions.
  303. //
  304. DebugPrint((2,"InitHwExtWithIdentify: Marking drive %d as removable. SFE = %d\n",
  305. DeviceNumber,
  306. IdentifyData->MediaStatusNotification));
  307. deviceExtension->DeviceFlags[DeviceNumber] |= DFLAGS_MSN_SUPPORT;
  308. }
  309. if (RemovableMedia) {
  310. //
  311. // This device has removable media
  312. //
  313. deviceExtension->DeviceFlags[DeviceNumber] |= DFLAGS_REMOVABLE_DRIVE;
  314. CLRMASK (deviceExtension->DeviceFlags[DeviceNumber], DFLAGS_IDENTIFY_VALID);
  315. DebugPrint((2,
  316. "InitHwExtWithIdentify: Device media is removable\n"));
  317. } else {
  318. DebugPrint((2,
  319. "InitHwExtWithIdentify: Device media is NOT removable\n"));
  320. }
  321. if (IdentifyData->GeneralConfiguration & 0x20 &&
  322. Command != IDE_COMMAND_IDENTIFY) {
  323. //
  324. // This device interrupts with the assertion of DRQ after receiving
  325. // Atapi Packet Command
  326. //
  327. deviceExtension->DeviceFlags[DeviceNumber] |= DFLAGS_INT_DRQ;
  328. DebugPrint((2,
  329. "InitHwExtWithIdentify: Device interrupts on assertion of DRQ.\n"));
  330. } else {
  331. DebugPrint((2,
  332. "InitHwExtWithIdentify: Device does not interrupt on assertion of DRQ.\n"));
  333. }
  334. if (((IdentifyData->GeneralConfiguration & 0xF00) == 0x100) &&
  335. Command != IDE_COMMAND_IDENTIFY) {
  336. //
  337. // This is a tape.
  338. //
  339. deviceExtension->DeviceFlags[DeviceNumber] |= DFLAGS_TAPE_DEVICE;
  340. DebugPrint((2,
  341. "InitHwExtWithIdentify: Device is a tape drive.\n"));
  342. } else {
  343. DebugPrint((2,
  344. "InitHwExtWithIdentify: Device is not a tape drive.\n"));
  345. }
  346. return;
  347. } // InitHwExtWithIdentify
  348. BOOLEAN
  349. SetDriveParameters(
  350. IN PVOID HwDeviceExtension,
  351. IN ULONG DeviceNumber,
  352. IN BOOLEAN Sync
  353. )
  354. /*++
  355. Routine Description:
  356. Set drive parameters using the IDENTIFY data.
  357. Arguments:
  358. HwDeviceExtension - HBA miniport driver's adapter data storage
  359. DeviceNumber - Indicates which device.
  360. Return Value:
  361. TRUE if all goes well.
  362. --*/
  363. {
  364. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  365. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  366. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  367. ULONG i;
  368. UCHAR statusByte;
  369. DebugPrint ((DBG_BUSSCAN, "SetDriveParameters: %s %d\n", __FILE__, __LINE__));
  370. DebugPrint((1,
  371. "SetDriveParameters: Number of heads %x\n",
  372. deviceExtension->NumberOfHeads[DeviceNumber]));
  373. DebugPrint((1,
  374. "SetDriveParameters: Sectors per track %x\n",
  375. deviceExtension->SectorsPerTrack[DeviceNumber]));
  376. if (deviceExtension->DeviceFlags[DeviceNumber] & DFLAGS_IDENTIFY_VALID) {
  377. ASSERT(!(deviceExtension->DeviceFlags[DeviceNumber] & DFLAGS_REMOVABLE_DRIVE));
  378. SETMASK(deviceExtension->DeviceFlags[DeviceNumber], DFLAGS_IDENTIFY_INVALID);
  379. CLRMASK(deviceExtension->DeviceFlags[DeviceNumber], DFLAGS_IDENTIFY_VALID);
  380. }
  381. //
  382. // Set up registers for SET PARAMETER command.
  383. //
  384. SelectIdeDevice(baseIoAddress1, DeviceNumber, (deviceExtension->NumberOfHeads[DeviceNumber] - 1));
  385. IdePortOutPortByte(baseIoAddress1->BlockCount,
  386. (UCHAR)deviceExtension->SectorsPerTrack[DeviceNumber]);
  387. DebugPrint ((DBG_BUSSCAN, "SetDriveParameters: %s %d\n", __FILE__, __LINE__));
  388. //
  389. // Send SET PARAMETER command.
  390. //
  391. IdePortOutPortByte(baseIoAddress1->Command,
  392. IDE_COMMAND_SET_DRIVE_PARAMETERS);
  393. DebugPrint ((DBG_BUSSCAN, "SetDriveParameters: %s %d\n", __FILE__, __LINE__));
  394. if (Sync) {
  395. DebugPrint ((DBG_BUSSCAN, "SetDriveParameters: %s %d\n", __FILE__, __LINE__));
  396. //
  397. // Wait for ERROR or command complete.
  398. //
  399. WaitOnBusy(baseIoAddress1,statusByte);
  400. DebugPrint ((DBG_BUSSCAN, "SetDriveParameters: %s %d\n", __FILE__, __LINE__));
  401. if (statusByte & IDE_STATUS_BUSY) {
  402. return FALSE;
  403. } else {
  404. if (statusByte & IDE_STATUS_ERROR) {
  405. UCHAR errorByte;
  406. errorByte = IdePortInPortByte(baseIoAddress1->Error);
  407. DebugPrint((1,
  408. "SetDriveParameters: Error bit set. Status %x, error %x\n",
  409. errorByte,
  410. statusByte));
  411. return FALSE;
  412. } else {
  413. return TRUE;
  414. }
  415. }
  416. } else {
  417. return TRUE;
  418. }
  419. } // end SetDriveParameters()
  420. BOOLEAN
  421. AtapiResetController(
  422. IN PVOID HwDeviceExtension,
  423. IN ULONG PathId,
  424. IN PULONG CallAgain
  425. )
  426. /*++
  427. Routine Description:
  428. Reset IDE controller and/or Atapi device.
  429. Arguments:
  430. HwDeviceExtension - HBA miniport driver's adapter data storage
  431. Return Value:
  432. Nothing.
  433. --*/
  434. {
  435. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  436. PIDE_REGISTERS_1 baseIoAddress1;
  437. PIDE_REGISTERS_2 baseIoAddress2;
  438. BOOLEAN result = FALSE;
  439. ULONG i;
  440. UCHAR statusByte;
  441. ULONG numStates;
  442. BOOLEAN enumProbing = FALSE;
  443. ULONG lineNumber, deviceNumber;
  444. BOOLEAN setResetFinalState;
  445. baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  446. baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  447. if (*CallAgain == 0) {
  448. #if DBG
  449. __DebugResetCounter = 0;
  450. #endif
  451. // build state table
  452. numStates = 0;
  453. setResetFinalState = FALSE;
  454. for (lineNumber = 0; lineNumber < (deviceExtension->MaxIdeDevice/MAX_IDE_DEVICE); lineNumber++) {
  455. if (Is98LegacyIde(baseIoAddress1)) {
  456. if (!(deviceExtension->DeviceFlags[lineNumber * MAX_IDE_DEVICE] & DFLAGS_DEVICE_PRESENT)) {
  457. continue;
  458. }
  459. }
  460. deviceExtension->ResetState.DeviceNumber[numStates] = lineNumber * MAX_IDE_DEVICE;
  461. deviceExtension->ResetState.State[numStates++] = IdeResetBegin;
  462. deviceExtension->ResetState.DeviceNumber[numStates] = lineNumber * MAX_IDE_DEVICE;
  463. deviceExtension->ResetState.State[numStates++] = ideResetBusResetInProgress;
  464. for (i = 0; i < MAX_IDE_DEVICE; i++) {
  465. deviceNumber = (lineNumber * MAX_IDE_DEVICE) + i;
  466. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT) {
  467. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_ATAPI_DEVICE) {
  468. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  469. deviceExtension->ResetState.State[numStates++] = ideResetAtapiReset;
  470. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  471. deviceExtension->ResetState.State[numStates++] = ideResetAtapiResetInProgress;
  472. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  473. deviceExtension->ResetState.State[numStates++] = ideResetAtapiIdentifyData;
  474. } else {
  475. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  476. deviceExtension->ResetState.State[numStates++] = ideResetAtaIDP;
  477. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  478. deviceExtension->ResetState.State[numStates++] = ideResetAtaIDPInProgress;
  479. deviceExtension->ResetState.DeviceNumber[numStates] = deviceNumber;
  480. deviceExtension->ResetState.State[numStates++] = ideResetAtaMSN;
  481. }
  482. }
  483. setResetFinalState = TRUE;
  484. }
  485. }
  486. if (setResetFinalState) {
  487. deviceExtension->ResetState.DeviceNumber[numStates] = 0;
  488. deviceExtension->ResetState.State[numStates++] = ideResetFinal;
  489. }
  490. ASSERT (numStates <= RESET_STATE_TABLE_LEN);
  491. }
  492. SelectIdeLine (baseIoAddress1,((deviceExtension->ResetState.DeviceNumber[*CallAgain] >> 1) == 0)?0:1);
  493. DebugPrint ((DBG_RESET,
  494. "AtapiResetController CallAgain = 0x%x, device = 0x%x, busyCount = 0x%x\n",
  495. *CallAgain,
  496. deviceExtension->ResetState.DeviceNumber[*CallAgain],
  497. deviceExtension->ResetState.WaitBusyCount
  498. ));
  499. switch (deviceExtension->ResetState.State[*CallAgain]) {
  500. case IdeResetBegin:
  501. DebugPrint((DBG_RESET,
  502. "AtapiResetController: Reset 0x%x IDE...\n",
  503. deviceExtension->BaseIoAddress1.RegistersBaseAddress));
  504. if (Is98LegacyIde(baseIoAddress1) && !(deviceExtension->ResetState.DeviceNumber[*CallAgain] & 0x2)) {
  505. UCHAR driveHeadReg;
  506. SelectIdeDevice(baseIoAddress1, deviceExtension->ResetState.DeviceNumber[*CallAgain], 0);
  507. driveHeadReg = IdePortInPortByte(baseIoAddress1->DriveSelect);
  508. if (driveHeadReg != ((deviceExtension->ResetState.DeviceNumber[*CallAgain] & 0x1) << 4 | 0xA0)) {
  509. //
  510. // Select the secondary line, when there is no primary line.
  511. //
  512. SelectIdeLine (baseIoAddress1, 1);
  513. GetStatus(baseIoAddress1,statusByte);
  514. }
  515. }
  516. //
  517. // Check if request is in progress.
  518. //
  519. if (deviceExtension->CurrentSrb) {
  520. enumProbing = TestForEnumProbing (deviceExtension->CurrentSrb);
  521. if ((deviceExtension->CurrentSrb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH) ||
  522. (deviceExtension->CurrentSrb->Function == SRB_FUNCTION_ATA_PASS_THROUGH)) {
  523. PATA_PASS_THROUGH ataPassThroughData;
  524. ataPassThroughData = deviceExtension->CurrentSrb->DataBuffer;
  525. AtapiTaskRegisterSnapshot (baseIoAddress1, &ataPassThroughData->IdeReg);
  526. }
  527. //
  528. // Complete outstanding request with SRB_STATUS_BUS_RESET.
  529. //
  530. IdePortCompleteRequest(deviceExtension,
  531. deviceExtension->CurrentSrb,
  532. (ULONG)SRB_STATUS_BUS_RESET);
  533. //
  534. // Clear request tracking fields.
  535. //
  536. deviceExtension->CurrentSrb = NULL;
  537. deviceExtension->BytesLeft = 0;
  538. deviceExtension->DataBuffer = NULL;
  539. //
  540. // Indicate ready for next request.
  541. //
  542. IdePortNotification(IdeNextRequest,
  543. deviceExtension,
  544. NULL);
  545. }
  546. //
  547. // Clear DMA
  548. //
  549. if (deviceExtension->DMAInProgress) {
  550. deviceExtension->DMAInProgress = FALSE;
  551. deviceExtension->BusMasterInterface.BmDisarm (deviceExtension->BusMasterInterface.Context);
  552. }
  553. //
  554. // Clear expecting interrupt flag.
  555. //
  556. deviceExtension->ExpectingInterrupt = FALSE;
  557. deviceExtension->RDP = FALSE;
  558. if (!enumProbing) {
  559. //
  560. // ATA soft reset. reset only ATA devices
  561. //
  562. IdeHardReset (
  563. baseIoAddress1,
  564. baseIoAddress2,
  565. TRUE,
  566. FALSE
  567. );
  568. (*CallAgain)++;
  569. deviceExtension->ResetState.WaitBusyCount = 0;
  570. //
  571. // go to the next stage if a short wait satisfies the
  572. // requirement
  573. //
  574. GetStatus(baseIoAddress1,statusByte);
  575. WaitOnBusyUntil(baseIoAddress1, statusByte, 200);
  576. if (statusByte & IDE_STATUS_BUSY) {
  577. return TRUE;
  578. } else {
  579. return AtapiResetController(
  580. HwDeviceExtension,
  581. PathId,
  582. CallAgain
  583. );
  584. }
  585. } else {
  586. //
  587. // timeout is caused by a command sent to a non-existing device
  588. // no need to reset
  589. //
  590. *CallAgain = 0;
  591. }
  592. return TRUE;
  593. break;
  594. //
  595. // all these states waits for BUSY to go clear
  596. // then go to the next state
  597. //
  598. case ideResetBusResetInProgress:
  599. if (Is98LegacyIde(baseIoAddress1) && !(deviceExtension->ResetState.DeviceNumber[*CallAgain] & 0x2)) {
  600. UCHAR driveHeadReg;
  601. SelectIdeDevice(baseIoAddress1, deviceExtension->ResetState.DeviceNumber[*CallAgain], 0);
  602. driveHeadReg = IdePortInPortByte(baseIoAddress1->DriveSelect);
  603. if (driveHeadReg != ((deviceExtension->ResetState.DeviceNumber[*CallAgain] & 0x1) << 4 | 0xA0)) {
  604. //
  605. // Select the secondary line, when there is no primary line.
  606. //
  607. SelectIdeLine (baseIoAddress1, 1);
  608. }
  609. }
  610. //
  611. // select the slave when there is no master
  612. //
  613. if (!(deviceExtension->DeviceFlags[deviceExtension->ResetState.DeviceNumber[*CallAgain]] &
  614. DFLAGS_DEVICE_PRESENT)) {
  615. SelectIdeDevice(baseIoAddress1, (deviceExtension->ResetState.DeviceNumber[*CallAgain] | 0x1), 0);
  616. }
  617. case ideResetAtapiResetInProgress:
  618. case ideResetAtaIDPInProgress:
  619. GetStatus(baseIoAddress1,statusByte);
  620. if (statusByte & IDE_STATUS_BUSY) {
  621. deviceExtension->ResetState.WaitBusyCount++;
  622. if ((deviceExtension->ResetState.WaitBusyCount > 30) ||
  623. (statusByte == 0xff)) {
  624. UCHAR deviceSelect = IdePortInPortByte(baseIoAddress1->DriveSelect);
  625. //
  626. // reset fails
  627. //
  628. DebugPrint ((DBG_ALWAYS, "ATAPI ResetController: ATA soft reset fails\n"));
  629. // if ((statusByte == 0xff) && (deviceSelect == 0xff)) {
  630. //
  631. // ULONG i;
  632. //
  633. // DebugPrint ((
  634. // DBG_ALWAYS,
  635. // "ATAPI: ide Channel 0x%x is gone!!\n",
  636. // baseIoAddress1->RegistersBaseAddress
  637. // ));
  638. //
  639. // for (i=0; i<deviceExtension->MaxIdeDevice; i++) {
  640. //
  641. // deviceExtension->DeviceFlags[i] &= ~DFLAGS_DEVICE_PRESENT;
  642. // }
  643. // }
  644. if (IdePortChannelEmpty (baseIoAddress1,
  645. baseIoAddress2, deviceExtension->MaxIdeDevice)) {
  646. IdePortNotification(IdeAllDeviceMissing,
  647. deviceExtension,
  648. NULL);
  649. *CallAgain = 0;
  650. IdePortOutPortByte (baseIoAddress2->DeviceControl, IDE_DC_REENABLE_CONTROLLER);
  651. return TRUE;
  652. }
  653. //
  654. // no choice, but continue with the reset
  655. //
  656. // *CallAgain = 0;
  657. // IdePortOutPortByte (baseIoAddress2, IDE_DC_REENABLE_CONTROLLER);
  658. // return FALSE;
  659. } else {
  660. DebugPrint ((DBG_ALWAYS, "ATAPI: ResetController not ready (status = 0x%x) ...wait for 1 sec\n", statusByte));
  661. return TRUE;
  662. }
  663. }
  664. (*CallAgain)++;
  665. return AtapiResetController(
  666. HwDeviceExtension,
  667. PathId,
  668. CallAgain
  669. );
  670. break;
  671. case ideResetAtapiReset:
  672. SelectIdeDevice(baseIoAddress1, deviceExtension->ResetState.DeviceNumber[*CallAgain], 0);
  673. IdePortOutPortByte(baseIoAddress1->Command, IDE_COMMAND_ATAPI_RESET);
  674. deviceExtension->ResetState.WaitBusyCount = 0;
  675. (*CallAgain)++;
  676. //
  677. // go to the next stage if a short wait satisfies the
  678. // requirement
  679. //
  680. GetStatus(baseIoAddress1,statusByte);
  681. WaitOnBusyUntil(baseIoAddress1, statusByte, 200);
  682. if (statusByte & IDE_STATUS_BUSY) {
  683. return TRUE;
  684. } else {
  685. return AtapiResetController(
  686. HwDeviceExtension,
  687. PathId,
  688. CallAgain
  689. );
  690. }
  691. return TRUE;
  692. break;
  693. case ideResetAtaIDP:
  694. if (!Is98LegacyIde(baseIoAddress1)) {
  695. SetDriveParameters(HwDeviceExtension,
  696. deviceExtension->ResetState.DeviceNumber[*CallAgain],
  697. FALSE);
  698. }
  699. deviceExtension->ResetState.WaitBusyCount = 0;
  700. (*CallAgain)++;
  701. //
  702. // go to the next stage if a short wait satisfies the
  703. // requirement
  704. //
  705. GetStatus(baseIoAddress1,statusByte);
  706. WaitOnBusyUntil(baseIoAddress1, statusByte, 200);
  707. if (statusByte & IDE_STATUS_BUSY) {
  708. return TRUE;
  709. } else {
  710. return AtapiResetController(
  711. HwDeviceExtension,
  712. PathId,
  713. CallAgain
  714. );
  715. }
  716. return TRUE;
  717. break;
  718. case ideResetAtapiIdentifyData:
  719. //
  720. // the device shouldn't be busy at this point
  721. //
  722. SelectIdeDevice(&deviceExtension->BaseIoAddress1,
  723. deviceExtension->ResetState.DeviceNumber[*CallAgain],
  724. 0
  725. );
  726. WaitOnBusyUntil(&deviceExtension->BaseIoAddress1,
  727. statusByte,
  728. 100
  729. );
  730. //
  731. // issue identify command only if the device is not
  732. // already busy
  733. //
  734. if (!(statusByte & IDE_STATUS_BUSY)) {
  735. GetAtapiIdentifyQuick( &deviceExtension->BaseIoAddress1,
  736. &deviceExtension->BaseIoAddress2,
  737. deviceExtension->ResetState.DeviceNumber[*CallAgain],
  738. &deviceExtension->IdentifyData[deviceExtension->ResetState.DeviceNumber[*CallAgain]]
  739. );
  740. /*
  741. IssueIdentify(
  742. &deviceExtension->BaseIoAddress1,
  743. &deviceExtension->BaseIoAddress2,
  744. deviceExtension->ResetState.DeviceNumber[*CallAgain],
  745. IDE_COMMAND_ATAPI_IDENTIFY,
  746. FALSE,
  747. &deviceExtension->IdentifyData[deviceExtension->ResetState.DeviceNumber[*CallAgain]]
  748. );
  749. */
  750. }
  751. // InitHwExtWithIdentify(
  752. // HwDeviceExtension,
  753. // deviceExtension->ResetState.DeviceNumber[*CallAgain],
  754. // IDE_COMMAND_ATAPI_IDENTIFY,
  755. // &deviceExtension->IdentifyData[deviceExtension->ResetState.DeviceNumber[*CallAgain]]
  756. // );
  757. (*CallAgain)++;
  758. return AtapiResetController(
  759. HwDeviceExtension,
  760. PathId,
  761. CallAgain
  762. );
  763. break;
  764. case ideResetAtaMSN:
  765. IdeMediaStatus(
  766. TRUE,
  767. HwDeviceExtension,
  768. deviceExtension->ResetState.DeviceNumber[*CallAgain]
  769. );
  770. (*CallAgain)++;
  771. return AtapiResetController(
  772. HwDeviceExtension,
  773. PathId,
  774. CallAgain
  775. );
  776. break;
  777. case ideResetFinal:
  778. //
  779. // HACK: if any of the devices are busy at this point, then they should
  780. // be marked dead. This will anyway happen because of the timeout count.
  781. // However, the waitOnBusy macros in all the routines would consume upto
  782. // 30s leaving the sytem practically hung until the reset completes. Instead,
  783. // we just clear the device present flag before the routine is called and
  784. // restore it after that.
  785. //
  786. for (i = 0; i < (deviceExtension->MaxIdeDevice/MAX_IDE_DEVICE); i++) {
  787. if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) {
  788. SelectIdeDevice(baseIoAddress1, i, 0);
  789. WaitOnBusyUntil(baseIoAddress1, statusByte, 100);
  790. if (statusByte & IDE_STATUS_BUSY) {
  791. CLRMASK(deviceExtension->DeviceFlags[i], DFLAGS_DEVICE_PRESENT);
  792. SETMASK(deviceExtension->DeviceFlags[i], DFLAGS_DEVICE_ERASED);
  793. }
  794. }
  795. }
  796. AtapiHwInitialize(HwDeviceExtension, NULL);
  797. //
  798. // Restore the device present flag
  799. //
  800. for (i = 0; i < (deviceExtension->MaxIdeDevice/MAX_IDE_DEVICE); i++) {
  801. if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_ERASED) {
  802. SETMASK(deviceExtension->DeviceFlags[i], DFLAGS_DEVICE_PRESENT);
  803. }
  804. }
  805. if (IdePortChannelEmpty (baseIoAddress1,
  806. baseIoAddress2, deviceExtension->MaxIdeDevice)) {
  807. IdePortNotification(IdeAllDeviceMissing,
  808. deviceExtension,
  809. NULL);
  810. }
  811. *CallAgain = 0;
  812. for (i = 0; i < (deviceExtension->MaxIdeDevice/MAX_IDE_DEVICE); i++) {
  813. SelectIdeLine(baseIoAddress1, i);
  814. IdePortOutPortByte (baseIoAddress2->DeviceControl, IDE_DC_REENABLE_CONTROLLER);
  815. }
  816. return TRUE;
  817. break;
  818. default:
  819. ASSERT(FALSE);
  820. *CallAgain = 0;
  821. for (i = 0; i < (deviceExtension->MaxIdeDevice/MAX_IDE_DEVICE); i++) {
  822. SelectIdeLine(baseIoAddress1, i);
  823. IdePortOutPortByte (baseIoAddress2->DeviceControl, IDE_DC_REENABLE_CONTROLLER);
  824. }
  825. return FALSE;
  826. break;
  827. }
  828. } // end AtapiResetController()
  829. ULONG
  830. MapError(
  831. IN PVOID HwDeviceExtension,
  832. IN PSCSI_REQUEST_BLOCK Srb
  833. )
  834. /*++
  835. Routine Description:
  836. This routine maps ATAPI and IDE errors to specific SRB statuses.
  837. Arguments:
  838. HwDeviceExtension - HBA miniport driver's adapter data storage
  839. Srb - IO request packet
  840. Return Value:
  841. SRB status
  842. --*/
  843. {
  844. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  845. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  846. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  847. ULONG i;
  848. UCHAR errorByte;
  849. UCHAR srbStatus;
  850. UCHAR scsiStatus;
  851. SENSE_DATA tempSenseBuffer;
  852. PSENSE_DATA senseBuffer = (PSENSE_DATA)&tempSenseBuffer;
  853. //
  854. // Read the error register.
  855. //
  856. //errorByte = IdePortInPortByte(baseIoAddress1->Error);
  857. GetErrorByte(baseIoAddress1, errorByte);
  858. DebugPrint((DBG_IDE_DEVICE_ERROR,
  859. "MapError: cdb %x and Error register is %x\n",
  860. Srb->Cdb[0],
  861. errorByte));
  862. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
  863. switch (errorByte >> 4) {
  864. case SCSI_SENSE_NO_SENSE:
  865. DebugPrint((DBG_IDE_DEVICE_ERROR,
  866. "ATAPI: No sense information\n"));
  867. scsiStatus = SCSISTAT_CHECK_CONDITION;
  868. srbStatus = SRB_STATUS_ERROR;
  869. break;
  870. case SCSI_SENSE_RECOVERED_ERROR:
  871. DebugPrint((DBG_IDE_DEVICE_ERROR,
  872. "ATAPI: Recovered error\n"));
  873. scsiStatus = 0;
  874. srbStatus = SRB_STATUS_SUCCESS;
  875. break;
  876. case SCSI_SENSE_NOT_READY:
  877. DebugPrint((DBG_IDE_DEVICE_ERROR,
  878. "ATAPI: Device not ready\n"));
  879. scsiStatus = SCSISTAT_CHECK_CONDITION;
  880. srbStatus = SRB_STATUS_ERROR;
  881. break;
  882. case SCSI_SENSE_MEDIUM_ERROR:
  883. DebugPrint((DBG_IDE_DEVICE_ERROR,
  884. "ATAPI: Media error\n"));
  885. scsiStatus = SCSISTAT_CHECK_CONDITION;
  886. srbStatus = SRB_STATUS_ERROR;
  887. break;
  888. case SCSI_SENSE_HARDWARE_ERROR:
  889. DebugPrint((DBG_IDE_DEVICE_ERROR,
  890. "ATAPI: Hardware error\n"));
  891. scsiStatus = SCSISTAT_CHECK_CONDITION;
  892. srbStatus = SRB_STATUS_ERROR;
  893. break;
  894. case SCSI_SENSE_ILLEGAL_REQUEST:
  895. DebugPrint((DBG_IDE_DEVICE_ERROR,
  896. "ATAPI: Illegal request\n"));
  897. scsiStatus = SCSISTAT_CHECK_CONDITION;
  898. srbStatus = SRB_STATUS_ERROR;
  899. break;
  900. case SCSI_SENSE_UNIT_ATTENTION:
  901. DebugPrint((DBG_IDE_DEVICE_ERROR,
  902. "ATAPI: Unit attention\n"));
  903. scsiStatus = SCSISTAT_CHECK_CONDITION;
  904. srbStatus = SRB_STATUS_ERROR;
  905. break;
  906. case SCSI_SENSE_DATA_PROTECT:
  907. DebugPrint((DBG_IDE_DEVICE_ERROR,
  908. "ATAPI: Data protect\n"));
  909. scsiStatus = SCSISTAT_CHECK_CONDITION;
  910. srbStatus = SRB_STATUS_ERROR;
  911. break;
  912. case SCSI_SENSE_BLANK_CHECK:
  913. DebugPrint((DBG_IDE_DEVICE_ERROR,
  914. "ATAPI: Blank check\n"));
  915. scsiStatus = SCSISTAT_CHECK_CONDITION;
  916. srbStatus = SRB_STATUS_ERROR;
  917. break;
  918. case SCSI_SENSE_ABORTED_COMMAND:
  919. DebugPrint((DBG_IDE_DEVICE_ERROR,
  920. "Atapi: Command Aborted\n"));
  921. scsiStatus = SCSISTAT_CHECK_CONDITION;
  922. srbStatus = SRB_STATUS_ERROR;
  923. break;
  924. default:
  925. DebugPrint((DBG_IDE_DEVICE_ERROR,
  926. "ATAPI: Invalid sense information\n"));
  927. scsiStatus = SCSISTAT_CHECK_CONDITION;
  928. srbStatus = SRB_STATUS_ERROR;
  929. break;
  930. }
  931. } else {
  932. scsiStatus = 0;
  933. //
  934. // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
  935. //
  936. deviceExtension->ReturningMediaStatus = errorByte;
  937. RtlZeroMemory(senseBuffer, sizeof(SENSE_DATA));
  938. if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
  939. DebugPrint((DBG_IDE_DEVICE_ERROR,
  940. "IDE: Media change\n"));
  941. scsiStatus = SCSISTAT_CHECK_CONDITION;
  942. srbStatus = SRB_STATUS_ERROR;
  943. if (Srb->SenseInfoBuffer) {
  944. senseBuffer->ErrorCode = 0x70;
  945. senseBuffer->Valid = 1;
  946. senseBuffer->AdditionalSenseLength = 0xb;
  947. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  948. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_OPERATOR_REQUEST;
  949. senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_MEDIUM_REMOVAL;
  950. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  951. }
  952. } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
  953. DebugPrint((DBG_IDE_DEVICE_ERROR, "IDE: Command abort\n"));
  954. scsiStatus = SCSISTAT_CHECK_CONDITION;
  955. if ((errorByte & IDE_ERROR_CRC_ERROR) &&
  956. (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_USE_UDMA) &&
  957. SRB_USES_DMA(Srb)) {
  958. DebugPrint((1, "Srb 0x%x had a CRC error using UDMA\n", Srb));
  959. srbStatus = SRB_STATUS_PARITY_ERROR;
  960. if (Srb->SenseInfoBuffer) {
  961. senseBuffer->ErrorCode = 0x70;
  962. senseBuffer->Valid = 1;
  963. senseBuffer->AdditionalSenseLength = 0xb;
  964. senseBuffer->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
  965. senseBuffer->AdditionalSenseCode = 0x8;
  966. senseBuffer->AdditionalSenseCodeQualifier = 0x3;
  967. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  968. }
  969. } else {
  970. srbStatus = SRB_STATUS_ABORTED;
  971. if (Srb->SenseInfoBuffer) {
  972. senseBuffer->ErrorCode = 0x70;
  973. senseBuffer->Valid = 1;
  974. senseBuffer->AdditionalSenseLength = 0xb;
  975. senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
  976. senseBuffer->AdditionalSenseCode = 0;
  977. senseBuffer->AdditionalSenseCodeQualifier = 0;
  978. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  979. }
  980. }
  981. deviceExtension->ErrorCount++;
  982. } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
  983. DebugPrint((DBG_IDE_DEVICE_ERROR,
  984. "IDE: End of media\n"));
  985. scsiStatus = SCSISTAT_CHECK_CONDITION;
  986. srbStatus = SRB_STATUS_ERROR;
  987. if (Srb->SenseInfoBuffer) {
  988. senseBuffer->ErrorCode = 0x70;
  989. senseBuffer->Valid = 1;
  990. senseBuffer->AdditionalSenseLength = 0xb;
  991. senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
  992. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
  993. senseBuffer->AdditionalSenseCodeQualifier = 0;
  994. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  995. }
  996. if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED)) {
  997. deviceExtension->ErrorCount++;
  998. }
  999. } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
  1000. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1001. "IDE: Illegal length\n"));
  1002. srbStatus = SRB_STATUS_INVALID_REQUEST;
  1003. } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
  1004. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1005. "IDE: Bad block\n"));
  1006. srbStatus = SRB_STATUS_ERROR;
  1007. scsiStatus = SCSISTAT_CHECK_CONDITION;
  1008. if (Srb->SenseInfoBuffer) {
  1009. senseBuffer->ErrorCode = 0x70;
  1010. senseBuffer->Valid = 1;
  1011. senseBuffer->AdditionalSenseLength = 0xb;
  1012. senseBuffer->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
  1013. senseBuffer->AdditionalSenseCode = 0;
  1014. senseBuffer->AdditionalSenseCodeQualifier = 0;
  1015. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1016. }
  1017. } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
  1018. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1019. "IDE: Id not found\n"));
  1020. srbStatus = SRB_STATUS_ERROR;
  1021. scsiStatus = SCSISTAT_CHECK_CONDITION;
  1022. if (Srb->SenseInfoBuffer) {
  1023. senseBuffer->ErrorCode = 0x70;
  1024. senseBuffer->Valid = 1;
  1025. senseBuffer->AdditionalSenseLength = 0xb;
  1026. senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
  1027. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_ILLEGAL_BLOCK;
  1028. senseBuffer->AdditionalSenseCodeQualifier = 0;
  1029. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1030. }
  1031. deviceExtension->ErrorCount++;
  1032. } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
  1033. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1034. "IDE: Media change\n"));
  1035. scsiStatus = SCSISTAT_CHECK_CONDITION;
  1036. srbStatus = SRB_STATUS_ERROR;
  1037. if (Srb->SenseInfoBuffer) {
  1038. senseBuffer->ErrorCode = 0x70;
  1039. senseBuffer->Valid = 1;
  1040. senseBuffer->AdditionalSenseLength = 0xb;
  1041. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  1042. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  1043. senseBuffer->AdditionalSenseCodeQualifier = 0;
  1044. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1045. }
  1046. } else if (errorByte & IDE_ERROR_DATA_ERROR) {
  1047. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1048. "IDE: Data error\n"));
  1049. scsiStatus = SCSISTAT_CHECK_CONDITION;
  1050. srbStatus = SRB_STATUS_ERROR;
  1051. if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED)) {
  1052. deviceExtension->ErrorCount++;
  1053. }
  1054. //
  1055. // Build sense buffer
  1056. //
  1057. if (Srb->SenseInfoBuffer) {
  1058. senseBuffer->ErrorCode = 0x70;
  1059. senseBuffer->Valid = 1;
  1060. senseBuffer->AdditionalSenseLength = 0xb;
  1061. senseBuffer->SenseKey = (deviceExtension->
  1062. DeviceFlags[Srb->TargetId] & DFLAGS_REMOVABLE_DRIVE)? SCSI_SENSE_DATA_PROTECT : SCSI_SENSE_MEDIUM_ERROR;
  1063. senseBuffer->AdditionalSenseCode = 0;
  1064. senseBuffer->AdditionalSenseCodeQualifier = 0;
  1065. srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1066. }
  1067. } else { // no sense info
  1068. DebugPrint((DBG_IDE_DEVICE_ERROR,
  1069. "IdePort: No sense information\n"));
  1070. scsiStatus = SCSISTAT_CHECK_CONDITION;
  1071. srbStatus = SRB_STATUS_ERROR;
  1072. }
  1073. if (senseBuffer->Valid == 1) {
  1074. ULONG length = sizeof(SENSE_DATA);
  1075. if (Srb->SenseInfoBufferLength < length ) {
  1076. length = Srb->SenseInfoBufferLength;
  1077. }
  1078. ASSERT(length);
  1079. ASSERT(Srb->SenseInfoBuffer);
  1080. RtlCopyMemory(Srb->SenseInfoBuffer, (PVOID) senseBuffer, length);
  1081. }
  1082. if ((deviceExtension->ErrorCount >= MAX_ERRORS) &&
  1083. (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_USE_DMA))) {
  1084. deviceExtension->MaximumBlockXfer[Srb->TargetId] = 0;
  1085. DebugPrint((DBG_ALWAYS,
  1086. "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
  1087. if (deviceExtension->ErrorCount == MAX_ERRORS) {
  1088. //
  1089. // Log the error.
  1090. //
  1091. IdePortLogError( HwDeviceExtension,
  1092. Srb,
  1093. Srb->PathId,
  1094. Srb->TargetId,
  1095. Srb->Lun,
  1096. SP_BAD_FW_WARNING,
  1097. 4);
  1098. }
  1099. //
  1100. // Reprogram to not use Multi-sector.
  1101. //
  1102. for (i = 0; i < deviceExtension->MaxIdeDevice; i++) {
  1103. UCHAR statusByte;
  1104. if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT &&
  1105. !(deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE)) {
  1106. //
  1107. // Select the device.
  1108. //
  1109. SelectIdeDevice(baseIoAddress1, i, 0);
  1110. //
  1111. // Setup sector count to reflect the # of blocks.
  1112. //
  1113. IdePortOutPortByte(baseIoAddress1->BlockCount,
  1114. 0);
  1115. //
  1116. // Issue the command.
  1117. //
  1118. IdePortOutPortByte(baseIoAddress1->Command,
  1119. IDE_COMMAND_SET_MULTIPLE);
  1120. //
  1121. // Wait for busy to drop.
  1122. //
  1123. WaitOnBaseBusy(baseIoAddress1,statusByte);
  1124. //
  1125. // Check for errors. Reset the value to 0 (disable MultiBlock) if the
  1126. // command was aborted.
  1127. //
  1128. if (statusByte & IDE_STATUS_ERROR) {
  1129. //
  1130. // Read the error register.
  1131. //
  1132. errorByte = IdePortInPortByte(baseIoAddress1->Error);
  1133. DebugPrint((DBG_ALWAYS,
  1134. "AtapiHwInitialize: Error setting multiple mode. Status %x, error byte %x\n",
  1135. statusByte,
  1136. errorByte));
  1137. //
  1138. // Adjust the devExt. value, if necessary.
  1139. //
  1140. deviceExtension->MaximumBlockXfer[i] = 0;
  1141. }
  1142. deviceExtension->DeviceParameters[i].IdePioReadCommand = IDE_COMMAND_READ;
  1143. deviceExtension->DeviceParameters[i].IdePioWriteCommand = IDE_COMMAND_WRITE;
  1144. #ifdef ENABLE_48BIT_LBA
  1145. if (deviceExtension->DeviceFlags[i] & DFLAGS_48BIT_LBA) {
  1146. deviceExtension->DeviceParameters[i].IdePioReadCommandExt = IDE_COMMAND_READ_EXT;
  1147. deviceExtension->DeviceParameters[i].IdePioWriteCommandExt = IDE_COMMAND_WRITE_EXT;
  1148. }
  1149. #endif
  1150. deviceExtension->DeviceParameters[i].MaxBytePerPioInterrupt = 512;
  1151. deviceExtension->MaximumBlockXfer[i] = 0;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. //
  1157. // Set SCSI status to indicate a check condition.
  1158. //
  1159. Srb->ScsiStatus = scsiStatus;
  1160. return srbStatus;
  1161. } // end MapError()
  1162. NTSTATUS
  1163. AtapiSetTransferMode (
  1164. PHW_DEVICE_EXTENSION DeviceExtension,
  1165. ULONG DeviceNumber,
  1166. UCHAR ModeValue
  1167. )
  1168. {
  1169. PIDE_REGISTERS_1 baseIoAddress1 = &DeviceExtension->BaseIoAddress1;
  1170. UCHAR ideStatus;
  1171. if (DeviceExtension->CurrentSrb) {
  1172. DebugPrint ((DBG_ALWAYS, "DeviceExtension->CurrentSrb = 0x%x\n", DeviceExtension->CurrentSrb));
  1173. ASSERT(DeviceExtension->CurrentSrb == NULL);
  1174. }
  1175. ASSERT (DeviceExtension->ExpectingInterrupt == FALSE);
  1176. if (Is98LegacyIde(baseIoAddress1)) {
  1177. if ( !EnhancedIdeSupport() ) {
  1178. DebugPrint((1,"atapi: AtapiSetTransferMode - not enhanced-ide.\n"));
  1179. return STATUS_INVALID_DEVICE_REQUEST;
  1180. }
  1181. if (DeviceExtension->DeviceFlags[DeviceNumber] & DFLAGS_WD_MODE) {
  1182. //
  1183. // WD-Mode cd-rom can not set transfer mode.
  1184. //
  1185. DebugPrint((1,"atapi: AtapiSetTransferMode - not enhanced-ide.\n"));
  1186. return STATUS_INVALID_DEVICE_REQUEST;
  1187. }
  1188. }
  1189. SelectIdeDevice(baseIoAddress1, DeviceNumber, 0);
  1190. WaitOnBusy(baseIoAddress1, ideStatus);
  1191. IdePortOutPortByte(
  1192. baseIoAddress1->Error,
  1193. IDE_SET_FEATURE_SET_TRANSFER_MODE
  1194. );
  1195. IdePortOutPortByte(
  1196. baseIoAddress1->BlockCount,
  1197. ModeValue
  1198. );
  1199. IdePortOutPortByte(
  1200. baseIoAddress1->Command,
  1201. IDE_COMMAND_SET_FEATURE
  1202. );
  1203. WaitOnBusy(baseIoAddress1, ideStatus);
  1204. if (ideStatus & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
  1205. return STATUS_INVALID_DEVICE_REQUEST;
  1206. } else {
  1207. return STATUS_SUCCESS;
  1208. }
  1209. }
  1210. VOID
  1211. AtapiProgramTransferMode (
  1212. PHW_DEVICE_EXTENSION DeviceExtension
  1213. )
  1214. {
  1215. ULONG i;
  1216. for (i=0; i<DeviceExtension->MaxIdeDevice; i++) {
  1217. UCHAR ideCommand;
  1218. ULONG pioModeStatus;
  1219. ULONG dmaModeStatus;
  1220. ULONG xferMode;
  1221. if (!(DeviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT)) {
  1222. continue;
  1223. }
  1224. DebugPrint((DBG_XFERMODE, "ATAPI: ProgramTransferMode device %x- TMSelected = 0x%x\n",
  1225. i,
  1226. DeviceExtension->DeviceParameters[i].TransferModeSelected));
  1227. CLRMASK (DeviceExtension->DeviceFlags[i], DFLAGS_USE_DMA | DFLAGS_USE_UDMA);
  1228. if (!DeviceExtension->NoPioSetTransferMode) {
  1229. //
  1230. // many old devices just don't support set transfer mode
  1231. // they act unpredictably after receiving one
  1232. // e.g. "SAMSUNG SCR-730 REV D-05" cdrom will start returning
  1233. // no error on TEST_UNIT_READY even if it doesn't have a media
  1234. //
  1235. // we are going to apply some magic code here!!
  1236. // we would not set transfer mode if the device doesn't support
  1237. // timing faster than mode2
  1238. //
  1239. GetHighestPIOTransferMode(DeviceExtension->DeviceParameters[i].TransferModeSelected, xferMode);
  1240. if (xferMode > PIO2) {
  1241. DebugPrint((DBG_XFERMODE, "ATAPI: device %x, setting PIOmode 0x%x\n",
  1242. i,
  1243. xferMode));
  1244. ideCommand = IDE_SET_ADVANCE_PIO_MODE(xferMode-PIO0);
  1245. pioModeStatus = AtapiSetTransferMode (
  1246. DeviceExtension,
  1247. i,
  1248. ideCommand
  1249. );
  1250. if (!NT_SUCCESS(pioModeStatus)) {
  1251. DebugPrint ((DBG_ALWAYS,
  1252. "ATAPI: Unable to set pio xfer mode %d for 0x%x device %d\n",
  1253. xferMode,
  1254. DeviceExtension->BaseIoAddress1.RegistersBaseAddress,
  1255. i));
  1256. }
  1257. }
  1258. }
  1259. //
  1260. // Program DMA mode
  1261. //
  1262. GetHighestDMATransferMode(DeviceExtension->DeviceParameters[i].TransferModeSelected, xferMode);
  1263. if (xferMode >= UDMA0) {
  1264. ideCommand = IDE_SET_UDMA_MODE(xferMode-UDMA0);
  1265. } else if (xferMode >= MWDMA0) {
  1266. ideCommand = IDE_SET_MWDMA_MODE(xferMode-MWDMA0);
  1267. } else if (xferMode >= SWDMA0) {
  1268. ideCommand = IDE_SET_SWDMA_MODE(xferMode-SWDMA0);
  1269. }
  1270. //
  1271. // Issue the set features command only if we support
  1272. // any of the DMA modes
  1273. //
  1274. if (xferMode >= SWDMA0) {
  1275. DebugPrint((DBG_XFERMODE, "ATAPI: device %x, setting DMAmode 0x%x\n",
  1276. i,
  1277. xferMode));
  1278. dmaModeStatus = AtapiSetTransferMode (
  1279. DeviceExtension,
  1280. i,
  1281. ideCommand
  1282. );
  1283. if (NT_SUCCESS(dmaModeStatus)) {
  1284. DeviceExtension->DeviceFlags[i] |= DFLAGS_USE_DMA;
  1285. if (xferMode >= UDMA0) {
  1286. DeviceExtension->DeviceFlags[i] |= DFLAGS_USE_UDMA;
  1287. }
  1288. } else {
  1289. DebugPrint ((DBG_ALWAYS,
  1290. "ATAPI: Unable to set DMA mode %d for 0x%x device %d\n",
  1291. xferMode,
  1292. DeviceExtension->BaseIoAddress1.RegistersBaseAddress,
  1293. i));
  1294. }
  1295. }
  1296. }
  1297. return;
  1298. }
  1299. BOOLEAN
  1300. AtapiHwInitialize(
  1301. IN PVOID HwDeviceExtension,
  1302. IN UCHAR FlushCommand[MAX_IDE_DEVICE * MAX_IDE_LINE]
  1303. )
  1304. /*++
  1305. Routine Description:
  1306. Arguments:
  1307. HwDeviceExtension - HBA miniport driver's adapter data storage
  1308. Return Value:
  1309. TRUE - if initialization successful.
  1310. FALSE - if initialization unsuccessful.
  1311. --*/
  1312. {
  1313. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  1314. PIDE_REGISTERS_1 baseIoAddress;
  1315. ULONG i;
  1316. UCHAR statusByte, errorByte;
  1317. baseIoAddress = &deviceExtension->BaseIoAddress1;
  1318. for (i = 0; i < deviceExtension->MaxIdeDevice; i++) {
  1319. if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) {
  1320. //
  1321. // Select device
  1322. //
  1323. SelectIdeDevice(baseIoAddress, i, 0);
  1324. //
  1325. // Make sure device is ready for any command
  1326. //
  1327. if (!(deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE)) {
  1328. WaitForDRDY(baseIoAddress, statusByte);
  1329. }
  1330. if (!(deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE)) {
  1331. //
  1332. // Enable media status notification
  1333. //
  1334. IdeMediaStatus(TRUE,HwDeviceExtension,i);
  1335. //
  1336. // If supported, setup Multi-block transfers.
  1337. //
  1338. if (deviceExtension->MaximumBlockXfer[i]) {
  1339. //
  1340. // Select the device.
  1341. //
  1342. SelectIdeDevice(baseIoAddress, i, 0);
  1343. //
  1344. // Setup sector count to reflect the # of blocks.
  1345. //
  1346. IdePortOutPortByte(baseIoAddress->BlockCount,
  1347. deviceExtension->MaximumBlockXfer[i]);
  1348. //
  1349. // Issue the command.
  1350. //
  1351. IdePortOutPortByte(baseIoAddress->Command,
  1352. IDE_COMMAND_SET_MULTIPLE);
  1353. //
  1354. // Wait for busy to drop.
  1355. //
  1356. WaitOnBaseBusy(baseIoAddress,statusByte);
  1357. //
  1358. // Check for errors. Reset the value to 0 (disable MultiBlock) if the
  1359. // command was aborted.
  1360. //
  1361. if (statusByte & IDE_STATUS_ERROR) {
  1362. //
  1363. // Read the error register.
  1364. //
  1365. errorByte = IdePortInPortByte(baseIoAddress->Error);
  1366. DebugPrint((1,
  1367. "AtapiHwInitialize: Error setting multiple mode. Status %x, error byte %x\n",
  1368. statusByte,
  1369. errorByte));
  1370. //
  1371. // Adjust the devExt. value, if necessary.
  1372. //
  1373. deviceExtension->MaximumBlockXfer[i] = 0;
  1374. } else {
  1375. DebugPrint((2,
  1376. "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
  1377. i,
  1378. deviceExtension->MaximumBlockXfer[i]));
  1379. }
  1380. }
  1381. }
  1382. // IdeMediaStatus(TRUE,HwDeviceExtension,i);
  1383. //
  1384. // We need to get our device ready for action before
  1385. // returning from this function
  1386. //
  1387. // According to the atapi spec 2.5 or 2.6, an atapi device
  1388. // clears its status BSY bit when it is ready for atapi commands.
  1389. // However, some devices (Panasonic SQ-TC500N) are still
  1390. // not ready even when the status BSY is clear. They don't react
  1391. // to atapi commands.
  1392. //
  1393. // Since there is really no other indication that tells us
  1394. // the drive is really ready for action. We are going to check BSY
  1395. // is clear and then just wait for an arbitrary amount of time! At
  1396. // least for the older ATAPI changers.
  1397. //
  1398. if (deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE) {
  1399. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  1400. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  1401. ULONG waitCount;
  1402. // have to get out of the loop sometime!
  1403. // 10000 * 100us = 1000,000us = 1000ms = 1s
  1404. waitCount = 10000;
  1405. GetStatus(baseIoAddress1, statusByte);
  1406. while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
  1407. //
  1408. // Wait for Busy to drop.
  1409. //
  1410. KeStallExecutionProcessor(100);
  1411. GetStatus(baseIoAddress1, statusByte);
  1412. waitCount--;
  1413. }
  1414. }
  1415. }
  1416. }
  1417. AtapiProgramTransferMode (deviceExtension);
  1418. InitDeviceParameters (HwDeviceExtension, FlushCommand);
  1419. return TRUE;
  1420. } // end AtapiHwInitialize()
  1421. VOID
  1422. AtapiHwInitializeMultiLun (
  1423. IN PVOID HwDeviceExtension,
  1424. IN ULONG TargetId,
  1425. IN ULONG numSlot
  1426. )
  1427. {
  1428. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  1429. deviceExtension->DeviceFlags[TargetId] |= DFLAGS_MULTI_LUN_INITED;
  1430. deviceExtension->LastLun[TargetId] = (numSlot == 0) ? 0 : (numSlot - 1);
  1431. return;
  1432. }
  1433. #ifdef DRIVER_PARAMETER_REGISTRY_SUPPORT
  1434. ULONG
  1435. AtapiParseArgumentString(
  1436. IN PCHAR String,
  1437. IN PCHAR KeyWord
  1438. )
  1439. /*++
  1440. Routine Description:
  1441. This routine will parse the string for a match on the keyword, then
  1442. calculate the value for the keyword and return it to the caller.
  1443. Arguments:
  1444. String - The ASCII string to parse.
  1445. KeyWord - The keyword for the value desired.
  1446. Return Values:
  1447. Zero if value not found
  1448. Value converted from ASCII to binary.
  1449. --*/
  1450. {
  1451. PCHAR cptr;
  1452. PCHAR kptr;
  1453. ULONG value;
  1454. ULONG stringLength = 0;
  1455. ULONG keyWordLength = 0;
  1456. ULONG index;
  1457. if (!String) {
  1458. return 0;
  1459. }
  1460. if (!KeyWord) {
  1461. return 0;
  1462. }
  1463. //
  1464. // Calculate the string length and lower case all characters.
  1465. //
  1466. cptr = String;
  1467. while (*cptr) {
  1468. if (*cptr >= 'A' && *cptr <= 'Z') {
  1469. *cptr = *cptr + ('a' - 'A');
  1470. }
  1471. cptr++;
  1472. stringLength++;
  1473. }
  1474. //
  1475. // Calculate the keyword length and lower case all characters.
  1476. //
  1477. cptr = KeyWord;
  1478. while (*cptr) {
  1479. if (*cptr >= 'A' && *cptr <= 'Z') {
  1480. *cptr = *cptr + ('a' - 'A');
  1481. }
  1482. cptr++;
  1483. keyWordLength++;
  1484. }
  1485. if (keyWordLength > stringLength) {
  1486. //
  1487. // Can't possibly have a match.
  1488. //
  1489. return 0;
  1490. }
  1491. //
  1492. // Now setup and start the compare.
  1493. //
  1494. cptr = String;
  1495. ContinueSearch:
  1496. //
  1497. // The input string may start with white space. Skip it.
  1498. //
  1499. while (*cptr == ' ' || *cptr == '\t') {
  1500. cptr++;
  1501. }
  1502. if (*cptr == '\0') {
  1503. //
  1504. // end of string.
  1505. //
  1506. return 0;
  1507. }
  1508. kptr = KeyWord;
  1509. while (*cptr++ == *kptr++) {
  1510. if (*(cptr - 1) == '\0') {
  1511. //
  1512. // end of string
  1513. //
  1514. return 0;
  1515. }
  1516. }
  1517. if (*(kptr - 1) == '\0') {
  1518. //
  1519. // May have a match backup and check for blank or equals.
  1520. //
  1521. cptr--;
  1522. while (*cptr == ' ' || *cptr == '\t') {
  1523. cptr++;
  1524. }
  1525. //
  1526. // Found a match. Make sure there is an equals.
  1527. //
  1528. if (*cptr != '=') {
  1529. //
  1530. // Not a match so move to the next semicolon.
  1531. //
  1532. while (*cptr) {
  1533. if (*cptr++ == ';') {
  1534. goto ContinueSearch;
  1535. }
  1536. }
  1537. return 0;
  1538. }
  1539. //
  1540. // Skip the equals sign.
  1541. //
  1542. cptr++;
  1543. //
  1544. // Skip white space.
  1545. //
  1546. while ((*cptr == ' ') || (*cptr == '\t')) {
  1547. cptr++;
  1548. }
  1549. if (*cptr == '\0') {
  1550. //
  1551. // Early end of string, return not found
  1552. //
  1553. return 0;
  1554. }
  1555. if (*cptr == ';') {
  1556. //
  1557. // This isn't it either.
  1558. //
  1559. cptr++;
  1560. goto ContinueSearch;
  1561. }
  1562. value = 0;
  1563. if ((*cptr == '0') && (*(cptr + 1) == 'x')) {
  1564. //
  1565. // Value is in Hex. Skip the "0x"
  1566. //
  1567. cptr += 2;
  1568. for (index = 0; *(cptr + index); index++) {
  1569. if (*(cptr + index) == ' ' ||
  1570. *(cptr + index) == '\t' ||
  1571. *(cptr + index) == ';') {
  1572. break;
  1573. }
  1574. if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
  1575. value = (16 * value) + (*(cptr + index) - '0');
  1576. } else {
  1577. if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
  1578. value = (16 * value) + (*(cptr + index) - 'a' + 10);
  1579. } else {
  1580. //
  1581. // Syntax error, return not found.
  1582. //
  1583. return 0;
  1584. }
  1585. }
  1586. }
  1587. } else {
  1588. //
  1589. // Value is in Decimal.
  1590. //
  1591. for (index = 0; *(cptr + index); index++) {
  1592. if (*(cptr + index) == ' ' ||
  1593. *(cptr + index) == '\t' ||
  1594. *(cptr + index) == ';') {
  1595. break;
  1596. }
  1597. if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
  1598. value = (10 * value) + (*(cptr + index) - '0');
  1599. } else {
  1600. //
  1601. // Syntax error return not found.
  1602. //
  1603. return 0;
  1604. }
  1605. }
  1606. }
  1607. return value;
  1608. } else {
  1609. //
  1610. // Not a match check for ';' to continue search.
  1611. //
  1612. while (*cptr) {
  1613. if (*cptr++ == ';') {
  1614. goto ContinueSearch;
  1615. }
  1616. }
  1617. return 0;
  1618. }
  1619. }
  1620. #endif
  1621. VOID
  1622. InitDeviceParameters (
  1623. IN PVOID HwDeviceExtension,
  1624. IN UCHAR FlushCommand[MAX_IDE_DEVICE * MAX_IDE_LINE]
  1625. )
  1626. {
  1627. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  1628. ULONG deviceNumber;
  1629. //
  1630. // pick out the ATA or ATAPI r/w command we are going to use
  1631. //
  1632. for (deviceNumber = 0; deviceNumber < deviceExtension->MaxIdeDevice; deviceNumber++) {
  1633. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT) {
  1634. DebugPrint ((DBG_BUSSCAN, "ATAPI: Base=0x%x Device %d is going to do ", deviceExtension->BaseIoAddress1.RegistersBaseAddress, deviceNumber));
  1635. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_USE_DMA) {
  1636. DebugPrint ((DBG_BUSSCAN, "DMA\n"));
  1637. } else {
  1638. DebugPrint ((DBG_BUSSCAN, "PIO\n"));
  1639. }
  1640. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_ATAPI_DEVICE) {
  1641. deviceExtension->DeviceParameters[deviceNumber].MaxBytePerPioInterrupt = 512;
  1642. } else {
  1643. if (deviceExtension->MaximumBlockXfer[deviceNumber]) {
  1644. DebugPrint ((DBG_BUSSCAN, "ATAPI: ATA Device (%d) is going to do PIO Multiple\n", deviceNumber));
  1645. deviceExtension->DeviceParameters[deviceNumber].IdePioReadCommand = IDE_COMMAND_READ_MULTIPLE;
  1646. deviceExtension->DeviceParameters[deviceNumber].IdePioWriteCommand = IDE_COMMAND_WRITE_MULTIPLE;
  1647. #ifdef ENABLE_48BIT_LBA
  1648. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_48BIT_LBA) {
  1649. deviceExtension->DeviceParameters[deviceNumber].IdePioReadCommandExt = IDE_COMMAND_READ_MULTIPLE_EXT;
  1650. deviceExtension->DeviceParameters[deviceNumber].IdePioWriteCommandExt = IDE_COMMAND_WRITE_MULTIPLE_EXT;
  1651. }
  1652. #endif
  1653. deviceExtension->DeviceParameters[deviceNumber].MaxBytePerPioInterrupt =
  1654. deviceExtension->MaximumBlockXfer[deviceNumber] * 512;
  1655. } else {
  1656. DebugPrint ((DBG_BUSSCAN, "ATAPI: ATA Device (%d) is going to do PIO Single\n", deviceNumber));
  1657. deviceExtension->DeviceParameters[deviceNumber].IdePioReadCommand = IDE_COMMAND_READ;
  1658. deviceExtension->DeviceParameters[deviceNumber].IdePioWriteCommand = IDE_COMMAND_WRITE;
  1659. #ifdef ENABLE_48BIT_LBA
  1660. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_48BIT_LBA) {
  1661. deviceExtension->DeviceParameters[deviceNumber].IdePioReadCommandExt = IDE_COMMAND_READ_EXT;
  1662. deviceExtension->DeviceParameters[deviceNumber].IdePioWriteCommandExt = IDE_COMMAND_WRITE_EXT;
  1663. }
  1664. #endif
  1665. deviceExtension->DeviceParameters[deviceNumber].MaxBytePerPioInterrupt = 512;
  1666. }
  1667. if (FlushCommand) {
  1668. deviceExtension->DeviceParameters[deviceNumber].IdeFlushCommand = FlushCommand[deviceNumber];
  1669. #ifdef ENABLE_48BIT_LBA
  1670. //
  1671. // if the flush command worked then we are going to assume that the flush command
  1672. // for the 48 bit LBA feature set is supported.
  1673. //
  1674. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_48BIT_LBA) {
  1675. deviceExtension->DeviceParameters[deviceNumber].IdeFlushCommandExt = IDE_COMMAND_FLUSH_CACHE_EXT;
  1676. deviceExtension->DeviceParameters[deviceNumber].IdeFlushCommand = IDE_COMMAND_NO_FLUSH;
  1677. }
  1678. #endif
  1679. }
  1680. }
  1681. }
  1682. }
  1683. }
  1684. ULONG
  1685. Atapi2Scsi(
  1686. IN PHW_DEVICE_EXTENSION DeviceExtension,
  1687. IN PSCSI_REQUEST_BLOCK Srb,
  1688. IN char *DataBuffer,
  1689. IN ULONG ByteCount
  1690. )
  1691. /*++
  1692. Routine Description:
  1693. Convert atapi cdb and mode sense data to scsi format
  1694. Arguments:
  1695. Srb - SCSI request block
  1696. DataBuffer - mode sense data
  1697. ByteCount - mode sense data length
  1698. Return Value:
  1699. byte adjust
  1700. --*/
  1701. {
  1702. ULONG bytesAdjust = 0;
  1703. if (DeviceExtension->scsi2atapi) {
  1704. if (Srb->Cdb[0] == ATAPI_MODE_SENSE) {
  1705. ASSERT(FALSE);
  1706. } else if (Srb->Cdb[0] == ATAPI_LS120_FORMAT_UNIT) {
  1707. Srb->Cdb[0] = SCSIOP_FORMAT_UNIT;
  1708. }
  1709. RESTORE_ORIGINAL_CDB(DeviceExtension, Srb);
  1710. DeviceExtension->scsi2atapi = FALSE;
  1711. }
  1712. return bytesAdjust;
  1713. }
  1714. VOID
  1715. AtapiCallBack(
  1716. IN PVOID HwDeviceExtension
  1717. )
  1718. {
  1719. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  1720. PSCSI_REQUEST_BLOCK srb = deviceExtension->CurrentSrb;
  1721. PATAPI_REGISTERS_1 baseIoAddress1;
  1722. UCHAR statusByte;
  1723. //
  1724. // If the last command was DSC restrictive, see if it's set. If so, the device is
  1725. // ready for a new request. Otherwise, reset the timer and come back to here later.
  1726. //
  1727. if (srb && (!(deviceExtension->ExpectingInterrupt))) {
  1728. #if DBG
  1729. if (!SRB_IS_RDP(srb)) {
  1730. DebugPrint((1,
  1731. "AtapiCallBack: Invalid CDB marked as RDP - %x\n",
  1732. srb->Cdb[0]));
  1733. }
  1734. #endif
  1735. baseIoAddress1 = (PATAPI_REGISTERS_1)&deviceExtension->BaseIoAddress1;
  1736. if (deviceExtension->RDP) {
  1737. GetStatus(baseIoAddress1, statusByte);
  1738. if (statusByte & IDE_STATUS_DSC) {
  1739. IdePortNotification(IdeRequestComplete,
  1740. deviceExtension,
  1741. srb);
  1742. //
  1743. // Clear current SRB.
  1744. //
  1745. deviceExtension->CurrentSrb = NULL;
  1746. deviceExtension->RDP = FALSE;
  1747. //
  1748. // Ask for next request.
  1749. //
  1750. IdePortNotification(IdeNextRequest,
  1751. deviceExtension,
  1752. NULL);
  1753. return;
  1754. } else {
  1755. DebugPrint((3,
  1756. "AtapiCallBack: Requesting another timer for Op %x\n",
  1757. deviceExtension->CurrentSrb->Cdb[0]));
  1758. IdePortNotification(IdeRequestTimerCall,
  1759. HwDeviceExtension,
  1760. AtapiCallBack,
  1761. 1000);
  1762. return;
  1763. }
  1764. }
  1765. }
  1766. DebugPrint((2,
  1767. "AtapiCallBack: Calling ISR directly due to BUSY\n"));
  1768. AtapiInterrupt(HwDeviceExtension);
  1769. }
  1770. //#define IdeCrashDumpLogIsrStatus(hwExtension, isrStatus) hwExtension->CrashDumpIsrStatus[hwExtension->CrashDumpLogIndex]=isrStatus;
  1771. BOOLEAN
  1772. AtapiInterrupt(
  1773. IN PVOID HwDeviceExtension
  1774. )
  1775. /*++
  1776. Routine Description:
  1777. This is the interrupt service routine for ATAPI IDE miniport driver.
  1778. Arguments:
  1779. HwDeviceExtension - HBA miniport driver's adapter data storage
  1780. Return Value:
  1781. TRUE if expecting an interrupt.
  1782. --*/
  1783. {
  1784. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  1785. PSCSI_REQUEST_BLOCK srb = deviceExtension->CurrentSrb;
  1786. PATAPI_REGISTERS_1 baseIoAddress1;
  1787. PATAPI_REGISTERS_2 baseIoAddress2;
  1788. ULONG byteCount = 0, bytesThisInterrupt = 512;
  1789. ULONG status;
  1790. ULONG i;
  1791. UCHAR statusByte,interruptReason;
  1792. BOOLEAN commandComplete = FALSE;
  1793. BOOLEAN atapiDev = FALSE;
  1794. UCHAR dmaStatus;
  1795. BOOLEAN fakeStatus = FALSE;
  1796. BOOLEAN packetBasedSrb;
  1797. BOOLEAN wdModeCdRom;
  1798. BMSTATUS bmStatus=0;
  1799. BOOLEAN dmaInProgress = FALSE;
  1800. BOOLEAN alwaysClearBusMasterInterrupt;
  1801. UCHAR savedCmd;
  1802. BOOLEAN interruptCleared = FALSE;
  1803. alwaysClearBusMasterInterrupt = deviceExtension->BusMasterInterface.AlwaysClearBusMasterInterrupt;
  1804. //
  1805. // if this flag is set, we must try to clear the busmaster interrupt
  1806. // this is to overcome a bug in the cpq controller
  1807. // this is set for native mode contollers
  1808. //
  1809. if (alwaysClearBusMasterInterrupt) {
  1810. if (deviceExtension->BusMasterInterface.BmStatus) {
  1811. bmStatus = deviceExtension->BusMasterInterface.BmStatus (deviceExtension->BusMasterInterface.Context);
  1812. if (bmStatus & BMSTATUS_INTERRUPT) {
  1813. deviceExtension->BusMasterInterface.BmDisarm (deviceExtension->BusMasterInterface.Context);
  1814. interruptCleared = TRUE;
  1815. }
  1816. }
  1817. }
  1818. if (srb) {
  1819. baseIoAddress1 = (PATAPI_REGISTERS_1)&deviceExtension->BaseIoAddress1;
  1820. baseIoAddress2 = (PATAPI_REGISTERS_2)&deviceExtension->BaseIoAddress2;
  1821. } else {
  1822. DebugPrint((1,
  1823. "AtapiInterrupt: CurrentSrb is NULL. Bogus Interrupt\n"));
  1824. if (deviceExtension->InterruptMode == LevelSensitive) {
  1825. if (deviceExtension->BaseIoAddress1.RegistersBaseAddress != NULL) {
  1826. baseIoAddress1 = (PATAPI_REGISTERS_1)&deviceExtension->BaseIoAddress1;
  1827. GetBaseStatus(baseIoAddress1, statusByte);
  1828. /*
  1829. GetSelectedIdeDevice(baseIoAddress1, savedCmd);
  1830. SelectIdeDevice(baseIoAddress1, 0, 0);
  1831. GetBaseStatus(baseIoAddress1, statusByte);
  1832. SelectIdeDevice(baseIoAddress1, 1, 0);
  1833. GetBaseStatus(baseIoAddress1, statusByte);
  1834. ReSelectIdeDevice(baseIoAddress1, savedCmd);
  1835. */
  1836. }
  1837. }
  1838. return interruptCleared;
  1839. }
  1840. if (!(deviceExtension->ExpectingInterrupt)) {
  1841. DebugPrint((1,
  1842. "AtapiInterrupt: Unexpected interrupt.\n"));
  1843. return interruptCleared;
  1844. }
  1845. if (!alwaysClearBusMasterInterrupt) {
  1846. if (deviceExtension->BusMasterInterface.BmStatus) {
  1847. bmStatus = deviceExtension->BusMasterInterface.BmStatus (deviceExtension->BusMasterInterface.Context);
  1848. if (bmStatus & BMSTATUS_INTERRUPT) {
  1849. deviceExtension->BusMasterInterface.BmDisarm (deviceExtension->BusMasterInterface.Context);
  1850. }
  1851. }
  1852. }
  1853. //
  1854. // For SiS IDE Controller, we have to read the bm status register first
  1855. //
  1856. if (deviceExtension->DMAInProgress) {
  1857. // PCI Busmaster IDE Controller spec defines a bit in its status
  1858. // register which indicates pending interrupt. However,
  1859. // CMD 646 (maybe some other one, too) doesn't always do that if
  1860. // the interrupt is from a atapi device. (strange, but true!)
  1861. // Since we can look at this interrupt bit only if we are sharing
  1862. // interrupt, we will do just that
  1863. //
  1864. // Doesn't look like it is our interrupt
  1865. // If we are called from crashdmp (polling mode) then prociess the interrupt
  1866. // even if the bit is not set. It is checked in the crashdmp routine.
  1867. //
  1868. if (!(bmStatus & BMSTATUS_INTERRUPT) &&
  1869. !(deviceExtension->DriverMustPoll)) {
  1870. DebugPrint((1, "No BusMaster Interrupt\n"));
  1871. ASSERT(interruptCleared == FALSE);
  1872. return FALSE;
  1873. }
  1874. dmaInProgress = deviceExtension->DMAInProgress;
  1875. deviceExtension->DMAInProgress = FALSE;
  1876. if (deviceExtension->BusMasterInterface.IgnoreActiveBitForAtaDevice) {
  1877. if (!(deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE)) {
  1878. CLRMASK (bmStatus, BMSTATUS_NOT_REACH_END_OF_TRANSFER);
  1879. }
  1880. }
  1881. }
  1882. //
  1883. // should we check for the interrupt bit for PIO transfers?
  1884. //
  1885. //
  1886. // Select IDE line(Primary or Secondary).
  1887. //
  1888. SelectIdeLine(baseIoAddress1, srb->TargetId >> 1);
  1889. //
  1890. // Clear interrupt by reading status.
  1891. //
  1892. GetBaseStatus(baseIoAddress1, statusByte);
  1893. #ifdef ENABLE_ATAPI_VERIFIER
  1894. if (ViIdeGenerateDmaTimeout(deviceExtension, dmaInProgress)) {
  1895. deviceExtension->ExpectingInterrupt = FALSE;
  1896. return TRUE;
  1897. }
  1898. #endif
  1899. //
  1900. // Log the bus master status
  1901. //
  1902. if (!deviceExtension->DriverMustPoll) {
  1903. IdeLogBmStatus(srb, bmStatus);
  1904. }
  1905. //IdeCrashDumpLogIsrStatus(deviceExtension, bmStatus);
  1906. //
  1907. // check the type of srb we have
  1908. //
  1909. if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
  1910. packetBasedSrb = TRUE;
  1911. } else {
  1912. packetBasedSrb = FALSE;
  1913. }
  1914. if ((srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH) ||
  1915. (srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  1916. PATA_PASS_THROUGH ataPassThroughData;
  1917. PIDEREGS pIdeReg;
  1918. packetBasedSrb = FALSE;
  1919. ataPassThroughData = srb->DataBuffer;
  1920. pIdeReg = &ataPassThroughData->IdeReg;
  1921. //
  1922. // if the last command we issued was a SLEEP command,
  1923. // the device interface (task registers) is invalid.
  1924. // In order to complete the interrupt, will fake the
  1925. // a good status
  1926. //
  1927. if (pIdeReg->bCommandReg == IDE_COMMAND_SLEEP) {
  1928. fakeStatus = TRUE;
  1929. }
  1930. }
  1931. if (fakeStatus) {
  1932. statusByte = IDE_STATUS_IDLE;
  1933. }
  1934. DebugPrint((1,
  1935. "AtapiInterrupt: Entered with status (%x)\n",
  1936. statusByte));
  1937. if (statusByte & IDE_STATUS_BUSY) {
  1938. if (deviceExtension->DriverMustPoll) {
  1939. //
  1940. // Crashdump is polling and we got caught with busy asserted.
  1941. // Just go away, and we will be polled again shortly.
  1942. //
  1943. DebugPrint((1,
  1944. "AtapiInterrupt: Hit status=0x%x while polling during crashdump.\n",
  1945. statusByte
  1946. ));
  1947. deviceExtension->DMAInProgress = TRUE;
  1948. return TRUE;
  1949. }
  1950. if (dmaInProgress) {
  1951. //
  1952. // this is really bad since we already disabled
  1953. // dma at this point, but the device is still busy
  1954. // can't really recover. just return from now.
  1955. // the timeout code will kick in and save the world
  1956. //
  1957. DebugPrint((DBG_ALWAYS,
  1958. "AtapiInterrupt: End of DMA transfer but device is still BUSY. status = 0x%x\n",
  1959. statusByte));
  1960. //
  1961. // we are not expecting interrupt anymore. Clear the flag.
  1962. //
  1963. deviceExtension->ExpectingInterrupt = FALSE;
  1964. return interruptCleared;
  1965. }
  1966. //
  1967. // Ensure BUSY is non-asserted.
  1968. //
  1969. for (i = 0; i < 10; i++) {
  1970. GetBaseStatus(baseIoAddress1, statusByte);
  1971. if (!(statusByte & IDE_STATUS_BUSY)) {
  1972. break;
  1973. }
  1974. }
  1975. if (i == 10) {
  1976. DebugPrint((2,
  1977. "AtapiInterrupt: BUSY on entry. Status %x, Base IO %x\n",
  1978. statusByte,
  1979. baseIoAddress1));
  1980. IdePortNotification(IdeRequestTimerCall,
  1981. HwDeviceExtension,
  1982. AtapiCallBack,
  1983. 500);
  1984. return interruptCleared;
  1985. }
  1986. }
  1987. //
  1988. // Check for error conditions.
  1989. //
  1990. if (statusByte & IDE_STATUS_ERROR) {
  1991. if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
  1992. //
  1993. // Fail this request.
  1994. //
  1995. status = SRB_STATUS_ERROR;
  1996. goto CompleteRequest;
  1997. }
  1998. }
  1999. wdModeCdRom = FALSE;
  2000. if (Is98LegacyIde(baseIoAddress1)) {
  2001. if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_WD_MODE) {
  2002. if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
  2003. wdModeCdRom = TRUE;
  2004. } else {
  2005. status = SRB_STATUS_ERROR;
  2006. goto CompleteRequest;
  2007. }
  2008. }
  2009. }
  2010. //
  2011. // check reason for this interrupt.
  2012. //
  2013. if (packetBasedSrb && !wdModeCdRom) {
  2014. interruptReason = (IdePortInPortByte(baseIoAddress1->InterruptReason) & 0x3);
  2015. atapiDev = TRUE;
  2016. bytesThisInterrupt = 512;
  2017. if (dmaInProgress) {
  2018. if (interruptReason != 0x3) {
  2019. //
  2020. // the device causes an interrupt in the middle of a
  2021. // dma transfer! bad bad bad device!
  2022. // do nothing and just return. this will get translated
  2023. // to a timeout and we will retry.
  2024. //
  2025. DebugPrint((1,
  2026. "Interrupt during DMA transfer, reason %x != 0x3\n",
  2027. interruptReason
  2028. ));
  2029. deviceExtension->ExpectingInterrupt = FALSE;
  2030. // ISSUE: should we return TRUE?
  2031. return interruptCleared;
  2032. }
  2033. }
  2034. } else {
  2035. if (dmaInProgress) {
  2036. interruptReason = 0x3;
  2037. } else if (statusByte & IDE_STATUS_DRQ) {
  2038. if (deviceExtension->MaximumBlockXfer[srb->TargetId]) {
  2039. bytesThisInterrupt = 512 * deviceExtension->MaximumBlockXfer[srb->TargetId];
  2040. }
  2041. if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  2042. interruptReason = 0x2;
  2043. } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  2044. interruptReason = 0x0;
  2045. } else {
  2046. status = SRB_STATUS_ERROR;
  2047. goto CompleteRequest;
  2048. }
  2049. } else if (statusByte & IDE_STATUS_BUSY) {
  2050. ASSERT(interruptCleared == FALSE);
  2051. return FALSE;
  2052. } else {
  2053. if (deviceExtension->BytesLeft && (!Is98LegacyIde(baseIoAddress1))) {
  2054. //
  2055. // We should return interruptCleared.
  2056. //
  2057. return interruptCleared;
  2058. } else {
  2059. //
  2060. // Command complete - verify, write, or the SMART enable/disable.
  2061. //
  2062. // Also get_media_status
  2063. interruptReason = 0x3;
  2064. }
  2065. }
  2066. }
  2067. if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
  2068. //
  2069. // Write the packet.
  2070. //
  2071. DebugPrint((2,
  2072. "AtapiInterrupt: Writing Atapi packet.\n"));
  2073. //
  2074. // Send CDB to device.
  2075. //
  2076. WriteBuffer(baseIoAddress1,
  2077. (PUSHORT)srb->Cdb,
  2078. 6);
  2079. if (SRB_USES_DMA(srb)) {
  2080. deviceExtension->DMAInProgress = TRUE;
  2081. deviceExtension->BusMasterInterface.BmArm (deviceExtension->BusMasterInterface.Context);
  2082. }
  2083. return interruptCleared;
  2084. } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
  2085. //
  2086. // Write the data.
  2087. //
  2088. if (packetBasedSrb) {
  2089. //
  2090. // Pick up bytes to transfer and convert to words.
  2091. //
  2092. byteCount =
  2093. IdePortInPortByte(baseIoAddress1->ByteCountLow);
  2094. byteCount |=
  2095. IdePortInPortByte(baseIoAddress1->ByteCountHigh) << 8;
  2096. if (byteCount != deviceExtension->BytesLeft) {
  2097. DebugPrint((3,
  2098. "AtapiInterrupt: %d bytes requested; %d bytes xferred\n",
  2099. deviceExtension->BytesLeft,
  2100. byteCount));
  2101. }
  2102. //
  2103. // Verify this makes sense.
  2104. //
  2105. if (byteCount > deviceExtension->BytesLeft) {
  2106. byteCount = deviceExtension->BytesLeft;
  2107. }
  2108. } else {
  2109. //
  2110. // IDE path. Check if words left is at least 256.
  2111. //
  2112. if (deviceExtension->BytesLeft < bytesThisInterrupt) {
  2113. //
  2114. // Transfer only words requested.
  2115. //
  2116. byteCount = deviceExtension->BytesLeft;
  2117. } else {
  2118. //
  2119. // Transfer next block.
  2120. //
  2121. byteCount = bytesThisInterrupt;
  2122. }
  2123. }
  2124. //
  2125. // Ensure that this is a write command.
  2126. //
  2127. if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
  2128. DebugPrint((3,
  2129. "AtapiInterrupt: Write interrupt\n"));
  2130. WaitOnBusy(baseIoAddress1,statusByte);
  2131. WriteBuffer(baseIoAddress1,
  2132. (PUSHORT)deviceExtension->DataBuffer,
  2133. byteCount / sizeof(USHORT));
  2134. if (byteCount & 1) {
  2135. //
  2136. // grab the last byte
  2137. //
  2138. IdePortOutPortByte(
  2139. (PUCHAR)(baseIoAddress1->Data),
  2140. deviceExtension->DataBuffer[byteCount - 1]
  2141. );
  2142. }
  2143. } else {
  2144. DebugPrint((1,
  2145. "AtapiInterrupt: Int reason %x, but srb is for a write %x.\n",
  2146. interruptReason,
  2147. srb));
  2148. //
  2149. // Fail this request.
  2150. //
  2151. status = SRB_STATUS_ERROR;
  2152. goto CompleteRequest;
  2153. }
  2154. //
  2155. // Advance data buffer pointer and bytes left.
  2156. //
  2157. deviceExtension->DataBuffer += byteCount;
  2158. deviceExtension->BytesLeft -= byteCount;
  2159. return interruptCleared;
  2160. } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
  2161. if (packetBasedSrb) {
  2162. //
  2163. // Pick up bytes to transfer
  2164. //
  2165. byteCount =
  2166. IdePortInPortByte(baseIoAddress1->ByteCountLow);
  2167. byteCount |=
  2168. IdePortInPortByte(baseIoAddress1->ByteCountHigh) << 8;
  2169. if (byteCount != deviceExtension->BytesLeft) {
  2170. DebugPrint((3,
  2171. "AtapiInterrupt: %d bytes requested; %d bytes xferred\n",
  2172. deviceExtension->BytesLeft,
  2173. byteCount));
  2174. }
  2175. //
  2176. // Verify this makes sense.
  2177. //
  2178. if (byteCount > deviceExtension->BytesLeft) {
  2179. byteCount = deviceExtension->BytesLeft;
  2180. }
  2181. } else {
  2182. //
  2183. // Check if words left is at least 256.
  2184. //
  2185. if (deviceExtension->BytesLeft < bytesThisInterrupt) {
  2186. //
  2187. // Transfer only words requested.
  2188. //
  2189. byteCount = deviceExtension->BytesLeft;
  2190. } else {
  2191. //
  2192. // Transfer next block.
  2193. //
  2194. byteCount = bytesThisInterrupt;
  2195. }
  2196. }
  2197. //
  2198. // Ensure that this is a read command.
  2199. //
  2200. if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  2201. DebugPrint((3,
  2202. "AtapiInterrupt: Read interrupt\n"));
  2203. WaitOnBusy(baseIoAddress1,statusByte);
  2204. ReadBuffer(baseIoAddress1,
  2205. (PUSHORT)deviceExtension->DataBuffer,
  2206. byteCount / sizeof(USHORT));
  2207. if (byteCount & 1) {
  2208. //
  2209. // grab the last byte
  2210. //
  2211. deviceExtension->DataBuffer[byteCount - 1] = IdePortInPortByte((PUCHAR)(baseIoAddress1->Data));
  2212. }
  2213. } else {
  2214. DebugPrint((1,
  2215. "AtapiInterrupt: Int reason %x, but srb is for a read %x.\n",
  2216. interruptReason,
  2217. srb));
  2218. //
  2219. // Fail this request.
  2220. //
  2221. status = SRB_STATUS_ERROR;
  2222. goto CompleteRequest;
  2223. }
  2224. //
  2225. // Translate ATAPI data back to SCSI data if needed
  2226. //
  2227. if (deviceExtension->scsi2atapi) {
  2228. //
  2229. //convert and adjust the wordCount
  2230. //
  2231. byteCount -= Atapi2Scsi(
  2232. deviceExtension,
  2233. srb,
  2234. deviceExtension->DataBuffer,
  2235. byteCount
  2236. );
  2237. }
  2238. //
  2239. // Advance data buffer pointer and bytes left.
  2240. //
  2241. deviceExtension->DataBuffer += byteCount;
  2242. deviceExtension->BytesLeft -= byteCount;
  2243. //
  2244. // Check for read command complete.
  2245. //
  2246. if (deviceExtension->BytesLeft == 0) {
  2247. if (packetBasedSrb) {
  2248. //
  2249. // Work around to make many atapi devices return correct sector size
  2250. // of 2048. Also certain devices will have sector count == 0x00, check
  2251. // for that also.
  2252. //
  2253. if (!(deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_MULTI_LUN_INITED)) {
  2254. if ((srb->Cdb[0] == 0x25) &&
  2255. ((deviceExtension->IdentifyData[srb->TargetId].GeneralConfiguration >> 8) & 0x1f) == 0x05) {
  2256. deviceExtension->DataBuffer -= byteCount;
  2257. if (deviceExtension->DataBuffer[0] == 0x00) {
  2258. *((ULONG *) &(deviceExtension->DataBuffer[0])) = 0xFFFFFF7F;
  2259. }
  2260. *((ULONG *) &(deviceExtension->DataBuffer[2])) = 0x00080000;
  2261. deviceExtension->DataBuffer += byteCount;
  2262. }
  2263. }
  2264. } else {
  2265. //
  2266. // Completion for IDE drives.
  2267. //
  2268. if (deviceExtension->BytesLeft) {
  2269. status = SRB_STATUS_DATA_OVERRUN;
  2270. } else {
  2271. status = SRB_STATUS_SUCCESS;
  2272. }
  2273. goto CompleteRequest;
  2274. }
  2275. }
  2276. return interruptCleared;
  2277. } else if (interruptReason == 0x3) { // && !(statusByte & IDE_STATUS_DRQ)) {
  2278. if (dmaInProgress) {
  2279. deviceExtension->BytesLeft = 0;
  2280. ASSERT (interruptReason == 3);
  2281. //
  2282. // bmStatus is initalized eariler.
  2283. //
  2284. if (!BMSTATUS_SUCCESS(bmStatus)) {
  2285. if (bmStatus & BMSTATUS_ERROR_TRANSFER) {
  2286. status = SRB_STATUS_ERROR;
  2287. }
  2288. if (bmStatus & BMSTATUS_NOT_REACH_END_OF_TRANSFER) {
  2289. status = SRB_STATUS_DATA_OVERRUN;
  2290. }
  2291. } else {
  2292. status = SRB_STATUS_SUCCESS;
  2293. }
  2294. } else {
  2295. //
  2296. // Command complete.
  2297. //
  2298. if (deviceExtension->BytesLeft) {
  2299. status = SRB_STATUS_DATA_OVERRUN;
  2300. } else {
  2301. status = SRB_STATUS_SUCCESS;
  2302. }
  2303. }
  2304. CompleteRequest:
  2305. if (status == SRB_STATUS_ERROR) {
  2306. DebugPrint ((1,
  2307. "AtapiInterrupt: last command return status byte = 0x%x and error byte = 0x%x\n",
  2308. statusByte,
  2309. IdePortInPortByte(baseIoAddress1->Error)));
  2310. if (deviceExtension->scsi2atapi) {
  2311. RESTORE_ORIGINAL_CDB(deviceExtension, srb);
  2312. deviceExtension->scsi2atapi = FALSE;
  2313. }
  2314. //
  2315. // Map error to specific SRB status and handle request sense.
  2316. //
  2317. if ((srb->Function == SRB_FUNCTION_FLUSH) ||
  2318. (srb->Function == SRB_FUNCTION_SHUTDOWN)) {
  2319. //
  2320. // return status success even if a flush fails
  2321. //
  2322. status = SRB_STATUS_SUCCESS;
  2323. } else {
  2324. //
  2325. // log only the error that is caused by normal reuqest that
  2326. // fails
  2327. //
  2328. if ((srb->Function != SRB_FUNCTION_ATA_PASS_THROUGH) &&
  2329. (srb->Function != SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  2330. status = MapError(deviceExtension,
  2331. srb);
  2332. }
  2333. }
  2334. deviceExtension->RDP = FALSE;
  2335. #if DBG
  2336. //#define ATAPI_RANDOM_RW_ERROR_FREQUENCY 50
  2337. #if ATAPI_RANDOM_RW_ERROR_FREQUENCY
  2338. } else if (status == SRB_STATUS_SUCCESS) {
  2339. static ULONG _____RWCount = 0;
  2340. if ((srb->Cdb[0] == SCSIOP_READ) || (srb->Cdb[0] == SCSIOP_WRITE)) {
  2341. _____RWCount++;
  2342. // if (baseIoAddress1 == (PATAPI_REGISTERS_1)0x170) {
  2343. {
  2344. if ((_____RWCount % ATAPI_RANDOM_RW_ERROR_FREQUENCY) == 0) {
  2345. DebugPrint ((1, "ATAPI: Forcing R/W error\n"));
  2346. srb->SrbStatus = SRB_STATUS_ERROR;
  2347. srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  2348. if (srb->SenseInfoBuffer) {
  2349. PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
  2350. senseBuffer->ErrorCode = 0x70;
  2351. senseBuffer->Valid = 1;
  2352. senseBuffer->AdditionalSenseLength = 0xb;
  2353. senseBuffer->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
  2354. senseBuffer->AdditionalSenseCode = 0;
  2355. senseBuffer->AdditionalSenseCodeQualifier = 0;
  2356. srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  2357. }
  2358. status = srb->SrbStatus;
  2359. }
  2360. }
  2361. }
  2362. #endif // DBG
  2363. #endif // ATAPI_GENERATE_RANDOM_RW_ERROR
  2364. } else {
  2365. //
  2366. // Wait for busy to drop.
  2367. //
  2368. for (i = 0; i < 60; i++) {
  2369. if (fakeStatus) {
  2370. statusByte = IDE_STATUS_IDLE;
  2371. } else {
  2372. GetStatus(baseIoAddress1,statusByte);
  2373. }
  2374. if (!(statusByte & IDE_STATUS_BUSY)) {
  2375. break;
  2376. }
  2377. KeStallExecutionProcessor(500);
  2378. }
  2379. if (i == 60) {
  2380. //
  2381. // reset the controller.
  2382. //
  2383. DebugPrint((0,
  2384. "AtapiInterrupt: Resetting due to BSY still up - %x. Base Io %x\n",
  2385. statusByte,
  2386. baseIoAddress1));
  2387. if (deviceExtension->DriverMustPoll) {
  2388. //
  2389. // When we are polling, no dpc gets enqueued.
  2390. // Try a quick reset...
  2391. //
  2392. //AtapiSyncResetController (HwDeviceExtension,srb->PathId);
  2393. status = SRB_STATUS_BUS_RESET;
  2394. } else {
  2395. //
  2396. // Reset the controller in the completion DPC
  2397. //
  2398. //AtapiSyncResetController (HwDeviceExtension,srb->PathId);
  2399. IdePortNotification(IdeResetRequest,
  2400. deviceExtension,
  2401. NULL);
  2402. return interruptCleared;
  2403. }
  2404. }
  2405. //
  2406. // Check to see if DRQ is still up.
  2407. //
  2408. if (statusByte & IDE_STATUS_DRQ) {
  2409. for (i = 0; i < 500; i++) {
  2410. GetStatus(baseIoAddress1,statusByte);
  2411. if (!(statusByte & IDE_STATUS_DRQ)) {
  2412. break;
  2413. }
  2414. KeStallExecutionProcessor(100);
  2415. }
  2416. if (i == 500) {
  2417. //
  2418. // reset the controller.
  2419. //
  2420. DebugPrint((0,
  2421. "AtapiInterrupt: Resetting due to DRQ still up - %x\n",
  2422. statusByte));
  2423. if (deviceExtension->DriverMustPoll) {
  2424. //
  2425. // When we are polling, no dpc gets enqueued.
  2426. // Try a quick reset...
  2427. //
  2428. //AtapiSyncResetController (HwDeviceExtension,srb->PathId);
  2429. status = SRB_STATUS_BUS_RESET;
  2430. } else {
  2431. //
  2432. // Reset the controller in the completion DPC
  2433. //
  2434. //AtapiSyncResetController (HwDeviceExtension,srb->PathId);
  2435. IdePortNotification(IdeResetRequest,
  2436. deviceExtension,
  2437. NULL);
  2438. return interruptCleared;
  2439. }
  2440. }
  2441. }
  2442. }
  2443. //
  2444. // Clear interrupt expecting and dmaInProgress flag.
  2445. //
  2446. deviceExtension->ExpectingInterrupt = FALSE;
  2447. //
  2448. // Sanity check that there is a current request.
  2449. //
  2450. if (srb != NULL) {
  2451. //
  2452. // Set status in SRB.
  2453. //
  2454. srb->SrbStatus = (UCHAR)status;
  2455. //
  2456. // Check for underflow.
  2457. //
  2458. if (deviceExtension->BytesLeft) {
  2459. //
  2460. // Subtract out residual words and update if filemark hit,
  2461. // setmark hit , end of data, end of media...
  2462. //
  2463. if (!(deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_TAPE_DEVICE)) {
  2464. if (status == SRB_STATUS_DATA_OVERRUN) {
  2465. srb->DataTransferLength -= deviceExtension->BytesLeft;
  2466. } else {
  2467. srb->DataTransferLength = 0;
  2468. }
  2469. } else {
  2470. srb->DataTransferLength -= deviceExtension->BytesLeft;
  2471. }
  2472. }
  2473. if ((srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH) ||
  2474. (srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  2475. PATA_PASS_THROUGH ataPassThroughData = srb->DataBuffer;
  2476. AtapiTaskRegisterSnapshot ((PIDE_REGISTERS_1)baseIoAddress1, &ataPassThroughData->IdeReg);
  2477. }
  2478. if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
  2479. //
  2480. // Indicate command complete.
  2481. //
  2482. if (!(deviceExtension->RDP) &&
  2483. !(deviceExtension->DriverMustPoll)) {
  2484. IdePortNotification(IdeRequestComplete,
  2485. deviceExtension,
  2486. srb);
  2487. }
  2488. } else {
  2489. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  2490. UCHAR error = 0;
  2491. if (status != SRB_STATUS_SUCCESS) {
  2492. error = IdePortInPortByte(baseIoAddress1->Error);
  2493. }
  2494. //
  2495. // Build the SMART status block depending upon the completion status.
  2496. //
  2497. cmdOutParameters->cBufferSize = byteCount;
  2498. cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
  2499. cmdOutParameters->DriverStatus.bIDEError = error;
  2500. //
  2501. // If the sub-command is return smart status, jam the value from cylinder low and high, into the
  2502. // data buffer.
  2503. //
  2504. if (deviceExtension->SmartCommand == RETURN_SMART_STATUS) {
  2505. cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
  2506. cmdOutParameters->bBuffer[1] = IdePortInPortByte(baseIoAddress1->InterruptReason);
  2507. cmdOutParameters->bBuffer[2] = IdePortInPortByte(baseIoAddress1->Unused1);
  2508. cmdOutParameters->bBuffer[3] = IdePortInPortByte(baseIoAddress1->ByteCountLow);
  2509. cmdOutParameters->bBuffer[4] = IdePortInPortByte(baseIoAddress1->ByteCountHigh);
  2510. cmdOutParameters->bBuffer[5] = IdePortInPortByte(baseIoAddress1->DriveSelect);
  2511. cmdOutParameters->bBuffer[6] = SMART_CMD;
  2512. cmdOutParameters->cBufferSize = 8;
  2513. }
  2514. //
  2515. // Indicate command complete.
  2516. //
  2517. IdePortNotification(IdeRequestComplete,
  2518. deviceExtension,
  2519. srb);
  2520. }
  2521. } else {
  2522. DebugPrint((1,
  2523. "AtapiInterrupt: No SRB!\n"));
  2524. }
  2525. //
  2526. // Indicate ready for next request.
  2527. //
  2528. if (!(deviceExtension->RDP)) {
  2529. //
  2530. // Clear current SRB.
  2531. //
  2532. deviceExtension->CurrentSrb = NULL;
  2533. if (!deviceExtension->DriverMustPoll) {
  2534. IdePortNotification(IdeNextRequest,
  2535. deviceExtension,
  2536. NULL);
  2537. }
  2538. } else {
  2539. ASSERT(!deviceExtension->DriverMustPoll);
  2540. IdePortNotification(IdeRequestTimerCall,
  2541. HwDeviceExtension,
  2542. AtapiCallBack,
  2543. 2000);
  2544. }
  2545. return interruptCleared;
  2546. } else {
  2547. //
  2548. // Unexpected int.
  2549. //
  2550. DebugPrint((0,
  2551. "AtapiInterrupt: Unexpected interrupt. InterruptReason %x. Status %x.\n",
  2552. interruptReason,
  2553. statusByte));
  2554. ASSERT(interruptCleared == FALSE);
  2555. return FALSE;
  2556. }
  2557. return interruptCleared;
  2558. } // end AtapiInterrupt()
  2559. ULONG
  2560. IdeSendSmartCommand(
  2561. IN PVOID HwDeviceExtension,
  2562. IN PSCSI_REQUEST_BLOCK Srb
  2563. )
  2564. /*++
  2565. Routine Description:
  2566. This routine handles SMART enable, disable, read attributes and threshold commands.
  2567. Arguments:
  2568. HwDeviceExtension - HBA miniport driver's adapter data storage
  2569. Srb - IO request packet
  2570. Return Value:
  2571. SRB status
  2572. --*/
  2573. {
  2574. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  2575. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  2576. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  2577. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  2578. PSENDCMDINPARAMS pCmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  2579. SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  2580. PIDEREGS regs = &cmdInParameters.irDriveRegs;
  2581. ULONG i;
  2582. UCHAR statusByte,targetId;
  2583. ULONG byteCount;
  2584. if (cmdInParameters.irDriveRegs.bCommandReg == SMART_CMD) {
  2585. targetId = cmdInParameters.bDriveNumber;
  2586. //TODO optimize this check
  2587. if ((!(deviceExtension->DeviceFlags[targetId] & DFLAGS_DEVICE_PRESENT)) ||
  2588. (deviceExtension->DeviceFlags[targetId] & DFLAGS_ATAPI_DEVICE)) {
  2589. return SRB_STATUS_SELECTION_TIMEOUT;
  2590. }
  2591. deviceExtension->SmartCommand = cmdInParameters.irDriveRegs.bFeaturesReg;
  2592. //
  2593. // fudge the target Id field in the srb
  2594. // atapi interrupt will use this field.
  2595. //
  2596. Srb->TargetId = targetId;
  2597. //
  2598. // Determine which of the commands to carry out.
  2599. //
  2600. #ifdef ENABLE_SMARTLOG_SUPPORT
  2601. if ((cmdInParameters.irDriveRegs.bFeaturesReg == READ_ATTRIBUTES) ||
  2602. (cmdInParameters.irDriveRegs.bFeaturesReg == READ_THRESHOLDS) ||
  2603. (cmdInParameters.irDriveRegs.bFeaturesReg == SMART_READ_LOG)) {
  2604. #else
  2605. if ((cmdInParameters.irDriveRegs.bFeaturesReg == READ_ATTRIBUTES) ||
  2606. (cmdInParameters.irDriveRegs.bFeaturesReg == READ_THRESHOLDS)) {
  2607. #endif
  2608. ULONG dataLength = 0;
  2609. SelectIdeLine(baseIoAddress1, targetId >> 1);
  2610. WaitOnBusy(baseIoAddress1,statusByte);
  2611. if (statusByte & IDE_STATUS_BUSY) {
  2612. DebugPrint((1,
  2613. "IdeSendSmartCommand: Returning BUSY status\n"));
  2614. return SRB_STATUS_BUSY;
  2615. }
  2616. #ifdef ENABLE_SMARTLOG_SUPPORT
  2617. if (cmdInParameters.irDriveRegs.bFeaturesReg == SMART_READ_LOG) {
  2618. dataLength = cmdInParameters.irDriveRegs.bSectorCountReg* SMART_LOG_SECTOR_SIZE;
  2619. } else {
  2620. dataLength = READ_ATTRIBUTE_BUFFER_SIZE;
  2621. }
  2622. #else
  2623. dataLength = READ_ATTRIBUTE_BUFFER_SIZE;
  2624. #endif
  2625. //
  2626. // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
  2627. //
  2628. for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + dataLength - 1); i++) {
  2629. ((PUCHAR)cmdOutParameters)[i] = 0;
  2630. }
  2631. //
  2632. // Set data buffer pointer and words left.
  2633. //
  2634. deviceExtension->DataBuffer = (PUCHAR)cmdOutParameters->bBuffer;
  2635. deviceExtension->BytesLeft = dataLength;
  2636. //
  2637. // Indicate expecting an interrupt.
  2638. //
  2639. deviceExtension->ExpectingInterrupt = TRUE;
  2640. SelectIdeDevice(baseIoAddress1, targetId, 0);
  2641. IdePortOutPortByte(baseIoAddress1->Error,regs->bFeaturesReg);
  2642. IdePortOutPortByte(baseIoAddress1->BlockCount,regs->bSectorCountReg);
  2643. IdePortOutPortByte(baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
  2644. IdePortOutPortByte(baseIoAddress1->CylinderLow,regs->bCylLowReg);
  2645. IdePortOutPortByte(baseIoAddress1->CylinderHigh,regs->bCylHighReg);
  2646. IdePortOutPortByte(baseIoAddress1->Command,regs->bCommandReg);
  2647. //
  2648. // Wait for interrupt.
  2649. //
  2650. return SRB_STATUS_PENDING;
  2651. } else if ((cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_SMART) ||
  2652. (cmdInParameters.irDriveRegs.bFeaturesReg == DISABLE_SMART) ||
  2653. (cmdInParameters.irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) ||
  2654. (cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE) ||
  2655. (cmdInParameters.irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS) ||
  2656. (cmdInParameters.irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES) ||
  2657. (cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTO_OFFLINE)) {
  2658. #ifdef ENABLE_SMARTLOG_SUPPORT
  2659. //
  2660. // Allow only the non-captive tests, for now.
  2661. //
  2662. if (cmdInParameters.irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS) {
  2663. UCHAR sectorNumber = regs->bSectorNumberReg;
  2664. if ((sectorNumber == SMART_OFFLINE_ROUTINE_OFFLINE) ||
  2665. (sectorNumber == SMART_SHORT_SELFTEST_OFFLINE) ||
  2666. (sectorNumber == SMART_EXTENDED_SELFTEST_OFFLINE) ||
  2667. (sectorNumber == SMART_ABORT_OFFLINE_SELFTEST)) {
  2668. DebugPrint((1,
  2669. "The SMART offline command %x is allowed\n",
  2670. sectorNumber));
  2671. } else if ((sectorNumber == SMART_SHORT_SELFTEST_CAPTIVE) ||
  2672. (sectorNumber == SMART_EXTENDED_SELFTEST_CAPTIVE)) {
  2673. //
  2674. // Don't allow captive mode requests, if you have a slave(another)
  2675. // device
  2676. //
  2677. if (HasSlaveDevice(deviceExtension, targetId)) {
  2678. return SRB_STATUS_INVALID_REQUEST;
  2679. }
  2680. }
  2681. }
  2682. #endif
  2683. SelectIdeLine(baseIoAddress1, targetId >> 1);
  2684. WaitOnBusy(baseIoAddress1,statusByte);
  2685. if (statusByte & IDE_STATUS_BUSY) {
  2686. DebugPrint((1,
  2687. "IdeSendSmartCommand: Returning BUSY status\n"));
  2688. return SRB_STATUS_BUSY;
  2689. }
  2690. //
  2691. // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
  2692. //
  2693. for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) - 1); i++) {
  2694. ((PUCHAR)cmdOutParameters)[i] = 0;
  2695. }
  2696. //
  2697. // Set data buffer pointer and indicate no data transfer.
  2698. //
  2699. deviceExtension->DataBuffer = (PUCHAR)cmdOutParameters->bBuffer;
  2700. deviceExtension->BytesLeft = 0;
  2701. //
  2702. // Indicate expecting an interrupt.
  2703. //
  2704. deviceExtension->ExpectingInterrupt = TRUE;
  2705. SelectIdeDevice(baseIoAddress1, targetId, 0);
  2706. IdePortOutPortByte(baseIoAddress1->Error,regs->bFeaturesReg);
  2707. IdePortOutPortByte(baseIoAddress1->BlockCount,regs->bSectorCountReg);
  2708. IdePortOutPortByte(baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
  2709. IdePortOutPortByte(baseIoAddress1->CylinderLow,regs->bCylLowReg);
  2710. IdePortOutPortByte(baseIoAddress1->CylinderHigh,regs->bCylHighReg);
  2711. IdePortOutPortByte(baseIoAddress1->Command,regs->bCommandReg);
  2712. //
  2713. // Wait for interrupt.
  2714. //
  2715. return SRB_STATUS_PENDING;
  2716. }
  2717. #ifdef ENABLE_SMARTLOG_SUPPORT
  2718. else if (cmdInParameters.irDriveRegs.bFeaturesReg == SMART_WRITE_LOG) {
  2719. SelectIdeLine(baseIoAddress1, targetId >> 1);
  2720. WaitOnBusy(baseIoAddress1,statusByte);
  2721. if (statusByte & IDE_STATUS_BUSY) {
  2722. DebugPrint((1,
  2723. "IdeSendSmartCommand: Returning BUSY status\n"));
  2724. return SRB_STATUS_BUSY;
  2725. }
  2726. //
  2727. // we are assuming that the drive will return an error if we try to
  2728. // write multiple sectors when it is not supported.
  2729. //
  2730. //
  2731. // set the input buffer and the datalength fields.
  2732. //
  2733. deviceExtension->DataBuffer = (PUCHAR)pCmdInParameters->bBuffer;
  2734. deviceExtension->BytesLeft = cmdInParameters.irDriveRegs.bSectorCountReg* SMART_LOG_SECTOR_SIZE;
  2735. //
  2736. // Indicate expecting an interrupt.
  2737. //
  2738. deviceExtension->ExpectingInterrupt = TRUE;
  2739. SelectIdeDevice(baseIoAddress1, targetId, 0);
  2740. IdePortOutPortByte(baseIoAddress1->Error,regs->bFeaturesReg);
  2741. IdePortOutPortByte(baseIoAddress1->BlockCount,regs->bSectorCountReg);
  2742. IdePortOutPortByte(baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
  2743. IdePortOutPortByte(baseIoAddress1->CylinderLow,regs->bCylLowReg);
  2744. IdePortOutPortByte(baseIoAddress1->CylinderHigh,regs->bCylHighReg);
  2745. IdePortOutPortByte(baseIoAddress1->Command,regs->bCommandReg);
  2746. ASSERT(!SRB_USES_DMA(Srb));
  2747. if (!SRB_USES_DMA(Srb)) {
  2748. if (deviceExtension->BytesLeft <
  2749. deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt) {
  2750. byteCount = deviceExtension->BytesLeft;
  2751. } else {
  2752. byteCount = deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt;
  2753. }
  2754. //
  2755. // Wait for BSY and DRQ.
  2756. //
  2757. WaitOnBaseBusy(baseIoAddress1,statusByte);
  2758. if (statusByte & IDE_STATUS_BUSY) {
  2759. DebugPrint((1,
  2760. "IdeSendSmartCommand: Returning BUSY status %x\n",
  2761. statusByte));
  2762. return SRB_STATUS_BUSY;
  2763. }
  2764. if (statusByte & IDE_STATUS_ERROR) {
  2765. DebugPrint((1,
  2766. "IdeSendSmartCommand: Returning ERROR status %x\n",
  2767. statusByte));
  2768. deviceExtension->BytesLeft = 0;
  2769. //
  2770. // Clear interrupt expecting flag.
  2771. //
  2772. deviceExtension->ExpectingInterrupt = FALSE;
  2773. return MapError(deviceExtension, Srb);
  2774. }
  2775. for (i = 0; i < 1000; i++) {
  2776. GetBaseStatus(baseIoAddress1, statusByte);
  2777. if (statusByte & IDE_STATUS_DRQ) {
  2778. break;
  2779. }
  2780. KeStallExecutionProcessor(200);
  2781. }
  2782. if (!(statusByte & IDE_STATUS_DRQ)) {
  2783. DebugPrint((1,
  2784. "IdeSmartCommand: DRQ never asserted (%x)\n",
  2785. statusByte));
  2786. deviceExtension->BytesLeft = 0;
  2787. //
  2788. // Clear interrupt expecting flag.
  2789. //
  2790. deviceExtension->ExpectingInterrupt = FALSE;
  2791. //
  2792. // Clear current SRB.
  2793. //
  2794. deviceExtension->CurrentSrb = NULL;
  2795. return SRB_STATUS_SELECTION_TIMEOUT;
  2796. }
  2797. //
  2798. // Write next 256 words.
  2799. //
  2800. WriteBuffer(baseIoAddress1,
  2801. (PUSHORT)deviceExtension->DataBuffer,
  2802. byteCount / sizeof(USHORT));
  2803. //
  2804. // Adjust buffer address and words left count.
  2805. //
  2806. deviceExtension->BytesLeft -= byteCount;
  2807. deviceExtension->DataBuffer += byteCount;
  2808. }
  2809. //
  2810. // Wait for interrupt.
  2811. //
  2812. return SRB_STATUS_PENDING;
  2813. }
  2814. #endif
  2815. }
  2816. return SRB_STATUS_INVALID_REQUEST;
  2817. } // end IdeSendSmartCommand()
  2818. #ifdef ENABLE_48BIT_LBA
  2819. ULONG
  2820. IdeReadWriteExt(
  2821. IN PVOID HwDeviceExtension,
  2822. IN PSCSI_REQUEST_BLOCK Srb
  2823. )
  2824. /*++
  2825. Routine Description:
  2826. This routine handles IDE read and writes.
  2827. Arguments:
  2828. HwDeviceExtension - HBA miniport driver's adapter data storage
  2829. Srb - IO request packet
  2830. Return Value:
  2831. SRB status
  2832. --*/
  2833. {
  2834. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  2835. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  2836. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  2837. ULONG i;
  2838. ULONG byteCount;
  2839. UCHAR statusByte,statusByte2;
  2840. UCHAR cylinderHigh,cylinderLow,drvSelect;
  2841. ULONG sectorCount;
  2842. LARGE_INTEGER startingSector;
  2843. //
  2844. // the device should support 48 bit LBA
  2845. //
  2846. ASSERT(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA);
  2847. ASSERT(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LBA);
  2848. //
  2849. // Select device 0 or 1.
  2850. //
  2851. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  2852. GetStatus(baseIoAddress1, statusByte2);
  2853. if (statusByte2 & IDE_STATUS_BUSY) {
  2854. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  2855. "IdeReadWrite: Returning BUSY status\n"));
  2856. return SRB_STATUS_BUSY;
  2857. }
  2858. if (!(statusByte2 & IDE_STATUS_DRDY)) {
  2859. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  2860. "IdeReadWrite: IDE_STATUS_DRDY not set\n"));
  2861. return SRB_STATUS_BUSY;
  2862. }
  2863. //
  2864. // Set data buffer pointer and words left.
  2865. // BytesLeft should be 64-bit.
  2866. //
  2867. deviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
  2868. deviceExtension->BytesLeft = Srb->DataTransferLength;
  2869. //
  2870. // Indicate expecting an interrupt.
  2871. //
  2872. deviceExtension->ExpectingInterrupt = TRUE;
  2873. //
  2874. // Set up sector count register. Round up to next block.
  2875. //
  2876. sectorCount = (Srb->DataTransferLength + 0x1FF) / 0x200;
  2877. ASSERT(sectorCount != 0);
  2878. //
  2879. // Get starting sector number from CDB.
  2880. //
  2881. startingSector.QuadPart = 0;
  2882. startingSector.LowPart = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
  2883. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
  2884. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
  2885. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
  2886. DebugPrint((1,
  2887. "startingSector = 0x%x, length = 0x%x\n",
  2888. startingSector.LowPart,
  2889. sectorCount
  2890. ));
  2891. //
  2892. // the device shall support LBA. We will not use CHS
  2893. //
  2894. SelectIdeDevice(baseIoAddress1,
  2895. Srb->TargetId,
  2896. IDE_LBA_MODE);
  2897. //
  2898. // load the higher order bytes
  2899. //
  2900. IdePortOutPortByte (
  2901. baseIoAddress1->BlockCount,
  2902. (UCHAR)((sectorCount & 0x0000ff00) >> 8));
  2903. IdePortOutPortByte (
  2904. baseIoAddress1->BlockNumber,
  2905. (UCHAR) (((startingSector.LowPart) & 0xff000000) >> 24));
  2906. IdePortOutPortByte (
  2907. baseIoAddress1->CylinderLow,
  2908. (UCHAR) (((startingSector.HighPart) & 0x000000ff) >> 0));
  2909. IdePortOutPortByte (
  2910. baseIoAddress1->CylinderHigh,
  2911. (UCHAR) (((startingSector.HighPart) & 0x0000ff00) >> 8));
  2912. //
  2913. // load the lower order bytes
  2914. //
  2915. IdePortOutPortByte (
  2916. baseIoAddress1->BlockCount,
  2917. (UCHAR)((sectorCount & 0x000000ff) >> 0));
  2918. IdePortOutPortByte (
  2919. baseIoAddress1->BlockNumber,
  2920. (UCHAR) (((startingSector.LowPart) & 0x000000ff) >> 0));
  2921. IdePortOutPortByte (
  2922. baseIoAddress1->CylinderLow,
  2923. (UCHAR) (((startingSector.LowPart) & 0x0000ff00) >> 8));
  2924. IdePortOutPortByte (
  2925. baseIoAddress1->CylinderHigh,
  2926. (UCHAR) (((startingSector.LowPart) & 0x00ff0000) >> 16));
  2927. //
  2928. // Check if write request.
  2929. //
  2930. if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  2931. //
  2932. // Send read command.
  2933. //
  2934. if (SRB_USES_DMA(Srb)) {
  2935. IdePortOutPortByte (
  2936. baseIoAddress1->Command,
  2937. IDE_COMMAND_READ_DMA_EXT);
  2938. } else {
  2939. ASSERT (deviceExtension->DeviceParameters[Srb->TargetId].IdePioReadCommandExt);
  2940. IdePortOutPortByte (
  2941. baseIoAddress1->Command,
  2942. deviceExtension->DeviceParameters[Srb->TargetId].IdePioReadCommandExt);
  2943. }
  2944. } else {
  2945. //
  2946. // Send write command.
  2947. //
  2948. if (SRB_USES_DMA(Srb)) {
  2949. IdePortOutPortByte (
  2950. baseIoAddress1->Command,
  2951. IDE_COMMAND_WRITE_DMA_EXT);
  2952. } else {
  2953. ASSERT(deviceExtension->DeviceParameters[Srb->TargetId].IdePioWriteCommandExt);
  2954. IdePortOutPortByte (
  2955. baseIoAddress1->Command,
  2956. deviceExtension->DeviceParameters[Srb->TargetId].IdePioWriteCommandExt);
  2957. }
  2958. if (!SRB_USES_DMA(Srb)) {
  2959. if (deviceExtension->BytesLeft <
  2960. deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt) {
  2961. byteCount = deviceExtension->BytesLeft;
  2962. } else {
  2963. byteCount = deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt;
  2964. }
  2965. //
  2966. // Wait for BSY and DRQ.
  2967. //
  2968. WaitOnBaseBusy(baseIoAddress1,statusByte);
  2969. if (statusByte & IDE_STATUS_BUSY) {
  2970. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  2971. "IdeReadWrite 2: Returning BUSY status %x\n",
  2972. statusByte));
  2973. return SRB_STATUS_BUSY;
  2974. }
  2975. for (i = 0; i < 1000; i++) {
  2976. GetBaseStatus(baseIoAddress1, statusByte);
  2977. if (statusByte & IDE_STATUS_DRQ) {
  2978. break;
  2979. }
  2980. KeStallExecutionProcessor(200);
  2981. }
  2982. if (!(statusByte & IDE_STATUS_DRQ)) {
  2983. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  2984. "IdeReadWrite: DRQ never asserted (%x) original status (%x)\n",
  2985. statusByte,
  2986. statusByte2));
  2987. deviceExtension->BytesLeft = 0;
  2988. //
  2989. // Clear interrupt expecting flag.
  2990. //
  2991. deviceExtension->ExpectingInterrupt = FALSE;
  2992. //
  2993. // Clear current SRB.
  2994. //
  2995. deviceExtension->CurrentSrb = NULL;
  2996. return SRB_STATUS_TIMEOUT;
  2997. }
  2998. //
  2999. // Write next 256 words.
  3000. //
  3001. WriteBuffer(baseIoAddress1,
  3002. (PUSHORT)deviceExtension->DataBuffer,
  3003. byteCount / sizeof(USHORT));
  3004. //
  3005. // Adjust buffer address and words left count.
  3006. //
  3007. deviceExtension->BytesLeft -= byteCount;
  3008. deviceExtension->DataBuffer += byteCount;
  3009. }
  3010. }
  3011. if (SRB_USES_DMA(Srb)) {
  3012. deviceExtension->DMAInProgress = TRUE;
  3013. deviceExtension->BusMasterInterface.BmArm (deviceExtension->BusMasterInterface.Context);
  3014. }
  3015. //
  3016. // Wait for interrupt.
  3017. //
  3018. return SRB_STATUS_PENDING;
  3019. } // end IdeReadWriteExt()
  3020. #endif
  3021. ULONG
  3022. IdeReadWrite(
  3023. IN PVOID HwDeviceExtension,
  3024. IN PSCSI_REQUEST_BLOCK Srb
  3025. )
  3026. /*++
  3027. Routine Description:
  3028. This routine handles IDE read and writes.
  3029. Arguments:
  3030. HwDeviceExtension - HBA miniport driver's adapter data storage
  3031. Srb - IO request packet
  3032. Return Value:
  3033. SRB status
  3034. --*/
  3035. {
  3036. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3037. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3038. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  3039. ULONG startingSector,i;
  3040. ULONG byteCount;
  3041. UCHAR statusByte,statusByte2;
  3042. UCHAR cylinderHigh,cylinderLow,drvSelect,sectorNumber;
  3043. //
  3044. // Select device 0 or 1.
  3045. //
  3046. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  3047. GetStatus(baseIoAddress1, statusByte2);
  3048. if (statusByte2 & IDE_STATUS_BUSY) {
  3049. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3050. "IdeReadWrite: Returning BUSY status\n"));
  3051. return SRB_STATUS_BUSY;
  3052. }
  3053. if (!(statusByte2 & IDE_STATUS_DRDY)) {
  3054. if ((statusByte2 == 0) &&
  3055. (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_SONY_MEMORYSTICK)) {
  3056. statusByte2=IDE_STATUS_DRDY;
  3057. } else {
  3058. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3059. "IdeReadWrite: IDE_STATUS_DRDY not set\n"));
  3060. return SRB_STATUS_BUSY;
  3061. }
  3062. }
  3063. //
  3064. // returns status busy when atapi verifier is enabled
  3065. //
  3066. //ViIdeFakeHungController(HwDeviceExtension);
  3067. //
  3068. // Set data buffer pointer and words left.
  3069. //
  3070. deviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
  3071. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3072. //
  3073. // Indicate expecting an interrupt.
  3074. //
  3075. deviceExtension->ExpectingInterrupt = TRUE;
  3076. //
  3077. // Set up sector count register. Round up to next block.
  3078. //
  3079. IdePortOutPortByte (
  3080. baseIoAddress1->BlockCount,
  3081. (UCHAR)((Srb->DataTransferLength + 0x1FF) / 0x200));
  3082. //
  3083. // Get starting sector number from CDB.
  3084. //
  3085. startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
  3086. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
  3087. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
  3088. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
  3089. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3090. "IdeReadWrite: Starting sector is %x, Number of bytes %x\n",
  3091. startingSector,
  3092. Srb->DataTransferLength));
  3093. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LBA) {
  3094. SelectIdeDevice(baseIoAddress1,
  3095. Srb->TargetId,
  3096. (IDE_LBA_MODE | ((startingSector & 0x0f000000) >> 24)));
  3097. IdePortOutPortByte (
  3098. baseIoAddress1->BlockNumber,
  3099. (UCHAR) ((startingSector & 0x000000ff) >> 0));
  3100. IdePortOutPortByte (
  3101. baseIoAddress1->CylinderLow,
  3102. (UCHAR) ((startingSector & 0x0000ff00) >> 8));
  3103. IdePortOutPortByte (
  3104. baseIoAddress1->CylinderHigh,
  3105. (UCHAR) ((startingSector & 0x00ff0000) >> 16));
  3106. } else { //CHS
  3107. //
  3108. // Set up sector number register.
  3109. //
  3110. sectorNumber = (UCHAR)((startingSector % deviceExtension->SectorsPerTrack[Srb->TargetId]) + 1);
  3111. IdePortOutPortByte (
  3112. baseIoAddress1->BlockNumber,
  3113. sectorNumber);
  3114. //
  3115. // Set up cylinder low register.
  3116. //
  3117. cylinderLow = (UCHAR)(startingSector / (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3118. deviceExtension->NumberOfHeads[Srb->TargetId]));
  3119. IdePortOutPortByte (
  3120. baseIoAddress1->CylinderLow,
  3121. cylinderLow);
  3122. //
  3123. // Set up cylinder high register.
  3124. //
  3125. cylinderHigh = (UCHAR)((startingSector / (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3126. deviceExtension->NumberOfHeads[Srb->TargetId])) >> 8);
  3127. IdePortOutPortByte (
  3128. baseIoAddress1->CylinderHigh,
  3129. cylinderHigh);
  3130. //
  3131. // Set up head and drive select register.
  3132. //
  3133. drvSelect = (UCHAR)(((startingSector / deviceExtension->SectorsPerTrack[Srb->TargetId]) %
  3134. deviceExtension->NumberOfHeads[Srb->TargetId]));
  3135. SelectIdeDevice(baseIoAddress1, Srb->TargetId, drvSelect);
  3136. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3137. "IdeReadWrite: Cylinder %x Head %x Sector %x\n",
  3138. startingSector /
  3139. (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3140. deviceExtension->NumberOfHeads[Srb->TargetId]),
  3141. (startingSector /
  3142. deviceExtension->SectorsPerTrack[Srb->TargetId]) %
  3143. deviceExtension->NumberOfHeads[Srb->TargetId],
  3144. startingSector %
  3145. deviceExtension->SectorsPerTrack[Srb->TargetId] + 1));
  3146. }
  3147. //
  3148. // Check if write request.
  3149. //
  3150. if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
  3151. //
  3152. // Send read command.
  3153. //
  3154. if (SRB_USES_DMA(Srb)) {
  3155. IdePortOutPortByte (
  3156. baseIoAddress1->Command,
  3157. IDE_COMMAND_READ_DMA);
  3158. } else {
  3159. IdePortOutPortByte (
  3160. baseIoAddress1->Command,
  3161. deviceExtension->DeviceParameters[Srb->TargetId].IdePioReadCommand);
  3162. }
  3163. } else {
  3164. //
  3165. // Send write command.
  3166. //
  3167. if (SRB_USES_DMA(Srb)) {
  3168. IdePortOutPortByte (
  3169. baseIoAddress1->Command,
  3170. IDE_COMMAND_WRITE_DMA);
  3171. } else {
  3172. IdePortOutPortByte (
  3173. baseIoAddress1->Command,
  3174. deviceExtension->DeviceParameters[Srb->TargetId].IdePioWriteCommand);
  3175. }
  3176. if (!SRB_USES_DMA(Srb)) {
  3177. if (deviceExtension->BytesLeft <
  3178. deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt) {
  3179. byteCount = deviceExtension->BytesLeft;
  3180. } else {
  3181. byteCount = deviceExtension->DeviceParameters[Srb->TargetId].MaxBytePerPioInterrupt;
  3182. }
  3183. //
  3184. // Wait for BSY and DRQ.
  3185. //
  3186. WaitOnBaseBusy(baseIoAddress1,statusByte);
  3187. if (statusByte & IDE_STATUS_BUSY) {
  3188. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3189. "IdeReadWrite 2: Returning BUSY status %x\n",
  3190. statusByte));
  3191. return SRB_STATUS_BUSY;
  3192. }
  3193. for (i = 0; i < 1000; i++) {
  3194. GetBaseStatus(baseIoAddress1, statusByte);
  3195. if (statusByte & IDE_STATUS_DRQ) {
  3196. break;
  3197. }
  3198. KeStallExecutionProcessor(200);
  3199. }
  3200. if (!(statusByte & IDE_STATUS_DRQ)) {
  3201. DebugPrint((DBG_CRASHDUMP | DBG_READ_WRITE,
  3202. "IdeReadWrite: DRQ never asserted (%x) original status (%x)\n",
  3203. statusByte,
  3204. statusByte2));
  3205. deviceExtension->BytesLeft = 0;
  3206. //
  3207. // Clear interrupt expecting flag.
  3208. //
  3209. deviceExtension->ExpectingInterrupt = FALSE;
  3210. //
  3211. // Clear current SRB.
  3212. //
  3213. deviceExtension->CurrentSrb = NULL;
  3214. return SRB_STATUS_TIMEOUT;
  3215. }
  3216. //
  3217. // Write next 256 words.
  3218. //
  3219. WriteBuffer(baseIoAddress1,
  3220. (PUSHORT)deviceExtension->DataBuffer,
  3221. byteCount / sizeof(USHORT));
  3222. //
  3223. // Adjust buffer address and words left count.
  3224. //
  3225. deviceExtension->BytesLeft -= byteCount;
  3226. deviceExtension->DataBuffer += byteCount;
  3227. }
  3228. }
  3229. if (SRB_USES_DMA(Srb)) {
  3230. deviceExtension->DMAInProgress = TRUE;
  3231. deviceExtension->BusMasterInterface.BmArm (deviceExtension->BusMasterInterface.Context);
  3232. }
  3233. //
  3234. // Wait for interrupt.
  3235. //
  3236. return SRB_STATUS_PENDING;
  3237. } // end IdeReadWrite()
  3238. #ifdef ENABLE_48BIT_LBA
  3239. ULONG
  3240. IdeVerifyExt(
  3241. IN PVOID HwDeviceExtension,
  3242. IN PSCSI_REQUEST_BLOCK Srb
  3243. )
  3244. /*++
  3245. Routine Description:
  3246. This routine handles IDE Verify.
  3247. Arguments:
  3248. HwDeviceExtension - HBA miniport driver's adapter data storage
  3249. Srb - IO request packet
  3250. Return Value:
  3251. SRB status
  3252. --*/
  3253. {
  3254. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3255. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3256. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  3257. LARGE_INTEGER startingSector;
  3258. ULONG sectors;
  3259. ULONG endSector;
  3260. ULONG sectorCount;
  3261. //
  3262. // the device should support 48 bit LBA
  3263. //
  3264. ASSERT(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA);
  3265. ASSERT(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LBA);
  3266. //
  3267. // Get starting sector number from CDB.
  3268. //
  3269. startingSector.QuadPart = 0;
  3270. startingSector.LowPart = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
  3271. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
  3272. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
  3273. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
  3274. sectorCount = (USHORT)((((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
  3275. ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb );
  3276. DebugPrint((3,
  3277. "IdeVerify: Starting sector %x. Number of blocks %x\n",
  3278. startingSector.LowPart,
  3279. sectorCount));
  3280. if (sectorCount > 0x10000) {
  3281. DebugPrint((DBG_ALWAYS,
  3282. "IdeVerify: verify too many sectors 0x%x\n",
  3283. sectorCount));
  3284. return SRB_STATUS_INVALID_REQUEST;
  3285. }
  3286. //
  3287. // Set data buffer pointer and words left.
  3288. //
  3289. deviceExtension->DataBuffer = Srb->DataBuffer;
  3290. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3291. //
  3292. // Indicate expecting an interrupt.
  3293. //
  3294. deviceExtension->ExpectingInterrupt = TRUE;
  3295. SelectIdeDevice(baseIoAddress1,
  3296. Srb->TargetId,
  3297. IDE_LBA_MODE);
  3298. //
  3299. // Load the higer order bytes
  3300. //
  3301. IdePortOutPortByte(baseIoAddress1->BlockNumber,
  3302. (UCHAR) (((startingSector.LowPart) & 0xff000000) >> 24));
  3303. IdePortOutPortByte(baseIoAddress1->CylinderLow,
  3304. (UCHAR) (((startingSector.HighPart) & 0x000000ff) >> 0));
  3305. IdePortOutPortByte(baseIoAddress1->CylinderHigh,
  3306. (UCHAR) (((startingSector.HighPart) & 0x0000ff00) >> 8));
  3307. IdePortOutPortByte(baseIoAddress1->BlockCount,
  3308. (UCHAR)((sectorCount & 0x0000ff00) >> 8));
  3309. //
  3310. // Load the lower order bytes
  3311. //
  3312. IdePortOutPortByte(baseIoAddress1->BlockNumber,
  3313. (UCHAR) (((startingSector.LowPart) & 0x000000ff) >> 0));
  3314. IdePortOutPortByte(baseIoAddress1->CylinderLow,
  3315. (UCHAR) (((startingSector.LowPart) & 0x0000ff00) >> 8));
  3316. IdePortOutPortByte(baseIoAddress1->CylinderHigh,
  3317. (UCHAR) (((startingSector.LowPart) & 0x00ff0000) >> 16));
  3318. IdePortOutPortByte(baseIoAddress1->BlockCount,
  3319. (UCHAR)((sectorCount & 0x000000ff) >> 0));
  3320. //
  3321. // Send verify command.
  3322. //
  3323. IdePortOutPortByte(baseIoAddress1->Command,
  3324. IDE_COMMAND_VERIFY_EXT);
  3325. //
  3326. // Wait for interrupt.
  3327. //
  3328. return SRB_STATUS_PENDING;
  3329. } // end IdeVerifyExt()
  3330. #endif
  3331. ULONG
  3332. IdeVerify(
  3333. IN PVOID HwDeviceExtension,
  3334. IN PSCSI_REQUEST_BLOCK Srb
  3335. )
  3336. /*++
  3337. Routine Description:
  3338. This routine handles IDE Verify.
  3339. Arguments:
  3340. HwDeviceExtension - HBA miniport driver's adapter data storage
  3341. Srb - IO request packet
  3342. Return Value:
  3343. SRB status
  3344. --*/
  3345. {
  3346. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3347. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3348. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  3349. ULONG startingSector;
  3350. ULONG sectors;
  3351. ULONG endSector;
  3352. USHORT sectorCount;
  3353. //
  3354. // Drive has these number sectors.
  3355. //
  3356. #if DBG
  3357. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LBA) { // LBA
  3358. sectors = deviceExtension->IdentifyData[Srb->TargetId].UserAddressableSectors;
  3359. } else {
  3360. sectors = deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3361. deviceExtension->NumberOfHeads[Srb->TargetId] *
  3362. deviceExtension->NumberOfCylinders[Srb->TargetId];
  3363. }
  3364. #endif
  3365. DebugPrint((3,
  3366. "IdeVerify: Total sectors %x\n",
  3367. sectors));
  3368. //
  3369. // Get starting sector number from CDB.
  3370. //
  3371. startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
  3372. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
  3373. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
  3374. ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
  3375. DebugPrint((3,
  3376. "IdeVerify: Starting sector %x. Number of blocks %x\n",
  3377. startingSector,
  3378. ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb));
  3379. sectorCount = (USHORT)(((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8 |
  3380. ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb );
  3381. endSector = startingSector + sectorCount;
  3382. DebugPrint((3,
  3383. "IdeVerify: Ending sector %x\n",
  3384. endSector));
  3385. if (sectorCount > 0x100) {
  3386. DebugPrint((DBG_ALWAYS,
  3387. "IdeVerify: verify too many sectors 0x%x\n",
  3388. sectorCount));
  3389. return SRB_STATUS_INVALID_REQUEST;
  3390. }
  3391. //
  3392. // Set data buffer pointer and words left.
  3393. //
  3394. deviceExtension->DataBuffer = Srb->DataBuffer;
  3395. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3396. //
  3397. // Indicate expecting an interrupt.
  3398. //
  3399. deviceExtension->ExpectingInterrupt = TRUE;
  3400. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LBA) { // LBA
  3401. SelectIdeDevice(baseIoAddress1,
  3402. Srb->TargetId,
  3403. (IDE_LBA_MODE |((startingSector & 0x0f000000) >> 24)));
  3404. IdePortOutPortByte(baseIoAddress1->BlockNumber,
  3405. (UCHAR) ((startingSector & 0x000000ff) >> 0));
  3406. IdePortOutPortByte(baseIoAddress1->CylinderLow,
  3407. (UCHAR) ((startingSector & 0x0000ff00) >> 8));
  3408. IdePortOutPortByte(baseIoAddress1->CylinderHigh,
  3409. (UCHAR) ((startingSector & 0x00ff0000) >> 16));
  3410. DebugPrint((2,
  3411. "IdeVerify: LBA: startingSector %x\n",
  3412. startingSector));
  3413. } else { //CHS
  3414. //
  3415. // Set up head and drive select register.
  3416. //
  3417. SelectIdeDevice(baseIoAddress1,
  3418. Srb->TargetId,
  3419. (UCHAR)((startingSector /
  3420. deviceExtension->SectorsPerTrack[Srb->TargetId]) %
  3421. deviceExtension->NumberOfHeads[Srb->TargetId]));
  3422. //
  3423. // Set up sector number register.
  3424. //
  3425. IdePortOutPortByte(baseIoAddress1->BlockNumber,
  3426. (UCHAR)((startingSector %
  3427. deviceExtension->SectorsPerTrack[Srb->TargetId]) + 1));
  3428. //
  3429. // Set up cylinder low register.
  3430. //
  3431. IdePortOutPortByte(baseIoAddress1->CylinderLow,
  3432. (UCHAR)(startingSector /
  3433. (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3434. deviceExtension->NumberOfHeads[Srb->TargetId])));
  3435. //
  3436. // Set up cylinder high register.
  3437. //
  3438. IdePortOutPortByte(baseIoAddress1->CylinderHigh,
  3439. (UCHAR)((startingSector /
  3440. (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3441. deviceExtension->NumberOfHeads[Srb->TargetId])) >> 8));
  3442. DebugPrint((2,
  3443. "IdeVerify: CHS: Cylinder %x Head %x Sector %x\n",
  3444. startingSector /
  3445. (deviceExtension->SectorsPerTrack[Srb->TargetId] *
  3446. deviceExtension->NumberOfHeads[Srb->TargetId]),
  3447. (startingSector /
  3448. deviceExtension->SectorsPerTrack[Srb->TargetId]) %
  3449. deviceExtension->NumberOfHeads[Srb->TargetId],
  3450. startingSector %
  3451. deviceExtension->SectorsPerTrack[Srb->TargetId] + 1));
  3452. }
  3453. /********
  3454. if (endSector > sectors) {
  3455. //
  3456. // Too big, round down.
  3457. //
  3458. DebugPrint((1,
  3459. "IdeVerify: Truncating request to %x blocks\n",
  3460. sectors - startingSector - 1));
  3461. IdePortOutPortByte(baseIoAddress1->BlockCount,
  3462. (UCHAR)(sectors - startingSector - 1));
  3463. } else {
  3464. IdePortOutPortByte(baseIoAddress1->BlockCount,(UCHAR)sectorCount);
  3465. }
  3466. ******/
  3467. IdePortOutPortByte(baseIoAddress1->BlockCount,(UCHAR)sectorCount);
  3468. //
  3469. // Send verify command.
  3470. //
  3471. IdePortOutPortByte(baseIoAddress1->Command,
  3472. IDE_COMMAND_VERIFY);
  3473. //
  3474. // Wait for interrupt.
  3475. //
  3476. return SRB_STATUS_PENDING;
  3477. } // end IdeVerify()
  3478. VOID
  3479. Scsi2Atapi(
  3480. IN PHW_DEVICE_EXTENSION DeviceExtension,
  3481. IN PSCSI_REQUEST_BLOCK Srb
  3482. )
  3483. /*++
  3484. Routine Description:
  3485. Convert SCSI packet command to Atapi packet command.
  3486. Arguments:
  3487. Srb - IO request packet
  3488. Return Value:
  3489. None
  3490. --*/
  3491. {
  3492. SAVE_ORIGINAL_CDB(DeviceExtension, Srb);
  3493. DeviceExtension->scsi2atapi = FALSE;
  3494. if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_TAPE_DEVICE)) {
  3495. //
  3496. // Change the cdb length
  3497. //
  3498. //Srb->CdbLength = 12;
  3499. switch (Srb->Cdb[0]) {
  3500. case SCSIOP_MODE_SENSE: {
  3501. ASSERT(FALSE);
  3502. break;
  3503. }
  3504. case SCSIOP_MODE_SELECT: {
  3505. ASSERT (FALSE);
  3506. break;
  3507. }
  3508. case SCSIOP_START_STOP_UNIT: {
  3509. //
  3510. // Bad Cd-roms
  3511. // STOP command (1B) hangs during shutdown/hibernation on
  3512. // some cd-rom drives. Setting the Immediate bit to 0 seems
  3513. // to work
  3514. //
  3515. PCDB cdb = (PCDB)Srb->Cdb;
  3516. if ((cdb->START_STOP.Immediate == 1) &&
  3517. (cdb->START_STOP.LoadEject == 0) &&
  3518. (cdb->START_STOP.Start == 0))
  3519. cdb->START_STOP.Immediate=0;
  3520. DeviceExtension->scsi2atapi = TRUE;
  3521. break;
  3522. }
  3523. case SCSIOP_FORMAT_UNIT:
  3524. if (DeviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_LS120_FORMAT) {
  3525. Srb->Cdb[0] = ATAPI_LS120_FORMAT_UNIT;
  3526. DeviceExtension->scsi2atapi = TRUE;
  3527. }
  3528. break;
  3529. }
  3530. }
  3531. return;
  3532. } // Scsi2Atapi
  3533. ULONG
  3534. AtapiSendCommand(
  3535. IN PVOID HwDeviceExtension,
  3536. IN PSCSI_REQUEST_BLOCK Srb
  3537. )
  3538. /*++
  3539. Routine Description:
  3540. Send ATAPI packet command to device.
  3541. Arguments:
  3542. HwDeviceExtension - HBA miniport driver's adapter data storage
  3543. Srb - IO request packet
  3544. Return Value:
  3545. --*/
  3546. {
  3547. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3548. PATAPI_REGISTERS_1 baseIoAddress1 = (PATAPI_REGISTERS_1)&deviceExtension->BaseIoAddress1;
  3549. PATAPI_REGISTERS_2 baseIoAddress2 = (PATAPI_REGISTERS_2)&deviceExtension->BaseIoAddress2;
  3550. ULONG i;
  3551. ULONG flags;
  3552. UCHAR statusByte,byteCountLow,byteCountHigh;
  3553. #ifdef ENABLE_48BIT_LBA
  3554. ASSERT(!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA));
  3555. #endif
  3556. DebugPrint((DBG_ATAPI_DEVICES,
  3557. "AtapiSendCommand: Command %x to TargetId %d lun %d\n",
  3558. Srb->Cdb[0],
  3559. Srb->TargetId,
  3560. Srb->Lun));
  3561. if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) {
  3562. DebugPrint((DBG_ATAPI_DEVICES,
  3563. "AtapiSendCommand: xferLength=%x, LBA=%x\n",
  3564. Srb->DataTransferLength,
  3565. (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 |
  3566. (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 8) |
  3567. (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 16) |
  3568. (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 << 24))
  3569. ));
  3570. }
  3571. //
  3572. // Make sure command is to ATAPI device.
  3573. //
  3574. flags = deviceExtension->DeviceFlags[Srb->TargetId];
  3575. if (Srb->Lun > deviceExtension->LastLun[Srb->TargetId]) {
  3576. return SRB_STATUS_SELECTION_TIMEOUT;
  3577. }
  3578. if (!(flags & DFLAGS_ATAPI_DEVICE)) {
  3579. return SRB_STATUS_SELECTION_TIMEOUT;
  3580. }
  3581. //
  3582. // Select device 0 or 1.
  3583. //
  3584. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  3585. //
  3586. // Verify that controller is ready for next command.
  3587. //
  3588. GetStatus(baseIoAddress1,statusByte);
  3589. DebugPrint((2,
  3590. "AtapiSendCommand: Entered with status %x\n",
  3591. statusByte));
  3592. if (statusByte & IDE_STATUS_BUSY) {
  3593. DebugPrint((1,
  3594. "AtapiSendCommand: Device busy (%x)\n",
  3595. statusByte));
  3596. return SRB_STATUS_BUSY;
  3597. }
  3598. //
  3599. // If a tape drive has doesn't have DSC set and the last command is restrictive, don't send
  3600. // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
  3601. //
  3602. #if 0
  3603. if ((!(statusByte & IDE_STATUS_DSC)) &&
  3604. (flags & DFLAGS_TAPE_DEVICE) && deviceExtension->RDP) {
  3605. KeStallExecutionProcessor(1000);
  3606. DebugPrint((2,"AtapiSendCommand: DSC not set. %x\n",statusByte));
  3607. return SRB_STATUS_BUSY;
  3608. }
  3609. #endif
  3610. //
  3611. // Extended RDP to include SEEK commands for CD-ROMS.
  3612. //
  3613. if ((!(statusByte & IDE_STATUS_DSC)) && deviceExtension->RDP &&
  3614. (flags & DFLAGS_RDP_SET)) {
  3615. KeStallExecutionProcessor(1000);
  3616. DebugPrint((DBG_ATAPI_DEVICES,
  3617. "AtapiSendCommand: DSC not set. %x\n",
  3618. statusByte
  3619. ));
  3620. return SRB_STATUS_BUSY;
  3621. }
  3622. if (SRB_IS_RDP(Srb)) {
  3623. deviceExtension->RDP = TRUE;
  3624. SETMASK(deviceExtension->DeviceFlags[Srb->TargetId], DFLAGS_RDP_SET);
  3625. DebugPrint((3,
  3626. "AtapiSendCommand: %x mapped as DSC restrictive\n",
  3627. Srb->Cdb[0]));
  3628. } else {
  3629. deviceExtension->RDP = FALSE;
  3630. CLRMASK(deviceExtension->DeviceFlags[Srb->TargetId], DFLAGS_RDP_SET);
  3631. }
  3632. //
  3633. // Convert SCSI to ATAPI commands if needed
  3634. //
  3635. Scsi2Atapi(deviceExtension, Srb);
  3636. //
  3637. // Set data buffer pointer and words left.
  3638. //
  3639. deviceExtension->DataBuffer = Srb->DataBuffer;
  3640. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3641. WaitOnBusy(baseIoAddress1,statusByte);
  3642. //
  3643. // Write transfer byte count to registers.
  3644. //
  3645. byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
  3646. byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
  3647. if (Srb->DataTransferLength >= 0x10000) {
  3648. byteCountLow = byteCountHigh = 0xFF;
  3649. }
  3650. IdePortOutPortByte(baseIoAddress1->ByteCountLow,byteCountLow);
  3651. IdePortOutPortByte(baseIoAddress1->ByteCountHigh, byteCountHigh);
  3652. if (SRB_USES_DMA(Srb)) {
  3653. IdePortOutPortByte(baseIoAddress1->Error, 0x1);
  3654. } else {
  3655. IdePortOutPortByte(baseIoAddress1->Error, 0x0);
  3656. }
  3657. if (flags & DFLAGS_INT_DRQ) {
  3658. //
  3659. // This device interrupts when ready to receive the packet.
  3660. //
  3661. // Write ATAPI packet command.
  3662. //
  3663. deviceExtension->ExpectingInterrupt = TRUE;
  3664. IdePortOutPortByte(baseIoAddress1->Command,
  3665. IDE_COMMAND_ATAPI_PACKET);
  3666. DebugPrint((3,
  3667. "AtapiSendCommand: Wait for int. to send packet. Status (%x)\n",
  3668. statusByte));
  3669. return SRB_STATUS_PENDING;
  3670. } else {
  3671. //
  3672. // Write ATAPI packet command.
  3673. //
  3674. IdePortOutPortByte(baseIoAddress1->Command,
  3675. IDE_COMMAND_ATAPI_PACKET);
  3676. //
  3677. // Wait for DRQ.
  3678. //
  3679. WaitOnBusy(baseIoAddress1, statusByte);
  3680. WaitForDrq(baseIoAddress1, statusByte);
  3681. if (!(statusByte & IDE_STATUS_DRQ)) {
  3682. DebugPrint((1,
  3683. "AtapiSendCommand: DRQ never asserted (%x)\n",
  3684. statusByte));
  3685. return SRB_STATUS_ERROR;
  3686. }
  3687. }
  3688. //
  3689. // Need to read status register.
  3690. //
  3691. GetBaseStatus(baseIoAddress1, statusByte);
  3692. //
  3693. // Indicate expecting an interrupt and wait for it.
  3694. //
  3695. deviceExtension->ExpectingInterrupt = TRUE;
  3696. //
  3697. // Send CDB to device.
  3698. //
  3699. WaitOnBusy(baseIoAddress1,statusByte);
  3700. WriteBuffer(baseIoAddress1,
  3701. (PUSHORT)Srb->Cdb,
  3702. 6);
  3703. if (SRB_USES_DMA(Srb)) {
  3704. deviceExtension->DMAInProgress = TRUE;
  3705. deviceExtension->BusMasterInterface.BmArm (deviceExtension->BusMasterInterface.Context);
  3706. }
  3707. return SRB_STATUS_PENDING;
  3708. } // end AtapiSendCommand()
  3709. ULONG
  3710. IdeSendFlushCommand(
  3711. IN PVOID HwDeviceExtension,
  3712. IN PSCSI_REQUEST_BLOCK Srb
  3713. )
  3714. /*++
  3715. Routine Description:
  3716. Program ATA registers for IDE flush command.
  3717. Arguments:
  3718. HwDeviceExtension - ATAPI driver storage.
  3719. Srb - System request block.
  3720. Return Value:
  3721. SRB status (pending if all goes well).
  3722. --*/
  3723. {
  3724. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3725. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3726. UCHAR flushCommand;
  3727. ULONG status;
  3728. //
  3729. // Get the flush command
  3730. //
  3731. flushCommand = deviceExtension->DeviceParameters[Srb->TargetId].IdeFlushCommand;
  3732. //
  3733. // We should check for the case where we have already queued a
  3734. // flush cache command.
  3735. //
  3736. if (flushCommand == IDE_COMMAND_NO_FLUSH) {
  3737. return SRB_STATUS_SUCCESS;
  3738. }
  3739. //
  3740. // if we reached this stage then the device should support flush command
  3741. //
  3742. ASSERT (flushCommand != IDE_COMMAND_NO_FLUSH);
  3743. DebugPrint((1,
  3744. "IdeSendFlushCommand: device %d, srb 0x%x\n",
  3745. Srb->TargetId,
  3746. Srb
  3747. ));
  3748. //
  3749. // Select the right device
  3750. //
  3751. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  3752. //
  3753. // Set data buffer pointer and words left.
  3754. //
  3755. deviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
  3756. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3757. //
  3758. // Indicate expecting an interrupt.
  3759. //
  3760. deviceExtension->ExpectingInterrupt = TRUE;
  3761. status = SRB_STATUS_PENDING;
  3762. //
  3763. // Program the TaskFile registers
  3764. //
  3765. IdePortOutPortByte(baseIoAddress1->Error, 0);
  3766. IdePortOutPortByte(baseIoAddress1->BlockCount, 0);
  3767. IdePortOutPortByte(baseIoAddress1->BlockNumber, 0);
  3768. IdePortOutPortByte(baseIoAddress1->CylinderLow, 0);
  3769. IdePortOutPortByte(baseIoAddress1->CylinderHigh, 0);
  3770. IdePortOutPortByte(baseIoAddress1->Command, flushCommand);
  3771. return status;
  3772. }
  3773. #ifdef ENABLE_48BIT_LBA
  3774. ULONG
  3775. IdeSendFlushCommandExt(
  3776. IN PVOID HwDeviceExtension,
  3777. IN PSCSI_REQUEST_BLOCK Srb
  3778. )
  3779. /*++
  3780. Routine Description:
  3781. Program ATA registers for IDE flush ext command.
  3782. Arguments:
  3783. HwDeviceExtension - ATAPI driver storage.
  3784. Srb - System request block.
  3785. Return Value:
  3786. SRB status (pending if all goes well).
  3787. --*/
  3788. {
  3789. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3790. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3791. UCHAR flushCommand;
  3792. ULONG status;
  3793. UCHAR statusByte;
  3794. //
  3795. // the device should support 48 bit LBA
  3796. //
  3797. ASSERT(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA);
  3798. //
  3799. // Get the flush command
  3800. //
  3801. flushCommand = deviceExtension->DeviceParameters[Srb->TargetId].IdeFlushCommandExt;
  3802. //
  3803. // We should check for the case where we have already queued a
  3804. // flush cache command.
  3805. //
  3806. if (flushCommand == IDE_COMMAND_NO_FLUSH) {
  3807. return SRB_STATUS_SUCCESS;
  3808. }
  3809. //
  3810. // if we reached this stage then the device should support flush command
  3811. //
  3812. ASSERT (flushCommand != IDE_COMMAND_NO_FLUSH);
  3813. DebugPrint((1,
  3814. "IdeSendFlushCommand: device %d, srb 0x%x\n",
  3815. Srb->TargetId,
  3816. Srb
  3817. ));
  3818. //
  3819. // Select the right device
  3820. //
  3821. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  3822. //
  3823. // Set data buffer pointer and words left.
  3824. //
  3825. deviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
  3826. deviceExtension->BytesLeft = Srb->DataTransferLength;
  3827. //
  3828. // Indicate expecting an interrupt.
  3829. //
  3830. deviceExtension->ExpectingInterrupt = TRUE;
  3831. status = SRB_STATUS_PENDING;
  3832. //
  3833. // Program the TaskFile registers (previous content)
  3834. //
  3835. IdePortOutPortByte(baseIoAddress1->Error, 0);
  3836. IdePortOutPortByte(baseIoAddress1->BlockCount, 0);
  3837. IdePortOutPortByte(baseIoAddress1->BlockNumber, 0);
  3838. IdePortOutPortByte(baseIoAddress1->CylinderLow, 0);
  3839. IdePortOutPortByte(baseIoAddress1->CylinderHigh, 0);
  3840. //
  3841. // Program the TaskFile registers (current content)
  3842. //
  3843. IdePortOutPortByte(baseIoAddress1->Error, 0);
  3844. IdePortOutPortByte(baseIoAddress1->BlockCount, 0);
  3845. IdePortOutPortByte(baseIoAddress1->BlockNumber, 0);
  3846. IdePortOutPortByte(baseIoAddress1->CylinderLow, 0);
  3847. IdePortOutPortByte(baseIoAddress1->CylinderHigh, 0);
  3848. IdePortOutPortByte(baseIoAddress1->Command, flushCommand);
  3849. return status;
  3850. }
  3851. #endif
  3852. ULONG
  3853. IdeSendCommand(
  3854. IN PVOID HwDeviceExtension,
  3855. IN PSCSI_REQUEST_BLOCK Srb
  3856. )
  3857. /*++
  3858. Routine Description:
  3859. Program ATA registers for IDE disk transfer.
  3860. Arguments:
  3861. HwDeviceExtension - ATAPI driver storage.
  3862. Srb - System request block.
  3863. Return Value:
  3864. SRB status (pending if all goes well).
  3865. --*/
  3866. {
  3867. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  3868. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  3869. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  3870. PCDB cdb;
  3871. UCHAR statusByte,errorByte;
  3872. ULONG status;
  3873. ULONG i;
  3874. PMODE_PARAMETER_HEADER modeData;
  3875. DebugPrint((2,
  3876. "IdeSendCommand: Command %x to device %d\n",
  3877. Srb->Cdb[0],
  3878. Srb->TargetId));
  3879. switch (Srb->Cdb[0]) {
  3880. case SCSIOP_INQUIRY:
  3881. //
  3882. // Filter out all TIDs but 0 and 1 since this is an IDE interface
  3883. // which support up to two devices.
  3884. //
  3885. if ((Srb->Lun != 0) ||
  3886. (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT))) {
  3887. //
  3888. // Indicate no device found at this address.
  3889. //
  3890. status = SRB_STATUS_SELECTION_TIMEOUT;
  3891. break;
  3892. } else {
  3893. INQUIRYDATA inquiryData;
  3894. PIDENTIFY_DATA identifyData = &deviceExtension->IdentifyData[Srb->TargetId];
  3895. //
  3896. // Zero INQUIRY data structure.
  3897. //
  3898. RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
  3899. RtlZeroMemory((PUCHAR) &inquiryData, sizeof(INQUIRYDATA));
  3900. inquiryData.DeviceType = DIRECT_ACCESS_DEVICE;
  3901. //
  3902. // Set the removable bit, if applicable.
  3903. //
  3904. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_REMOVABLE_DRIVE) {
  3905. inquiryData.RemovableMedia = 1;
  3906. }
  3907. //
  3908. // Fill in vendor identification fields.
  3909. //
  3910. for (i = 0; i < 20; i += 2) {
  3911. inquiryData.VendorId[i] =
  3912. ((PUCHAR)identifyData->ModelNumber)[i + 1];
  3913. inquiryData.VendorId[i+1] =
  3914. ((PUCHAR)identifyData->ModelNumber)[i];
  3915. }
  3916. //
  3917. // Initialize unused portion of product id.
  3918. //
  3919. for (i = 0; i < 4; i++) {
  3920. inquiryData.ProductId[12+i] = ' ';
  3921. }
  3922. //
  3923. // Move firmware revision from IDENTIFY data to
  3924. // product revision in INQUIRY data.
  3925. //
  3926. for (i = 0; i < 4; i += 2) {
  3927. inquiryData.ProductRevisionLevel[i] =
  3928. ((PUCHAR)identifyData->FirmwareRevision)[i+1];
  3929. inquiryData.ProductRevisionLevel[i+1] =
  3930. ((PUCHAR)identifyData->FirmwareRevision)[i];
  3931. }
  3932. //
  3933. // Copy as much the return data as possible
  3934. //
  3935. RtlMoveMemory (
  3936. Srb->DataBuffer,
  3937. &inquiryData,
  3938. Srb->DataTransferLength > sizeof (INQUIRYDATA) ?
  3939. sizeof (INQUIRYDATA) :
  3940. Srb->DataTransferLength
  3941. );
  3942. status = SRB_STATUS_SUCCESS;
  3943. }
  3944. break;
  3945. case SCSIOP_TEST_UNIT_READY:
  3946. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED) {
  3947. //
  3948. // Select device 0 or 1.
  3949. //
  3950. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  3951. IdePortOutPortByte(baseIoAddress1->Command,IDE_COMMAND_GET_MEDIA_STATUS);
  3952. //
  3953. // Wait for busy. If media has not changed, return success
  3954. //
  3955. WaitOnBusy(baseIoAddress1,statusByte);
  3956. if (!(statusByte & IDE_STATUS_ERROR)) {
  3957. deviceExtension->ExpectingInterrupt = FALSE;
  3958. status = SRB_STATUS_SUCCESS;
  3959. } else {
  3960. errorByte = IdePortInPortByte(baseIoAddress1->Error);
  3961. if (errorByte == IDE_ERROR_DATA_ERROR) {
  3962. //
  3963. // Special case: If current media is write-protected,
  3964. // the 0xDA command will always fail since the write-protect bit
  3965. // is sticky,so we can ignore this error
  3966. //
  3967. GetBaseStatus(baseIoAddress1, statusByte);
  3968. status = SRB_STATUS_SUCCESS;
  3969. } else {
  3970. deviceExtension->ReturningMediaStatus = errorByte;
  3971. //
  3972. // we need to set the scsi status here. Otherwise we
  3973. // won't issue a request sense
  3974. //
  3975. Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  3976. Srb->SrbStatus = SRB_STATUS_ERROR;
  3977. status = SRB_STATUS_ERROR;
  3978. }
  3979. }
  3980. } else {
  3981. status = SRB_STATUS_SUCCESS;
  3982. }
  3983. break;
  3984. case SCSIOP_VERIFY:
  3985. #ifdef ENABLE_48BIT_LBA
  3986. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA) {
  3987. status = IdeVerifyExt(HwDeviceExtension, Srb);
  3988. break;
  3989. }
  3990. #endif
  3991. status = IdeVerify(HwDeviceExtension,Srb);
  3992. break;
  3993. #ifdef DIDE_CPQ_BM
  3994. case SCSIOP_DVD_READ:
  3995. case SCSIOP_REPORT_KEY:
  3996. case SCSIOP_SEND_KEY:
  3997. case SCSIOP_READ_DVD_STRUCTURE:
  3998. #endif
  3999. case SCSIOP_READ:
  4000. case SCSIOP_WRITE:
  4001. #ifdef ENABLE_48BIT_LBA
  4002. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA) {
  4003. status = IdeReadWriteExt(HwDeviceExtension,
  4004. Srb);
  4005. break;
  4006. }
  4007. #endif
  4008. status = IdeReadWrite(HwDeviceExtension,
  4009. Srb);
  4010. break;
  4011. case SCSIOP_START_STOP_UNIT:
  4012. //
  4013. //Determine what type of operation we should perform
  4014. //
  4015. cdb = (PCDB)Srb->Cdb;
  4016. if (cdb->START_STOP.LoadEject == 1) {
  4017. SelectIdeLine(baseIoAddress1, Srb->TargetId >> 1);
  4018. //
  4019. // Eject media,
  4020. // first select device 0 or 1.
  4021. //
  4022. WaitOnBusy(baseIoAddress1,statusByte);
  4023. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  4024. IdePortOutPortByte(baseIoAddress1->Command,IDE_COMMAND_MEDIA_EJECT);
  4025. }
  4026. status = SRB_STATUS_SUCCESS;
  4027. break;
  4028. case SCSIOP_MEDIUM_REMOVAL:
  4029. cdb = (PCDB)Srb->Cdb;
  4030. SelectIdeLine(baseIoAddress1, Srb->TargetId >> 1);
  4031. WaitOnBusy(baseIoAddress1,statusByte);
  4032. SelectIdeDevice(baseIoAddress1, Srb->TargetId, 0);
  4033. if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
  4034. IdePortOutPortByte(baseIoAddress1->Command,IDE_COMMAND_DOOR_LOCK);
  4035. } else {
  4036. IdePortOutPortByte(baseIoAddress1->Command,IDE_COMMAND_DOOR_UNLOCK);
  4037. }
  4038. status = SRB_STATUS_SUCCESS;
  4039. WaitOnBusy(baseIoAddress1,statusByte);
  4040. if (statusByte & IDE_STATUS_ERROR) {
  4041. errorByte = IdePortInPortByte(baseIoAddress1->Error);
  4042. status = MapError(HwDeviceExtension, Srb);
  4043. }
  4044. break;
  4045. case SCSIOP_REQUEST_SENSE:
  4046. // this function makes sense buffers to report the results
  4047. // of the original GET_MEDIA_STATUS command
  4048. if ((deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED) &&
  4049. (Srb->DataTransferLength >= sizeof(SENSE_DATA))) {
  4050. status = IdeBuildSenseBuffer(HwDeviceExtension, Srb);
  4051. } else {
  4052. status = SRB_STATUS_INVALID_REQUEST;
  4053. }
  4054. break;
  4055. case SCSIOP_SYNCHRONIZE_CACHE:
  4056. DebugPrint((1,
  4057. "Flush the cache for IDE device %d\n",
  4058. Srb->TargetId
  4059. ));
  4060. status = SRB_STATUS_SUCCESS;
  4061. //
  4062. // Send the flush command if one exists
  4063. //
  4064. if (deviceExtension->DeviceParameters[Srb->TargetId].IdeFlushCommand !=
  4065. IDE_COMMAND_NO_FLUSH) {
  4066. #ifdef ENABLE_48BIT_LBA
  4067. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA) {
  4068. status = IdeSendFlushCommandExt(HwDeviceExtension,
  4069. Srb);
  4070. } else
  4071. #endif
  4072. status = IdeSendFlushCommand(deviceExtension, Srb);
  4073. }
  4074. break;
  4075. case SCSIOP_FORMAT_UNIT:
  4076. if ( IsNEC_98 ) {
  4077. //
  4078. // Support physical format of fixed disk.
  4079. // It is meaningful for SCSI device.
  4080. // So, we do not execute it on IDE device.
  4081. // But we need to return the success in order to fit with SCSI
  4082. //
  4083. status = SRB_STATUS_SUCCESS;
  4084. break;
  4085. }
  4086. default:
  4087. DebugPrint((1,
  4088. "IdeSendCommand: Unsupported command %x\n",
  4089. Srb->Cdb[0]));
  4090. status = SRB_STATUS_INVALID_REQUEST;
  4091. } // end switch
  4092. return status;
  4093. } // end IdeSendCommand()
  4094. ULONG
  4095. IdeSendPassThroughCommand(
  4096. IN PVOID HwDeviceExtension,
  4097. IN PSCSI_REQUEST_BLOCK Srb
  4098. )
  4099. /*++
  4100. Routine Description:
  4101. Program ATA registers for IDE disk transfer.
  4102. Arguments:
  4103. HwDeviceExtension - ATAPI driver storage.
  4104. Srb - System request block.
  4105. Return Value:
  4106. SRB status (pending if all goes well).
  4107. --*/
  4108. {
  4109. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  4110. PIDE_REGISTERS_1 baseIoAddress1 = &deviceExtension->BaseIoAddress1;
  4111. PIDE_REGISTERS_2 baseIoAddress2 = &deviceExtension->BaseIoAddress2;
  4112. PCDB cdb;
  4113. UCHAR statusByte,errorByte;
  4114. ULONG status;
  4115. PATA_PASS_THROUGH ataPassThroughData;
  4116. PIDEREGS pIdeReg;
  4117. ataPassThroughData = Srb->DataBuffer;
  4118. pIdeReg = &ataPassThroughData->IdeReg;
  4119. //
  4120. // select the right device
  4121. //
  4122. CLRMASK (pIdeReg->bDriveHeadReg, 0xb0);
  4123. pIdeReg->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
  4124. SelectIdeDevice(baseIoAddress1, Srb->TargetId, pIdeReg->bDriveHeadReg);
  4125. //
  4126. // check to see if this is a "no-op" SRB
  4127. //
  4128. if (pIdeReg->bReserved & ATA_PTFLAGS_NO_OP) {
  4129. ULONG repeatCount = (ULONG)ataPassThroughData->IdeReg.bSectorCountReg;
  4130. UCHAR busyWait = pIdeReg->bSectorNumberReg;
  4131. //
  4132. // wait for busy if this is set
  4133. //
  4134. if (busyWait != 0) {
  4135. ULONG busyWaitTime;
  4136. if (busyWait > 30) {
  4137. busyWait = 30;
  4138. }
  4139. busyWaitTime = busyWait * 1000;
  4140. WaitOnBusyUntil(baseIoAddress1, statusByte, busyWaitTime);
  4141. }
  4142. if (repeatCount <= 0) {
  4143. repeatCount = 1;
  4144. }
  4145. while (repeatCount) {
  4146. repeatCount--;
  4147. KeStallExecutionProcessor(100);
  4148. //
  4149. // get a copy of the task file registers
  4150. //
  4151. AtapiTaskRegisterSnapshot (
  4152. baseIoAddress1,
  4153. pIdeReg
  4154. );
  4155. }
  4156. return SRB_STATUS_SUCCESS;
  4157. }
  4158. if (pIdeReg->bReserved & ATA_PTFLAGS_EMPTY_CHANNEL_TEST) {
  4159. #ifdef DPC_FOR_EMPTY_CHANNEL
  4160. if (status=IdePortChannelEmptyQuick(baseIoAddress1, baseIoAddress2,
  4161. deviceExtension->MaxIdeDevice, &deviceExtension->CurrentIdeDevice,
  4162. &deviceExtension->MoreWait, &deviceExtension->NoRetry)) {
  4163. if (status==STATUS_RETRY) {
  4164. return SRB_STATUS_PENDING;
  4165. }
  4166. return SRB_STATUS_SUCCESS;
  4167. } else {
  4168. return SRB_STATUS_ERROR;
  4169. }
  4170. #endif
  4171. if (IdePortChannelEmpty(baseIoAddress1, baseIoAddress2, deviceExtension->MaxIdeDevice)) {
  4172. return SRB_STATUS_SUCCESS;
  4173. } else {
  4174. return SRB_STATUS_ERROR;
  4175. }
  4176. }
  4177. if (pIdeReg->bReserved & ATA_PTFLAGS_INLINE_HARD_RESET) {
  4178. IdeHardReset (
  4179. baseIoAddress1,
  4180. baseIoAddress2,
  4181. FALSE,
  4182. TRUE
  4183. );
  4184. //
  4185. // re-select the right device
  4186. //
  4187. SelectIdeDevice(baseIoAddress1, Srb->TargetId, pIdeReg->bDriveHeadReg);
  4188. }
  4189. GetStatus(baseIoAddress1, statusByte);
  4190. if (statusByte & IDE_STATUS_BUSY) {
  4191. DebugPrint((1,
  4192. "IdeSendPassThroughCommand: Returning BUSY status\n"));
  4193. return SRB_STATUS_BUSY;
  4194. }
  4195. if (pIdeReg->bReserved & ATA_PTFLAGS_STATUS_DRDY_REQUIRED) {
  4196. if (!(statusByte & IDE_STATUS_DRDY)) {
  4197. if ((statusByte == 0) &&
  4198. (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_SONY_MEMORYSTICK)) {
  4199. statusByte = IDE_STATUS_DRDY;
  4200. } else {
  4201. DebugPrint((1,
  4202. "IdeSendPassThroughCommand: DRDY not ready\n"));
  4203. return SRB_STATUS_BUSY;
  4204. }
  4205. }
  4206. }
  4207. if (pIdeReg->bCommandReg != IDE_COMMAND_ATAPI_RESET) {
  4208. // if identifydata in device extension is valid, use it
  4209. #if 1
  4210. if ((deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_IDENTIFY_VALID) &&
  4211. (pIdeReg->bCommandReg == IDE_COMMAND_IDENTIFY)) {
  4212. ASSERT(!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_REMOVABLE_DRIVE));
  4213. DebugPrint((1, "Bypassing identify command\n"));
  4214. RtlMoveMemory(ataPassThroughData->DataBuffer, &(deviceExtension->IdentifyData[Srb->TargetId]),
  4215. ataPassThroughData->DataBufferSize);
  4216. return SRB_STATUS_SUCCESS;
  4217. }
  4218. #endif
  4219. //
  4220. // Set data buffer pointer and bytes left.
  4221. //
  4222. deviceExtension->DataBuffer = ataPassThroughData->DataBuffer;
  4223. deviceExtension->BytesLeft = ataPassThroughData->DataBufferSize;
  4224. //
  4225. // Indicate expecting an interrupt.
  4226. //
  4227. deviceExtension->ExpectingInterrupt = TRUE;
  4228. status = SRB_STATUS_PENDING;
  4229. IdePortOutPortByte(baseIoAddress1->Error, pIdeReg->bFeaturesReg);
  4230. IdePortOutPortByte(baseIoAddress1->BlockCount, pIdeReg->bSectorCountReg);
  4231. IdePortOutPortByte(baseIoAddress1->BlockNumber, pIdeReg->bSectorNumberReg);
  4232. IdePortOutPortByte(baseIoAddress1->CylinderLow, pIdeReg->bCylLowReg);
  4233. IdePortOutPortByte(baseIoAddress1->CylinderHigh, pIdeReg->bCylHighReg);
  4234. IdePortOutPortByte(baseIoAddress1->Command, pIdeReg->bCommandReg);
  4235. } else {
  4236. //
  4237. // perform sync. atapi soft reset because this command doesn't generate interrupts
  4238. //
  4239. AtapiSoftReset(baseIoAddress1, baseIoAddress2, Srb->TargetId & 0x1, FALSE);
  4240. status = SRB_STATUS_SUCCESS;
  4241. }
  4242. DebugPrint ((1, "IdeSendPassThroughCommand: 0x%x 0x%x command = 0x%x\n", baseIoAddress1->RegistersBaseAddress, Srb->TargetId, pIdeReg->bCommandReg));
  4243. return status;
  4244. } // end IdeSendPassThroughCommand()
  4245. VOID
  4246. IdeMediaStatus(
  4247. BOOLEAN EnableMSN,
  4248. IN PVOID HwDeviceExtension,
  4249. ULONG DeviceNumber
  4250. )
  4251. /*++
  4252. Routine Description:
  4253. Enables disables media status notification
  4254. Arguments:
  4255. HwDeviceExtension - ATAPI driver storage.
  4256. --*/
  4257. {
  4258. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  4259. PIDE_REGISTERS_1 baseIoAddress = &deviceExtension->BaseIoAddress1;
  4260. UCHAR statusByte,errorByte;
  4261. if (EnableMSN == TRUE) {
  4262. //
  4263. // If supported enable Media Status Notification support
  4264. //
  4265. if ((deviceExtension->DeviceFlags[DeviceNumber] & DFLAGS_MSN_SUPPORT)) {
  4266. //
  4267. // enable
  4268. //
  4269. SelectIdeDevice(baseIoAddress, DeviceNumber, 0);
  4270. IdePortOutPortByte(baseIoAddress->Error,(UCHAR) (0x95));
  4271. IdePortOutPortByte(baseIoAddress->Command,
  4272. IDE_COMMAND_SET_FEATURE);
  4273. WaitOnBaseBusy(baseIoAddress,statusByte);
  4274. if (statusByte & IDE_STATUS_ERROR) {
  4275. //
  4276. // Read the error register.
  4277. //
  4278. errorByte = IdePortInPortByte(baseIoAddress->Error);
  4279. DebugPrint((1,
  4280. "IdeMediaStatus: Error enabling media status. Status %x, error byte %x\n",
  4281. statusByte,
  4282. errorByte));
  4283. } else {
  4284. deviceExtension->DeviceFlags[DeviceNumber] |= DFLAGS_MEDIA_STATUS_ENABLED;
  4285. DebugPrint((1,"IdeMediaStatus: Media Status Notification Supported\n"));
  4286. deviceExtension->ReturningMediaStatus = 0;
  4287. }
  4288. }
  4289. } else { // end if EnableMSN == TRUE
  4290. //
  4291. // disable if previously enabled
  4292. //
  4293. if ((deviceExtension->DeviceFlags[DeviceNumber] & DFLAGS_MEDIA_STATUS_ENABLED)) {
  4294. SelectIdeDevice(baseIoAddress, DeviceNumber, 0);
  4295. IdePortOutPortByte(baseIoAddress->Error,(UCHAR) (0x31));
  4296. IdePortOutPortByte(baseIoAddress->Command,
  4297. IDE_COMMAND_SET_FEATURE);
  4298. WaitOnBaseBusy(baseIoAddress,statusByte);
  4299. CLRMASK (deviceExtension->DeviceFlags[DeviceNumber], DFLAGS_MEDIA_STATUS_ENABLED);
  4300. }
  4301. }
  4302. }
  4303. ULONG
  4304. IdeBuildSenseBuffer(
  4305. IN PVOID HwDeviceExtension,
  4306. IN PSCSI_REQUEST_BLOCK Srb
  4307. )
  4308. /*++
  4309. Routine Description:
  4310. Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
  4311. command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
  4312. Arguments:
  4313. HwDeviceExtension - ATAPI driver storage.
  4314. Srb - System request block.
  4315. Return Value:
  4316. SRB status (ALWAYS SUCCESS).
  4317. --*/
  4318. {
  4319. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  4320. ULONG status;
  4321. PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
  4322. if (senseBuffer) {
  4323. if (deviceExtension->ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
  4324. senseBuffer->ErrorCode = 0x70;
  4325. senseBuffer->Valid = 1;
  4326. senseBuffer->AdditionalSenseLength = 0xb;
  4327. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  4328. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
  4329. senseBuffer->AdditionalSenseCodeQualifier = 0;
  4330. } else if (deviceExtension->ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
  4331. senseBuffer->ErrorCode = 0x70;
  4332. senseBuffer->Valid = 1;
  4333. senseBuffer->AdditionalSenseLength = 0xb;
  4334. senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
  4335. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_OPERATOR_REQUEST;
  4336. senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_MEDIUM_REMOVAL;
  4337. } else if (deviceExtension->ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
  4338. senseBuffer->ErrorCode = 0x70;
  4339. senseBuffer->Valid = 1;
  4340. senseBuffer->AdditionalSenseLength = 0xb;
  4341. senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
  4342. senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
  4343. senseBuffer->AdditionalSenseCodeQualifier = 0;
  4344. } else if (deviceExtension->ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
  4345. senseBuffer->ErrorCode = 0x70;
  4346. senseBuffer->Valid = 1;
  4347. senseBuffer->AdditionalSenseLength = 0xb;
  4348. senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
  4349. senseBuffer->AdditionalSenseCode = 0;
  4350. senseBuffer->AdditionalSenseCodeQualifier = 0;
  4351. }
  4352. return SRB_STATUS_SUCCESS;
  4353. }
  4354. return SRB_STATUS_ERROR;
  4355. }// End of IdeBuildSenseBuffer
  4356. BOOLEAN
  4357. AtapiStartIo(
  4358. IN PVOID HwDeviceExtension,
  4359. IN PSCSI_REQUEST_BLOCK Srb
  4360. )
  4361. /*++
  4362. Routine Description:
  4363. This routine is called from the port driver synchronized
  4364. with the kernel to start an IO request.
  4365. Arguments:
  4366. HwDeviceExtension - HBA miniport driver's adapter data storage
  4367. Srb - IO request packet
  4368. Return Value:
  4369. TRUE
  4370. --*/
  4371. {
  4372. PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
  4373. ULONG status;
  4374. //
  4375. // Determine which function.
  4376. //
  4377. switch (Srb->Function) {
  4378. case SRB_FUNCTION_ATA_POWER_PASS_THROUGH:
  4379. case SRB_FUNCTION_FLUSH:
  4380. case SRB_FUNCTION_SHUTDOWN:
  4381. case SRB_FUNCTION_ATA_PASS_THROUGH:
  4382. case SRB_FUNCTION_EXECUTE_SCSI:
  4383. //
  4384. // Sanity check. Only one request can be outstanding on a
  4385. // controller.
  4386. //
  4387. if (deviceExtension->CurrentSrb) {
  4388. DebugPrint((1,
  4389. "AtapiStartIo: Already have a request!\n"));
  4390. Srb->SrbStatus = SRB_STATUS_BUSY;
  4391. IdePortNotification(IdeRequestComplete,
  4392. deviceExtension,
  4393. Srb);
  4394. return FALSE;
  4395. }
  4396. //
  4397. // Indicate that a request is active on the controller.
  4398. //
  4399. deviceExtension->CurrentSrb = Srb;
  4400. //
  4401. // Send command to device.
  4402. //
  4403. // ATA_PASSTHORUGH
  4404. if ((Srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH) ||
  4405. (Srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  4406. status = IdeSendPassThroughCommand(HwDeviceExtension,
  4407. Srb);
  4408. } else if ((deviceExtension->DeviceFlags[Srb->TargetId] &
  4409. (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT)) ==
  4410. (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT)) {
  4411. status = AtapiSendCommand(HwDeviceExtension,
  4412. Srb);
  4413. } else if ((Srb->Function == SRB_FUNCTION_FLUSH) ||
  4414. (Srb->Function == SRB_FUNCTION_SHUTDOWN)) {
  4415. #ifdef ENABLE_48BIT_LBA
  4416. if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_48BIT_LBA) {
  4417. status = IdeSendFlushCommandExt(HwDeviceExtension,
  4418. Srb);
  4419. } else {
  4420. #endif
  4421. status = IdeSendFlushCommand(HwDeviceExtension,
  4422. Srb);
  4423. #ifdef ENABLE_48BIT_LBA
  4424. }
  4425. #endif
  4426. } else if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) {
  4427. status = IdeSendCommand(HwDeviceExtension,
  4428. Srb);
  4429. } else {
  4430. status = SRB_STATUS_SELECTION_TIMEOUT;
  4431. }
  4432. break;
  4433. case SRB_FUNCTION_ABORT_COMMAND:
  4434. //
  4435. // Verify that SRB to abort is still outstanding.
  4436. //
  4437. if (!deviceExtension->CurrentSrb) {
  4438. DebugPrint((1, "AtapiStartIo: SRB to abort already completed\n"));
  4439. //
  4440. // Complete abort SRB.
  4441. //
  4442. status = SRB_STATUS_ABORT_FAILED;
  4443. break;
  4444. }
  4445. //
  4446. // Abort function indicates that a request timed out.
  4447. // Call reset routine. Card will only be reset if
  4448. // status indicates something is wrong.
  4449. // Fall through to reset code.
  4450. //
  4451. case SRB_FUNCTION_RESET_BUS:
  4452. //
  4453. // Reset Atapi and SCSI bus.
  4454. //
  4455. DebugPrint((1, "AtapiStartIo: Reset bus request received\n"));
  4456. SelectIdeLine(&deviceExtension->BaseIoAddress1, Srb->TargetId >> 1);
  4457. if (!AtapiSyncResetController(deviceExtension,
  4458. Srb->PathId)) {
  4459. DebugPrint((1,"AtapiStartIo: Reset bus failed\n"));
  4460. //
  4461. // Log reset failure.
  4462. //
  4463. IdePortLogError(
  4464. HwDeviceExtension,
  4465. NULL,
  4466. 0,
  4467. 0,
  4468. 0,
  4469. SP_INTERNAL_ADAPTER_ERROR,
  4470. 5 << 8
  4471. );
  4472. status = SRB_STATUS_ERROR;
  4473. } else {
  4474. status = SRB_STATUS_SUCCESS;
  4475. }
  4476. break;
  4477. case SRB_FUNCTION_IO_CONTROL:
  4478. if (deviceExtension->CurrentSrb) {
  4479. DebugPrint((1,
  4480. "AtapiStartIo: Already have a request!\n"));
  4481. Srb->SrbStatus = SRB_STATUS_BUSY;
  4482. IdePortNotification(IdeRequestComplete,
  4483. deviceExtension,
  4484. Srb);
  4485. return FALSE;
  4486. }
  4487. //
  4488. // Indicate that a request is active on the controller.
  4489. //
  4490. deviceExtension->CurrentSrb = Srb;
  4491. if (strlen("SCSIDISK") != RtlCompareMemory(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,"SCSIDISK",strlen("SCSIDISK"))) {
  4492. DebugPrint((1,
  4493. "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s\n",
  4494. ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
  4495. "SCSIDISK"));
  4496. status = SRB_STATUS_INVALID_REQUEST;
  4497. break;
  4498. }
  4499. switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
  4500. case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
  4501. PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4502. UCHAR deviceNumber;
  4503. UCHAR channelNo;
  4504. //
  4505. // Version and revision per SMART 1.03
  4506. //
  4507. versionParameters->bVersion = 1;
  4508. versionParameters->bRevision = 1;
  4509. versionParameters->bReserved = 0;
  4510. //
  4511. // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
  4512. //
  4513. versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
  4514. //
  4515. // This is done because of how the IOCTL_SCSI_MINIPORT
  4516. // determines 'targetid's'. Disk.sys places the real target id value
  4517. // in the DeviceMap field. Once we do some parameter checking, the value passed
  4518. // back to the application will be determined.
  4519. //
  4520. //
  4521. // HACK: atapi doesn't have the channel number. So it uses the hack below.
  4522. // this should work on non native mode IDE controllers
  4523. //
  4524. channelNo = (deviceExtension->PrimaryAddress)? 0:1;
  4525. //
  4526. // the bIDEDeviceMap is a bit map, with the bits defined as follows
  4527. // bit 0 - IDE drive as master on Primary channel
  4528. // bit 1 - IDE drive as slave on Primary channel
  4529. // bit 2 - IDE drive as master on Secondary channel
  4530. // bit 3 - IDE drive as slave on Secondary Channel
  4531. // bit 4 - ATAPI drive as master on Primary Channle
  4532. // bit 5 - ATAPI drive as slave on Primary Channle
  4533. // bit 6 - ATAPI drive as master on secondary Channle
  4534. // bit 7 - ATAPI drive as slave on secondary Channle
  4535. //
  4536. // since we have an FDO per channel, we can only fill in the fields
  4537. // pertinent to this channel.
  4538. //
  4539. versionParameters->bIDEDeviceMap = 0;
  4540. //
  4541. // Master device
  4542. //
  4543. deviceNumber = 0;
  4544. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT) {
  4545. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_ATAPI_DEVICE) {
  4546. deviceNumber += channelNo*2 + 4;
  4547. } else {
  4548. deviceNumber += channelNo*2;
  4549. }
  4550. versionParameters->bIDEDeviceMap |= (1 << deviceNumber);
  4551. }
  4552. //
  4553. // slave device
  4554. //
  4555. deviceNumber = 1;
  4556. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_DEVICE_PRESENT) {
  4557. if (deviceExtension->DeviceFlags[deviceNumber] & DFLAGS_ATAPI_DEVICE) {
  4558. deviceNumber += channelNo*2 + 4;
  4559. } else {
  4560. deviceNumber += channelNo*2;
  4561. }
  4562. versionParameters->bIDEDeviceMap |= (1 << deviceNumber);
  4563. }
  4564. status = SRB_STATUS_SUCCESS;
  4565. break;
  4566. }
  4567. case IOCTL_SCSI_MINIPORT_IDENTIFY: {
  4568. PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4569. SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
  4570. ULONG i;
  4571. UCHAR targetId;
  4572. if (cmdInParameters.irDriveRegs.bCommandReg == ID_CMD) {
  4573. //
  4574. // Extract the target.
  4575. //
  4576. targetId = cmdInParameters.bDriveNumber;
  4577. if (!(deviceExtension->DeviceFlags[targetId] & DFLAGS_DEVICE_PRESENT) ||
  4578. (deviceExtension->DeviceFlags[targetId] & DFLAGS_ATAPI_DEVICE)) {
  4579. status = SRB_STATUS_SELECTION_TIMEOUT;
  4580. break;
  4581. }
  4582. //
  4583. // Zero the output buffer
  4584. //
  4585. for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
  4586. ((PUCHAR)cmdOutParameters)[i] = 0;
  4587. }
  4588. //
  4589. // Build status block.
  4590. //
  4591. cmdOutParameters->cBufferSize = IDENTIFY_BUFFER_SIZE;
  4592. cmdOutParameters->DriverStatus.bDriverError = 0;
  4593. cmdOutParameters->DriverStatus.bIDEError = 0;
  4594. //
  4595. // Extract the identify data from the device extension.
  4596. //
  4597. RtlMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->IdentifyData[targetId], IDENTIFY_DATA_SIZE);
  4598. status = SRB_STATUS_SUCCESS;
  4599. } else {
  4600. status = SRB_STATUS_INVALID_REQUEST;
  4601. }
  4602. break;
  4603. }
  4604. case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
  4605. case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
  4606. case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
  4607. case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
  4608. case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
  4609. case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
  4610. case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
  4611. case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
  4612. case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
  4613. #ifdef ENABLE_SMARTLOG_SUPPORT
  4614. case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
  4615. case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
  4616. #endif
  4617. status = IdeSendSmartCommand(HwDeviceExtension,Srb);
  4618. break;
  4619. default :
  4620. status = SRB_STATUS_INVALID_REQUEST;
  4621. break;
  4622. }
  4623. break;
  4624. default:
  4625. //
  4626. // Indicate unsupported command.
  4627. //
  4628. status = SRB_STATUS_INVALID_REQUEST;
  4629. break;
  4630. } // end switch
  4631. //
  4632. // Check if command complete.
  4633. //
  4634. if (status != SRB_STATUS_PENDING) {
  4635. DebugPrint((2,
  4636. "AtapiStartIo: Srb %x complete with status %x\n",
  4637. Srb,
  4638. status));
  4639. //
  4640. // Clear current SRB.
  4641. //
  4642. deviceExtension->CurrentSrb = NULL;
  4643. //
  4644. // Set status in SRB.
  4645. //
  4646. Srb->SrbStatus = (UCHAR)status;
  4647. //
  4648. // Indicate command complete.
  4649. //
  4650. IdePortNotification(IdeRequestComplete,
  4651. deviceExtension,
  4652. Srb);
  4653. //
  4654. // Indicate ready for next request.
  4655. //
  4656. IdePortNotification(IdeNextRequest,
  4657. deviceExtension,
  4658. NULL);
  4659. }
  4660. return TRUE;
  4661. } // end AtapiStartIo()
  4662. BOOLEAN
  4663. AtapiSyncResetController(
  4664. IN PVOID HwDeviceExtension,
  4665. IN ULONG PathId
  4666. )
  4667. {
  4668. ULONG callAgain = 0;
  4669. BOOLEAN result;
  4670. do {
  4671. result = AtapiResetController(
  4672. HwDeviceExtension,
  4673. PathId,
  4674. &callAgain
  4675. );
  4676. } while (callAgain);
  4677. return result;
  4678. }
  4679. NTSTATUS
  4680. IdeHardReset (
  4681. PIDE_REGISTERS_1 BaseIoAddress1,
  4682. PIDE_REGISTERS_2 BaseIoAddress2,
  4683. BOOLEAN InterruptOff,
  4684. BOOLEAN Sync
  4685. )
  4686. {
  4687. UCHAR resetByte;
  4688. DebugPrint((1,
  4689. "IdeHardReset: Resetting controller.\n"));
  4690. //
  4691. // Kingston DP-ATA/20 pcmcia flash card
  4692. //
  4693. // if we don't make sure we select master device,
  4694. // later when we check for busy status, we will
  4695. // get the non-existing slave status
  4696. //
  4697. IdePortOutPortByte (BaseIoAddress1->DriveSelect, 0xA0);
  4698. IdePortOutPortByte (BaseIoAddress2->DeviceControl, IDE_DC_RESET_CONTROLLER | IDE_DC_DISABLE_INTERRUPTS);
  4699. //
  4700. // ATA-2 spec requires a minimum of 5 microsec stall here
  4701. //
  4702. KeStallExecutionProcessor (10);
  4703. if (InterruptOff) {
  4704. resetByte = IDE_DC_DISABLE_INTERRUPTS;
  4705. } else {
  4706. resetByte = IDE_DC_REENABLE_CONTROLLER;
  4707. }
  4708. IdePortOutPortByte (BaseIoAddress2->DeviceControl, resetByte);
  4709. //
  4710. // ATA-2 spec requires a minimum of 400 ns stall here
  4711. //
  4712. KeStallExecutionProcessor (1);
  4713. if (Sync) {
  4714. UCHAR deviceSelect;
  4715. UCHAR status;
  4716. ULONG sec;
  4717. ULONG i;
  4718. UCHAR statusByte;
  4719. WaitOnBusyUntil(BaseIoAddress1, statusByte, 500);
  4720. IdePortOutPortByte (BaseIoAddress1->DriveSelect, 0xa0);
  4721. deviceSelect = IdePortInPortByte(BaseIoAddress1->DriveSelect);
  4722. if (deviceSelect != 0xa0) {
  4723. //
  4724. // slave only channel
  4725. //
  4726. KeStallExecutionProcessor(1000);
  4727. IdePortOutPortByte (BaseIoAddress1->DriveSelect, 0xb0);
  4728. }
  4729. //
  4730. // ATA-2 spec allows a maximum of 31s for both master and slave device to come back from reset
  4731. //
  4732. for (sec=0; sec<31; sec++) {
  4733. /**/
  4734. /* one second loop */
  4735. /**/
  4736. for (i=0; i<2500; i++) {
  4737. GetStatus(BaseIoAddress1, status);
  4738. if (status & IDE_STATUS_BUSY) {
  4739. KeStallExecutionProcessor(400);
  4740. continue;
  4741. } else {
  4742. break;
  4743. }
  4744. }
  4745. if (status == 0xff) {
  4746. break;
  4747. } else if (status & IDE_STATUS_BUSY) {
  4748. DebugPrint ((0, "ATAPI: IdeHardReset WaitOnBusy failed. status = 0x%x\n", (ULONG) (status)));
  4749. } else {
  4750. break;
  4751. }
  4752. }
  4753. if (status & IDE_STATUS_BUSY) {
  4754. DebugPrint ((0, "ATAPI: IdeHardReset WaitOnBusy failed. status = 0x%x\n", (ULONG) (status)));
  4755. return STATUS_UNSUCCESSFUL;
  4756. } else {
  4757. return STATUS_SUCCESS;
  4758. }
  4759. } else {
  4760. return STATUS_SUCCESS;
  4761. }
  4762. }
  4763. VOID
  4764. AtapiTaskRegisterSnapshot (
  4765. IN PIDE_REGISTERS_1 CmdRegBase,
  4766. IN OUT PIDEREGS IdeReg
  4767. )
  4768. {
  4769. ASSERT(IdeReg);
  4770. IdeReg->bFeaturesReg = IdePortInPortByte(CmdRegBase->Error);
  4771. IdeReg->bSectorCountReg = IdePortInPortByte(CmdRegBase->BlockCount);
  4772. IdeReg->bSectorNumberReg = IdePortInPortByte(CmdRegBase->BlockNumber);
  4773. IdeReg->bCylLowReg = IdePortInPortByte(CmdRegBase->CylinderLow);
  4774. IdeReg->bCylHighReg = IdePortInPortByte(CmdRegBase->CylinderHigh);
  4775. IdeReg->bDriveHeadReg = IdePortInPortByte(CmdRegBase->DriveSelect);
  4776. IdeReg->bCommandReg = IdePortInPortByte(CmdRegBase->Command);
  4777. return;
  4778. } // AtapiTaskFileSnapshot
  4779. BOOLEAN
  4780. GetAtapiIdentifyQuick (
  4781. IN PIDE_REGISTERS_1 BaseIoAddress1,
  4782. IN PIDE_REGISTERS_2 BaseIoAddress2,
  4783. IN ULONG DeviceNumber,
  4784. OUT PIDENTIFY_DATA IdentifyData
  4785. )
  4786. {
  4787. UCHAR statusByte;
  4788. ULONG i;
  4789. SelectIdeDevice(BaseIoAddress1, DeviceNumber, 0);
  4790. GetStatus(BaseIoAddress1, statusByte);
  4791. if (statusByte & IDE_STATUS_BUSY) {
  4792. return FALSE;
  4793. }
  4794. IdePortOutPortByte(BaseIoAddress1->Command, IDE_COMMAND_ATAPI_IDENTIFY);
  4795. WaitOnBusyUntil(BaseIoAddress1, statusByte, 500);
  4796. if ((statusByte & IDE_STATUS_BUSY) ||
  4797. (statusByte & IDE_STATUS_ERROR)) {
  4798. return FALSE;
  4799. }
  4800. if (statusByte & IDE_STATUS_DRQ) {
  4801. ReadBuffer(BaseIoAddress1,
  4802. (PUSHORT)IdentifyData,
  4803. sizeof (IDENTIFY_DATA) / 2);
  4804. }
  4805. GetStatus(BaseIoAddress1, statusByte);
  4806. //
  4807. // pull out any remaining bytes and throw away.
  4808. //
  4809. i=0;
  4810. while ((statusByte & IDE_STATUS_DRQ) && (i < 100)) {
  4811. READ_PORT_USHORT(BaseIoAddress1->Data);
  4812. GetStatus(BaseIoAddress1, statusByte);
  4813. KeStallExecutionProcessor(50);
  4814. i++;
  4815. }
  4816. return TRUE;
  4817. }