converted to use the new ata_request_* functions
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23345 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,10 +21,25 @@
|
|||||||
#define TRACE dprintf
|
#define TRACE dprintf
|
||||||
#define FLOW dprintf
|
#define FLOW dprintf
|
||||||
|
|
||||||
/** emulate MODE SENSE 10 command */
|
|
||||||
|
|
||||||
|
// set sense buffer according to device sense in ata_request
|
||||||
|
void
|
||||||
|
scsi_set_sense(scsi_sense *sense, const ata_request *request)
|
||||||
|
{
|
||||||
|
memset(sense, 0, sizeof(*sense));
|
||||||
|
|
||||||
|
sense->error_code = SCSIS_CURR_ERROR;
|
||||||
|
sense->sense_key = request->senseKey;
|
||||||
|
sense->add_sense_length = sizeof(*sense) - 7;
|
||||||
|
sense->asc = request->senseAsc;
|
||||||
|
sense->ascq = request->senseAscq;
|
||||||
|
sense->sense_key_spec.raw.SKSV = 0; // no additional info
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ata_mode_sense_10(ide_device_info *device, ata_request *request)
|
scsi_mode_sense_10(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb = request->ccb;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)ccb->cdb;
|
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)ccb->cdb;
|
||||||
@@ -51,7 +66,7 @@ ata_mode_sense_10(ide_device_info *device, ata_request *request)
|
|||||||
if ((cmd->page_code != SCSI_MODEPAGE_CONTROL && cmd->page_code != SCSI_MODEPAGE_ALL)
|
if ((cmd->page_code != SCSI_MODEPAGE_CONTROL && cmd->page_code != SCSI_MODEPAGE_ALL)
|
||||||
|| (cmd->page_control != SCSI_MODE_SENSE_PC_CURRENT
|
|| (cmd->page_control != SCSI_MODE_SENSE_PC_CURRENT
|
||||||
&& cmd->page_control != SCSI_MODE_SENSE_PC_SAVED)) {
|
&& cmd->page_control != SCSI_MODE_SENSE_PC_SAVED)) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +124,7 @@ ata_mode_select_control_page(ide_device_info *device, ata_request *request,
|
|||||||
scsi_modepage_control *page)
|
scsi_modepage_control *page)
|
||||||
{
|
{
|
||||||
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
|
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +136,7 @@ ata_mode_select_control_page(ide_device_info *device, ata_request *request,
|
|||||||
|
|
||||||
/*! Emulate MODE SELECT 10 command */
|
/*! Emulate MODE SELECT 10 command */
|
||||||
static void
|
static void
|
||||||
ata_mode_select_10(ide_device_info *device, ata_request *request)
|
scsi_mode_select_10(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb = request->ccb;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)ccb->cdb;
|
scsi_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)ccb->cdb;
|
||||||
@@ -132,7 +147,7 @@ ata_mode_select_10(ide_device_info *device, ata_request *request)
|
|||||||
char modepage_buffer[64]; // !!! enlarge this to support longer mode pages
|
char modepage_buffer[64]; // !!! enlarge this to support longer mode pages
|
||||||
|
|
||||||
if (cmd->save_pages || cmd->pf != 1) {
|
if (cmd->save_pages || cmd->pf != 1) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +198,7 @@ ata_mode_select_10(ide_device_info *device, ata_request *request)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST,
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_PARAM_LIST_FIELD);
|
||||||
SCSIS_ASC_INV_PARAM_LIST_FIELD);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,29 +213,31 @@ ata_mode_select_10(ide_device_info *device, ata_request *request)
|
|||||||
|
|
||||||
// if we arrive here, data length was incorrect
|
// if we arrive here, data length was incorrect
|
||||||
err:
|
err:
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate TEST UNIT READY */
|
static void
|
||||||
static status_t
|
scsi_test_unit_ready(ide_device_info *device, ata_request *request)
|
||||||
ata_test_unit_ready(ide_device_info *device, ata_request *request)
|
|
||||||
{
|
{
|
||||||
TRACE("ata_test_unit_ready\n");
|
TRACE("scsi_test_unit_ready\n");
|
||||||
|
|
||||||
if (!device->infoblock.RMSN_supported
|
if (device->infoblock.RMSN_supported == 0
|
||||||
|| device->infoblock._127_RMSN_support != 1)
|
|| device->infoblock._127_RMSN_support != 1)
|
||||||
return B_OK;
|
return;
|
||||||
|
|
||||||
// ask device about status
|
// ask device about status
|
||||||
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 (ata_send_command(device, request, true, 15, ide_state_pio) != B_OK)
|
if (ata_send_command(request, true, 15, ata_state_pio) != B_OK) {
|
||||||
return B_ERROR;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ata_pio_wait_drdy(device) != B_OK)
|
if (ata_pio_wait_drdy(device) != B_OK) {
|
||||||
return B_ERROR;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// bits ide_error_mcr | ide_error_mc | ide_error_wp are also valid
|
// bits ide_error_mcr | ide_error_mc | ide_error_wp are also valid
|
||||||
@@ -234,14 +250,12 @@ ata_test_unit_ready(ide_device_info *device, ata_request *request)
|
|||||||
// but what to do if there is one? anyway - we report them
|
// but what to do if there is one? anyway - we report them
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Flush internal device cache */
|
/*! Flush internal device cache */
|
||||||
static bool
|
static bool
|
||||||
ata_flush_cache(ide_device_info *device, ata_request *request)
|
scsi_synchronize_cache(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
// we should also ask for FLUSH CACHE support, but everyone denies it
|
// we should also ask for FLUSH CACHE support, but everyone denies it
|
||||||
@@ -270,7 +284,7 @@ ata_flush_cache(ide_device_info *device, ata_request *request)
|
|||||||
load = true - load medium
|
load = true - load medium
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
ata_load_eject(ide_device_info *device, ata_request *request, bool load)
|
scsi_load_eject(ide_device_info *device, ata_request *request, bool load)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
if (load) {
|
if (load) {
|
||||||
@@ -293,18 +307,15 @@ ata_load_eject(ide_device_info *device, ata_request *request, bool load)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate PREVENT ALLOW command */
|
static void
|
||||||
static bool
|
scsi_prevent_allow(ide_device_info *device, ata_request *request, bool prevent)
|
||||||
ata_prevent_allow(ide_device_info *device, bool prevent)
|
|
||||||
{
|
{
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_ILL_FUNCTION);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_ILL_FUNCTION);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate INQUIRY command */
|
|
||||||
static void
|
static void
|
||||||
ata_inquiry(ide_device_info *device, ata_request *request)
|
scsi_inquiry(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb = request->ccb;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_res_inquiry data;
|
scsi_res_inquiry data;
|
||||||
@@ -313,7 +324,7 @@ ata_inquiry(ide_device_info *device, ata_request *request)
|
|||||||
uint32 transfer_size;
|
uint32 transfer_size;
|
||||||
|
|
||||||
if (cmd->evpd || cmd->page_code) {
|
if (cmd->evpd || cmd->page_code) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,9 +373,9 @@ ata_inquiry(ide_device_info *device, ata_request *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate READ CAPACITY command */
|
|
||||||
static void
|
static void
|
||||||
read_capacity(ide_device_info *device, ata_request *request)
|
scsi_read_capacity(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb = request->ccb;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_res_read_capacity data;
|
scsi_res_read_capacity data;
|
||||||
@@ -372,7 +383,7 @@ read_capacity(ide_device_info *device, ata_request *request)
|
|||||||
uint32 lastBlock;
|
uint32 lastBlock;
|
||||||
|
|
||||||
if (cmd->pmi || cmd->lba) {
|
if (cmd->pmi || cmd->lba) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +398,35 @@ read_capacity(ide_device_info *device, ata_request *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
scsi_request_sense(ide_device_info *device, ata_request *request)
|
||||||
|
{
|
||||||
|
scsi_ccb *ccb = request->ccb;
|
||||||
|
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)ccb->cdb;
|
||||||
|
scsi_sense sense;
|
||||||
|
uint32 transferSize;
|
||||||
|
|
||||||
|
// Copy sense data from last request into data buffer of current request.
|
||||||
|
// The sense data of last request is still present in the current request,
|
||||||
|
// as is isn't been cleared by ata_exec_io for SCSI_OP_REQUEST_SENSE.
|
||||||
|
|
||||||
|
if (request->senseKey != 0)
|
||||||
|
scsi_set_sense(&sense, request);
|
||||||
|
else
|
||||||
|
memset(&sense, 0, sizeof(sense));
|
||||||
|
|
||||||
|
copy_sg_data(ccb, 0, cmd->allocation_length, &sense, sizeof(sense), false);
|
||||||
|
|
||||||
|
transferSize = min(sizeof(sense), cmd->allocation_length);
|
||||||
|
transferSize = min(transferSize, ccb->data_length);
|
||||||
|
|
||||||
|
ccb->data_resid = ccb->data_length - transferSize;
|
||||||
|
|
||||||
|
// reset sense information on read
|
||||||
|
ata_request_clear_sense(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Execute SCSI command */
|
/*! Execute SCSI command */
|
||||||
void
|
void
|
||||||
ata_exec_io(ide_device_info *device, ata_request *request)
|
ata_exec_io(ide_device_info *device, ata_request *request)
|
||||||
@@ -398,56 +438,58 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
// ATA devices have one LUN only
|
// ATA devices have one LUN only
|
||||||
if (ccb->target_lun != 0) {
|
if (ccb->target_lun != 0) {
|
||||||
FLOW("ata_exec_io: wrong target lun\n");
|
FLOW("ata_exec_io: wrong target lun\n");
|
||||||
ccb->subsys_status = SCSI_SEL_TIMEOUT;
|
ata_request_set_status(request, SCSI_SEL_TIMEOUT);
|
||||||
finish_request(request, false);
|
ata_request_finish(request, false /* no resubmit */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// starting a ccb means deleting sense, so don't do it if
|
if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE) {
|
||||||
// the command wants to read it
|
// No initial clear sense, as this request is used
|
||||||
if (ccb->cdb[0] != SCSI_OP_REQUEST_SENSE)
|
// by the scsi stack to request the sense data of
|
||||||
start_request(device, request);
|
// the previous command.
|
||||||
|
scsi_request_sense(device, request);
|
||||||
|
ata_request_finish(request, false /* no resubmit */);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_request_clear_sense(request);
|
||||||
|
|
||||||
switch (ccb->cdb[0]) {
|
switch (ccb->cdb[0]) {
|
||||||
case SCSI_OP_TEST_UNIT_READY:
|
case SCSI_OP_TEST_UNIT_READY:
|
||||||
ata_test_unit_ready(device, request);
|
scsi_test_unit_ready(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_REQUEST_SENSE:
|
|
||||||
ide_request_sense(device, request);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SCSI_OP_FORMAT: /* FORMAT UNIT */
|
case SCSI_OP_FORMAT: /* FORMAT UNIT */
|
||||||
// we could forward ccb to disk, but modern disks cannot
|
// we could forward ccb to disk, but modern disks cannot
|
||||||
// be formatted anyway, so we just refuse ccb
|
// be formatted anyway, so we just refuse ccb
|
||||||
// (exceptions are removable media devices, but to my knowledge
|
// (exceptions are removable media devices, but to my knowledge
|
||||||
// they don't have to be formatted as well)
|
// they don't have to be formatted as well)
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_INQUIRY:
|
case SCSI_OP_INQUIRY:
|
||||||
ata_inquiry(device, request);
|
scsi_inquiry(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SELECT_10:
|
case SCSI_OP_MODE_SELECT_10:
|
||||||
ata_mode_select_10(device, request);
|
scsi_mode_select_10(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SENSE_10:
|
case SCSI_OP_MODE_SENSE_10:
|
||||||
ata_mode_sense_10(device, request);
|
scsi_mode_sense_10(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SELECT_6:
|
case SCSI_OP_MODE_SELECT_6:
|
||||||
case SCSI_OP_MODE_SENSE_6:
|
case SCSI_OP_MODE_SENSE_6:
|
||||||
// we've told SCSI bus manager to emulates these commands
|
// we've told SCSI bus manager to emulates these commands
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_RESERVE:
|
case SCSI_OP_RESERVE:
|
||||||
case SCSI_OP_RELEASE:
|
case SCSI_OP_RELEASE:
|
||||||
// though mandatory, this doesn't make much sense in a
|
// though mandatory, this doesn't make much sense in a
|
||||||
// single initiator environment; so what
|
// single initiator environment; so what
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_START_STOP: {
|
case SCSI_OP_START_STOP: {
|
||||||
@@ -460,34 +502,33 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
|
|
||||||
if (!cmd->start)
|
if (!cmd->start)
|
||||||
// we must always flush cache if start = 0
|
// we must always flush cache if start = 0
|
||||||
ata_flush_cache(device, request);
|
scsi_synchronize_cache(device, request);
|
||||||
|
|
||||||
if (cmd->load_eject)
|
if (cmd->load_eject)
|
||||||
ata_load_eject(device, request, cmd->start);
|
scsi_load_eject(device, request, cmd->start);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCSI_OP_PREVENT_ALLOW: {
|
case SCSI_OP_PREVENT_ALLOW:
|
||||||
|
{
|
||||||
scsi_cmd_prevent_allow *cmd = (scsi_cmd_prevent_allow *)ccb->cdb;
|
scsi_cmd_prevent_allow *cmd = (scsi_cmd_prevent_allow *)ccb->cdb;
|
||||||
|
scsi_prevent_allow(device, request, cmd->prevent);
|
||||||
ata_prevent_allow(device, cmd->prevent);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCSI_OP_READ_CAPACITY:
|
case SCSI_OP_READ_CAPACITY:
|
||||||
read_capacity(device, request);
|
scsi_read_capacity(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_VERIFY:
|
case SCSI_OP_VERIFY:
|
||||||
// does anyone uses this function?
|
// does anyone uses this function?
|
||||||
// effectly, it does a read-and-compare, which IDE doesn't support
|
// effectly, it does a read-and-compare, which IDE doesn't support
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_SYNCHRONIZE_CACHE:
|
case SCSI_OP_SYNCHRONIZE_CACHE:
|
||||||
// we ignore range and immediate bit, we always immediately flush everything
|
// we ignore range and immediate bit, we always immediately flush everything
|
||||||
ata_flush_cache(device, request);
|
scsi_synchronize_cache(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// sadly, there are two possible read/write operation codes;
|
// sadly, there are two possible read/write operation codes;
|
||||||
@@ -523,17 +564,16 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
|
|
||||||
if (length != 0) {
|
if (length != 0) {
|
||||||
ata_exec_read_write(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
|
ata_exec_read_write(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
// we cannot transfer zero blocks (apart from LBA48)
|
// we cannot transfer zero blocks (apart from LBA48)
|
||||||
finish_request(request, false);
|
ata_request_set_status(request, SCSI_REQ_CMP);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FLOW("command not implemented\n");
|
FLOW("command not implemented\n");
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
ata_request_set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
}
|
}
|
||||||
|
ata_request_finish(request, false /* no resubmit */);
|
||||||
finish_checksense(request);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user