modified device detection
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23281 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel bus_managers ide ;
|
SubDir HAIKU_TOP src add-ons kernel bus_managers ata ;
|
||||||
|
|
||||||
UsePrivateHeaders drivers kernel ;
|
UsePrivateHeaders drivers kernel ;
|
||||||
UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ;
|
UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "ide_sim.h"
|
#include "ide_sim.h"
|
||||||
#include "ide_cmds.h"
|
#include "ide_cmds.h"
|
||||||
|
|
||||||
|
#define TRACE dprintf
|
||||||
|
|
||||||
/** verify that device is ready for further PIO transmission */
|
/** verify that device is ready for further PIO transmission */
|
||||||
|
|
||||||
@@ -785,3 +786,51 @@ void
|
|||||||
enable_CQ(ide_device_info *device, bool enable)
|
enable_CQ(ide_device_info *device, bool enable)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ata_read_infoblock(ide_device_info *device, bool isAtapi)
|
||||||
|
{
|
||||||
|
ide_bus_info *bus = device->bus;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
TRACE("ata_read_infoblock: device %p, isAtapi %d\n", device, isAtapi);
|
||||||
|
|
||||||
|
// disable interrupts
|
||||||
|
bus->controller->write_device_control(bus->channel_cookie, ide_devctrl_bit3 | ide_devctrl_nien);
|
||||||
|
|
||||||
|
device->tf_param_mask = 0;
|
||||||
|
device->tf.write.command = isAtapi ? IDE_CMD_IDENTIFY_PACKET_DEVICE : IDE_CMD_IDENTIFY_DEVICE;
|
||||||
|
|
||||||
|
// initialize device selection flags,
|
||||||
|
// this is the only place where this bit gets initialized in the task file
|
||||||
|
if (bus->controller->read_command_block_regs(bus->channel_cookie, &device->tf,
|
||||||
|
ide_mask_device_head) != B_OK) {
|
||||||
|
TRACE("ata_read_infoblock: read_command_block_regs failed\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->tf.lba.device = device->is_device1;
|
||||||
|
|
||||||
|
if (!send_command(device, NULL, isAtapi ? false : true, 20, ide_state_sync_waiting)) {
|
||||||
|
TRACE("ata_read_infoblock: send_command failed\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ata_wait(bus, ide_status_drq, ide_status_bsy, true, 4000000) != B_OK) {
|
||||||
|
TRACE("ata_read_infoblock: wait failed\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the infoblock
|
||||||
|
bus->controller->read_pio(bus->channel_cookie, (uint16 *)&device->infoblock,
|
||||||
|
sizeof(device->infoblock) / sizeof(uint16), false);
|
||||||
|
|
||||||
|
if (!wait_for_drqdown(device)) {
|
||||||
|
TRACE("scan_device_int: wait_for_drqdown failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("ata_read_infoblock: success\n");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
// TODO: the device will abort next command with a reset condition
|
// TODO: the device will abort next command with a reset condition
|
||||||
// perhaps we should hide that by reading sense?
|
// perhaps we should hide that by reading sense?
|
||||||
SHOW_FLOW0(3, "Reset");
|
SHOW_FLOW0(3, "Reset");
|
||||||
reset_device(device, qrequest);
|
// reset_device(device, qrequest);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(qrequest);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -53,142 +53,83 @@ wait_for_drdy(ide_device_info *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** reset entire IDE bus
|
status_t
|
||||||
* all active request apart from <ignore> are resubmitted
|
reset_bus(ide_bus_info *bus, uint32 *sigDev0, uint32 *sigDev1)
|
||||||
*/
|
|
||||||
|
|
||||||
bool
|
|
||||||
reset_bus(ide_device_info *device, ide_qrequest *ignore)
|
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
|
||||||
ide_controller_interface *controller = bus->controller;
|
ide_controller_interface *controller = bus->controller;
|
||||||
ide_channel_cookie channel = bus->channel_cookie;
|
ide_channel_cookie channel = bus->channel_cookie;
|
||||||
|
ide_task_file tf;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
dprintf("ide: reset_bus() device %p, bus %p\n", device, bus);
|
dprintf("ATA: reset_bus %p\n", bus);
|
||||||
|
|
||||||
FAST_LOG0(bus->log, ev_ide_reset_bus);
|
// 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)
|
||||||
|
goto error;
|
||||||
|
spin(20);
|
||||||
|
|
||||||
if (device->reconnect_timer_installed) {
|
// clear SRST for at least 2 ms
|
||||||
cancel_timer(&device->reconnect_timer.te);
|
if (controller->write_device_control(channel, ide_devctrl_bit3 | ide_devctrl_nien) != B_OK)
|
||||||
device->reconnect_timer_installed = false;
|
goto error;
|
||||||
|
snooze(5000);
|
||||||
|
|
||||||
|
// wait up to 30 seconds for busy to clear, abort when error is set
|
||||||
|
status = ata_wait(bus, 0, ide_status_bsy, true, 33000000);
|
||||||
|
if (status != B_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
tf.chs.head = 0;
|
||||||
|
tf.chs.mode = ide_mode_lba;
|
||||||
|
|
||||||
|
// select device 0
|
||||||
|
tf.chs.device = 0;
|
||||||
|
if (controller->write_command_block_regs(channel, &tf, ide_mask_device_head) != B_OK)
|
||||||
|
goto error;
|
||||||
|
status = ata_wait(bus, 0, ide_status_bsy | ide_status_drq, true, 50000);
|
||||||
|
if (status != B_OK) {
|
||||||
|
dprintf("ATA: reset_bus: device 0 not present\n");
|
||||||
|
*sigDev0 = 0;
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->other_device->reconnect_timer_installed) {
|
// select device 1
|
||||||
cancel_timer(&device->other_device->reconnect_timer.te);
|
tf.chs.device = 1;
|
||||||
device->other_device->reconnect_timer_installed = false;
|
if (controller->write_command_block_regs(channel, &tf, ide_mask_device_head) != B_OK)
|
||||||
|
goto error;
|
||||||
|
status = ata_wait(bus, 0, ide_status_bsy | ide_status_drq, true, 50000);
|
||||||
|
if (status != B_OK) {
|
||||||
|
dprintf("ATA: reset_bus: device 1 not present\n");
|
||||||
|
*sigDev1 = 0;
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// activate srst signal for 5 µs
|
dprintf("ATA: reset_bus success, device 0 signature: 0x%08lx, device 1 signature: 0x%08lx\n", *sigDev0, *sigDev1);
|
||||||
// also, deactivate IRQ
|
|
||||||
// (as usual, we will get an IRQ on disabling, but as we leave them
|
|
||||||
// disabled for 2 ms, this false report is ignored)
|
|
||||||
if (controller->write_device_control(channel,
|
|
||||||
ide_devctrl_nien | ide_devctrl_srst | ide_devctrl_bit3) != B_OK)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
spin(5);
|
return B_OK;
|
||||||
|
|
||||||
if (controller->write_device_control(channel, ide_devctrl_nien | ide_devctrl_bit3) != B_OK)
|
error:
|
||||||
goto err0;
|
|
||||||
|
|
||||||
// let devices wake up
|
dprintf("ATA: reset_bus failed\n");
|
||||||
snooze(2000);
|
return B_ERROR;
|
||||||
|
|
||||||
// ouch, we have to wait up to 31 seconds!
|
|
||||||
if (!ide_wait(device, 0, ide_status_bsy, true, 31000000)) {
|
|
||||||
// as we don't know which of the devices is broken
|
|
||||||
// we leave them both alive
|
|
||||||
if (controller->write_device_control(channel, ide_devctrl_bit3) != B_OK)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_TIMEOUT);
|
|
||||||
goto err1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controller->write_device_control(channel, ide_devctrl_bit3) != B_OK)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
finish_all_requests(bus->devices[0], ignore, SCSI_SCSI_BUS_RESET, true);
|
|
||||||
finish_all_requests(bus->devices[1], ignore, SCSI_SCSI_BUS_RESET, true);
|
|
||||||
|
|
||||||
dprintf("ide: reset_bus() device %p, bus %p success\n", device, bus);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
err0:
|
|
||||||
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE);
|
|
||||||
|
|
||||||
err1:
|
|
||||||
finish_all_requests(bus->devices[0], ignore, SCSI_SCSI_BUS_RESET, true);
|
|
||||||
finish_all_requests(bus->devices[1], ignore, SCSI_SCSI_BUS_RESET, true);
|
|
||||||
|
|
||||||
//xpt->call_async( bus->xpt_cookie, -1, -1, AC_BUS_RESET, NULL, 0 );
|
|
||||||
|
|
||||||
dprintf("ide: reset_bus() device %p, bus %p failed\n", device, bus);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** execute packet device reset.
|
|
||||||
* resets entire bus on fail or if device is not atapi;
|
|
||||||
* all requests but <ignore> are resubmitted
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool
|
|
||||||
reset_device(ide_device_info *device, ide_qrequest *ignore)
|
|
||||||
{
|
|
||||||
ide_bus_info *bus = device->bus;
|
|
||||||
status_t res;
|
|
||||||
uint8 orig_command;
|
|
||||||
|
|
||||||
dprintf("ide: reset_device() device %p\n", device);
|
|
||||||
|
|
||||||
FAST_LOG1(bus->log, ev_ide_reset_device, device->is_device1);
|
|
||||||
SHOW_FLOW0(3, "");
|
|
||||||
|
|
||||||
if (!device->is_atapi)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (device->reconnect_timer_installed) {
|
|
||||||
cancel_timer(&device->reconnect_timer.te);
|
|
||||||
device->reconnect_timer_installed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// select device
|
|
||||||
if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf,
|
|
||||||
ide_mask_device_head) != B_OK)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
// safe original command to let caller restart it
|
|
||||||
orig_command = device->tf.write.command;
|
|
||||||
|
|
||||||
// send device reset, independ of current device state
|
|
||||||
// (that's the point of a reset)
|
|
||||||
device->tf.write.command = IDE_CMD_DEVICE_RESET;
|
|
||||||
res = bus->controller->write_command_block_regs(bus->channel_cookie,
|
|
||||||
&device->tf, ide_mask_command);
|
|
||||||
device->tf.write.command = orig_command;
|
|
||||||
|
|
||||||
if (res != B_OK)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
// don't know how long to wait, but 31 seconds, like soft reset,
|
|
||||||
// should be enough
|
|
||||||
if (!ide_wait(device, 0, ide_status_bsy, true, 31000000))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
// alright, resubmit all requests
|
|
||||||
finish_all_requests(device, ignore, SCSI_SCSI_BUS_RESET, true);
|
|
||||||
|
|
||||||
SHOW_FLOW0(3, "done");
|
|
||||||
dprintf("ide: reset_device() device %p success\n", device);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
err:
|
|
||||||
// do the hard way
|
|
||||||
dprintf("ide: reset_device() device %p failed, calling reset_bus\n", device);
|
|
||||||
return reset_bus(device, ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** new_state must be either accessing, async_waiting or sync_waiting
|
/** new_state must be either accessing, async_waiting or sync_waiting
|
||||||
* param_mask must not include command register
|
* param_mask must not include command register
|
||||||
*/
|
*/
|
||||||
@@ -250,12 +191,13 @@ retry:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// reset device and retry
|
// reset device and retry
|
||||||
if (reset_device(device, qrequest) && ++num_retries <= MAX_FAILED_SEND) {
|
if (reset_device(device, qrequest) && ++num_retries <= MAX_FAILED_SEND) {
|
||||||
SHOW_FLOW0(1, "retrying");
|
SHOW_FLOW0(1, "retrying");
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
SHOW_FLOW0(1, "giving up");
|
SHOW_FLOW0(1, "giving up");
|
||||||
|
|
||||||
// reset to often - abort request
|
// reset to often - abort request
|
||||||
@@ -331,6 +273,39 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ata_wait(ide_bus_info *bus, uint8 mask, uint8 not_mask,
|
||||||
|
bool check_err, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
bigtime_t startTime = system_time();
|
||||||
|
bigtime_t elapsedTime;
|
||||||
|
uint8 status;
|
||||||
|
|
||||||
|
spin(1); // device needs 400ns to set status
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
status = bus->controller->get_altstatus(bus->channel_cookie);
|
||||||
|
|
||||||
|
if (check_err && (status & ide_status_err) != 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if ((status & mask) == mask && (status & not_mask) == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
elapsedTime = system_time() - startTime;
|
||||||
|
|
||||||
|
if (elapsedTime > timeout)
|
||||||
|
return B_TIMED_OUT;
|
||||||
|
|
||||||
|
if (elapsedTime < 5000)
|
||||||
|
spin(1);
|
||||||
|
else
|
||||||
|
snooze(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** busy-wait for device
|
/** busy-wait for device
|
||||||
* mask - bits of status register that must be set
|
* mask - bits of status register that must be set
|
||||||
* not_mask - bits of status register that must not be set
|
* not_mask - bits of status register that must not be set
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ cleanup_device_links(ide_device_info *device)
|
|||||||
|
|
||||||
/** destroy device info */
|
/** destroy device info */
|
||||||
|
|
||||||
static void
|
void
|
||||||
destroy_device(ide_device_info *device)
|
destroy_device(ide_device_info *device)
|
||||||
{
|
{
|
||||||
TRACE("destroy_device: device %p\n", device);
|
TRACE("destroy_device: device %p\n", device);
|
||||||
@@ -101,7 +101,7 @@ setup_device_links(ide_bus_info *bus, ide_device_info *device)
|
|||||||
|
|
||||||
/** create device info */
|
/** create device info */
|
||||||
|
|
||||||
static ide_device_info *
|
ide_device_info *
|
||||||
create_device(ide_bus_info *bus, bool is_device1)
|
create_device(ide_bus_info *bus, bool is_device1)
|
||||||
{
|
{
|
||||||
ide_device_info *device;
|
ide_device_info *device;
|
||||||
@@ -185,7 +185,7 @@ prep_infoblock(ide_device_info *device)
|
|||||||
|
|
||||||
|
|
||||||
/** read info block of ATA or ATAPI device */
|
/** read info block of ATA or ATAPI device */
|
||||||
|
/*
|
||||||
static bool
|
static bool
|
||||||
scan_device_int(ide_device_info *device, bool atapi)
|
scan_device_int(ide_device_info *device, bool atapi)
|
||||||
{
|
{
|
||||||
@@ -284,10 +284,24 @@ scan_device_int(ide_device_info *device, bool atapi)
|
|||||||
prep_infoblock(device);
|
prep_infoblock(device);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/** scan one device */
|
/** scan one device */
|
||||||
|
status_t
|
||||||
|
scan_device(ide_device_info *device, bool isAtapi)
|
||||||
|
{
|
||||||
|
dprintf("ATA: scan_device\n");
|
||||||
|
|
||||||
|
if (ata_read_infoblock(device, isAtapi) != B_OK) {
|
||||||
|
dprintf("ATA: couldn't read infoblock for device %p\n", device);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
prep_infoblock(device);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void
|
void
|
||||||
scan_device_worker(ide_bus_info *bus, void *arg)
|
scan_device_worker(ide_bus_info *bus, void *arg)
|
||||||
{
|
{
|
||||||
@@ -321,12 +335,11 @@ scan_device_worker(ide_bus_info *bus, void *arg)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
bus->state = ide_state_idle;
|
bus->state = ide_state_idle;
|
||||||
release_sem(bus->scan_device_sem);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
destroy_device(device);
|
destroy_device(device);
|
||||||
|
|
||||||
bus->state = ide_state_idle;
|
bus->state = ide_state_idle;
|
||||||
release_sem(bus->scan_device_sem);
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@@ -221,9 +221,6 @@ struct ide_bus_info {
|
|||||||
ide_device_info *devices[2];
|
ide_device_info *devices[2];
|
||||||
ide_device_info *first_device;
|
ide_device_info *first_device;
|
||||||
|
|
||||||
ide_synced_pc scan_bus_syncinfo; // used to start bus scan
|
|
||||||
sem_id scan_device_sem; // released when device has been scanned
|
|
||||||
|
|
||||||
ide_synced_pc disconnect_syncinfo; // used to handle lost controller
|
ide_synced_pc disconnect_syncinfo; // used to handle lost controller
|
||||||
|
|
||||||
uchar path_id;
|
uchar path_id;
|
||||||
@@ -331,6 +328,8 @@ void ata_dpc_PIO(ide_qrequest *qrequest);
|
|||||||
|
|
||||||
void ata_exec_io(ide_device_info *device, ide_qrequest *qrequest);
|
void ata_exec_io(ide_device_info *device, ide_qrequest *qrequest);
|
||||||
|
|
||||||
|
status_t ata_read_infoblock(ide_device_info *device, bool isAtapi);
|
||||||
|
|
||||||
|
|
||||||
// atapi.c
|
// atapi.c
|
||||||
|
|
||||||
@@ -343,6 +342,9 @@ void atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest);
|
|||||||
|
|
||||||
// basic_prot.c
|
// basic_prot.c
|
||||||
|
|
||||||
|
status_t ata_wait(ide_bus_info *bus, uint8 mask, uint8 not_mask, bool check_err, bigtime_t timeout);
|
||||||
|
|
||||||
|
|
||||||
bool ide_wait(ide_device_info *device, int mask, int not_mask, bool check_err,
|
bool ide_wait(ide_device_info *device, int mask, int not_mask, bool check_err,
|
||||||
bigtime_t timeout);
|
bigtime_t timeout);
|
||||||
bool wait_for_drq(ide_device_info *device);
|
bool wait_for_drq(ide_device_info *device);
|
||||||
@@ -353,11 +355,13 @@ bool wait_for_drdy(ide_device_info *device);
|
|||||||
bool send_command(ide_device_info *device, ide_qrequest *qrequest,
|
bool send_command(ide_device_info *device, ide_qrequest *qrequest,
|
||||||
bool need_drdy, uint32 timeout, ide_bus_state new_state);
|
bool need_drdy, uint32 timeout, ide_bus_state new_state);
|
||||||
bool device_start_service( ide_device_info *device, int *tag);
|
bool device_start_service( ide_device_info *device, int *tag);
|
||||||
bool reset_device(ide_device_info *device, ide_qrequest *ignore);
|
//bool reset_device(ide_device_info *device, ide_qrequest *ignore);
|
||||||
bool reset_bus(ide_device_info *device, ide_qrequest *ignore);
|
//bool reset_bus(ide_device_info *device, ide_qrequest *ignore);
|
||||||
|
|
||||||
bool check_service_req(ide_device_info *device);
|
bool check_service_req(ide_device_info *device);
|
||||||
|
|
||||||
|
status_t reset_bus(ide_bus_info *bus, uint32 *sigDev0, uint32 *sigDev1);
|
||||||
|
|
||||||
|
|
||||||
// channel_mgr.c
|
// channel_mgr.c
|
||||||
|
|
||||||
@@ -366,7 +370,10 @@ extern ide_for_controller_interface ide_for_controller_module;
|
|||||||
|
|
||||||
// device_mgr.c
|
// device_mgr.c
|
||||||
|
|
||||||
void scan_device_worker(ide_bus_info *bus, void *arg);
|
status_t scan_device(ide_device_info *device, bool isAtapi);
|
||||||
|
void destroy_device(ide_device_info *device);
|
||||||
|
ide_device_info *create_device(ide_bus_info *bus, bool is_device1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// dma.c
|
// dma.c
|
||||||
|
|||||||
@@ -79,20 +79,7 @@ static void set_check_condition(ide_qrequest *qrequest);
|
|||||||
static inline bool
|
static inline bool
|
||||||
is_queuable(ide_device_info *device, scsi_ccb *request)
|
is_queuable(ide_device_info *device, scsi_ccb *request)
|
||||||
{
|
{
|
||||||
int opcode = request->cdb[0];
|
return false;
|
||||||
|
|
||||||
// XXX disable queuing
|
|
||||||
if (!device->CQ_enabled)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// make sure the caller allows queuing
|
|
||||||
if ((request->flags & SCSI_ORDERED_QTAG) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// for atapi, all commands could be queued, but all
|
|
||||||
// atapi devices I know don't support queuing anyway
|
|
||||||
return opcode == SCSI_OP_READ_6 || opcode == SCSI_OP_WRITE_6
|
|
||||||
|| opcode == SCSI_OP_READ_10 || opcode == SCSI_OP_WRITE_10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -241,34 +228,38 @@ sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
scan_device(ide_bus_info *bus, int device)
|
|
||||||
{
|
|
||||||
SHOW_FLOW0(4, "");
|
|
||||||
|
|
||||||
// currently, the SCSI bus manager doesn't block the
|
|
||||||
// bus when a bus or device scan is issued, so we
|
|
||||||
// have to use a SPC for that to be sure no one else
|
|
||||||
// is accessing the device or bus concurrently
|
|
||||||
schedule_synced_pc(bus, &bus->scan_bus_syncinfo, (void *)device);
|
|
||||||
|
|
||||||
acquire_sem(bus->scan_device_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uchar
|
static uchar
|
||||||
sim_scan_bus(ide_bus_info *bus)
|
sim_scan_bus(ide_bus_info *bus)
|
||||||
{
|
{
|
||||||
|
uint32 deviceSignature[2];
|
||||||
|
ide_device_info *device;
|
||||||
|
status_t status;
|
||||||
|
bool isAtapi;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
SHOW_FLOW0(4, "");
|
dprintf("ATA: sim_scan_bus: bus %p\n", bus);
|
||||||
|
|
||||||
if (bus->disconnected)
|
if (bus->disconnected)
|
||||||
return SCSI_NO_HBA;
|
return SCSI_NO_HBA;
|
||||||
|
|
||||||
|
// IDE_LOCK(bus);
|
||||||
|
|
||||||
|
status = reset_bus(bus, &deviceSignature[0], &deviceSignature[1]);
|
||||||
|
|
||||||
for (i = 0; i < bus->max_devices; ++i) {
|
for (i = 0; i < bus->max_devices; ++i) {
|
||||||
scan_device(bus, i);
|
if (bus->devices[i])
|
||||||
|
destroy_device(bus->devices[i]);
|
||||||
|
|
||||||
|
if (status == B_OK && deviceSignature[i] != 0) {
|
||||||
|
isAtapi = deviceSignature[i] == 0xeb140101;
|
||||||
|
device = create_device(bus, i /* isDevice1 */);
|
||||||
|
if (scan_device(device, isAtapi) != B_OK)
|
||||||
|
destroy_device(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// IDE_UNLOCK(bus);
|
||||||
|
|
||||||
|
dprintf("ATA: sim_scan_bus: bus %p finished\n", bus);
|
||||||
|
|
||||||
return SCSI_REQ_CMP;
|
return SCSI_REQ_CMP;
|
||||||
}
|
}
|
||||||
@@ -581,7 +572,6 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_synced_pc(&bus->scan_bus_syncinfo, scan_device_worker);
|
|
||||||
init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
|
init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
|
||||||
|
|
||||||
bus->scsi_cookie = user_cookie;
|
bus->scsi_cookie = user_cookie;
|
||||||
@@ -601,12 +591,6 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
|
|
||||||
bus->devices[0] = bus->devices[1] = NULL;
|
bus->devices[0] = bus->devices[1] = NULL;
|
||||||
|
|
||||||
bus->scan_device_sem = create_sem(0, "ide_scan_finished");
|
|
||||||
if (bus->scan_device_sem < 0) {
|
|
||||||
status = bus->scan_device_sem;
|
|
||||||
goto err3;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
|
status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err4;
|
goto err4;
|
||||||
@@ -675,13 +659,11 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
err5:
|
err5:
|
||||||
DELETE_BEN(&bus->status_report_ben);
|
DELETE_BEN(&bus->status_report_ben);
|
||||||
err4:
|
err4:
|
||||||
delete_sem(bus->scan_device_sem);
|
|
||||||
err3:
|
err3:
|
||||||
delete_sem(bus->sync_wait_sem);
|
delete_sem(bus->sync_wait_sem);
|
||||||
err2:
|
err2:
|
||||||
scsi->free_dpc(bus->irq_dpc);
|
scsi->free_dpc(bus->irq_dpc);
|
||||||
err1:
|
err1:
|
||||||
uninit_synced_pc(&bus->scan_bus_syncinfo);
|
|
||||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
uninit_synced_pc(&bus->disconnect_syncinfo);
|
||||||
#ifdef USE_FAST_LOG
|
#ifdef USE_FAST_LOG
|
||||||
fast_log->stop_log(bus->log);
|
fast_log->stop_log(bus->log);
|
||||||
@@ -702,10 +684,8 @@ ide_sim_uninit_bus(ide_bus_info *bus)
|
|||||||
pnp->put_device_node(parent);
|
pnp->put_device_node(parent);
|
||||||
|
|
||||||
DELETE_BEN(&bus->status_report_ben);
|
DELETE_BEN(&bus->status_report_ben);
|
||||||
delete_sem(bus->scan_device_sem);
|
|
||||||
delete_sem(bus->sync_wait_sem);
|
delete_sem(bus->sync_wait_sem);
|
||||||
scsi->free_dpc(bus->irq_dpc);
|
scsi->free_dpc(bus->irq_dpc);
|
||||||
uninit_synced_pc(&bus->scan_bus_syncinfo);
|
|
||||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
uninit_synced_pc(&bus->disconnect_syncinfo);
|
||||||
// fast_log->stop_log(bus->log);
|
// fast_log->stop_log(bus->log);
|
||||||
|
|
||||||
|
|||||||
@@ -370,5 +370,6 @@ send_abort_queue(ide_device_info *device)
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
// ouch! device didn't react - we have to reset it
|
// ouch! device didn't react - we have to reset it
|
||||||
return reset_device(device, NULL);
|
//return reset_device(device, NULL);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ ide_timeout_dpc(void *arg)
|
|||||||
FAST_LOG1(bus->log, ev_ide_timeout_dpc, (uint32)qrequest);
|
FAST_LOG1(bus->log, ev_ide_timeout_dpc, (uint32)qrequest);
|
||||||
|
|
||||||
// this also resets overlapped commands
|
// this also resets overlapped commands
|
||||||
reset_device(device, qrequest);
|
// reset_device(device, qrequest);
|
||||||
|
|
||||||
device->subsys_status = SCSI_CMD_TIMEOUT;
|
device->subsys_status = SCSI_CMD_TIMEOUT;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user