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

📄 lun.c

📁 This software package contains the USB framework core developped by ATMEL, as well as a Mass stora
💻 C
字号:
/* ----------------------------------------------------------------------------
 *         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: lun.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 "msd.h"
#include "media.h"
#include "sbc.h"
#include "lun.h"

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

//! \brief  Inquiry data used to describe the device
//! \see    S_sbc_inquiry_data
static S_sbc_inquiry_data sInquiryData = {

    SBC_DIRECT_ACCESS_BLOCK_DEVICE,  // Direct-access block device
    SBC_PERIPHERAL_DEVICE_CONNECTED, // Peripheral device is connected
    0x00,                            // Reserved bits
    0x01,                            // Media is removable
    SBC_SPC_VERSION_4,               // SPC-4 supported
    0x2,                             // Response data format, must be 0x2
    false,                           // Hierarchical addressing not supported
    false,                           // ACA not supported
    0x0,                             // Obsolete bits
    sizeof(S_sbc_inquiry_data) - 5,  // Additional length
    false,                           // No embedded SCC
    false,                           // No access control coordinator
    SBC_TPGS_NONE,                   // No target port support group
    false,                           // Third-party copy not supported
    0x0,                             // Reserved bits
    false,                           // Protection information not supported
    0x0,                             // Obsolete bit
    false,                           // No embedded enclosure service component
    0x0,                             // ???
    false,                           // Device is not multi-port
    0x0,                             // Obsolete bits
    0x0,                             // Unused feature
    0x0,                             // Unused features
    false,                           // Task management model not supported
    0x0,                             // ???
    'A','T','M','E','L',' ',' ',' ',
    'M','a','s','s',' ','S','t','o','r','a','g','e',' ','M','S','D',
    '0','.','0','1',
    'M','a','s','s',' ','S','t','o','r','a','g','e',' ','E','x','a','m','p','l','e',
    0x00,                            // Unused features
    0x00,                            // Reserved bits
    SBC_VERSION_DESCRIPTOR_SBC_3,    // SBC-3 compliant device
    // Reserved
};

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief  Initializes a LUN instance.
//! \param  pLun         Pointer to the S_lun instance to initialize
//! \param  pMedia       Media on which the LUN is constructed
//! \param  pBuffer      Pointer to a buffer used for read/write operation and
//!                      which must be dBlockSize bytes long.
//! \param  dBaseAddress Base address of the LUN on the media
//! \param  dSize        Total size of the LUN in bytes
//! \param  dBlockSize   Length of one block of the LUN
//------------------------------------------------------------------------------
void LUN_Init(S_lun         *pLun,
              S_media       *pMedia,
              unsigned char *pBuffer,
              unsigned int  dBaseAddress,
              unsigned int  dSize,
              unsigned int  dBlockSize)
{
    unsigned int dLogicalBlockAddress = (dSize / dBlockSize) - 1;
    TRACE_INFO("I: LUN init\n\r");

    // Initialize LUN
    pLun->pMedia = pMedia;
    pLun->dBaseAddress = dBaseAddress;
    pLun->dSize = dSize;
    pLun->dBlockSize = dBlockSize;
    pLun->pReadWriteBuffer = pBuffer;

    // Initialize request sense data
    pLun->sRequestSenseData.bResponseCode = SBC_SENSE_DATA_FIXED_CURRENT;
    pLun->sRequestSenseData.isValid = true;
    pLun->sRequestSenseData.bObsolete1 = 0;
    pLun->sRequestSenseData.bSenseKey = SBC_SENSE_KEY_NO_SENSE;
    pLun->sRequestSenseData.bReserved1 = 0;
    pLun->sRequestSenseData.isILI = false;
    pLun->sRequestSenseData.isEOM = false;
    pLun->sRequestSenseData.isFilemark = false;
    pLun->sRequestSenseData.pInformation[0] = 0;
    pLun->sRequestSenseData.pInformation[1] = 0;
    pLun->sRequestSenseData.pInformation[2] = 0;
    pLun->sRequestSenseData.pInformation[3] = 0;
    pLun->sRequestSenseData.bAdditionalSenseLength
        = sizeof(S_sbc_request_sense_data) - 8;
    pLun->sRequestSenseData.bAdditionalSenseCode = 0;
    pLun->sRequestSenseData.bAdditionalSenseCodeQualifier = 0;
    pLun->sRequestSenseData.bFieldReplaceableUnitCode = 0;
    pLun->sRequestSenseData.bSenseKeySpecific = 0;
    pLun->sRequestSenseData.pSenseKeySpecific[0] = 0;
    pLun->sRequestSenseData.pSenseKeySpecific[0] = 0;
    pLun->sRequestSenseData.isSKSV = false;

    // Initialize inquiry data
    pLun->pInquiryData = &sInquiryData;

    // Initialize read capacity data
    STORE_DWORDB(dLogicalBlockAddress,
                 pLun->sReadCapacityData.pLogicalBlockAddress);
    STORE_DWORDB(dBlockSize, pLun->sReadCapacityData.pLogicalBlockLength);
}

//------------------------------------------------------------------------------
//! \brief  Writes data on the a LUN starting at the specified block address.
//! \param  pLUN          Pointer to a S_lun instance
//! \param  dBlockAddress First block address to write
//! \param  pData         Pointer to the data to write
//! \param  dLength       Number of blocks to write
//! \param  fCallback     Optional callback to invoke when the write finishes
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char LUN_Write(S_lun        *pLun,
                        unsigned int dBlockAddress,
                        void         *pData,
                        unsigned int dLength,
                        Callback_f   fCallback,
                        void         *pArgument)
{
    unsigned int  dAddress;
    unsigned char bStatus;

    TRACE_DEBUG_M("LUNWrite(%d) ", dBlockAddress);

    // Check that the data is not too big
    if ((dLength * pLun->dBlockSize)
        > (pLun->dSize - pLun->dBlockSize * dBlockAddress)) {

        TRACE_WARNING("W: LUN_Write: Data too big\n\r");
        bStatus = USB_STATUS_ABORTED;
    }
    else {

        // Compute write start address
        dAddress = pLun->pMedia->dBaseAddress
                   + pLun->dBaseAddress
                   + dBlockAddress * pLun->dBlockSize;

        // Start write operation
        bStatus = MED_Write(pLun->pMedia,
                            dAddress,
                            pData,
                            dLength * pLun->dBlockSize,
                            (Callback_f) fCallback,
                            pArgument);

        // Check operation result code
        if (bStatus == MED_STATUS_SUCCESS) {

            bStatus = USB_STATUS_SUCCESS;
        }
        else {

            TRACE_WARNING("W: LUN_Write: Cannot write media\n\r");
            bStatus = USB_STATUS_ABORTED;
        }
    }

    return bStatus;
}

//------------------------------------------------------------------------------
//! \brief  Reads data from a LUN, starting at the specified block address.
//! \param  pLUN          Pointer to a S_lun instance
//! \param  dBlockAddress First block address to read
//! \param  pData         Pointer to a data buffer in which to store the data
//! \param  dLength       Number of blocks to read
//! \param  fCallback     Optional callback to invoke when the read finishes
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char LUN_Read(S_lun        *pLun,
                       unsigned int dBlockAddress,
                       void         *pData,
                       unsigned int dLength,
                       Callback_f   fCallback,
                       void         *pArgument)
{
    unsigned int dAddress;
    unsigned char bStatus;

    // Check that the data is not too big
    if ((dLength * pLun->dBlockSize)
        > (pLun->dSize - pLun->dBlockSize * dBlockAddress)) {

        TRACE_WARNING("W: LUN_Read: Data too big\n\r");
        bStatus = USB_STATUS_ABORTED;
    }
    else {

        TRACE_DEBUG_M("LUNRead(%d) ", dBlockAddress);

        // Compute read start address
        dAddress = pLun->pMedia->dBaseAddress
                   + pLun->dBaseAddress
                   + dBlockAddress * pLun->dBlockSize;

        // Start write operation
        bStatus = MED_Read(pLun->pMedia,
                           dAddress,
                           pData,
                           dLength * pLun->dBlockSize,
                           (Callback_f) fCallback,
                           pArgument);

        // Check result code
        if (bStatus == MED_STATUS_SUCCESS) {

            bStatus = USB_STATUS_SUCCESS;
        }
        else {

            TRACE_WARNING("W: LUN_Read: Cannot read media\n\r");
            bStatus = USB_STATUS_ABORTED;
        }
    }

    return bStatus;
}

⌨️ 快捷键说明

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