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

📄 sbcmethods.c

📁 Include startup files and peripherial devices Code for Atmel ARM7 development
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ----------------------------------------------------------------------------
 *         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 + -