Partially applied our style guide.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9968 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
/** verify that device is ready for further PIO transmission */
|
/** verify that device is ready for further PIO transmission */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_rw_status(ide_device_info *device, bool drq_required)
|
check_rw_status(ide_device_info *device, bool drqStatus)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
int status;
|
int status;
|
||||||
@@ -31,7 +31,7 @@ check_rw_status(ide_device_info *device, bool drq_required)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drq_required != ((status & ide_status_drq) != 0)) {
|
if (drqStatus != ((status & ide_status_drq) != 0)) {
|
||||||
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ ata_dpc_PIO(ide_qrequest *qrequest)
|
|||||||
uint32 timeout = qrequest->request->timeout > 0 ?
|
uint32 timeout = qrequest->request->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
if (check_rw_error(device, qrequest)
|
if (check_rw_error(device, qrequest)
|
||||||
|| !check_rw_status(device, qrequest->is_write ? device->left_blocks > 1 : true))
|
|| !check_rw_status(device, qrequest->is_write ? device->left_blocks > 1 : true))
|
||||||
@@ -67,18 +67,18 @@ ata_dpc_PIO(ide_qrequest *qrequest)
|
|||||||
if (qrequest->is_write) {
|
if (qrequest->is_write) {
|
||||||
if (device->left_blocks == 0) {
|
if (device->left_blocks == 0) {
|
||||||
// this was the end-of-transmission IRQ
|
// this was the end-of-transmission IRQ
|
||||||
SHOW_FLOW0( 3, "write access finished" );
|
SHOW_FLOW0(3, "write access finished");
|
||||||
if (!wait_for_drq(device)) {
|
if (!wait_for_drq(device)) {
|
||||||
SHOW_ERROR0( 3, "device wants to transmit data though command is finished" );
|
SHOW_ERROR0(3, "device wants to transmit data though command is finished");
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until device requests data
|
// wait until device requests data
|
||||||
SHOW_FLOW0( 3, "Waiting for device ready to transmit" );
|
SHOW_FLOW0(3, "Waiting for device ready to transmit");
|
||||||
if (!wait_for_drq(device)) {
|
if (!wait_for_drq(device)) {
|
||||||
SHOW_FLOW0( 3, "device not ready for data transmission - abort" );
|
SHOW_FLOW0(3, "device not ready for data transmission - abort");
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ ata_dpc_PIO(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
// having a too short data buffer shouldn't happen here
|
// having a too short data buffer shouldn't happen here
|
||||||
// anyway - we are prepared
|
// anyway - we are prepared
|
||||||
SHOW_FLOW0( 3, "Writing one block" );
|
SHOW_FLOW0(3, "Writing one block");
|
||||||
if (write_PIO_block(qrequest, 512) == B_ERROR)
|
if (write_PIO_block(qrequest, 512) == B_ERROR)
|
||||||
goto finish_cancel_timeout;
|
goto finish_cancel_timeout;
|
||||||
|
|
||||||
@@ -180,7 +180,8 @@ static uint8 cmd_28[2][2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// create IDE read/write command
|
/** create IDE read/write command */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
||||||
uint64 pos, size_t length, bool write)
|
uint64 pos, size_t length, bool write)
|
||||||
@@ -239,7 +240,7 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// normal LBA
|
// normal LBA
|
||||||
SHOW_FLOW0( 3, "using LBA" );
|
SHOW_FLOW0(3, "using LBA");
|
||||||
|
|
||||||
if (length > 0x100)
|
if (length > 0x100)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -247,14 +248,13 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
if (qrequest->queuable) {
|
if (qrequest->queuable) {
|
||||||
// queued LBA
|
// queued LBA
|
||||||
SHOW_FLOW( 3, "creating DMA queued command, tag=%d", qrequest->tag );
|
SHOW_FLOW( 3, "creating DMA queued command, tag=%d", qrequest->tag );
|
||||||
device->tf_param_mask =
|
device->tf_param_mask = ide_mask_features
|
||||||
ide_mask_features |
|
| ide_mask_sector_count
|
||||||
ide_mask_sector_count |
|
| ide_mask_LBA_low
|
||||||
ide_mask_LBA_low |
|
| ide_mask_LBA_mid
|
||||||
ide_mask_LBA_mid |
|
| ide_mask_LBA_high
|
||||||
ide_mask_LBA_high |
|
| ide_mask_device_head;
|
||||||
ide_mask_device_head;
|
|
||||||
|
|
||||||
device->tf.queued.sector_count = length & 0xff;
|
device->tf.queued.sector_count = length & 0xff;
|
||||||
device->tf.queued.tag = qrequest->tag;
|
device->tf.queued.tag = qrequest->tag;
|
||||||
device->tf.queued.lba_0_7 = pos & 0xff;
|
device->tf.queued.lba_0_7 = pos & 0xff;
|
||||||
@@ -264,16 +264,14 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
device->tf.queued.command = write ? IDE_CMD_WRITE_DMA_QUEUED
|
device->tf.queued.command = write ? IDE_CMD_WRITE_DMA_QUEUED
|
||||||
: IDE_CMD_READ_DMA_QUEUED;
|
: IDE_CMD_READ_DMA_QUEUED;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// non-queued LBA
|
// non-queued LBA
|
||||||
SHOW_FLOW0( 3, "creating normal DMA/PIO command" );
|
SHOW_FLOW0( 3, "creating normal DMA/PIO command" );
|
||||||
device->tf_param_mask =
|
device->tf_param_mask = ide_mask_sector_count
|
||||||
ide_mask_sector_count |
|
| ide_mask_LBA_low
|
||||||
ide_mask_LBA_low |
|
| ide_mask_LBA_mid
|
||||||
ide_mask_LBA_mid |
|
| ide_mask_LBA_high
|
||||||
ide_mask_LBA_high |
|
| ide_mask_device_head;
|
||||||
ide_mask_device_head;
|
|
||||||
|
|
||||||
device->tf.lba.sector_count = length & 0xff;
|
device->tf.lba.sector_count = length & 0xff;
|
||||||
device->tf.lba.lba_0_7 = pos & 0xff;
|
device->tf.lba.lba_0_7 = pos & 0xff;
|
||||||
@@ -282,7 +280,6 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
device->tf.lba.lba_24_27 = (pos >> 24) & 0xf;
|
device->tf.lba.lba_24_27 = (pos >> 24) & 0xf;
|
||||||
device->tf.lba.command = cmd_28[qrequest->uses_dma][write];
|
device->tf.lba.command = cmd_28[qrequest->uses_dma][write];
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -290,29 +287,28 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
// (probably, noone would notice if we'd dropped support)
|
// (probably, noone would notice if we'd dropped support)
|
||||||
uint32 track_size, cylinder_offset, cylinder;
|
uint32 track_size, cylinder_offset, cylinder;
|
||||||
ide_device_infoblock *infoblock = &device->infoblock;
|
ide_device_infoblock *infoblock = &device->infoblock;
|
||||||
|
|
||||||
if( length > 0x100 )
|
if (length > 0x100)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
device->tf.chs.mode = ide_mode_chs;
|
device->tf.chs.mode = ide_mode_chs;
|
||||||
|
|
||||||
device->tf_param_mask =
|
device->tf_param_mask = ide_mask_sector_count
|
||||||
ide_mask_sector_count |
|
| ide_mask_sector_number
|
||||||
ide_mask_sector_number |
|
| ide_mask_cylinder_low
|
||||||
ide_mask_cylinder_low |
|
| ide_mask_cylinder_high
|
||||||
ide_mask_cylinder_high |
|
| ide_mask_device_head;
|
||||||
ide_mask_device_head;
|
|
||||||
|
|
||||||
device->tf.chs.sector_count = length & 0xff;
|
device->tf.chs.sector_count = length & 0xff;
|
||||||
|
|
||||||
track_size = infoblock->current_heads * infoblock->current_sectors;
|
track_size = infoblock->current_heads * infoblock->current_sectors;
|
||||||
|
|
||||||
if( track_size == 0 ) {
|
if (track_size == 0) {
|
||||||
set_sense( device,
|
set_sense(device,
|
||||||
SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED );
|
SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cylinder = pos / track_size;
|
cylinder = pos / track_size;
|
||||||
|
|
||||||
device->tf.chs.cylinder_0_7 = cylinder & 0xff;
|
device->tf.chs.cylinder_0_7 = cylinder & 0xff;
|
||||||
@@ -322,354 +318,365 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
|
|
||||||
device->tf.chs.sector_number = (cylinder_offset % infoblock->current_sectors + 1) & 0xff;
|
device->tf.chs.sector_number = (cylinder_offset % infoblock->current_sectors + 1) & 0xff;
|
||||||
device->tf.chs.head = cylinder_offset / infoblock->current_sectors;
|
device->tf.chs.head = cylinder_offset / infoblock->current_sectors;
|
||||||
|
|
||||||
device->tf.chs.command = cmd_28[qrequest->uses_dma][write];
|
device->tf.chs.command = cmd_28[qrequest->uses_dma][write];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
set_sense( device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD );
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// execute read/write command
|
/** execute read/write command
|
||||||
// pos - first block
|
* pos - first block
|
||||||
// length - number of blocks
|
* length - number of blocks
|
||||||
void ata_send_rw( ide_device_info *device, ide_qrequest *qrequest,
|
*/
|
||||||
uint64 pos, size_t length, bool write )
|
|
||||||
|
void
|
||||||
|
ata_send_rw(ide_device_info *device, ide_qrequest *qrequest,
|
||||||
|
uint64 pos, size_t length, bool write)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
uint32 timeout;
|
uint32 timeout;
|
||||||
|
|
||||||
// make a copy first as settings may get changed by user during execution
|
// make a copy first as settings may get changed by user during execution
|
||||||
qrequest->is_write = write;
|
qrequest->is_write = write;
|
||||||
qrequest->uses_dma = device->DMA_enabled;
|
qrequest->uses_dma = device->DMA_enabled;
|
||||||
|
|
||||||
if( qrequest->uses_dma ) {
|
if (qrequest->uses_dma) {
|
||||||
if( !prepare_dma( device, qrequest )) {
|
if (!prepare_dma(device, qrequest)) {
|
||||||
// fall back to PIO on error
|
// fall back to PIO on error
|
||||||
|
|
||||||
// if command queueing is used and there is another command
|
// if command queueing is used and there is another command
|
||||||
// already running, we cannot fallback to PIO immediately -> declare
|
// already running, we cannot fallback to PIO immediately -> declare
|
||||||
// command as not queuable and resubmit it, so the scsi bus manager
|
// command as not queuable and resubmit it, so the scsi bus manager
|
||||||
// will block other requests on retry
|
// will block other requests on retry
|
||||||
// (XXX this is not fine if the caller wants to recycle the CCB)
|
// (XXX this is not fine if the caller wants to recycle the CCB)
|
||||||
if( device->num_running_reqs > 1 ) {
|
if (device->num_running_reqs > 1) {
|
||||||
qrequest->request->flags &= ~SCSI_ORDERED_QTAG;
|
qrequest->request->flags &= ~SCSI_ORDERED_QTAG;
|
||||||
finish_retry( qrequest );
|
finish_retry(qrequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qrequest->uses_dma = false;
|
qrequest->uses_dma = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !qrequest->uses_dma ) {
|
if (!qrequest->uses_dma) {
|
||||||
prep_PIO_transfer( device, qrequest );
|
prep_PIO_transfer(device, qrequest);
|
||||||
device->left_blocks = length;
|
device->left_blocks = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compose command
|
// compose command
|
||||||
if( !create_rw_taskfile( device, qrequest, pos, length, write ))
|
if (!create_rw_taskfile(device, qrequest, pos, length, write))
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
|
|
||||||
// if no timeout is specified, use standard
|
// if no timeout is specified, use standard
|
||||||
timeout = qrequest->request->timeout > 0 ?
|
timeout = qrequest->request->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
// in DMA mode, we continue with "accessing",
|
// in DMA mode, we continue with "accessing",
|
||||||
// on PIO read, we continue with "async waiting"
|
// on PIO read, we continue with "async waiting"
|
||||||
// on PIO write, we continue with "accessing"
|
// on PIO write, we continue with "accessing"
|
||||||
if( !send_command( device, qrequest, !device->is_atapi, timeout,
|
if (!send_command(device, qrequest, !device->is_atapi, timeout,
|
||||||
(!qrequest->uses_dma && !qrequest->is_write) ?
|
(!qrequest->uses_dma && !qrequest->is_write) ?
|
||||||
ide_state_async_waiting : ide_state_accessing ))
|
ide_state_async_waiting : ide_state_accessing))
|
||||||
goto err_send;
|
goto err_send;
|
||||||
|
|
||||||
if( qrequest->uses_dma ) {
|
if (qrequest->uses_dma) {
|
||||||
// if queuing used, we have to ask device first whether it wants
|
// if queuing used, we have to ask device first whether it wants
|
||||||
// to postpone the command
|
// to postpone the command
|
||||||
// XXX: using the bus release IRQ we don't have to busy wait for
|
// XXX: using the bus release IRQ we don't have to busy wait for
|
||||||
// a response, but I heard that IBM drives have problems with
|
// a response, but I heard that IBM drives have problems with
|
||||||
// that IRQ; to be evaluated
|
// that IRQ; to be evaluated
|
||||||
if( qrequest->queuable ) {
|
if (qrequest->queuable) {
|
||||||
if( !wait_for_drdy( device ))
|
if (!wait_for_drdy(device))
|
||||||
goto err_send;
|
goto err_send;
|
||||||
|
|
||||||
if( check_rw_error( device, qrequest ))
|
if (check_rw_error(device, qrequest))
|
||||||
goto err_send;
|
goto err_send;
|
||||||
|
|
||||||
if( device_released_bus( device )) {
|
if (device_released_bus(device)) {
|
||||||
// device enqueued command, so we have to wait;
|
// device enqueued command, so we have to wait;
|
||||||
// in access_finished, we'll ask device whether it wants to
|
// in access_finished, we'll ask device whether it wants to
|
||||||
// continue some other command
|
// continue some other command
|
||||||
bus->active_qrequest = NULL;
|
bus->active_qrequest = NULL;
|
||||||
|
|
||||||
access_finished( bus, device );
|
access_finished(bus, device);
|
||||||
// we may have rejected commands meanwhile, so tell
|
// we may have rejected commands meanwhile, so tell
|
||||||
// the SIM that it can resend them now
|
// the SIM that it can resend them now
|
||||||
scsi->cont_send_bus( bus->scsi_cookie );
|
scsi->cont_send_bus(bus->scsi_cookie);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SHOW_ERROR0( 2, "device executes command instantly" );
|
|
||||||
}
|
|
||||||
|
|
||||||
start_dma_wait_no_lock( device, qrequest );
|
//SHOW_ERROR0( 2, "device executes command instantly" );
|
||||||
|
}
|
||||||
|
|
||||||
|
start_dma_wait_no_lock(device, qrequest);
|
||||||
} else {
|
} else {
|
||||||
// on PIO read, we start with waiting, on PIO write we can
|
// on PIO read, we start with waiting, on PIO write we can
|
||||||
// transmit data immediately; we let the service thread do
|
// transmit data immediately; we let the service thread do
|
||||||
// the writing, so the caller can issue the next command
|
// the writing, so the caller can issue the next command
|
||||||
// immediately (this optimisation really pays on SMP systems
|
// immediately (this optimisation really pays on SMP systems
|
||||||
// only)
|
// only)
|
||||||
SHOW_FLOW0( 3, "Ready for PIO" );
|
SHOW_FLOW0(3, "Ready for PIO");
|
||||||
if( qrequest->is_write ) {
|
if (qrequest->is_write) {
|
||||||
SHOW_FLOW0( 3, "Scheduling write DPC" );
|
SHOW_FLOW0(3, "Scheduling write DPC");
|
||||||
scsi->schedule_dpc( bus->scsi_cookie, bus->irq_dpc, ide_dpc, bus );
|
scsi->schedule_dpc(bus->scsi_cookie, bus->irq_dpc, ide_dpc, bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_setup:
|
err_setup:
|
||||||
// error during setup
|
// error during setup
|
||||||
if( qrequest->uses_dma )
|
if (qrequest->uses_dma)
|
||||||
abort_dma( device, qrequest );
|
abort_dma(device, qrequest);
|
||||||
|
|
||||||
finish_checksense( qrequest );
|
finish_checksense(qrequest);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_send:
|
err_send:
|
||||||
// error during/after send;
|
// error during/after send;
|
||||||
// in this case, the device discards queued request automatically
|
// in this case, the device discards queued request automatically
|
||||||
if( qrequest->uses_dma )
|
if (qrequest->uses_dma)
|
||||||
abort_dma( device, qrequest );
|
abort_dma(device, qrequest);
|
||||||
|
|
||||||
finish_reset_queue( qrequest );
|
finish_reset_queue(qrequest);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// check for errors reported by read/write command
|
/** check for errors reported by read/write command
|
||||||
// return: true, if an error occured
|
* return: true, if an error occured
|
||||||
bool check_rw_error( ide_device_info *device, ide_qrequest *qrequest )
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
check_rw_error(ide_device_info *device, ide_qrequest *qrequest)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
uint8 status;
|
uint8 status;
|
||||||
|
|
||||||
status = bus->controller->get_altstatus( bus->channel );
|
|
||||||
|
|
||||||
if( (status & ide_status_err) != 0 ) {
|
status = bus->controller->get_altstatus(bus->channel);
|
||||||
|
|
||||||
|
if ((status & ide_status_err) != 0) {
|
||||||
uint8 error;
|
uint8 error;
|
||||||
|
|
||||||
if( bus->controller->read_command_block_regs( bus->channel,
|
if (bus->controller->read_command_block_regs(bus->channel,
|
||||||
&device->tf, ide_mask_error ) != B_OK )
|
&device->tf, ide_mask_error) != B_OK) {
|
||||||
{
|
|
||||||
device->subsys_status = SCSI_HBA_ERR;
|
device->subsys_status = SCSI_HBA_ERR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = device->tf.read.error;
|
error = device->tf.read.error;
|
||||||
|
|
||||||
if( (error & ide_error_icrc) != 0 ) {
|
if ((error & ide_error_icrc) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC );
|
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( qrequest->is_write ) {
|
if (qrequest->is_write) {
|
||||||
if( (error & ide_error_wp) != 0 ) {
|
if ((error & ide_error_wp) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED );
|
set_sense(device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( (error & ide_error_unc) != 0 ) {
|
if ((error & ide_error_unc) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR );
|
set_sense(device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_mc) != 0 ) {
|
if ((error & ide_error_mc) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED );
|
set_sense(device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (error & ide_error_idnf) != 0 ) {
|
|
||||||
// ID not found - invalid CHS mapping (was: seek error?)
|
|
||||||
set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (error & ide_error_mcr) != 0 ) {
|
|
||||||
// XXX proper sense key?
|
|
||||||
// for TUR this case is not defined !?
|
|
||||||
set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (error & ide_error_nm) != 0 ) {
|
|
||||||
set_sense( device, SCSIS_KEY_NOT_READY, SCSIS_ASC_NO_MEDIUM );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (error & ide_error_abrt) != 0 ) {
|
|
||||||
set_sense( device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE );
|
if ((error & ide_error_idnf) != 0) {
|
||||||
|
// ID not found - invalid CHS mapping (was: seek error?)
|
||||||
|
set_sense(device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error & ide_error_mcr) != 0) {
|
||||||
|
// XXX proper sense key?
|
||||||
|
// for TUR this case is not defined !?
|
||||||
|
set_sense(device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error & ide_error_nm) != 0) {
|
||||||
|
set_sense(device, SCSIS_KEY_NOT_READY, SCSIS_ASC_NO_MEDIUM);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error & ide_error_abrt) != 0) {
|
||||||
|
set_sense(device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// check result of ATA command
|
/** check result of ATA command
|
||||||
// drdy_required - true if drdy must be set by device
|
* drdy_required - true if drdy must be set by device
|
||||||
// error_mask - bits to be checked in error register
|
* error_mask - bits to be checked in error register
|
||||||
// is_write - true, if command was a write command
|
* is_write - true, if command was a write command
|
||||||
bool check_output( ide_device_info *device,
|
*/
|
||||||
bool drdy_required, int error_mask, bool is_write )
|
|
||||||
|
bool
|
||||||
|
check_output(ide_device_info *device, bool drdy_required,
|
||||||
|
int error_mask, bool is_write)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
uint8 status;
|
uint8 status;
|
||||||
|
|
||||||
// check IRQ timeout
|
// check IRQ timeout
|
||||||
if( bus->sync_wait_timeout ) {
|
if (bus->sync_wait_timeout) {
|
||||||
bus->sync_wait_timeout = false;
|
bus->sync_wait_timeout = false;
|
||||||
|
|
||||||
device->subsys_status = SCSI_CMD_TIMEOUT;
|
device->subsys_status = SCSI_CMD_TIMEOUT;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = bus->controller->get_altstatus( bus->channel );
|
status = bus->controller->get_altstatus(bus->channel);
|
||||||
|
|
||||||
// if device is busy, other flags are indeterminate
|
// if device is busy, other flags are indeterminate
|
||||||
if( (status & ide_status_bsy) != 0 ) {
|
if ((status & ide_status_bsy) != 0) {
|
||||||
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( drdy_required && ((status & ide_status_drdy) == 0) ) {
|
|
||||||
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (status & ide_status_err) != 0 ) {
|
if (drdy_required && ((status & ide_status_drdy) == 0)) {
|
||||||
|
device->subsys_status = SCSI_SEQUENCE_FAIL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & ide_status_err) != 0) {
|
||||||
uint8 error;
|
uint8 error;
|
||||||
|
|
||||||
if( bus->controller->read_command_block_regs( bus->channel,
|
if (bus->controller->read_command_block_regs(bus->channel,
|
||||||
&device->tf, ide_mask_error ) != B_OK )
|
&device->tf, ide_mask_error) != B_OK) {
|
||||||
{
|
|
||||||
device->subsys_status = SCSI_HBA_ERR;
|
device->subsys_status = SCSI_HBA_ERR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = device->tf.read.error & error_mask;
|
error = device->tf.read.error & error_mask;
|
||||||
|
|
||||||
if( (error & ide_error_icrc) != 0 ) {
|
if ((error & ide_error_icrc) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC );
|
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( is_write ) {
|
if (is_write) {
|
||||||
if( (error & ide_error_wp) != 0 ) {
|
if ((error & ide_error_wp) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED );
|
set_sense(device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( (error & ide_error_unc) != 0 ) {
|
if ((error & ide_error_unc) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR );
|
set_sense(device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_mc) != 0 ) {
|
if ((error & ide_error_mc) != 0) {
|
||||||
// XXX proper sense key?
|
// XXX proper sense key?
|
||||||
set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED );
|
set_sense(device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_idnf) != 0 ) {
|
if ((error & ide_error_idnf) != 0) {
|
||||||
// XXX strange error code, don't really know what it means
|
// XXX strange error code, don't really know what it means
|
||||||
set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR );
|
set_sense(device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_mcr) != 0 ) {
|
if ((error & ide_error_mcr) != 0) {
|
||||||
// XXX proper sense key?
|
// XXX proper sense key?
|
||||||
set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED );
|
set_sense(device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_nm) != 0 ) {
|
if ((error & ide_error_nm) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_NO_MEDIUM );
|
set_sense(device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_NO_MEDIUM);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (error & ide_error_abrt) != 0 ) {
|
if ((error & ide_error_abrt) != 0) {
|
||||||
set_sense( device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE );
|
set_sense(device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// either there was no error bit set or it was masked out
|
// either there was no error bit set or it was masked out
|
||||||
set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE );
|
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute SET FEATURE command
|
|
||||||
// set subcommand in task file before calling this
|
/** execute SET FEATURE command
|
||||||
static bool device_set_feature( ide_device_info *device, int feature )
|
* set subcommand in task file before calling this
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool
|
||||||
|
device_set_feature(ide_device_info *device, int feature)
|
||||||
{
|
{
|
||||||
device->tf_param_mask = ide_mask_features;
|
device->tf_param_mask = ide_mask_features;
|
||||||
|
|
||||||
device->tf.write.features = feature;
|
device->tf.write.features = feature;
|
||||||
device->tf.write.command = IDE_CMD_SET_FEATURES;
|
device->tf.write.command = IDE_CMD_SET_FEATURES;
|
||||||
|
|
||||||
if( !send_command( device, NULL, true, 1, ide_state_sync_waiting ))
|
if (!send_command(device, NULL, true, 1, ide_state_sync_waiting))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wait_for_sync( device->bus );
|
wait_for_sync(device->bus);
|
||||||
|
|
||||||
return check_output( device, true, ide_error_abrt, false );
|
return check_output(device, true, ide_error_abrt, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool configure_rmsn( ide_device_info *device )
|
|
||||||
|
static bool
|
||||||
|
configure_rmsn(ide_device_info *device)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( !device->infoblock.RMSN_supported ||
|
if (!device->infoblock.RMSN_supported
|
||||||
device->infoblock._127_RMSN_support != 1 )
|
|| device->infoblock._127_RMSN_support != 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( !device_set_feature( device, IDE_CMD_SET_FEATURES_ENABLE_MSN ))
|
if (!device_set_feature(device, IDE_CMD_SET_FEATURES_ENABLE_MSN))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bus->controller->read_command_block_regs( bus->channel, &device->tf,
|
bus->controller->read_command_block_regs(bus->channel, &device->tf,
|
||||||
ide_mask_LBA_mid | ide_mask_LBA_high );
|
ide_mask_LBA_mid | ide_mask_LBA_high);
|
||||||
|
|
||||||
for( i = 0; i < 5; ++i ) {
|
for (i = 0; i < 5; ++i) {
|
||||||
// don't use TUR as it checks not ide_error_mcr | ide_error_mc | ide_error_wp
|
// don't use TUR as it checks not ide_error_mcr | ide_error_mc | ide_error_wp
|
||||||
// but: we don't check wp as well
|
// but: we don't check wp as well
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
|
|
||||||
device->tf_param_mask = 0;
|
device->tf_param_mask = 0;
|
||||||
device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS;
|
device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS;
|
||||||
|
|
||||||
if( !send_command( device, NULL, true, 15, ide_state_sync_waiting ))
|
if (!send_command(device, NULL, true, 15, ide_state_sync_waiting))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( check_output( device, true,
|
if (check_output(device, true,
|
||||||
ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc,
|
ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc,
|
||||||
true )
|
true)
|
||||||
|| decode_sense_asc_ascq( device->combined_sense ) == SCSIS_ASC_NO_MEDIUM )
|
|| decode_sense_asc_ascq(device->combined_sense) == SCSIS_ASC_NO_MEDIUM)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,13 +716,13 @@ prep_ata(ide_device_info *device)
|
|||||||
{
|
{
|
||||||
ide_device_infoblock *infoblock = &device->infoblock;
|
ide_device_infoblock *infoblock = &device->infoblock;
|
||||||
uint32 chs_capacity;
|
uint32 chs_capacity;
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
device->is_atapi = false;
|
device->is_atapi = false;
|
||||||
device->exec_io = ata_exec_io;
|
device->exec_io = ata_exec_io;
|
||||||
device->last_lun = 0;
|
device->last_lun = 0;
|
||||||
|
|
||||||
// warning: ata == 0 means "this is ata"...
|
// warning: ata == 0 means "this is ata"...
|
||||||
if (infoblock->_0.ata.ATA != 0) {
|
if (infoblock->_0.ata.ATA != 0) {
|
||||||
// CF has either magic header or CFA bit set
|
// CF has either magic header or CFA bit set
|
||||||
@@ -726,7 +733,7 @@ prep_ata(ide_device_info *device)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "1" );
|
SHOW_FLOW0(3, "1");
|
||||||
|
|
||||||
if (!infoblock->_54_58_valid) {
|
if (!infoblock->_54_58_valid) {
|
||||||
// normally, current_xxx contains active CHS mapping,
|
// normally, current_xxx contains active CHS mapping,
|
||||||
@@ -735,16 +742,16 @@ prep_ata(ide_device_info *device)
|
|||||||
infoblock->current_sectors = infoblock->sectors;
|
infoblock->current_sectors = infoblock->sectors;
|
||||||
infoblock->current_cylinders = infoblock->cylinders;
|
infoblock->current_cylinders = infoblock->cylinders;
|
||||||
infoblock->current_heads = infoblock->heads;
|
infoblock->current_heads = infoblock->heads;
|
||||||
}
|
}
|
||||||
|
|
||||||
// just in case capacity_xxx isn't initialized - calculate it manually
|
// just in case capacity_xxx isn't initialized - calculate it manually
|
||||||
// (seems that this information is really redundant; hopefully)
|
// (seems that this information is really redundant; hopefully)
|
||||||
chs_capacity = infoblock->current_sectors * infoblock->current_cylinders *
|
chs_capacity = infoblock->current_sectors * infoblock->current_cylinders *
|
||||||
infoblock->current_heads;
|
infoblock->current_heads;
|
||||||
|
|
||||||
infoblock->capacity_low = chs_capacity & 0xff;
|
infoblock->capacity_low = chs_capacity & 0xff;
|
||||||
infoblock->capacity_high = chs_capacity >> 8;
|
infoblock->capacity_high = chs_capacity >> 8;
|
||||||
|
|
||||||
// checking LBA_supported flag should be sufficient, but it seems
|
// checking LBA_supported flag should be sufficient, but it seems
|
||||||
// that checking LBA_total_sectors is a good idea
|
// that checking LBA_total_sectors is a good idea
|
||||||
device->use_LBA = infoblock->LBA_supported && infoblock->LBA_total_sectors != 0;
|
device->use_LBA = infoblock->LBA_supported && infoblock->LBA_total_sectors != 0;
|
||||||
@@ -770,7 +777,7 @@ prep_ata(ide_device_info *device)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "3");
|
SHOW_FLOW0(3, "3");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user