* 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;
|
||||
}
|
||||
|
||||
bool devicePresent[fDeviceCount];
|
||||
uint32 deviceSignature[fDeviceCount];
|
||||
status_t result = Reset(deviceSignature);
|
||||
status_t result = Reset(devicePresent, deviceSignature);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("resetting the channel failed\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < fDeviceCount; i++) {
|
||||
if (!devicePresent[i])
|
||||
continue;
|
||||
|
||||
ATADevice *device = NULL;
|
||||
if (deviceSignature[i] == ATA_SIGNATURE_ATAPI)
|
||||
device = new(std::nothrow) ATAPIDevice(this, i);
|
||||
@@ -261,7 +265,7 @@ ATAChannel::SelectDevice(uint8 device)
|
||||
_WriteRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
||||
_FlushAndWait(1);
|
||||
|
||||
#if KDEBUG > 0
|
||||
#if 0
|
||||
// for debugging only
|
||||
_ReadRegs(&taskFile, ATA_MASK_DEVICE_HEAD);
|
||||
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
|
||||
ATAChannel::Reset(uint32 *signatures)
|
||||
ATAChannel::Reset(bool *presence, uint32 *signatures)
|
||||
{
|
||||
TRACE_FUNCTION("\n");
|
||||
|
||||
@@ -299,16 +312,26 @@ ATAChannel::Reset(uint32 *signatures)
|
||||
|
||||
_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);
|
||||
if (SelectedDevice() != i) {
|
||||
TRACE_ALWAYS("cannot select device %d, assuming not present\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ensure interrupts are disabled for this device
|
||||
_WriteControl(ATA_DEVICE_CONTROL_DISABLE_INTS);
|
||||
|
||||
// wait up to 31 seconds for busy to clear
|
||||
if (Wait(0, ATA_STATUS_BUSY, 0, 31 * 1000 * 1000) != B_OK) {
|
||||
TRACE_ERROR("reset timeout\n");
|
||||
return B_TIMED_OUT;
|
||||
TRACE_ERROR("device %d reset timeout\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
ata_task_file taskFile;
|
||||
@@ -322,13 +345,18 @@ ATAChannel::Reset(uint32 *signatures)
|
||||
&& (i > 0 || taskFile.read.error != 0x81)) {
|
||||
TRACE_ERROR("device %d failed, error code is 0x%02x\n", i,
|
||||
taskFile.read.error);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 0 && taskFile.read.error >= 0x80) {
|
||||
TRACE_ERROR("device %d indicates that other device failed"
|
||||
" with code 0x%02x\n", i, taskFile.read.error);
|
||||
deviceCount = 1;
|
||||
}
|
||||
|
||||
if (presence != NULL)
|
||||
presence[i] = true;
|
||||
|
||||
if (signatures != NULL) {
|
||||
signatures[i] = taskFile.lba.sector_count
|
||||
| (((uint32)taskFile.lba.lba_0_7) << 8)
|
||||
|
||||
@@ -136,7 +136,7 @@ ata_sim_reset_bus(scsi_sim_cookie cookie)
|
||||
if (channel->Bus() == NULL)
|
||||
return SCSI_NO_HBA;
|
||||
|
||||
channel->Reset(NULL);
|
||||
channel->Reset(NULL, NULL);
|
||||
return SCSI_REQ_CMP;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,8 +77,9 @@ public:
|
||||
|
||||
// ATA stuff
|
||||
status_t SelectDevice(uint8 index);
|
||||
uint8 SelectedDevice();
|
||||
|
||||
status_t Reset(uint32 *signatures);
|
||||
status_t Reset(bool *presence, uint32 *signatures);
|
||||
|
||||
bool UseDMA() { return fUseDMA; };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user