⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbc_methods.c

📁 This software package contains the USB framework core developped by ATMEL, as well as a Mass stora
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
 * ----------------------------------------------------------------------------
 * Copyright (c) 2006, 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 disclaiimer below.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer below in the documentation and/or
 * other materials provided with the distribution.
 *
 * 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.
 * ----------------------------------------------------------------------------
 */

/*
$Id: sbc_methods.c 198 2006-10-30 10:01:09Z jjoannic $
*/

//------------------------------------------------------------------------------
//      Includes
//------------------------------------------------------------------------------

#include "core/common.h"
#include "core/device.h"
#include "core/board.h"
#include "core/trace.h"
#include "core/usb.h"
#include "core/standard.h"

#include "msd.h"
#include "media.h"
#include "sbc.h"
#include "lun.h"
#include "bot_driver.h"
#include "sbc_methods.h"

//------------------------------------------------------------------------------
//      Global variables
//------------------------------------------------------------------------------

//! \brief  Header for the mode pages data
//! \see    S_sbc_mode_parameter_header_6
static const S_sbc_mode_parameter_header_6 sModeParameterHeader6 = {

    sizeof(S_sbc_mode_parameter_header_6) - 1,  //!< Length of mode page data is 0x03
    SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE, //!< Direct-access block device
    0,                                          //!< Reserved bits
    false,                                      //!< DPO/FUA not supported
    0,                                          //!< Reserved bits
    false,                                      //!< Medium is 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 BOT_STATUS_INCOMPLETE indicates
//!         that at least another call of the method is necessary.
//! \param  pUsb          Pointer to a S_usb instance
//! \param  pLun          Pointer to the LUN affected by the command
//! \param  pCommandState Current state of the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see    S_usb
//! \see    S_lun
//! \see    S_bot_command_state
//------------------------------------------------------------------------------
static unsigned char SBC_Write10(const S_usb         *pUsb,
                                 S_lun               *pLun,
                                 S_bot_command_state *pCommandState)
{
    unsigned char  bStatus;
    unsigned char  bResult = BOT_STATUS_INCOMPLETE;
    S_bot_transfer *pTransfer = &(pCommandState->sTransfer);
    S_sbc_write_10 *pCommand = (S_sbc_write_10 *) pCommandState->sCbw.pCommand;

    // Init command state
    if (pCommandState->bState == 0) {

        pCommandState->bState = SBC_STATE_READ;
    }

    // Convert pLength from bytes to blocks
    pCommandState->dLength /= pLun->dBlockSize;

    // Check if pLength equals 0
    if (pCommandState->dLength == 0) {

        TRACE_DEBUG_M("End ");
        bResult = BOT_STATUS_SUCCESS;
    }
    else {

        // Current command status
        switch (pCommandState->bState) {
        //------------------
        case SBC_STATE_READ:
        //------------------
            TRACE_DEBUG_M("Receive ");
            // Read one block of data sent by the host
            bStatus = USB_Read(pUsb,
                               BOT_EPT_BULK_OUT,
                               pLun->pReadWriteBuffer,
                               pLun->dBlockSize,
                               (Callback_f) BOT_Callback,
                               (void *) pTransfer);

            // Check operation result code
            if (bStatus != USB_STATUS_SUCCESS) {

                TRACE_WARNING("W: RBC_Write10: Failed to start receiving data\n\r");
                SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                    SBC_SENSE_KEY_HARDWARE_ERROR,
                                    0,
                                    0);
                bResult = BOT_STATUS_ERROR;
            }
            else {

                // Prepare next device state
                pCommandState->bState = SBC_STATE_WAIT_READ;
            }
            break;

        //-----------------------
        case SBC_STATE_WAIT_READ:
        //-----------------------
            TRACE_DEBUG_M("Wait ");

            // Check semaphore
            if (pTransfer->bSemaphore > 0) {

                pTransfer->bSemaphore--;
                pCommandState->bState = SBC_STATE_WRITE;
            }
            break;

        //-------------------
        case SBC_STATE_WRITE:
        //-------------------
            // Check the result code of the read operation
            if (pTransfer->bStatus != USB_STATUS_SUCCESS) {

                TRACE_WARNING("W: RBC_Write10: Failed to received data\n\r");
                SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                    SBC_SENSE_KEY_HARDWARE_ERROR,
                                    0,
                                    0);
                bResult = BOT_STATUS_ERROR;
            }
            else {

                // Write the block to the media
                bStatus = LUN_Write(pLun,
                                    DWORDB(pCommand->pLogicalBlockAddress),
                                    pLun->pReadWriteBuffer,
                                    1,
                                    (Callback_f) BOT_Callback,
                                    (void *) pTransfer);

                // Check operation result code
                if (bStatus != USB_STATUS_SUCCESS) {

                    TRACE_WARNING("W: RBC_Write10: Failed to start media write\n\r");
                    SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                        SBC_SENSE_KEY_NOT_READY,
                                        0,
                                        0);
                    bResult = BOT_STATUS_ERROR;
                }
                else {

                    // Prepare next state
                    pCommandState->bState = SBC_STATE_WAIT_WRITE;
                }
            }
            break;

        //------------------------
        case SBC_STATE_WAIT_WRITE:
        //------------------------
            TRACE_DEBUG_M("Wait ");

            // Check semaphore value
            if (pTransfer->bSemaphore > 0) {

                // Take semaphore and move to next state
                pTransfer->bSemaphore--;
                pCommandState->bState = SBC_STATE_NEXT_BLOCK;
            }
            break;

        //------------------------
        case SBC_STATE_NEXT_BLOCK:
        //------------------------
            // Check operation result code
            if (pTransfer->bStatus != USB_STATUS_SUCCESS) {

                TRACE_WARNING("W: RBC_Write10: Failed to write media\n\r");
                SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                    SBC_SENSE_KEY_RECOVERED_ERROR,
                                    SBC_ASC_TOO_MUCH_WRITE_DATA,
                                    0);
                bResult = BOT_STATUS_ERROR;
            }
            else {

                // Update transfer length and block address
                pCommandState->dLength--;
                STORE_DWORDB(DWORDB(pCommand->pLogicalBlockAddress) + 1,
                             pCommand->pLogicalBlockAddress);

                // Check if transfer is finished
                if (pCommandState->dLength == 0) {

                    bResult = BOT_STATUS_SUCCESS;
                }
                else {

                    pCommandState->bState = SBC_STATE_READ;
                }
            }
            break;
        }
    }

    // Convert dLength from blocks to bytes
    pCommandState->dLength *= pLun->dBlockSize;

    return bResult;
}

//------------------------------------------------------------------------------
//! \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 BOT_STATUS_INCOMPLETE indicates
//!         that at least another call of the method is necessary.
//! \param  pUsb          Pointer to a S_usb instance
//! \param  pLun          Pointer to the LUN affected by the command
//! \param  pCommandState Current state of the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see    S_usb
//! \see    S_lun
//! \see    S_bot_command_state
//------------------------------------------------------------------------------
static unsigned char SBC_Read10(const S_usb         *pUsb,
                                S_lun               *pLun,
                                S_bot_command_state *pCommandState)
{
    unsigned char bStatus;
    unsigned char bResult = BOT_STATUS_INCOMPLETE;
    S_sbc_read_10 *pCommand = (S_sbc_read_10 *) pCommandState->sCbw.pCommand;
    S_bot_transfer *pTransfer = &(pCommandState->sTransfer);

    // Init command state
    if (pCommandState->bState == 0) {

        pCommandState->bState = SBC_STATE_READ;
    }

    // Convert dLength from bytes to blocks
    pCommandState->dLength /= pLun->dBlockSize;

    // Check length
    if (pCommandState->dLength == 0) {

        bResult = BOT_STATUS_SUCCESS;
    }
    else {

        // Command state management
        switch (pCommandState->bState) {
        //------------------
        case SBC_STATE_READ:
        //------------------
            // Read one block of data from the media
            bStatus = LUN_Read(pLun,
                               DWORDB(pCommand->pLogicalBlockAddress),
                               pLun->pReadWriteBuffer,
                               1,
                               (Callback_f) BOT_Callback,
                               (void *) pTransfer);

            // Check operation result code
            if (bStatus != LUN_STATUS_SUCCESS) {

                TRACE_WARNING("W: RBC_Read10: Failed to start reading media\n\r");
                SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                    SBC_SENSE_KEY_NOT_READY,
                                    SBC_ASC_LOGICAL_UNIT_NOT_READY,
                                    0);
                bResult = BOT_STATUS_ERROR;
            }
            else {

                // Move to next command state
                pCommandState->bState = SBC_STATE_WAIT_READ;
            }
            break;

        //-----------------------
        case SBC_STATE_WAIT_READ:
        //-----------------------
            // Check semaphore value
            if (pTransfer->bSemaphore > 0) {

                TRACE_DEBUG_M("Ok ");

                // Take semaphore and move to next state
                pTransfer->bSemaphore--;
                pCommandState->bState = SBC_STATE_WRITE;
            }
            break;

        //-------------------
        case SBC_STATE_WRITE:
        //-------------------
            // Check the operation result code
            if (pTransfer->bStatus != USB_STATUS_SUCCESS) {

                TRACE_WARNING("W: RBC_Read10: Failed to read media\n\r");
                SBC_UpdateSenseData(&(pLun->sRequestSenseData),
                                    SBC_SENSE_KEY_RECOVERED_ERROR,
                                    SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                                    0);
                bResult = BOT_STATUS_ERROR;
            }
            else {

                // Send the block to the host
                bStatus = USB_Write(pUsb,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -