Commit e1cf30a1 authored by Ben Avison's avatar Ben Avison
Browse files

Fix inability to recover from disc errors 08 and 21

Detail:
  These disc errors relate to the status of the task file registers before
  a command is issued, however with SATA (unlike PATA) we can't simply read
  the task file on demand, we need to issue a command to cause a register FIS
  transaction to happen on the bus. The only available command which is
  compatible with all device types (packet and non-packet) and which can be
  issued in not-ready state is EXECUTE_DEVICE_DIAGNOSTIC, so issue this when
  either disc error is encountered and retry to give the drive a chance to
  return to ready/not-busy state. This command has the advantage of having
  been mandatory back to ATA-1 so should be harmless for PATA drives, whether
  connected via a PATA-SATA bridge or via a future PATADriver module.
Admin:
  Tested on Titanium.

Version 4.02. Tagged as 'ADFS-4_02'
parent 86c19b05
/* (4.01)
/* (4.02)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 4.01
#define Module_MajorVersion_CMHG 4.02
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 13 Mar 2016
#define Module_Date_CMHG 24 Mar 2016
#define Module_MajorVersion "4.01"
#define Module_Version 401
#define Module_MajorVersion "4.02"
#define Module_Version 402
#define Module_MinorVersion ""
#define Module_Date "13 Mar 2016"
#define Module_Date "24 Mar 2016"
#define Module_ApplicationDate "13-Mar-16"
#define Module_ApplicationDate "24-Mar-16"
#define Module_ComponentName "ADFS"
#define Module_ComponentPath "cddl/RiscOS/Sources/FileSys/ADFS/ADFS"
#define Module_FullVersion "4.01"
#define Module_HelpVersion "4.01 (13 Mar 2016)"
#define Module_LibraryVersionInfo "4:1"
#define Module_FullVersion "4.02"
#define Module_HelpVersion "4.02 (24 Mar 2016)"
#define Module_LibraryVersionInfo "4:2"
......@@ -169,6 +169,26 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
e.oserror = MESSAGE_ERRORLOOKUP(true, ExtEscape, 0);
break; /* No retries for this one */
}
else if (e.oserror && (e.oserror->errnum == ErrorNumber_ATA_CmdBusy ||
e.oserror->errnum == ErrorNumber_ATA_CmdNotRdy))
{
/* With SATA, we need to kick the device to send us updated task file
* registers to enable us to recover from these error conditions. For
* this, we need a command with no side effects that is valid to issue
* when DRDY is not set; the only candidate valid for all types and
* generations of device is EXECUTE_DEVICE_DIAGNOSTIC. Throw away any
* errors returned from the kick command. */
ataop_param_lba28_t kick_p = {
.device = DEVICE_MAGIC,
.command = ATACOMMAND_EXECUTE_DEVICE_DIAGNOSTIC
};
uint32_t kick_flags = ATAOp_NoDRDY |
(dr->deviceid << ATAOp_DeviceIDShift) |
(dr->cpid << ATAOp_CPIDShift) |
ATAOp_TransNone |
(flags & ATAOp_DisableEscape);
ata_op_fg_nodata(kick_flags, 7, &kick_p, OP_TIMEOUT);
}
if (e.oserror && transferred)
++retries; /* At least some data transferred, so it's not fair to decrement the retry count when we loop */
}
......
......@@ -131,6 +131,7 @@ enum
ATACOMMAND_WRITE_DMA_EXT = 0x35,
ATACOMMAND_READ_VERIFY_SECTORS = 0x40,
ATACOMMAND_READ_VERIFY_SECTORS_EXT = 0x42,
ATACOMMAND_EXECUTE_DEVICE_DIAGNOSTIC = 0x90,
ATACOMMAND_PACKET = 0xA0,
ATACOMMAND_IDENTIFY_PACKET_DEVICE = 0xA1,
ATACOMMAND_READ_DMA = 0xC8,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment