* Copyright 2004-2013, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "scsi_periph_int.h"
#include <module.h>
#include <string.h>
device_manager_info* gDeviceManager;
status_t
periph_simple_exec(scsi_periph_device_info* device, void* cdb, uchar cdbLength,
void* data, size_t dataLength, int ccb_flags)
{
SHOW_FLOW0( 0, "" );
scsi_ccb* ccb = device->scsi->alloc_ccb(device->scsi_device);
if (ccb == NULL)
return B_NO_MEMORY;
ccb->flags = ccb_flags;
memcpy(ccb->cdb, cdb, cdbLength);
ccb->cdb_length = cdbLength;
ccb->sort = -1;
ccb->timeout = device->std_timeout;
ccb->data = (uint8*)data;
ccb->sg_list = NULL;
ccb->data_length = dataLength;
status_t status = periph_safe_exec(device, ccb);
device->scsi->free_ccb(ccb);
return status;
}
status_t
periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request)
{
err_res res;
int retries = 0;
do {
device->scsi->sync_io(request);
res = periph_check_error(device, request);
if (res.action == err_act_start) {
uint32 backup_flags;
uint8 backup_cdb[SCSI_MAX_CDB_SIZE];
uchar backup_cdb_len;
int64 backup_sort;
bigtime_t backup_timeout;
uchar *backup_data;
const physical_entry *backup_sg_list;
uint16 backup_sg_count;
uint32 backup_data_len;
backup_flags = request->flags;
memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
backup_cdb_len = request->cdb_length;
backup_sort = request->sort;
backup_timeout = request->timeout;
backup_data = request->data;
backup_sg_list = request->sg_list;
backup_sg_count = request->sg_count;
backup_data_len = request->data_length;
SHOW_INFO0( 2, "Sending start to init LUN" );
res = periph_send_start_stop(device, request, 1, device->removable);
request->flags = backup_flags;
memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE);
request->cdb_length = backup_cdb_len;
request->sort = backup_sort;
request->timeout = backup_timeout;
request->data = backup_data;
request->sg_list = backup_sg_list;
request->sg_count = backup_sg_count;
request->data_length = backup_data_len;
if (res.action == err_act_ok)
res.action = err_act_retry;
}
} while ((res.action == err_act_retry && retries++ < 3)
|| (res.action == err_act_many_retries && retries++ < 30));
return res.error_code;
}
module_dependency module_dependencies[] = {
{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
{}
};
static scsi_periph_interface sSCSIPeripheralModule = {
{
SCSI_PERIPH_MODULE_NAME,
0,
NULL
},
periph_register_device,
periph_unregister_device,
periph_safe_exec,
periph_simple_exec,
periph_handle_open,
periph_handle_close,
periph_handle_free,
periph_read_write,
periph_io,
periph_ioctl,
periph_check_capacity,
periph_synchronize_cache,
periph_trim_device,
periph_media_changed_public,
periph_check_error,
periph_send_start_stop,
periph_get_media_status,
periph_compose_device_name
};
scsi_periph_interface *modules[] = {
&sSCSIPeripheralModule,
NULL
};