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

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