bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, uint8_t *buffer, uint32_t n) { osalDbgCheck(lunp != NULL); bool ret = HAL_FAILED; uint16_t blocks; msd_result_t res; uint32_t actual_len; chSemWait(&lunp->sem); if (lunp->state != BLK_READY) { chSemSignal(&lunp->sem); return ret; } lunp->state = BLK_READING; while (n) { if (n > 0xffff) { blocks = 0xffff; } else { blocks = (uint16_t)n; } res = scsi_read10(lunp, startblk, blocks, buffer, &actual_len); if (res == MSD_RESULT_DISCONNECTED) { goto exit; } else if (res == MSD_RESULT_TRANSPORT_ERROR) { //retry? goto exit; } else if (res == MSD_RESULT_FAILED) { //retry? goto exit; } n -= blocks; startblk += blocks; buffer += blocks * lunp->info.blk_size; } ret = HAL_SUCCESS; exit: lunp->state = BLK_READY; chSemSignal(&lunp->sem); return ret; }
int scsi_parse(uint8_t *block, uint8_t in_len) { /* set new operation */ if (state == USB_MS_SCSI_STATE_IDLE) { state = USB_MS_SCSI_STATE_PARSE; op = block[0]; } /* skip operation if sending reply */ if (state != USB_MS_SCSI_STATE_REPLY) { switch (op) { case SCSI_INQUIRY: scsi_inquiry(block, in_len); break; case SCSI_MODE_SENSE6: scsi_mode_sense6(block, in_len); break; case SCSI_READ10: scsi_read10(block, in_len); break; case SCSI_READ_CAPACITY10: scsi_read_capacity10(block, in_len); break; case SCSI_READ_FORMAT_CAPACITIES: scsi_read_format_capacities(block, in_len); break; case SCSI_REPORT_LUNS: scsi_report_luns(block, in_len); break; case SCSI_REQUEST_SENSE: scsi_request_sense(block, in_len); break; case SCSI_START_STOP_UNIT: scsi_start_stop_unit(block, in_len); break; case SCSI_SYNCHRONIZE_CACHE10: scsi_synchronize_cache10(block, in_len); break; case SCSI_TEST_UNIT_READY: scsi_test_unit_ready(block, in_len); break; case SCSI_WRITE10: scsi_write10(block, in_len); break; default: state = USB_MS_SCSI_STATE_REPLY; scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_INVALID_COMMAND_OPERATION_CODE); break; } } /* error during data rx/tx */ if (((state == USB_MS_SCSI_STATE_DATA_OUT) || (state == USB_MS_SCSI_STATE_DATA_IN)) && scsi_sense_data.key) { btable_ep[USB_EP_MS_TX].tx_count = 0; state = USB_MS_SCSI_STATE_REPLY; return SCSI_STATUS_CONTINUE; } /* done sending data */ if (state == USB_MS_SCSI_STATE_REPLY) { state = USB_MS_SCSI_STATE_IDLE; return scsi_sense_data.key; } /* still sending/receiving data and no error has occurred */ return SCSI_STATUS_CONTINUE; }