📄 lun.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 + -