* Explicitly check device selection success. If device selection failed, assume
there is no device. Should fix long reset timeouts when only device 1 is present and therefore device 0 can't be selected. * In case a device reset error is reported, don't try to identify/use the device. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30286 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -122,14 +122,18 @@ ATAChannel::ScanBus()
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool devicePresent[fDeviceCount];
|
||||||
uint32 deviceSignature[fDeviceCount];
|
uint32 deviceSignature[fDeviceCount];
|
||||||
status_t result = Reset(deviceSignature);
|
status_t result = Reset(devicePresent, deviceSignature);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ERROR("resetting the channel failed\n");
|
TRACE_ERROR("resetting the channel failed\n");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8 i = 0; i < fDeviceCount; i++) {
|
for (uint8 i = 0; i < fDeviceCount; i++) {
|
||||||
|
if (!devicePresent[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
ATADevice *device = NULL;
|
ATADevice *device = NULL;
|
||||||
if (deviceSignature[i] == ATA_SIGNATURE_ATAPI)
|
if (deviceSignature[i] == ATA_SIGNATURE_ATAPI)
|
||||||
device = new(std::nothrow) ATAPIDevice(this, i);
|
device = new(std::nothrow) ATAPIDevice(this, i);
|
||||||
@@ -261,7 +265,7 @@ ATAChannel::SelectDevice(uint8 device)
|
|||||||
_WriteRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
_WriteRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
||||||
_FlushAndWait(1);
|
_FlushAndWait(1);
|
||||||
|
|
||||||
#if KDEBUG > 0
|
#if 0
|
||||||
// for debugging only
|
// for debugging only
|
||||||
_ReadRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
_ReadRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
||||||
if (taskFile.chs.device != device) {
|
if (taskFile.chs.device != device) {
|
||||||
@@ -275,8 +279,17 @@ ATAChannel::SelectDevice(uint8 device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
ATAChannel::SelectedDevice()
|
||||||
|
{
|
||||||
|
ata_task_file taskFile;
|
||||||
|
_ReadRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
||||||
|
return taskFile.lba.device;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ATAChannel::Reset(uint32 *signatures)
|
ATAChannel::Reset(bool *presence, uint32 *signatures)
|
||||||
{
|
{
|
||||||
TRACE_FUNCTION("\n");
|
TRACE_FUNCTION("\n");
|
||||||
|
|
||||||
@@ -299,16 +312,26 @@ ATAChannel::Reset(uint32 *signatures)
|
|||||||
|
|
||||||
_FlushAndWait(150 * 1000);
|
_FlushAndWait(150 * 1000);
|
||||||
|
|
||||||
for (uint8 i = 0; i < fDeviceCount; i++) {
|
if (presence != NULL) {
|
||||||
|
for (uint8 i = 0; i < fDeviceCount; i++)
|
||||||
|
presence[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 deviceCount = fDeviceCount;
|
||||||
|
for (uint8 i = 0; i < deviceCount; i++) {
|
||||||
SelectDevice(i);
|
SelectDevice(i);
|
||||||
|
if (SelectedDevice() != i) {
|
||||||
|
TRACE_ALWAYS("cannot select device %d, assuming not present\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// ensure interrupts are disabled for this device
|
// ensure interrupts are disabled for this device
|
||||||
_WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS);
|
_WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS);
|
||||||
|
|
||||||
// wait up to 31 seconds for busy to clear
|
// wait up to 31 seconds for busy to clear
|
||||||
if (Wait(0, ATA_STATUS_BUSY, 0, 31 * 1000 * 1000) != B_OK) {
|
if (Wait(0, ATA_STATUS_BUSY, 0, 31 * 1000 * 1000) != B_OK) {
|
||||||
TRACE_ERROR("reset timeout\n");
|
TRACE_ERROR("device %d reset timeout\n", i);
|
||||||
return B_TIMED_OUT;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ata_task_file taskFile;
|
ata_task_file taskFile;
|
||||||
@@ -322,13 +345,18 @@ ATAChannel::Reset(uint32 *signatures)
|
|||||||
&& (i > 0 || taskFile.read.error != 0x81)) {
|
&& (i > 0 || taskFile.read.error != 0x81)) {
|
||||||
TRACE_ERROR("device %d failed, error code is 0x%02x\n", i,
|
TRACE_ERROR("device %d failed, error code is 0x%02x\n", i,
|
||||||
taskFile.read.error);
|
taskFile.read.error);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0 && taskFile.read.error >= 0x80) {
|
if (i == 0 && taskFile.read.error >= 0x80) {
|
||||||
TRACE_ERROR("device %d indicates that other device failed"
|
TRACE_ERROR("device %d indicates that other device failed"
|
||||||
" with code 0x%02x\n", i, taskFile.read.error);
|
" with code 0x%02x\n", i, taskFile.read.error);
|
||||||
|
deviceCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (presence != NULL)
|
||||||
|
presence[i] = true;
|
||||||
|
|
||||||
if (signatures != NULL) {
|
if (signatures != NULL) {
|
||||||
signatures[i] = taskFile.lba.sector_count
|
signatures[i] = taskFile.lba.sector_count
|
||||||
| (((uint32)taskFile.lba.lba_0_7) << 8)
|
| (((uint32)taskFile.lba.lba_0_7) << 8)
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ ata_sim_reset_bus(scsi_sim_cookie cookie)
|
|||||||
if (channel->Bus() == NULL)
|
if (channel->Bus() == NULL)
|
||||||
return SCSI_NO_HBA;
|
return SCSI_NO_HBA;
|
||||||
|
|
||||||
channel->Reset(NULL);
|
channel->Reset(NULL, NULL);
|
||||||
return SCSI_REQ_CMP;
|
return SCSI_REQ_CMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ public:
|
|||||||
|
|
||||||
// ATA stuff
|
// ATA stuff
|
||||||
status_t SelectDevice(uint8 index);
|
status_t SelectDevice(uint8 index);
|
||||||
|
uint8 SelectedDevice();
|
||||||
|
|
||||||
status_t Reset(uint32 *signatures);
|
status_t Reset(bool *presence, uint32 *signatures);
|
||||||
|
|
||||||
bool UseDMA() { return fUseDMA; };
|
bool UseDMA() { return fUseDMA; };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user