From d8b1cf070360d24b896ff5d4f94e47272b0f58c5 Mon Sep 17 00:00:00 2001 From: imker Date: Fri, 8 Sep 2006 19:37:58 +0000 Subject: [PATCH] - fix warnings, produced by Haiku version of gcc; - space indentation replaced by tab-based one to conform with Haiku coding guidelines; - a bit of cleanup; NB: Sorry for big amount of changes. :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18781 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/busses/scsi/usb/proto_bulk.c | 578 +++++++++--------- .../kernel/busses/scsi/usb/proto_bulk.h | 16 +- .../kernel/busses/scsi/usb/proto_cbi.c | 346 +++++------ .../kernel/busses/scsi/usb/proto_cbi.h | 16 +- .../kernel/busses/scsi/usb/proto_common.c | 269 ++++---- .../kernel/busses/scsi/usb/proto_common.h | 40 +- .../kernel/busses/scsi/usb/proto_module.h | 96 +-- 7 files changed, 690 insertions(+), 671 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c index dc89975c25..cec9ad9a83 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c +++ b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c @@ -1,15 +1,21 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ - /** bulk-only protocol specific implementation */ /* References: * USB Mass Storage Class specifications: - * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf [1] - * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf [2] + * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf [1] + * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf [2] */ #include "usb_scsi.h" @@ -21,37 +27,37 @@ #include "usb_defs.h" -#include /* strncpy */ +#include /* strncpy */ /*Bulk-Only protocol specifics*/ -#define USB_REQ_MS_RESET 0xff /* Bulk-Only reset */ +#define USB_REQ_MS_RESET 0xff /* Bulk-Only reset */ #define USB_REQ_MS_GET_MAX_LUN 0xfe /* Get maximum lun */ /* Command Block Wrapper */ typedef struct _usb_mass_CBW{ - uint32 signature; - uint32 tag; - uint32 data_transfer_len; - uint8 flags; - uint8 lun; - uint8 cdb_len; + uint32 signature; + uint32 tag; + uint32 data_transfer_len; + uint8 flags; + uint8 lun; + uint8 cdb_len; #define CBW_CDB_LENGTH 16 - uint8 CDB[CBW_CDB_LENGTH]; + uint8 CDB[CBW_CDB_LENGTH]; } usb_mass_CBW; /*sizeof(usb_mass_CBW) must be 31*/ #define CBW_LENGTH 0x1f /* Command Status Wrapper */ typedef struct _usb_mass_CSW{ - uint32 signature; - uint32 tag; - uint32 data_residue; - uint8 status; + uint32 signature; + uint32 tag; + uint32 data_residue; + uint8 status; } usb_mass_CSW; /*sizeof(usb_mass_CSW) must be 13*/ #define CSW_LENGTH 0x0d -#define CSW_STATUS_GOOD 0x0 -#define CSW_STATUS_FAILED 0x1 -#define CSW_STATUS_PHASE 0x2 +#define CSW_STATUS_GOOD 0x0 +#define CSW_STATUS_FAILED 0x1 +#define CSW_STATUS_PHASE 0x2 #define CBW_SIGNATURE 0x43425355 #define CSW_SIGNATURE 0x53425355 @@ -59,325 +65,315 @@ typedef struct _usb_mass_CSW{ #define CBW_FLAGS_OUT 0x00 #define CBW_FLAGS_IN 0x80 +static void trace_CBW(usb_device_info *udi, const usb_mass_CBW *cbw); +static void trace_CSW(usb_device_info *udi, const usb_mass_CSW *csw); +static status_t bulk_only_initialize(usb_device_info *udi); +static status_t bulk_only_reset(usb_device_info *udi); +static void bulk_only_transfer(usb_device_info *udi, uint8 *cmd, + uint8 cmdlen, //sg_buffer *sgb, + iovec *sg_data, int32 sg_count, + int32 transfer_len, EDirection dir, + CCB_SCSIIO *ccbio, ud_transfer_callback cb); + /*=========================== tracing helpers ==================================*/ void trace_CBW(usb_device_info *udi, const usb_mass_CBW *cbw) { - char buf[sizeof(uint32) + 1] = {0}; - strncpy(buf, (char *)&cbw->signature, sizeof(uint32)); - PTRACE(udi, "\nCBW:{'%s'; tag:%d; data_len:%d; flags:0x%02x; lun:%d; cdb_len:%d;}\n", - buf, - cbw->tag, - cbw->data_transfer_len, - cbw->flags, - cbw->lun, - cbw->cdb_len); - udi->trace_bytes("CDB:\n", cbw->CDB, CBW_CDB_LENGTH); + char buf[sizeof(uint32) + 1] = {0}; + strncpy(buf, (char *)&cbw->signature, sizeof(uint32)); + PTRACE(udi, "\nCBW:{'%s'; tag:%d; data_len:%d; flags:0x%02x; lun:%d; cdb_len:%d;}\n", + buf, cbw->tag, cbw->data_transfer_len, + cbw->flags, cbw->lun, cbw->cdb_len); + udi->trace_bytes("CDB:\n", cbw->CDB, CBW_CDB_LENGTH); } void trace_CSW(usb_device_info *udi, const usb_mass_CSW *csw) { - char buf[sizeof(uint32) + 1] = {0}; - strncpy(buf, (char *)&csw->signature, sizeof(uint32)); - PTRACE(udi, "CSW:{'%s'; tag:%d; residue:%d; status:0x%02x}\n", - buf, - csw->tag, - csw->data_residue, - csw->status); + char buf[sizeof(uint32) + 1] = {0}; + strncpy(buf, (char *)&csw->signature, sizeof(uint32)); + PTRACE(udi, "CSW:{'%s'; tag:%d; residue:%d; status:0x%02x}\n", + buf, csw->tag, csw->data_residue, csw->status); } /** - \fn:get_max_luns - \param udi: device for wich max LUN info is requested - \return:always B_OK - if info was not retrieved max LUN is defaulted to 0 - - tries to retrieve the maximal Logical Unit Number supported by - this device. If device doesn't support GET_MAX_LUN request - single LUN is - assumed. ([2] 3.2) + \fn:get_max_luns + \param udi: device for wich max LUN info is requested + \return:always B_OK - if info was not retrieved max LUN is defaulted to 0 + + tries to retrieve the maximal Logical Unit Number supported by + this device. If device doesn't support GET_MAX_LUN request - single LUN is + assumed. ([2] 3.2) */ static status_t get_max_luns(usb_device_info *udi) { - status_t status = B_OK; - udi->max_lun = 0; - if(!HAS_FIXES(udi->properties, FIX_NO_GETMAXLUN)){ - size_t len = 0; - if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, - USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, - USB_REQ_MS_GET_MAX_LUN, 0x0, udi->interface, - 0x1, &udi->max_lun, &len))) - { - if(status == B_DEV_STALLED){ - PTRACE_ALWAYS(udi, "get_max_luns[%d]:not supported. " - "Assuming single LUN available.\n", udi->dev_num); - } else { - PTRACE(udi, "get_max_luns[%d]:failed(%08x)." - "Assuming single LUN available.\n", udi->dev_num, status); - } - udi->max_lun = 0; - status = B_OK; - } /* else - all is OK - max luns info readed */ - } - return status; + status_t status = B_OK; + udi->max_lun = 0; + if(!HAS_FIXES(udi->properties, FIX_NO_GETMAXLUN)){ + size_t len = 0; + if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, + USB_REQ_MS_GET_MAX_LUN, 0x0, udi->interface, + 0x1, &udi->max_lun, &len))) + { + if(status == B_DEV_STALLED){ + PTRACE_ALWAYS(udi, "get_max_luns[%d]:not supported. " + "Assuming single LUN available.\n", udi->dev_num); + } else { + PTRACE(udi, "get_max_luns[%d]:failed(%08x)." + "Assuming single LUN available.\n", udi->dev_num, status); + } + udi->max_lun = 0; + status = B_OK; + } /* else - all is OK - max luns info readed */ + } + return status; } /** - \fn:queue_bulk - \param udi: device for which que_bulk request is performed - \param buffer: data buffer, used in bulk i/o operation - \param len: length of data buffer - \param b_in: is "true" if input (device->host) data transfer, "false" otherwise - \return: status of operation. - - performs queue_bulk USB request for corresponding pipe and handle timeout of this - operation. + \fn:queue_bulk + \param udi: device for which que_bulk request is performed + \param buffer: data buffer, used in bulk i/o operation + \param len: length of data buffer + \param b_in: is "true" if input (device->host) data transfer, "false" otherwise + \return: status of operation. + + performs queue_bulk USB request for corresponding pipe and handle timeout of this + operation. */ static status_t -queue_bulk(usb_device_info *udi, - void *buffer, - size_t len, - bool b_in) +queue_bulk(usb_device_info *udi, void* buffer, size_t len, bool b_in) { - status_t status = B_OK; - usb_pipe pipe = b_in ? udi->pipe_in : udi->pipe_out; - status = (*udi->usb_m->queue_bulk)(pipe, buffer, len, bulk_callback, udi); - if(status != B_OK){ - PTRACE_ALWAYS(udi, "queue_bulk:failed:%08x\n", status); - } else { - status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); - if(status != B_OK){ - PTRACE_ALWAYS(udi, "queue_bulk:acquire_sem_etc failed:%08x\n", status); - (*udi->usb_m->cancel_queued_transfers)(pipe); - } - } - return status; + status_t status = B_OK; + usb_pipe pipe = b_in ? udi->pipe_in : udi->pipe_out; + status = (*udi->usb_m->queue_bulk)(pipe, buffer, len, bulk_callback, udi); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "queue_bulk:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "queue_bulk:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } + return status; } /** - \fn:check_CSW - \param udi:corresponding device info - \param csw: CSW to be checked for validity and meaningfullness - \param transfer_len: data transferred during operation, which is checked for status - \return: "true" if CSW valid and meanigfull, "false" otherwise - - checks CSW for validity and meaningfullness as required by USB mass strorge - BulkOnly specification ([2] 6.3) + \fn:check_CSW + \param udi:corresponding device info + \param csw: CSW to be checked for validity and meaningfullness + \param transfer_len: data transferred during operation, which is checked for status + \return: "true" if CSW valid and meanigfull, "false" otherwise + + checks CSW for validity and meaningfullness as required by USB mass strorge + BulkOnly specification ([2] 6.3) */ static bool -check_CSW(usb_device_info *udi, - usb_mass_CSW *csw, - int transfer_len) +check_CSW(usb_device_info *udi, usb_mass_CSW* csw, int transfer_len) { - bool is_valid = false; - do{ - /* check for CSW validity */ - if(udi->actual_len != CSW_LENGTH){ - PTRACE_ALWAYS(udi, "check_CSW:wrong length %d instead of %d\n", - udi->actual_len, CSW_LENGTH); - break;/* failed */ - } - if(csw->signature != CSW_SIGNATURE){ - PTRACE_ALWAYS(udi, "check_CSW:wrong signature %08x instead of %08x\n", - csw->signature, CSW_SIGNATURE); - break;/* failed */ - } - if(csw->tag != udi->tag - 1){ - PTRACE_ALWAYS(udi, "check_CSW:tag mismatch received:%d, awaited:%d\n", - csw->tag, udi->tag-1); - break;/* failed */ - } - /* check for CSW meaningfullness */ - if(CSW_STATUS_PHASE == csw->status){ - PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: phase error\n"); - break;/* failed */ - } - if(transfer_len < csw->data_residue){ - PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: " - "residue:%d is greater than transfer length:%d\n", - csw->data_residue, transfer_len); - break;/* failed */ - } - is_valid = true; - }while(false); - return is_valid; + bool is_valid = false; + do{ + /* check for CSW validity */ + if(udi->actual_len != CSW_LENGTH){ + PTRACE_ALWAYS(udi, "check_CSW:wrong length %d instead of %d\n", + udi->actual_len, CSW_LENGTH); + break;/* failed */ + } + if(csw->signature != CSW_SIGNATURE){ + PTRACE_ALWAYS(udi, "check_CSW:wrong signature %08x instead of %08x\n", + csw->signature, CSW_SIGNATURE); + break;/* failed */ + } + if(csw->tag != udi->tag - 1){ + PTRACE_ALWAYS(udi, "check_CSW:tag mismatch received:%d, awaited:%d\n", + csw->tag, udi->tag-1); + break;/* failed */ + } + /* check for CSW meaningfullness */ + if(CSW_STATUS_PHASE == csw->status){ + PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: phase error\n"); + break;/* failed */ + } + if(transfer_len < csw->data_residue){ + PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: " + "residue:%d is greater than transfer length:%d\n", + csw->data_residue, transfer_len); + break;/* failed */ + } + is_valid = true; + }while(false); + return is_valid; } /** - \fn:read_status - \param udi: corresponding device - \param csw: buffer for CSW data - \param transfer_len: data transferred during operation, which is checked for status - \return: success status code - - reads CSW from device as proposed in ([2] 5.3.3; Figure 2.). + \fn:read_status + \param udi: corresponding device + \param csw: buffer for CSW data + \param transfer_len: data transferred during operation, which is checked for status + \return: success status code + + reads CSW from device as proposed in ([2] 5.3.3; Figure 2.). */ static status_t -read_status(usb_device_info *udi, - usb_mass_CSW *csw, - int transfer_len) +read_status(usb_device_info *udi, usb_mass_CSW* csw, int transfer_len) { - status_t status = B_ERROR; - int try = 0; - do{ - status = queue_bulk(udi, csw, CSW_LENGTH, true); - if(0 == try){ - if(B_OK != status || B_OK != udi->status){ - status = (*udi->usb_m->clear_feature)(udi->pipe_in, USB_FEATURE_ENDPOINT_HALT); - if(status != 0){ - PTRACE_ALWAYS(udi, "read_status:failed 1st try, " - "status:%08x; usb_status:%08x\n", status, udi->status); - (*udi->protocol_m->reset)(udi); - break; - } - continue; /* go to second try*/ - } - /* CSW was readed without errors */ - } else { /* second try */ - if(B_OK != status || B_OK != udi->status){ - PTRACE_ALWAYS(udi, "read_status:failed 2nd try status:%08x; usb_status:%08x\n", - status, udi->status); - (*udi->protocol_m->reset)(udi); - status = (B_OK == status) ? udi->status : status; - break; - } - } - if(!check_CSW(udi, csw, transfer_len)){ - (*udi->protocol_m->reset)(udi); - status = B_ERROR; - break; - } - trace_CSW(udi, csw); - break; /* CSW was read successfully */ - }while(try++ < 2); - return status; + status_t status = B_ERROR; + int try = 0; + do{ + status = queue_bulk(udi, csw, CSW_LENGTH, true); + if(0 == try){ + if(B_OK != status || B_OK != udi->status){ + status = (*udi->usb_m->clear_feature)(udi->pipe_in, USB_FEATURE_ENDPOINT_HALT); + if(status != 0){ + PTRACE_ALWAYS(udi, "read_status:failed 1st try, " + "status:%08x; usb_status:%08x\n", status, udi->status); + (*udi->protocol_m->reset)(udi); + break; + } + continue; /* go to second try*/ + } + /* CSW was readed without errors */ + } else { /* second try */ + if(B_OK != status || B_OK != udi->status){ + PTRACE_ALWAYS(udi, "read_status:failed 2nd try status:%08x; usb_status:%08x\n", + status, udi->status); + (*udi->protocol_m->reset)(udi); + status = (B_OK == status) ? udi->status : status; + break; + } + } + if(!check_CSW(udi, csw, transfer_len)){ + (*udi->protocol_m->reset)(udi); + status = B_ERROR; + break; + } + trace_CSW(udi, csw); + break; /* CSW was read successfully */ + }while(try++ < 2); + return status; } /*================= "standard" protocol procedures ==============================*/ /** - \fn:bulk_only_initialize - \param udi: device on wich we should perform initialization - \return:error code if initialization failed or B_OK if it passed - - initialize procedure for bulk only protocol devices. + \fn:bulk_only_initialize + \param udi: device on wich we should perform initialization + \return:error code if initialization failed or B_OK if it passed + + initialize procedure for bulk only protocol devices. */ status_t bulk_only_initialize(usb_device_info *udi) { - status_t status = B_OK; - status = get_max_luns(udi); - return status; + status_t status = B_OK; + status = get_max_luns(udi); + return status; } /** - \fn:bulk_only_reset - \param udi: device on wich we should perform reset - \return:error code if reset failed or B_OK if it passed - - reset procedure for bulk only protocol devices. Tries to send - BulkOnlyReset USB request and clear USB_FEATURE_ENDPOINT_HALT features on - input and output pipes. ([2] 3.1) + \fn:bulk_only_reset + \param udi: device on wich we should perform reset + \return:error code if reset failed or B_OK if it passed + + reset procedure for bulk only protocol devices. Tries to send + BulkOnlyReset USB request and clear USB_FEATURE_ENDPOINT_HALT features on + input and output pipes. ([2] 3.1) */ status_t bulk_only_reset(usb_device_info *udi) { - status_t status = B_ERROR; - status = (*udi->usb_m->send_request)(udi->device, - USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, - USB_REQ_MS_RESET, 0, - udi->interface, 0, 0, 0); - if(status != B_OK){ - PTRACE_ALWAYS(udi, "bulk_only_reset: reset request failed: %08x\n", status); - } - if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, - USB_FEATURE_ENDPOINT_HALT))) - { - PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_in failed: %08x\n", status); - } - if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, - USB_FEATURE_ENDPOINT_HALT))) - { - PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_out failed: %08x\n", status); - } - PTRACE(udi, "bulk_only_reset:%08x\n", status); - return status; + status_t status = B_ERROR; + status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + USB_REQ_MS_RESET, 0, + udi->interface, 0, 0, 0); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "bulk_only_reset: reset request failed: %08x\n", status); + } + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, + USB_FEATURE_ENDPOINT_HALT))) + { + PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_in failed: %08x\n", status); + } + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, + USB_FEATURE_ENDPOINT_HALT))) + { + PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_out failed: %08x\n", status); + } + PTRACE(udi, "bulk_only_reset:%08x\n", status); + return status; } /** - \fn:bulk_only_transfer - \param udi: corresponding device - \param cmd: SCSI command to be performed on USB device - \param cmdlen: length of SCSI command - \param data_sg: io vectors array with data to transfer - \param sglist_count: count of entries in io vector array - \param transfer_len: overall length of data to be transferred - \param dir: direction of data transfer - \param ccbio: CCB_SCSIIO struct for original SCSI command - \param cb: callback to handle of final stage of command performing (autosense \ - request etc.) - - transfer procedure for bulk-only protocol. Performs SCSI command on USB device - [2] + \fn:bulk_only_transfer + \param udi: corresponding device + \param cmd: SCSI command to be performed on USB device + \param cmdlen: length of SCSI command + \param data_sg: io vectors array with data to transfer + \param sglist_count: count of entries in io vector array + \param transfer_len: overall length of data to be transferred + \param dir: direction of data transfer + \param ccbio: CCB_SCSIIO struct for original SCSI command + \param cb: callback to handle of final stage of command performing (autosense \ + request etc.) + + transfer procedure for bulk-only protocol. Performs SCSI command on USB device + [2] */ void -bulk_only_transfer(usb_device_info *udi, - uint8 *cmd, - uint8 cmdlen, - //sg_buffer *sgb, - iovec *sg_data, - int32 sg_count, - int32 transfer_len, - EDirection dir, - CCB_SCSIIO *ccbio, - ud_transfer_callback cb) +bulk_only_transfer(usb_device_info *udi, uint8 *cmd, uint8 cmdlen, //sg_buffer *sgb, + iovec *sg_data,int32 sg_count, int32 transfer_len, + EDirection dir, CCB_SCSIIO *ccbio, ud_transfer_callback cb) { - status_t status = B_OK; - status_t command_status = B_OK; - int32 residue = transfer_len; - usb_mass_CSW csw = {0}; - /* initialize and fill in Command Block Wrapper */ - usb_mass_CBW cbw = { - .signature = CBW_SIGNATURE, - .tag = atomic_add(&udi->tag, 1), - .data_transfer_len = transfer_len, - .flags = (dir == eDirIn) ? CBW_FLAGS_IN : CBW_FLAGS_OUT, - .lun = ccbio->cam_ch.cam_target_lun & 0xf, - .cdb_len = cmdlen, - }; - memcpy(cbw.CDB, cmd, cbw.cdb_len); - do{ - trace_CBW(udi, &cbw); - /* send CBW to device */ - status = queue_bulk(udi, &cbw, CBW_LENGTH, false); - if(status != B_OK || udi->status != B_OK){ - PTRACE_ALWAYS(udi, "bulk_only_transfer: queue_bulk failed:" - "status:%08x usb status:%08x\n", status, udi->status); - (*udi->protocol_m->reset)(udi); - command_status = B_CMD_WIRE_FAILED; - break; - } - /* perform data transfer if required */ - if(transfer_len != 0x0){ - status = process_data_io(udi, sg_data, sg_count, dir); - if(status != B_OK && status != B_DEV_STALLED){ - command_status = B_CMD_WIRE_FAILED; - break; - } - } - /* get status of command */ - status = read_status(udi, &csw, transfer_len); - if(B_OK != status){ - command_status = B_CMD_WIRE_FAILED; - break; - } - residue = csw.data_residue; - if(csw.status == CSW_STATUS_FAILED){ - command_status = B_CMD_FAILED; - }else{ - command_status = B_OK; - } - }while(false); - /* finalize transfer */ - cb(udi, ccbio, residue, command_status); + status_t status = B_OK; + status_t command_status = B_OK; + int32 residue = transfer_len; + usb_mass_CSW csw = {0}; + /* initialize and fill in Command Block Wrapper */ + usb_mass_CBW cbw = { + .signature = CBW_SIGNATURE, + .tag = atomic_add(&udi->tag, 1), + .data_transfer_len = transfer_len, + .flags = (dir == eDirIn) ? CBW_FLAGS_IN : CBW_FLAGS_OUT, + .lun = ccbio->cam_ch.cam_target_lun & 0xf, + .cdb_len = cmdlen, + }; + memcpy(cbw.CDB, cmd, cbw.cdb_len); + do{ + trace_CBW(udi, &cbw); + /* send CBW to device */ + status = queue_bulk(udi, &cbw, CBW_LENGTH, false); + if(status != B_OK || udi->status != B_OK){ + PTRACE_ALWAYS(udi, "bulk_only_transfer: queue_bulk failed:" + "status:%08x usb status:%08x\n", status, udi->status); + (*udi->protocol_m->reset)(udi); + command_status = B_CMD_WIRE_FAILED; + break; + } + /* perform data transfer if required */ + if(transfer_len != 0x0){ + status = process_data_io(udi, sg_data, sg_count, dir); + if(status != B_OK && status != B_DEV_STALLED){ + command_status = B_CMD_WIRE_FAILED; + break; + } + } + /* get status of command */ + status = read_status(udi, &csw, transfer_len); + if(B_OK != status){ + command_status = B_CMD_WIRE_FAILED; + break; + } + residue = csw.data_residue; + if(csw.status == CSW_STATUS_FAILED){ + command_status = B_CMD_FAILED; + }else{ + command_status = B_OK; + } + }while(false); + /* finalize transfer */ + cb(udi, ccbio, residue, command_status); } protocol_module_info bulk_only_protocol_m = { - {0, 0, 0}, /* this is not a real kernel module - just interface */ - bulk_only_initialize, - bulk_only_reset, - bulk_only_transfer, + {0, 0, 0}, /* this is not a real kernel module - just interface */ + bulk_only_initialize, + bulk_only_reset, + bulk_only_transfer, }; + diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h index 9d2588462f..8ca165f186 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h +++ b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h @@ -1,14 +1,20 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ - /** bulk-only protocol "standard" procedures */ #ifndef _PROTO_BULK_H_ - #define _PROTO_BULK_H_ + #define _PROTO_BULK_H_ #ifndef _PROTO_MODULE_H_ #include "proto_module.h" diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c index 6ffaa6de57..6973c972b0 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c +++ b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c @@ -1,9 +1,15 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ - /* References: * USB Mass Storage Class specifications: * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf @@ -27,9 +33,9 @@ typedef struct _usb_mass_CBI_CB{ - uint8 op; - uint8 op2; - uint8 padding[14]; + uint8 op; + uint8 op2; + uint8 padding[14]; } usb_mass_CBI_CB; #define CDB_LEN 16 @@ -38,220 +44,218 @@ typedef struct _usb_mass_CBI_CB{ //typedef uint8 usb_mass_CDB[CDB_LEN]; typedef union _usb_mass_CBI_IDB{ - struct { - uint8 type; - uint8 value; - } common; - struct { - uint8 asc; - uint8 ascq; - } ufi; + struct { + uint8 type; + uint8 value; + } common; + struct { + uint8 asc; + uint8 ascq; + } ufi; } usb_mass_CBI_IDB; -#define CBI_IDB_TYPE_CCI 0x00 -#define CBI_IDB_VALUE_PASS 0x00 -#define CBI_IDB_VALUE_FAIL 0x01 -#define CBI_IDB_VALUE_PHASE 0x02 -#define CBI_IDB_VALUE_PERSISTENT 0x03 -#define CBI_IDB_VALUE_STATUS_MASK 0x03 +#define CBI_IDB_TYPE_CCI 0x00 +#define CBI_IDB_VALUE_PASS 0x00 +#define CBI_IDB_VALUE_FAIL 0x01 +#define CBI_IDB_VALUE_PHASE 0x02 +#define CBI_IDB_VALUE_PERSISTENT 0x03 +#define CBI_IDB_VALUE_STATUS_MASK 0x03 + +static void trace_CDB(usb_device_info *udi, const usb_mass_CBI_CB *cb, int len); +static status_t cbi_reset(usb_device_info *udi); +static status_t cbi_initialize(usb_device_info *udi); +static void cbi_transfer(usb_device_info *udi, uint8 *cmd, uint8 cmdlen, //sg_buffer *sgb, + iovec *sg_data, int32 sg_count, int32 transfer_len, + EDirection dir, CCB_SCSIIO *ccbio, ud_transfer_callback cb); /** returns size of private protocol buffer */ //int cbi_buffer_length(){ return sizeof(usb_mass_CBI_CB) + sizeof(usb_mass_CBI_IDB); } /** casts private protocol buffer to CBI_IDB */ /*#define IDB_BUFFER(__buff)\ - ((usb_mass_CBI_IDB*)(((uint8*)__buff) + sizeof(usb_mass_CBI_CB))) + ((usb_mass_CBI_IDB*)(((uint8*)__buff) + sizeof(usb_mass_CBI_CB))) */ /** casts private protocol buffer to CBI_CB */ /*#define CB_BUFFER(__buff)\ - ((usb_mass_CBI_CB*)(__buff)) + ((usb_mass_CBI_CB*)(__buff)) */ void trace_CDB(usb_device_info *udi, const usb_mass_CBI_CB *cb, int len) { - PTRACE(udi, "CB:{op:0x%02x; op2:0x%02x;}\n", cb->op, cb->op2); - udi->trace_bytes(" padding:", cb->padding, len - 2); + PTRACE(udi, "CB:{op:0x%02x; op2:0x%02x;}\n", cb->op, cb->op2); + udi->trace_bytes(" padding:", cb->padding, len - 2); } static status_t -send_request_adsc(usb_device_info *udi, - void *cb, - int length) +send_request_adsc(usb_device_info *udi, void *cb, int length) { - status_t status = B_ERROR; - size_t len = 0; - trace_CDB(udi, cb, length); - status = (*udi->usb_m->send_request)(udi->device, - USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, - USB_REQ_CBI_ADSC, 0, - udi->interface, length, - cb, &len); - return status; + status_t status = B_ERROR; + size_t len = 0; + trace_CDB(udi, cb, length); + status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + USB_REQ_CBI_ADSC, 0, + udi->interface, length, + cb, &len); + return status; } static status_t -request_interrupt(usb_device_info *udi, - usb_mass_CBI_IDB *idb) +request_interrupt(usb_device_info *udi, usb_mass_CBI_IDB *idb) { - status_t status = B_ERROR; - status = (*udi->usb_m->queue_interrupt)(udi->pipe_intr, idb, - sizeof(usb_mass_CBI_IDB), bulk_callback, udi); - if(status != B_OK){ - PTRACE(udi, "request_interrupt:failed:%08x\n", status); - } else { - status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); - if(status != B_OK){ - PTRACE(udi, "request_interrupt:acquire_sem_etc failed:%08x\n", status); - (*udi->usb_m->cancel_queued_transfers)(udi->pipe_intr); - } - } - udi->trace_bytes("Intr status:", (uint8*)idb, sizeof(usb_mass_CBI_IDB)); - return status; + status_t status = B_ERROR; + status = (*udi->usb_m->queue_interrupt)(udi->pipe_intr, idb, + sizeof(usb_mass_CBI_IDB), bulk_callback, udi); + if(status != B_OK){ + PTRACE(udi, "request_interrupt:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status != B_OK){ + PTRACE(udi, "request_interrupt:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(udi->pipe_intr); + } + } + udi->trace_bytes("Intr status:", (uint8*)idb, sizeof(usb_mass_CBI_IDB)); + return status; } static status_t -parse_status(usb_device_info *udi, - usb_mass_CBI_IDB *idb) +parse_status(usb_device_info *udi, usb_mass_CBI_IDB *idb) { - status_t command_status = B_OK; - if(CMDSET(udi->properties) == CMDSET_UFI){ - if(idb->ufi.asc == 0 && idb->ufi.ascq == 0){ - command_status = B_OK; - }else{ - command_status = B_CMD_FAILED; - } - } else { - if(idb->common.type == CBI_IDB_TYPE_CCI){ - switch(idb->common.value & CBI_IDB_VALUE_STATUS_MASK){ - case CBI_IDB_VALUE_PASS: - command_status = B_OK; - break; - case CBI_IDB_VALUE_FAIL: - case CBI_IDB_VALUE_PERSISTENT: - command_status = B_CMD_FAILED; - break; - case CBI_IDB_VALUE_PHASE: - default: - command_status = B_CMD_WIRE_FAILED; - break; - } - } /* else ?? */ - } - return command_status; + status_t command_status = B_OK; + if(CMDSET(udi->properties) == CMDSET_UFI){ + if(idb->ufi.asc == 0 && idb->ufi.ascq == 0){ + command_status = B_OK; + }else{ + command_status = B_CMD_FAILED; + } + } else { + if(idb->common.type == CBI_IDB_TYPE_CCI){ + switch(idb->common.value & CBI_IDB_VALUE_STATUS_MASK){ + case CBI_IDB_VALUE_PASS: + command_status = B_OK; + break; + case CBI_IDB_VALUE_FAIL: + case CBI_IDB_VALUE_PERSISTENT: + command_status = B_CMD_FAILED; + break; + case CBI_IDB_VALUE_PHASE: + default: + command_status = B_CMD_WIRE_FAILED; + break; + } + } /* else ?? */ + } + return command_status; } /*================= "standard" protocol procedures ==============================*/ /** - \fn: - \param udi: ??? - \return:?? - - ?? + \fn: + \param udi: ??? + \return:?? + + ?? */ status_t cbi_reset(usb_device_info *udi) { - status_t status = B_ERROR; - //usb_mass_CBI_CB *cb = CB_BUFFER(udi->proto_buf); - //usb_mass_CDB cdb = {0x1d, 0x04, 0x00}; - //memset(cdb + 2, 0xff, CDB_RESET_LEN - 2); - usb_mass_CBI_CB cb = { - .op = 0x1D, - .op2 = 0x04, - }; - memset(cb.padding , 0xff, sizeof(cb.padding)); - status = send_request_adsc(udi, &cb, CDB_RESET_LEN); - if(status != B_OK) - PTRACE_ALWAYS(udi, "command_block_reset: reset request failed: %08x\n", status); - - if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, - USB_FEATURE_ENDPOINT_HALT))) - PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_in failed: %08x\n", status); + status_t status = B_ERROR; + //usb_mass_CBI_CB *cb = CB_BUFFER(udi->proto_buf); + //usb_mass_CDB cdb = {0x1d, 0x04, 0x00}; + //memset(cdb + 2, 0xff, CDB_RESET_LEN - 2); + usb_mass_CBI_CB cb = { + .op = 0x1D, + .op2 = 0x04, + }; + memset(cb.padding , 0xff, sizeof(cb.padding)); + status = send_request_adsc(udi, &cb, CDB_RESET_LEN); + if(status != B_OK) + PTRACE_ALWAYS(udi, "command_block_reset: reset request failed: %08x\n", status); + + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, + USB_FEATURE_ENDPOINT_HALT))) + PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_in failed: %08x\n", status); - if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, - USB_FEATURE_ENDPOINT_HALT))) - PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_out failed: %08x\n", status); - PTRACE(udi, "command_block_reset:%08x\n", status); + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, + USB_FEATURE_ENDPOINT_HALT))) + PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_out failed: %08x\n", status); + PTRACE(udi, "command_block_reset:%08x\n", status); - return status; + return status; } /** - \fn: + \fn: */ status_t cbi_initialize(usb_device_info *udi) { - status_t status = B_OK; - udi->max_lun = 0; - return status; + status_t status = B_OK; + udi->max_lun = 0; + return status; } /** - \fn:bulk_only_transfer - \param udi: ??? - \param cmd: ??? - \param cmdlen: ??? - \return:??? - - ??? + \fn:bulk_only_transfer + \param udi: ??? + \param cmd: ??? + \param cmdlen: ??? + \return:??? + + ??? */ void -cbi_transfer(usb_device_info *udi, - uint8 *cmd, - uint8 cmdlen, - //sg_buffer *sgb, - iovec *sg_data, - int32 sg_count, - int32 transfer_len, - EDirection dir, - CCB_SCSIIO *ccbio, - ud_transfer_callback cb) +cbi_transfer(usb_device_info *udi, uint8 *cmd, uint8 cmdlen, + //sg_buffer *sgb, + iovec *sg_data, int32 sg_count, int32 transfer_len, + EDirection dir,CCB_SCSIIO *ccbio, ud_transfer_callback cb) { - status_t status = B_OK; - status_t command_status = B_OK; - int32 residue = transfer_len; - usb_mass_CBI_IDB idb = {{0}}; - do{ - status = send_request_adsc(udi, cmd, cmdlen); - if(status != B_OK){ - PTRACE(udi, "cbi_transfer:send command block failed: %08x\n", status); - if(status == B_DEV_STALLED){ - command_status = B_CMD_FAILED; - } else { - command_status = B_CMD_WIRE_FAILED; - (*udi->protocol_m->reset)(udi); - } - break; - } - if(transfer_len != 0){ - status = process_data_io(udi, sg_data, sg_count, dir); - if(status != B_OK){ - command_status = B_CMD_WIRE_FAILED; - break; - } - } - - if(PROTO(udi->properties) == PROTO_CBI){ - status = request_interrupt(udi, &idb); - PTRACE(udi, "cbi_transfer:request interrupt: %08x(%08x)\n", status, udi->status); - if(status != B_OK){ - command_status = B_CMD_WIRE_FAILED; - break; - } - if(udi->status == B_DEV_STALLED){ - } - command_status = parse_status(udi, &idb); - } else { /* PROP_CB ???*/ - command_status = B_CMD_UNKNOWN; - } - residue = 0; /* DEBUG!!!!!!!!!*/ - }while(false); - cb(udi, ccbio, residue, command_status); + status_t status = B_OK; + status_t command_status = B_OK; + int32 residue = transfer_len; + usb_mass_CBI_IDB idb = {{0}}; + do{ + status = send_request_adsc(udi, cmd, cmdlen); + if(status != B_OK){ + PTRACE(udi, "cbi_transfer:send command block failed: %08x\n", status); + if(status == B_DEV_STALLED){ + command_status = B_CMD_FAILED; + } else { + command_status = B_CMD_WIRE_FAILED; + (*udi->protocol_m->reset)(udi); + } + break; + } + if(transfer_len != 0){ + status = process_data_io(udi, sg_data, sg_count, dir); + if(status != B_OK){ + command_status = B_CMD_WIRE_FAILED; + break; + } + } + + if(PROTO(udi->properties) == PROTO_CBI){ + status = request_interrupt(udi, &idb); + PTRACE(udi, "cbi_transfer:request interrupt: %08x(%08x)\n", status, udi->status); + if(status != B_OK){ + command_status = B_CMD_WIRE_FAILED; + break; + } + if(udi->status == B_DEV_STALLED){ + } + command_status = parse_status(udi, &idb); + } else { /* PROP_CB ???*/ + command_status = B_CMD_UNKNOWN; + } + residue = 0; /* DEBUG!!!!!!!!!*/ + }while(false); + cb(udi, ccbio, residue, command_status); } protocol_module_info cbi_protocol_m = { - {0, 0, 0}, /* this is not a real kernel module - just interface */ - cbi_initialize, - cbi_reset, - cbi_transfer, + {0, 0, 0}, /* this is not a real kernel module - just interface */ + cbi_initialize, + cbi_reset, + cbi_transfer, }; + diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h index 3121f923c1..cbb002d7cf 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h +++ b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h @@ -1,11 +1,17 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ - #ifndef _PROTO_CBI_H_ - #define _PROTO_CBI_H_ + #define _PROTO_CBI_H_ #ifndef _PROTO_MODULE_H_ #include "proto_module.h" diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.c b/src/add-ons/kernel/busses/scsi/usb/proto_common.c index 9c4e98836a..e8d1ab3099 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_common.c +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.c @@ -1,9 +1,15 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ - #include #include "usb_scsi.h" @@ -15,150 +21,141 @@ #include "scsi_commands.h" /** - \fn:bulk_callback - \param cookie:??? - \param status:??? - \param data:??? - \param actual_len:??? - \return:??? - - ??? + \fn:bulk_callback + \param cookie:??? + \param status:??? + \param data:??? + \param actual_len:??? + \return:??? + + ??? */ -void bulk_callback(void *cookie, - uint32 status, - void *data, - uint32 actual_len) +void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len) { - TRACE_BULK_CALLBACK(status, actual_len); - if(cookie){ - usb_device_info *udi = (usb_device_info *)cookie; - udi->status = status; - udi->data = data; - udi->actual_len = actual_len; - if(udi->status != B_CANCELED) - release_sem(udi->trans_sem); - } + TRACE_BULK_CALLBACK(status, actual_len); + if(cookie){ + usb_device_info *udi = (usb_device_info *)cookie; + udi->status = status; + udi->data = data; + udi->actual_len = actual_len; + if(udi->status != B_CANCELED) + release_sem(udi->trans_sem); + } } /** - \fn:exec_io - \param udi: ??? - \return:??? - - ??? + \fn:exec_io + \param udi: ??? + \return:??? + + ??? */ -status_t process_data_io(usb_device_info *udi, - //sg_buffer *sgb, - iovec *sg_data, int32 sg_count, - EDirection dir) +status_t process_data_io(usb_device_info *udi, //sg_buffer *sgb, + iovec *sg_data, int32 sg_count, EDirection dir) { - status_t status = B_OK; - usb_pipe pipe = (dir == eDirIn) ? udi->pipe_in : udi->pipe_out; -// TRACE_DATA_IO_SG(data_sg, sglist_count); - status = (*udi->usb_m->queue_bulk_v)(pipe, sg_data, sg_count, bulk_callback, udi); - if(status == B_OK){ - status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); - if(status == B_OK){ - status = udi->status; - if(udi->status == B_DEV_STALLED){ - status_t st=(*udi->usb_m->clear_feature)(pipe, USB_FEATURE_ENDPOINT_HALT); - TRACE_ALWAYS("clear_on_STALL:%08x\n",st); - } - }else{ - TRACE_ALWAYS("process_data_io:acquire_sem failed:%08x\n", status); - (*udi->usb_m->cancel_queued_transfers)(pipe); - } - } else { - TRACE_ALWAYS("process_data_io:queue_bulk_v failed:%08x\n", status); - } - TRACE_DATA_IO("process_data_io:processed:%d;status:%08x\n", udi->actual_len, status); - return status; + status_t status = B_OK; + usb_pipe pipe = (dir == eDirIn) ? udi->pipe_in : udi->pipe_out; +// TRACE_DATA_IO_SG(data_sg, sglist_count); + status = (*udi->usb_m->queue_bulk_v)(pipe, sg_data, sg_count, bulk_callback, udi); + if(status == B_OK){ + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status == B_OK){ + status = udi->status; + if(udi->status == B_DEV_STALLED){ + status_t st=(*udi->usb_m->clear_feature)(pipe, USB_FEATURE_ENDPOINT_HALT); + TRACE_ALWAYS("clear_on_STALL:%08x\n",st); + } + }else{ + TRACE_ALWAYS("process_data_io:acquire_sem failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } else { + TRACE_ALWAYS("process_data_io:queue_bulk_v failed:%08x\n", status); + } + TRACE_DATA_IO("process_data_io:processed:%d;status:%08x\n", udi->actual_len, status); + return status; } -void transfer_callback(struct _usb_device_info *udi, - CCB_SCSIIO *ccbio, - int32 residue, - status_t status) +void transfer_callback(struct _usb_device_info *udi, CCB_SCSIIO *ccbio, + int32 residue, status_t status) { - ccbio->cam_resid = residue; - switch(status){ - case B_OK: - ccbio->cam_ch.cam_status = CAM_REQ_CMP; - break; - case B_CMD_FAILED: - case B_CMD_UNKNOWN:{ - size_t sense_data_len = (0 != ccbio->cam_sense_len) ? - ccbio->cam_sense_len : SSD_MIN_SIZE; - uchar *sense_data_ptr = (NULL != ccbio->cam_sense_ptr) ? - ccbio->cam_sense_ptr : (uchar*)&udi->autosense_data; - uint8 lun = ((ccbio->cam_ch.cam_target_lun) << CMD_LUN_SHIFT) & CMD_LUN; - scsi_cmd_generic_6 cmd = { REQUEST_SENSE, {lun, 0}, sense_data_len, 0}; - /* transform command as required by protocol */ - uint8 *rcmd = udi->scsi_command_buf; - uint8 rcmdlen = sizeof(udi->scsi_command_buf); - iovec sense_sg = { sense_data_ptr, sense_data_len }; - TRACE("transfer_callback:requesting sense information " - "due status:%08x\n", status); - memset(&udi->autosense_data, 0, SSD_FULL_SIZE); /* just to be sure */ - if(B_OK != (*udi->transform_m->transform)(udi, (uint8 *)&cmd, sizeof(cmd), &rcmd, &rcmdlen)){ - TRACE_ALWAYS("transfer_callback: REQUEST SENSE command transform failed\n"); - ccbio->cam_ch.cam_status = CAM_IDE; //????????? - break; - } - /* transfer command to device. SCSI status will be handled in callback */ - (*udi->protocol_m->transfer)(udi, rcmd, rcmdlen, &sense_sg, 1, sense_data_len, - eDirIn, ccbio, sense_callback); - } - break; - case B_CMD_WIRE_FAILED: - ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR; - break; - default: - TRACE_ALWAYS("transfer_callback:unknown status:%08x\n", status); - ccbio->cam_ch.cam_status = CAM_IDE; - break; - } + ccbio->cam_resid = residue; + switch(status){ + case B_OK: + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + break; + case B_CMD_FAILED: + case B_CMD_UNKNOWN:{ + size_t sense_data_len = (0 != ccbio->cam_sense_len) ? + ccbio->cam_sense_len : SSD_MIN_SIZE; + uchar *sense_data_ptr = (NULL != ccbio->cam_sense_ptr) ? + ccbio->cam_sense_ptr : (uchar*)&udi->autosense_data; + uint8 lun = ((ccbio->cam_ch.cam_target_lun) << CMD_LUN_SHIFT) & CMD_LUN; + scsi_cmd_generic_6 cmd = { REQUEST_SENSE, {lun, 0}, sense_data_len, 0}; + /* transform command as required by protocol */ + uint8 *rcmd = udi->scsi_command_buf; + uint8 rcmdlen = sizeof(udi->scsi_command_buf); + iovec sense_sg = { sense_data_ptr, sense_data_len }; + TRACE("transfer_callback:requesting sense information " + "due status:%08x\n", status); + memset(&udi->autosense_data, 0, SSD_FULL_SIZE); /* just to be sure */ + if(B_OK != (*udi->transform_m->transform)(udi, (uint8 *)&cmd, sizeof(cmd), &rcmd, &rcmdlen)){ + TRACE_ALWAYS("transfer_callback: REQUEST SENSE command transform failed\n"); + ccbio->cam_ch.cam_status = CAM_IDE; //????????? + break; + } + /* transfer command to device. SCSI status will be handled in callback */ + (*udi->protocol_m->transfer)(udi, rcmd, rcmdlen, &sense_sg, 1, sense_data_len, + eDirIn, ccbio, sense_callback); + } + break; + case B_CMD_WIRE_FAILED: + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR; + break; + default: + TRACE_ALWAYS("transfer_callback:unknown status:%08x\n", status); + ccbio->cam_ch.cam_status = CAM_IDE; + break; + } } -void sense_callback(struct _usb_device_info *udi, - CCB_SCSIIO *ccbio, - int32 residue, - status_t status) +void sense_callback(struct _usb_device_info *udi, CCB_SCSIIO *ccbio, + int32 residue, status_t status) { - ccbio->cam_sense_resid = residue; - switch(status){ - case B_CMD_UNKNOWN: - case B_CMD_FAILED: - case B_OK:{ - bool b_own_data = (ccbio->cam_sense_ptr == NULL); - scsi_sense_data *sense_data = b_own_data ? - &udi->autosense_data : (scsi_sense_data *)ccbio->cam_sense_ptr; - int data_len = (ccbio->cam_sense_len != 0) ? ccbio->cam_sense_len : SSD_MIN_SIZE; - TRACE_SENSE_DATA((uint8*)sense_data, data_len); - if((sense_data->flags & SSD_KEY) == SSD_KEY_NO_SENSE){ - /* no problems. normal case for CB handling */ - TRACE("sense_callback: key OK\n"); - ccbio->cam_ch.cam_status = CAM_REQ_CMP; - } else { - if(!b_own_data){ /* we have used CCBIO provided buffer for sense data */ - TRACE("sense_callback:sense info OK????:%08x \n", sense_data); - ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR | CAM_AUTOSNS_VALID; - ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; - } else { - /*TODO: ?????????????????????????????????????? */ - ccbio->cam_ch.cam_status = CAM_REQ_CMP; - // ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR /*| CAM_AUTOSNS_VALID*/; - // ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; - TRACE("sense_callback: sense still not handled...\n"); - } - } - } - break; - default: - TRACE_ALWAYS("sense_callback:unknown status:%08x\n", status); - case B_CMD_WIRE_FAILED: - ccbio->cam_ch.cam_status = CAM_AUTOSENSE_FAIL; - break; - } + ccbio->cam_sense_resid = residue; + switch(status){ + case B_CMD_UNKNOWN: + case B_CMD_FAILED: + case B_OK:{ + bool b_own_data = (ccbio->cam_sense_ptr == NULL); + scsi_sense_data *sense_data = b_own_data ? + &udi->autosense_data : (scsi_sense_data *)ccbio->cam_sense_ptr; + int data_len = (ccbio->cam_sense_len != 0) ? ccbio->cam_sense_len : SSD_MIN_SIZE; + TRACE_SENSE_DATA((uint8*)sense_data, data_len); + if((sense_data->flags & SSD_KEY) == SSD_KEY_NO_SENSE){ + /* no problems. normal case for CB handling */ + TRACE("sense_callback: key OK\n"); + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + } else { + if(!b_own_data){ /* we have used CCBIO provided buffer for sense data */ + TRACE("sense_callback:sense info OK????:%08x \n", sense_data); + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR | CAM_AUTOSNS_VALID; + ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; + } else { + /*TODO: ?????????????????????????????????????? */ + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + // ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR /*| CAM_AUTOSNS_VALID*/; + // ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; + TRACE("sense_callback: sense still not handled...\n"); + } + } + } + break; + default: + TRACE_ALWAYS("sense_callback:unknown status:%08x\n", status); + case B_CMD_WIRE_FAILED: + ccbio->cam_ch.cam_status = CAM_AUTOSENSE_FAIL; + break; + } } diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.h b/src/add-ons/kernel/busses/scsi/usb/proto_common.h index f1ea0f2d2e..d2b65fb5dc 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_common.h +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.h @@ -1,28 +1,30 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ #ifndef _PROTO_COMMON_H_ - #define _PROTO_COMMON_H_ + #define _PROTO_COMMON_H_ #ifndef _DEVICE_INFO_H_ - #include "device_info.h" + #include "device_info.h" #endif /* _DEVICE_INFO_H_ */ -void bulk_callback(void *cookie, - uint32 status, - void *data, - uint32 actual_len); - +void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len); + status_t process_data_io(usb_device_info *udi, iovec *sg_data, int32 sg_count/*sg_buffer *sgb*/, EDirection dir); -void transfer_callback(usb_device_info *udi, - CCB_SCSIIO *ccbio, - int32 residue, - status_t status); -void sense_callback(usb_device_info *udi, - CCB_SCSIIO *ccbio, - int32 residue, - status_t status); -#endif /*_PROTO_COMMON_H_*/ +void transfer_callback(usb_device_info *udi, CCB_SCSIIO *ccbio, + int32 residue, status_t status); +void sense_callback(usb_device_info *udi, CCB_SCSIIO *ccbio, + int32 residue, status_t status); + +#endif /*_PROTO_COMMON_H_*/ + diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_module.h b/src/add-ons/kernel/busses/scsi/usb/proto_module.h index 6cc87d2981..b97a67b9cd 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_module.h +++ b/src/add-ons/kernel/busses/scsi/usb/proto_module.h @@ -1,81 +1,89 @@ -/* - * Copyright (c) 2003-2005 by Siarzhuk Zharski - * Distributed under the terms of the BSD License. +/** + * + * TODO: description * + * This file is a part of USB SCSI CAM for Haiku OS. + * May be used under terms of the MIT License + * + * Author(s): + * Siarzhuk Zharski + * + * */ #ifndef _PROTO_MODULE_H_ - #define _PROTO_MODULE_H_ + #define _PROTO_MODULE_H_ #ifndef _MODULE_H - #include + #include #endif /*_MODULE_H*/ /*#ifndef _SG_BUFFER_H_ - #include "sg_buffer.h" + #include "sg_buffer.h" #endif / *_SG_BUFFER_H_*/ enum { - /* B_OK */ /* JFYI:command is OK */ - B_CMD_FAILED = B_ERRORS_END + 1, /* command failed */ - B_CMD_WIRE_FAILED, /* device problems */ - B_CMD_UNKNOWN, /* command state unknown */ + /* B_OK */ /* JFYI:command is OK */ + B_CMD_FAILED = B_ERRORS_END + 1, /* command failed */ + B_CMD_WIRE_FAILED, /* device problems */ + B_CMD_UNKNOWN, /* command state unknown */ }; typedef enum{ - eDirNone = 0, - eDirIn, - eDirOut, + eDirNone = 0, + eDirIn, + eDirOut, } EDirection; struct _usb_device_info; /* forward, we can be included from device_info.h */ typedef void (*ud_transfer_callback)(struct _usb_device_info *udi, - CCB_SCSIIO *ccbio, - int32 residue, - status_t status); + CCB_SCSIIO *ccbio, + int32 residue, + status_t status); typedef struct { - module_info module; - - status_t (*init)(struct _usb_device_info *udi); - status_t (*reset)(struct _usb_device_info *udi); - void (*transfer)(struct _usb_device_info *udi, - uint8 *cmd, uint8 cmdlen, - //sg_buffer *sgb, - iovec *sg_data, - int32 sg_count, - int32 transfer_len, - EDirection dir, - CCB_SCSIIO *ccbio, - ud_transfer_callback cb); + module_info module; + + status_t (*init)(struct _usb_device_info *udi); + status_t (*reset)(struct _usb_device_info *udi); + void (*transfer)(struct _usb_device_info *udi, + uint8 *cmd, uint8 cmdlen, + //sg_buffer *sgb, + iovec *sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb); } protocol_module_info; typedef struct { - module_info module; + module_info module; - status_t (*transform)(struct _usb_device_info *udi, - uint8 *cmd, uint8 len, - uint8 **rcmd, uint8 *rlen); + status_t (*transform)(struct _usb_device_info *udi, + uint8 *cmd, uint8 len, + uint8 **rcmd, uint8 *rlen); } transform_module_info; -#define MODULE_PREFIX "generic/usb_scsi_extensions/" -#define PROTOCOL_SUFFIX "/protocol/v1" -#define TRANSFORM_SUFFIX "/transform/v1" -#define PROTOCOL_MODULE_MASK MODULE_PREFIX"%s"PROTOCOL_SUFFIX -#define TRANSFORM_MODULE_MASK MODULE_PREFIX"%s"TRANSFORM_SUFFIX +#define MODULE_PREFIX "generic/usb_scsi_extensions/" +#define PROTOCOL_SUFFIX "/protocol/v1" +#define TRANSFORM_SUFFIX "/transform/v1" +#define PROTOCOL_MODULE_MASK MODULE_PREFIX"%s"PROTOCOL_SUFFIX +#define TRANSFORM_MODULE_MASK MODULE_PREFIX"%s"TRANSFORM_SUFFIX /** - \define:_TRACE_ALWAYS - trace always - used mainly for error messages + \define:_TRACE_ALWAYS + trace always - used mainly for error messages */ #define PTRACE_ALWAYS(__udi, __x...) \ - { /*if(__udi->b_trace)*/ __udi->trace(true, __x); } + { /*if(__udi->b_trace)*/ __udi->trace(true, __x); } /** - \define:TRACE - trace only if logging is activated + \define:TRACE + trace only if logging is activated */ #define PTRACE(__udi, __x...) \ - { if(__udi->b_trace) __udi->trace(false, __x); } + { if(__udi->b_trace) __udi->trace(false, __x); } #endif /* _PROTO_MODULE_H_ */ +