From d394cf760ca2d27ebe4edd72ab0b1f197d13e982 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Tue, 8 Jan 2008 22:31:35 +0000 Subject: [PATCH] check for device presence before trying to read the signature git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23289 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/bus_managers/ata/ata.c | 23 ++++- .../kernel/bus_managers/ata/basic_protocol.c | 92 +++++++++++-------- .../kernel/bus_managers/ata/ide_internal.h | 2 + src/add-ons/kernel/bus_managers/ata/ide_sim.c | 7 ++ 4 files changed, 83 insertions(+), 41 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ata/ata.c b/src/add-ons/kernel/bus_managers/ata/ata.c index e3abbc01a9..b8cd17ca99 100644 --- a/src/add-ons/kernel/bus_managers/ata/ata.c +++ b/src/add-ons/kernel/bus_managers/ata/ata.c @@ -25,11 +25,32 @@ ata_select_device(ide_bus_info *bus, int device) tf.chs.mode = ide_mode_lba; tf.chs.device = device ? 1 : 0; - bus->controller->read_command_block_regs(bus->channel_cookie, &tf, ide_mask_device_head); + bus->controller->write_command_block_regs(bus->channel_cookie, &tf, ide_mask_device_head); spin(1); // wait 400 nsec } +bool +ata_is_device_present(ide_bus_info *bus, int device) +{ + ide_task_file tf; + + ata_select_device(bus, device); + + tf.lba.sector_count = 0xaa; + tf.lba.lba_0_7 = 0x55; + + bus->controller->write_command_block_regs(bus->channel_cookie, &tf, + ide_mask_sector_count | ide_mask_LBA_low); + spin(1); // wait 400 nsec + + bus->controller->read_command_block_regs(bus->channel_cookie, &tf, + ide_mask_sector_count | ide_mask_LBA_low); + + return tf.lba.sector_count == 0xaa && tf.lba.lba_0_7 == 0x55; +} + + /* void diff --git a/src/add-ons/kernel/bus_managers/ata/basic_protocol.c b/src/add-ons/kernel/bus_managers/ata/basic_protocol.c index 5d9b471f1e..65dea4ede4 100644 --- a/src/add-ons/kernel/bus_managers/ata/basic_protocol.c +++ b/src/add-ons/kernel/bus_managers/ata/basic_protocol.c @@ -60,9 +60,16 @@ reset_bus(ide_bus_info *bus, uint32 *sigDev0, uint32 *sigDev1) ide_channel_cookie channel = bus->channel_cookie; ide_task_file tf; status_t status; + bool devicePresent0; + bool devicePresent1; dprintf("ATA: reset_bus %p\n", bus); + devicePresent0 = ata_is_device_present(bus, 0); + devicePresent1 = ata_is_device_present(bus, 1); + + dprintf("ATA: reset_bus: ata_is_device_present device 0, present %d\n", devicePresent0); + dprintf("ATA: reset_bus: ata_is_device_present device 1, present %d\n", devicePresent1); // disable interrupts and assert SRST for at least 5 usec if (controller->write_device_control(channel, ide_devctrl_bit3 | ide_devctrl_nien | ide_devctrl_srst) != B_OK) @@ -74,55 +81,60 @@ reset_bus(ide_bus_info *bus, uint32 *sigDev0, uint32 *sigDev1) goto error; snooze(150000); - ata_select_device(bus, 0); + if (devicePresent0) { - dprintf("altstatus device 0: %x\n", controller->get_altstatus(channel)); + ata_select_device(bus, 0); + dprintf("altstatus device 0: %x\n", controller->get_altstatus(channel)); - // wait up to 31 seconds for busy to clear, abort when error is set - status = ata_wait(bus, 0, ide_status_bsy, false, 31000000); - if (status != B_OK) { - if (status == B_TIMED_OUT) - dprintf("ATA: reset_bus: timeout\n"); - else - dprintf("ATA: reset_bus: error bit set\n"); - goto error; + // wait up to 31 seconds for busy to clear, abort when error is set + status = ata_wait(bus, 0, ide_status_bsy, false, 31000000); + if (status != B_OK) { + if (status == B_TIMED_OUT) + dprintf("ATA: reset_bus: timeout\n"); + else + dprintf("ATA: reset_bus: error bit set\n"); + goto error; + } + + if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count | + ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high) != B_OK) + goto error; + + *sigDev0 = tf.lba.sector_count; + *sigDev0 |= ((uint32)tf.lba.lba_0_7) << 8; + *sigDev0 |= ((uint32)tf.lba.lba_8_15) << 16; + *sigDev0 |= ((uint32)tf.lba.lba_16_23) << 24; + } else { + *sigDev0 = 0; } - if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count | - ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high) != B_OK) - goto error; + if (devicePresent1) { + + ata_select_device(bus, 1); + dprintf("altstatus device 1: %x\n", controller->get_altstatus(channel)); - *sigDev0 = tf.lba.sector_count; - *sigDev0 |= ((uint32)tf.lba.lba_0_7) << 8; - *sigDev0 |= ((uint32)tf.lba.lba_8_15) << 16; - *sigDev0 |= ((uint32)tf.lba.lba_16_23) << 24; + // wait up to 31 seconds for busy to clear, abort when error is set + status = ata_wait(bus, 0, ide_status_bsy, false, 31000000); + if (status != B_OK) { + if (status == B_TIMED_OUT) + dprintf("ATA: reset_bus: timeout\n"); + else + dprintf("ATA: reset_bus: error bit set\n"); + goto error; + } + if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count | + ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high) != B_OK) + goto error; - - ata_select_device(bus, 1); - - dprintf("altstatus device 1: %x\n", controller->get_altstatus(channel)); - - // wait up to 31 seconds for busy to clear, abort when error is set - status = ata_wait(bus, 0, ide_status_bsy, false, 31000000); - if (status != B_OK) { - if (status == B_TIMED_OUT) - dprintf("ATA: reset_bus: timeout\n"); - else - dprintf("ATA: reset_bus: error bit set\n"); - goto error; + *sigDev1 = tf.lba.sector_count; + *sigDev1 |= ((uint32)tf.lba.lba_0_7) << 8; + *sigDev1 |= ((uint32)tf.lba.lba_8_15) << 16; + *sigDev1 |= ((uint32)tf.lba.lba_16_23) << 24; + } else { + *sigDev1 = 0; } - if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count | - ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high) != B_OK) - goto error; - - *sigDev1 = tf.lba.sector_count; - *sigDev1 |= ((uint32)tf.lba.lba_0_7) << 8; - *sigDev1 |= ((uint32)tf.lba.lba_8_15) << 16; - *sigDev1 |= ((uint32)tf.lba.lba_16_23) << 24; - - dprintf("ATA: reset_bus success, device 0 signature: 0x%08lx, device 1 signature: 0x%08lx\n", *sigDev0, *sigDev1); return B_OK; diff --git a/src/add-ons/kernel/bus_managers/ata/ide_internal.h b/src/add-ons/kernel/bus_managers/ata/ide_internal.h index 4aa9033328..c0a951e532 100644 --- a/src/add-ons/kernel/bus_managers/ata/ide_internal.h +++ b/src/add-ons/kernel/bus_managers/ata/ide_internal.h @@ -317,6 +317,8 @@ device_released_bus(ide_device_info *device) //void ata_select_device(ide_device_info *device); void ata_select_device(ide_bus_info *bus, int device); +bool ata_is_device_present(ide_bus_info *bus, int device); + bool check_rw_error(ide_device_info *device, ide_qrequest *qrequest); bool check_output(ide_device_info *device, bool drdy_required, int error_mask, bool is_write); diff --git a/src/add-ons/kernel/bus_managers/ata/ide_sim.c b/src/add-ons/kernel/bus_managers/ata/ide_sim.c index 91b83c6f5a..2d0b7b2b2a 100644 --- a/src/add-ons/kernel/bus_managers/ata/ide_sim.c +++ b/src/add-ons/kernel/bus_managers/ata/ide_sim.c @@ -659,6 +659,13 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie) *cookie = bus; +/* + // make sure LBA bit is set + bus->controller->read_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_device_head); + tf.chs.mode = ide_mode_lba; + bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_device_head); +*/ + // detect devices sim_scan_bus(bus); return B_OK;