📄 sbcmethods.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "SBCMethods.h"
#include "MSDDStateMachine.h"
#include <usb/device/core/USBD.h>
//------------------------------------------------------------------------------
// Global variables
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Header for the mode pages data
//! \see SBCModeParameterHeader6
//------------------------------------------------------------------------------
static const SBCModeParameterHeader6 modeParameterHeader6 = {
sizeof(SBCModeParameterHeader6) - 1, //! Length is 0x03
SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE, //! Direct-access block device
0, //! Reserved bits
0, //! DPO/FUA not supported
0, //! Reserved bits
0, //! not write-protected
0 //! No block descriptor
};
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Performs a WRITE (10) command on the specified LUN.
//!
//! The data to write is first received from the USB host and then
//! actually written on the media.
//! This function operates asynchronously and must be called multiple
//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
//! indicates that at least another call of the method is necessary.
//! \param lun Pointer to the LUN affected by the command
//! \param commandState Current state of the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see MSDLun
//! \see MSDCommandState
//------------------------------------------------------------------------------
static unsigned char SBC_Write10(MSDLun *lun,
MSDCommandState *commandState)
{
unsigned char status;
unsigned char result = MSDD_STATUS_INCOMPLETE;
MSDTransfer *transfer = &(commandState->transfer);
SBCWrite10 *command = (SBCWrite10 *) commandState->cbw.pCommand;
// Init command state
if (commandState->state == 0) {
commandState->state = SBC_STATE_READ;
}
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
// Convert length from bytes to blocks
commandState->length /= lun->blockSize;
#endif
// Check if length equals 0
if (commandState->length == 0) {
TRACE_INFO_WP("End ");
result = MSDD_STATUS_SUCCESS;
}
else {
// Current command status
switch (commandState->state) {
//------------------
case SBC_STATE_READ:
//------------------
TRACE_INFO_WP("Receive ");
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
// Read one block of data sent by the host
status = MSDD_Read((void*)lun->readWriteBuffer,
lun->blockSize,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#else
status = MSDD_Read((void*)(lun->media->baseAddress
+ lun->baseAddress
+ DWORDB(command->pLogicalBlockAddress) * lun->blockSize),
commandState->length,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#endif
// Check operation result code
if (status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Write10: Failed to start receiving data\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_HARDWARE_ERROR,
0,
0);
result = MSDD_STATUS_ERROR;
}
else {
// Prepare next device state
commandState->state = SBC_STATE_WAIT_READ;
}
break;
//-----------------------
case SBC_STATE_WAIT_READ:
//-----------------------
TRACE_INFO_WP("Wait ");
// Check semaphore
if (transfer->semaphore > 0) {
transfer->semaphore--;
commandState->state = SBC_STATE_WRITE;
}
break;
//-------------------
case SBC_STATE_WRITE:
//-------------------
// Check the result code of the read operation
if (transfer->status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Write10: Failed to received data\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_HARDWARE_ERROR,
0,
0);
result = MSDD_STATUS_ERROR;
}
else {
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
// Write the block to the media
status = LUN_Write(lun,
DWORDB(command->pLogicalBlockAddress),
lun->readWriteBuffer,
1,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#else
MSDDriver_Callback(transfer, MED_STATUS_SUCCESS, 0, 0);
status = LUN_STATUS_SUCCESS;
#endif
// Check operation result code
if (status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Write10: Failed to start media write\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NOT_READY,
0,
0);
result = MSDD_STATUS_ERROR;
}
else {
// Prepare next state
commandState->state = SBC_STATE_WAIT_WRITE;
}
}
break;
//------------------------
case SBC_STATE_WAIT_WRITE:
//------------------------
TRACE_INFO_WP("Wait ");
// Check semaphore value
if (transfer->semaphore > 0) {
// Take semaphore and move to next state
transfer->semaphore--;
commandState->state = SBC_STATE_NEXT_BLOCK;
}
break;
//------------------------
case SBC_STATE_NEXT_BLOCK:
//------------------------
// Check operation result code
if (transfer->status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Write10: Failed to write media\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_RECOVERED_ERROR,
SBC_ASC_TOO_MUCH_WRITE_DATA,
0);
result = MSDD_STATUS_ERROR;
}
else {
// Update transfer length and block address
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
commandState->length--;
#else
commandState->length = 0;
#endif
STORE_DWORDB(DWORDB(command->pLogicalBlockAddress) + 1,
command->pLogicalBlockAddress);
// Check if transfer is finished
if (commandState->length == 0) {
result = MSDD_STATUS_SUCCESS;
}
else {
commandState->state = SBC_STATE_READ;
}
}
break;
}
}
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
// Convert length from blocks to bytes
commandState->length *= lun->blockSize;
#endif
return result;
}
//------------------------------------------------------------------------------
//! \brief Performs a READ (10) command on specified LUN.
//!
//! The data is first read from the media and then sent to the USB host.
//! This function operates asynchronously and must be called multiple
//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
//! indicates that at least another call of the method is necessary.
//! \param lun Pointer to the LUN affected by the command
//! \param commandState Current state of the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see MSDLun
//! \see MSDCommandState
//------------------------------------------------------------------------------
static unsigned char SBC_Read10(MSDLun *lun,
MSDCommandState *commandState)
{
unsigned char status;
unsigned char result = MSDD_STATUS_INCOMPLETE;
SBCRead10 *command = (SBCRead10 *) commandState->cbw.pCommand;
MSDTransfer *transfer = &(commandState->transfer);
// Init command state
if (commandState->state == 0) {
commandState->state = SBC_STATE_READ;
}
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
// Convert length from bytes to blocks
commandState->length /= lun->blockSize;
#endif
// Check length
if (commandState->length == 0) {
result = MSDD_STATUS_SUCCESS;
}
else {
// Command state management
switch (commandState->state) {
//------------------
case SBC_STATE_READ:
//------------------
// Read one block of data from the media
#if !defined(AT91C_EBI_SDRAM) && !defined(BOARD_USB_UDPHS)
status = LUN_Read(lun,
DWORDB(command->pLogicalBlockAddress),
lun->readWriteBuffer,
1,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#else
MSDDriver_Callback(transfer, MED_STATUS_SUCCESS, 0, 0);
status = LUN_STATUS_SUCCESS;
#endif
// Check operation result code
if (status != LUN_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Read10: Failed to start reading media\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NOT_READY,
SBC_ASC_LOGICAL_UNIT_NOT_READY,
0);
result = MSDD_STATUS_ERROR;
}
else {
// Move to next command state
commandState->state = SBC_STATE_WAIT_READ;
}
break;
//-----------------------
case SBC_STATE_WAIT_READ:
//-----------------------
// Check semaphore value
if (transfer->semaphore > 0) {
TRACE_INFO_WP("Ok ");
// Take semaphore and move to next state
transfer->semaphore--;
commandState->state = SBC_STATE_WRITE;
}
break;
//-------------------
case SBC_STATE_WRITE:
//-------------------
// Check the operation result code
if (transfer->status != USBD_STATUS_SUCCESS) {
TRACE_WARNING(
"RBC_Read10: Failed to read media\n\r");
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_RECOVERED_ERROR,
SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
0);
result = MSDD_STATUS_ERROR;
}
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -