From b24866225a6301d3a663f874725e83c012dc25d3 Mon Sep 17 00:00:00 2001 From: Florent Duchon Date: Wed, 26 Dec 2012 17:36:00 +0100 Subject: digital/beacon: add bitcloud stack into common directory digital/zigbit --- .../USBClasses/MSD/include/abstractMemory.h | 83 +++ .../HAL/drivers/USBClasses/MSD/include/mem.h | 106 ++++ .../drivers/USBClasses/MSD/include/mscProtocol.h | 79 +++ .../drivers/USBClasses/MSD/include/scsiProtocol.h | 114 ++++ .../drivers/USBClasses/MSD/src/abstractMemory.c | 225 ++++++++ .../drivers/USBClasses/MSD/src/massStorageDevice.c | 327 +++++++++++ .../HAL/drivers/USBClasses/MSD/src/mmc.c | 618 +++++++++++++++++++++ .../HAL/drivers/USBClasses/MSD/src/mscProtocol.c | 53 ++ .../HAL/drivers/USBClasses/MSD/src/scsiProtocol.c | 398 +++++++++++++ 9 files changed, 2003 insertions(+) create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c (limited to 'digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD') diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h new file mode 100644 index 00000000..2eab5f00 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h @@ -0,0 +1,83 @@ +/****************************************************************************//** + \file abstactMemory.h + + \brief Declaration of abstract memory commands. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +#ifndef _ABSTRACT_MEMORY_H +#define _ABSTRACT_MEMORY_H + +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include + +/****************************************************************************** + Types section +******************************************************************************/ +typedef enum +{ + memorySuccessStatus, + memoryErrorStatus +} MemoryStatus_t; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +/**************************************************************************//** +\brief Writes data to memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of blocks to write. + callback - pointer to function to nofity upper layer about end of write + procedure. +\return + status of write procedure. +******************************************************************************/ +MemoryStatus_t absMemWrite(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t)); + +/**************************************************************************//** +\brief Reads data from memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of blocks to read. + callback - pointer to function to nofity upper layer about end of read + procedure. +\return + status of read procedure. +******************************************************************************/ +MemoryStatus_t absMemRead(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t)); + +/**************************************************************************//** +\brief Performs memory initialization. +\param[in] + descriptor - pointer to hsmci descriptor. +\return + status of initialization procedure. +******************************************************************************/ +MemoryStatus_t absMemInit(HAL_HsmciDescriptor_t *descriptor); + +/**************************************************************************//** +\brief Reads memory capacity. +\param[in] + descriptor - pointer to hsmci descriptor. +\param[out] + lastBlockNumber - number of last accessible block of memory. +\return + status of read capacity procedure. +******************************************************************************/ +MemoryStatus_t absMemCapacity(HAL_HsmciDescriptor_t *descriptor, uint32_t *lastBlockNumber); + +#endif /* _ABSTRACT_MEMORY_H */ +// eof abstactMemory.h diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h new file mode 100644 index 00000000..0197f13a --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h @@ -0,0 +1,106 @@ +/****************************************************************************//** + \file mem.h + + \brief Declaration of memory commands. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +#ifndef _MEM_H +#define _MEM_H + +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +// block length +#define STANDARD_BLOCK_LENGTH 512 + +/****************************************************************************** + Types section +******************************************************************************/ +typedef enum +{ + memSuccess, + hsmciError, + voltageError, + commandError, + initTimeoutError, + stateError, + hsmciReadError, + hsmciWriteError, + setMaxFreqError +} MemStatus_t; + +typedef struct +{ + uint32_t lastLogicalBlock; + uint32_t logicalBlockLength; +} MemCapacityInfo_t; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +/**************************************************************************//** +\brief Writes one data block to memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of block to write. +\return + status of write procedure. +******************************************************************************/ +MemStatus_t memWriteBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t)); + +/**************************************************************************//** +\brief Reads one data block from memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of block to read. +\return + status of read procedure. +******************************************************************************/ +MemStatus_t memReadBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t)); + +/**************************************************************************//** +\brief Performs memory initialization. +\param[in] + commandDescr - pointer to hsmci command descriptor. +\return + status of initialization procedure. +******************************************************************************/ +MemStatus_t memInit(HAL_HsmciDescriptor_t *commandDescr); + +/**************************************************************************//** +\brief Reads memory capacity. +\param[in] + descriptor - pointer to hsmci descriptor. +\param[out] + capInfo - pointer to memory capacity structure. +\return + status of read capacity procedure. +******************************************************************************/ +MemStatus_t memGetCapacityInfo(HAL_HsmciDescriptor_t *descriptor, MemCapacityInfo_t *capInfo); + +/**************************************************************************//** +\brief Checks if memory is ready for any data transfer. +\return + false - memory is busy; + true - memory is ready. +******************************************************************************/ +bool memIsBusy(void); + +#endif /* _MEM_H */ +// eof mem.h diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h new file mode 100644 index 00000000..aa5964ad --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h @@ -0,0 +1,79 @@ +/****************************************************************************//** + \file mscProtocol.h + + \brief Declaration of mass storage device protocol command. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +#ifndef _MSCPROTOCOL_H +#define _MSCPROTOCOL_H + +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +// data size in request structure +#define MSC_REQUEST_DATA_SIZE 1 + +// request codes for mass storage class +#define BULK_ONLY_MASS_STORAGE_RESET 0xFF +#define GET_MAX_LUN 0xFE +// maximum size of CBW data +#define CBW_DATA_SIZE 16 + +/****************************************************************************** + Types section +******************************************************************************/ +BEGIN_PACK +typedef struct PACK +{ + UsbRequest_t request; + uint8_t bData[MSC_REQUEST_DATA_SIZE]; +} UsbMscRequest_t; +// MSC command block wrapper (CBW) +typedef struct PACK +{ + uint32_t dCBWSignature; + uint32_t cDBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[CBW_DATA_SIZE]; +} MscCBW_t; +// MSC command status wrapper (CSW) +typedef struct PACK +{ + uint32_t dCSWSignature; + uint32_t cDSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +} MscCSW_t; +END_PACK + +/****************************************************************************** + Prototypes section +******************************************************************************/ +/**************************************************************************//** +\brief Mass storage device request handler. +\param[in] + data - pointer to host's request. +******************************************************************************/ +void msdRequestHandler(uint8_t *data); + +#endif /* _MSCPROTOCOL_H */ +// eof msdProtocol.h \ No newline at end of file diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h new file mode 100644 index 00000000..6a10b4dc --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h @@ -0,0 +1,114 @@ +/****************************************************************************//** + \file scsiProtocol.h + + \brief Declaration of scsi protocol commands. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +#ifndef _SCSIPROTOCOL_H +#define _SCSIPROTOCOL_H + +/****************************************************************************** + Includes section +******************************************************************************/ +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +// Maximum response length for scsi command +#define MAX_COMMAND_RESPONSE_LENGTH 36 + +/****************************************************************************** + Prototypes section +******************************************************************************/ +/**************************************************************************//** +\brief Checks if received scsi command is supported. +\param[in] + data - pointer to received command with parameters. +\return + false - command is not supported; + true - command is supported. +******************************************************************************/ +bool scsiIsValidCommand(uint8_t *data); + +/**************************************************************************//** +\brief Checks if any response or data transfer needed for received + scsi command. +\param[in] + command - received command. +\return + false - response is not needed; + true - response is needed. +******************************************************************************/ +bool scsiIsDataInOutPhaseNeeded(uint8_t *data); + +/**************************************************************************//** +\brief Checks if command is read or write command. +\param[in] + command - received command. +\return + false - command is not read/write command; + true - command is read/write command. +******************************************************************************/ +bool scsiIsReadWriteCommand(uint8_t *data); + +/**************************************************************************//** +\brief Checks if command is read command. +\param[in] + command - received command. +\return + false - command is not read command; + true - command is read command. +******************************************************************************/ +bool scsiIsReadCommand(uint8_t *data); + +/**************************************************************************//** +\brief Blocks for read/write command. +\param[in] + data - pointer to received command with parameters. +\return + number of blocks to read or write from memory. +******************************************************************************/ +uint16_t scsiBlocksAmount(uint8_t *data); + +/**************************************************************************//** +\brief Response for scsi command. +\param[in] + command - received command. +\param[out] + buffer - buffer with scsi command response. +\return + length of response +******************************************************************************/ +uint8_t scsiGetCommandResponse(uint8_t *data, uint8_t *buffer); + +/**************************************************************************//** +\brief Sets number of last available memory block for scsi response. +\param[in] + lastBlock - received command. +\param[out] + buffer - number of last available memory block +******************************************************************************/ +void scsiSetCapacity(uint32_t lastBlock); + +/**************************************************************************//** +\brief Block address for read/write command. +\param[in] + data - pointer to received command with parameters. +\return + block address for read or write from memory. +******************************************************************************/ +uint32_t scsiGetBlockAddress(uint8_t *data); + +#endif /* _SCSIPROTOCOL_H */ +// eof scsiProtocol.h diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c new file mode 100644 index 00000000..dc11be63 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c @@ -0,0 +1,225 @@ +/****************************************************************************//** + \files abstractMemory.c + + \brief Implementation of amstract memory commands. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 30/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +#define RETRY_COUNT 5 + +/****************************************************************************** + External global variables section +******************************************************************************/ +/****************************************************************************** + Types section +******************************************************************************/ +typedef struct +{ + uint16_t transferLength; + uint16_t blocksToTransfer; + uint32_t logicalBlockAddress; + HAL_HsmciDescriptor_t *hsmciDescriptor; + uint8_t *dataBuffer; +} AbsMemInternal_t; + +/****************************************************************************** + Global variables section +******************************************************************************/ +static void (*absMemCallback)(MemoryStatus_t status); +static AbsMemInternal_t apsMemInternal; + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief Current memory read callback. +\param[in] + status - status of read operation. +******************************************************************************/ +void absMemReadBlockCallback(MemStatus_t status) +{ + uint8_t i = RETRY_COUNT; + apsMemInternal.blocksToTransfer--; + uint16_t blocksRemaining = apsMemInternal.transferLength - apsMemInternal.blocksToTransfer; + HAL_HsmciDescriptor_t *descriptor = apsMemInternal.hsmciDescriptor; + + if (memSuccess != status) + absMemCallback(memoryErrorStatus); + if (0 == apsMemInternal.blocksToTransfer) + { + descriptor->dataTransferDescriptor->buffer = apsMemInternal.dataBuffer; + absMemCallback(memorySuccessStatus); + return; + } + + descriptor->dataTransferDescriptor->buffer += blocksRemaining * STANDARD_BLOCK_LENGTH; + + while(i--) + { + if (memSuccess == memReadBlock(descriptor, apsMemInternal.logicalBlockAddress + blocksRemaining, absMemReadBlockCallback)) + break; + } + if (0 == i) + absMemCallback(memoryErrorStatus); +} + +/**************************************************************************//** +\brief Current memory write callback. +\param[in] + status - status of write operation. +******************************************************************************/ +void absMemWriteBlockCallback(MemStatus_t status) +{ + uint8_t i = RETRY_COUNT; + apsMemInternal.blocksToTransfer--; + uint16_t blocksRemaining = apsMemInternal.transferLength - apsMemInternal.blocksToTransfer; + HAL_HsmciDescriptor_t *descriptor = apsMemInternal.hsmciDescriptor; + + if (memSuccess != status) + absMemCallback(memoryErrorStatus); + if (0 == apsMemInternal.blocksToTransfer) + { + descriptor->dataTransferDescriptor->buffer = apsMemInternal.dataBuffer; + absMemCallback(memorySuccessStatus); + return; + } + + descriptor->dataTransferDescriptor->buffer += blocksRemaining * STANDARD_BLOCK_LENGTH; + + while(i--) + { + if (memSuccess == memWriteBlock(descriptor, apsMemInternal.logicalBlockAddress + blocksRemaining, absMemWriteBlockCallback)) + break; + } + if (0 == i) + absMemCallback(memoryErrorStatus); +} + +/**************************************************************************//** +\brief Performs memory initialization. +\param[in] + descriptor - pointer to hsmci descriptor. +\return + status of initialization procedure. +******************************************************************************/ +MemoryStatus_t absMemInit(HAL_HsmciDescriptor_t *descriptor) +{ + if (memSuccess != memInit(descriptor)) + return memoryErrorStatus; + + return memorySuccessStatus; +} + +/**************************************************************************//** +\brief Reads memory capacity. +\param[in] + descriptor - pointer to hsmci descriptor. +\param[out] + lastBlockNumber - number of last accessible block of memory. +\return + status of read capacity procedure. +******************************************************************************/ +MemoryStatus_t absMemCapacity(HAL_HsmciDescriptor_t *descriptor, uint32_t *lastBlockNumber) +{ + MemCapacityInfo_t capInfo; + uint8_t i = RETRY_COUNT; + MemStatus_t status; + + while(i--) + { + status = memGetCapacityInfo(descriptor, &capInfo); + if (memSuccess == status) + { + *lastBlockNumber = capInfo.lastLogicalBlock; + return memorySuccessStatus; + } + } + + return memoryErrorStatus; +} + +/**************************************************************************//** +\brief Writes data to memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of blocks to write. + callback - pointer to function to nofity upper layer about end of write + procedure. +\return + status of write procedure. +******************************************************************************/ +MemoryStatus_t absMemWrite(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t)) +{ + HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor; + uint8_t i; + absMemCallback = callback; + + apsMemInternal.logicalBlockAddress = address; + apsMemInternal.transferLength = dataDescr->length / STANDARD_BLOCK_LENGTH; + apsMemInternal.blocksToTransfer = apsMemInternal.transferLength; + apsMemInternal.dataBuffer = descriptor->dataTransferDescriptor->buffer; + + dataDescr->length = STANDARD_BLOCK_LENGTH; + + i = RETRY_COUNT; + while(i--) + { + if (memSuccess == memWriteBlock(descriptor, address, absMemWriteBlockCallback)) + return memorySuccessStatus; + } + + return memoryErrorStatus; +} + +/**************************************************************************//** +\brief Reads data from memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of blocks to read. + callback - pointer to function to nofity upper layer about end of read + procedure. +\return + status of read procedure. +******************************************************************************/ +MemoryStatus_t absMemRead(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t)) +{ + HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor; + uint8_t i; + absMemCallback = callback; + + apsMemInternal.logicalBlockAddress = address; + apsMemInternal.transferLength = dataDescr->length / STANDARD_BLOCK_LENGTH; + apsMemInternal.blocksToTransfer = apsMemInternal.transferLength; + apsMemInternal.dataBuffer = descriptor->dataTransferDescriptor->buffer; + + dataDescr->length = STANDARD_BLOCK_LENGTH; + + i = RETRY_COUNT; + while(i--) + { + if (memSuccess == memReadBlock(descriptor, address, absMemReadBlockCallback)) + return memorySuccessStatus; + } + + return memoryErrorStatus; +} + +//eof abstractMemory.c diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c new file mode 100644 index 00000000..94c36c42 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c @@ -0,0 +1,327 @@ +/****************************************************************************//** + \file massStorageDevice.c + + \brief Implementation of mass storage API. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + Defines section +******************************************************************************/ +#define CBW_SIZE 31 +#define CBW_SIGNATURE 0x43425355 + +#define CSW_SIZE 13 +#define CSW_COMMAND_FAILED_STATUS 1 +#define CSW_COMMAND_SUCCESS_STATUS 0 + +/****************************************************************************** + Types section +******************************************************************************/ +typedef enum +{ + MSD_COMMAND_TRANSPORT, + MSD_SCSI_ANSWER, + MSD_DATA_INOUT, + MSD_STATUS_TRANSPORT +} MsdState_t; + +typedef struct +{ + uint32_t bufferOffset; + uint16_t buffersToTransfer; + uint32_t blockAddress; +} MsdReadWriteControl_t; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +static void msdBufferReadCallback(MemoryStatus_t status); +static void msdBufferWriteCallback(MemoryStatus_t status); + +/****************************************************************************** + External global variables section +******************************************************************************/ +static UsbMscRequest_t request; + +/****************************************************************************** + Global variables section +******************************************************************************/ +// pointer to application hsmci descriptor +static HAL_HsmciDescriptor_t msdDescr; +HAL_HsmciDescriptor_t *msdPointDescr; +static HAL_HsmciCommandDescriptor_t commandDescr; +static HAL_HsmciDataTransferDescriptor_t dataTransferDescr; +static MsdReadWriteControl_t rwControl; +static MscCSW_t csw; +static MsdState_t msdState; +static MSD_Callback_t msdCallback = NULL; + +void msdRcvCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining); + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief Transmitting callback of usb. +\param[in] + pArg - pointer to some data; + status - result of the USB transfer.; + transferred - how much data are transferred; + remaining - how much data are not transferred. +******************************************************************************/ +void msdTmtCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + (void)pArg; + (void)status; + (void)remaining; + (void)transferred; + + if (MSD_DATA_INOUT == msdState) + { + rwControl.buffersToTransfer--; + rwControl.blockAddress += msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH; + if (0 == rwControl.buffersToTransfer) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + else + if (memorySuccessStatus != absMemRead(&msdDescr, rwControl.blockAddress, msdBufferReadCallback)) + msdCallback(MSD_READ_ERROR); + + } + if (MSD_SCSI_ANSWER == msdState) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + if (MSD_STATUS_TRANSPORT == msdState) + { + if (msdCallback) + msdCallback(MSD_STATUS_SUCCESS); + msdState = MSD_COMMAND_TRANSPORT; + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, CBW_SIZE, msdRcvCallback, NULL); + return; + } +} + +/**************************************************************************//** +\brief Receiving callback of usb. +\param[in] + pArg - pointer to some data; + status - result of the USB transfer.; + transferred - how much data are transferred; + remaining - how much data are not transferred. +******************************************************************************/ +void msdRcvCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + bool validAndMeaningful = true; + MscCBW_t *cbw = (MscCBW_t *)(msdDescr.dataTransferDescriptor->buffer); + uint8_t length; + + (void)pArg; + (void)status; + (void)remaining; + + if (MSD_COMMAND_TRANSPORT == msdState) + { + /* check that CBW is valid */ + if ((CBW_SIZE != transferred) || (CBW_SIGNATURE != cbw->dCBWSignature)) + validAndMeaningful = false; + if (!validAndMeaningful) + { + HAL_Stall(ADDRESS_MSC_BULKIN_PIPE & 0x03); + return; + } + /* check that CBW is meaningful */ + if ((cbw->bCBWLUN > 0x0F) || (cbw->bCBWCBLength == 0) || (cbw->bCBWCBLength > 0x10) || (cbw->bmCBWFlags & 0x7F)) + validAndMeaningful = false; + if (!validAndMeaningful) + return; + /* fill csw with parameters from cbw */ + csw.cDSWTag = cbw->cDBWTag; + csw.dCSWSignature = CBW_SIGNATURE; + /* check that command is valid */ + if (!scsiIsValidCommand(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_FAILED_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + /* check that no data in-out phase is needed */ + if (!scsiIsDataInOutPhaseNeeded(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + /* check that command is no read-write command */ + if (!scsiIsReadWriteCommand(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_SCSI_ANSWER; + length = scsiGetCommandResponse(cbw->CBWCB, msdDescr.dataTransferDescriptor->buffer); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, length, msdTmtCallback, NULL); + return; + } + /* check that command is read command */ + rwControl.buffersToTransfer = scsiBlocksAmount(cbw->CBWCB) * (msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH); + rwControl.blockAddress = scsiGetBlockAddress(cbw->CBWCB); + if (scsiIsReadCommand(cbw->CBWCB)) + { + if (memorySuccessStatus != absMemRead(&msdDescr, rwControl.blockAddress, msdBufferReadCallback)) + msdCallback(MSD_READ_ERROR); + } + else + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, + BULK_SIZE, msdRcvCallback, NULL); + msdState = MSD_DATA_INOUT; + return; + } + if (MSD_DATA_INOUT == msdState) + { + /* increase internal write buffer offset*/ + rwControl.bufferOffset += transferred; + /* if buffer is full perform write to flash */ + if (rwControl.bufferOffset == msdDescr.dataTransferDescriptor->length) + { + if (memorySuccessStatus != absMemWrite(&msdDescr, rwControl.blockAddress, msdBufferWriteCallback)) + msdCallback(MSD_WRITE_ERROR); + /* wait for hsmci bus becomes free */ + rwControl.bufferOffset = 0; + rwControl.buffersToTransfer--; + rwControl.blockAddress += msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH; + return; + } + if (0 != rwControl.buffersToTransfer) + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer + rwControl.bufferOffset, + BULK_SIZE, msdRcvCallback, NULL); + + } +} + +/**************************************************************************//** +\brief Opens mass storage device. +\param[in] + callback - pointer to function to notify about MSD errors and transactions; + responseBuffer - pointer to hsmci command response buffer; it should have + a size of four; + buffer - pointer to buffer for hsmci data transfer; it should be + a multiplier of 512; + length - length of buffer for data transfer. +******************************************************************************/ +void MSD_Open(MSD_Callback_t callback, uint32_t *responseBuffer, uint8_t *buffer, uint32_t length) +{ + uint32_t lastBlock; + + msdCallback = callback; + + msdDescr.dataTransferDescriptor = &dataTransferDescr; + msdDescr.commandDescriptor = &commandDescr; + msdDescr.dataTransferDescriptor->buffer = buffer; + msdDescr.dataTransferDescriptor->length = length; + msdDescr.commandDescriptor->responseBuffer = responseBuffer; + msdDescr.dataTransferDescriptor->commandDescr = &commandDescr; + + msdPointDescr = & msdDescr; + + if (-1 == HAL_OpenHsmci(&msdDescr)) + if (msdCallback) + msdCallback(MSD_INTERFACE_BUSY); + + if (memorySuccessStatus != absMemInit(&msdDescr)) + if (msdCallback) + msdCallback(MSD_MEMORY_INIT_ERROR); + + if (memorySuccessStatus != absMemCapacity(&msdDescr, &lastBlock)) + if (msdCallback) + msdCallback(MSD_READ_CAPACITY_ERROR); + + scsiSetCapacity(lastBlock); + + rwControl.bufferOffset = 0; + rwControl.buffersToTransfer = 0; + msdState = MSD_COMMAND_TRANSPORT; + csw.dCSWDataResidue = 0; + + HAL_RegisterEndOfBusResetHandler(usbBusResetAction); + if (DEVICE_POWERED != HAL_GetState()) + HAL_UsbInit((uint8_t *)&request); +} + +/**************************************************************************//** +\brief Closes mass storage device. +******************************************************************************/ +void MSD_Close(void) +{ + if (-1 == HAL_CloseHsmci(&msdDescr)) + if (msdCallback) + msdCallback(MSD_INTERFACE_BUSY); +} + +/**************************************************************************//** +\brief Memory read callback function. +\param[in] + status - status of memory read procedure. +******************************************************************************/ +static void msdBufferReadCallback(MemoryStatus_t status) +{ + if (memorySuccessStatus != status) + msdCallback(MSD_READ_ERROR); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, + msdDescr.dataTransferDescriptor->length, msdTmtCallback, NULL); +} + +/**************************************************************************//** +\brief Memory write callback function. +\param[in] + status - status of memory write procedure. +******************************************************************************/ +static void msdBufferWriteCallback(MemoryStatus_t status) +{ + if (memorySuccessStatus != status) + msdCallback(MSD_WRITE_ERROR); + if (0 == rwControl.buffersToTransfer) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + } + else + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, + BULK_SIZE, msdRcvCallback, NULL); +} + +// eof massStorageDevice.c diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c new file mode 100644 index 00000000..b512bd04 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c @@ -0,0 +1,618 @@ +/****************************************************************************//** + \files mmc.c + + \brief Implementation of mmc protocol. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 30/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +// card voltage ranges +#define OCR_VDD_16_17 (1 << 4) +#define OCR_VDD_17_18 (1 << 5) +#define OCR_VDD_18_19 (1 << 6) +#define OCR_VDD_19_20 (1 << 7) +#define OCR_VDD_20_21 (1 << 8) +#define OCR_VDD_21_22 (1 << 9) +#define OCR_VDD_22_23 (1 << 10) +#define OCR_VDD_23_24 (1 << 11) +#define OCR_VDD_24_25 (1 << 12) +#define OCR_VDD_25_26 (1 << 13) +#define OCR_VDD_26_27 (1 << 14) +#define OCR_VDD_27_28 (1 << 15) +#define OCR_VDD_28_29 (1 << 16) +#define OCR_VDD_29_30 (1 << 17) +#define OCR_VDD_30_31 (1 << 18) +#define OCR_VDD_31_32 (1 << 19) +#define OCR_VDD_32_33 (1 << 20) +#define OCR_VDD_33_34 (1 << 21) +#define OCR_VDD_34_35 (1 << 22) +#define OCR_VDD_35_36 (1 << 23) +// R1 response statuses +#define STATUS_APP_CMD (1UL << 5) +#define STATUS_SWITCH_ERROR (1UL << 7) +#define STATUS_READY_FOR_DATA (1UL << 8) +#define STATUS_IDLE (0UL << 9) +#define STATUS_READY (1UL << 9) +#define STATUS_IDENT (2UL << 9) +#define STATUS_STBY (3UL << 9) +#define STATUS_TRAN (4UL << 9) +#define STATUS_DATA (5UL << 9) +#define STATUS_RCV (6UL << 9) +#define STATUS_PRG (7UL << 9) +#define STATUS_DIS (8UL << 9) +#define STATUS_STATE (0xFUL << 9) +#define STATUS_ERASE_RESET (1UL << 13) +#define STATUS_WP_ERASE_SKIP (1UL << 15) +#define STATUS_CIDCSD_OVERWRITE (1UL << 16) +#define STATUS_OVERRUN (1UL << 17) +#define STATUS_UNERRUN (1UL << 18) +#define STATUS_ERROR (1UL << 19) +#define STATUS_CC_ERROR (1UL << 20) +#define STATUS_CARD_ECC_FAILED (1UL << 21) +#define STATUS_ILLEGAL_COMMAND (1UL << 22) +#define STATUS_COM_CRC_ERROR (1UL << 23) +#define STATUS_UN_LOCK_FAILED (1UL << 24) +#define STATUS_CARD_IS_LOCKED (1UL << 25) +#define STATUS_WP_VIOLATION (1UL << 26) +#define STATUS_ERASE_PARAM (1UL << 27) +#define STATUS_ERASE_SEQ_ERROR (1UL << 28) +#define STATUS_BLOCK_LEN_ERROR (1UL << 29) +#define STATUS_ADDRESS_MISALIGN (1UL << 30) +#define STATUS_ADDR_OUT_OR_RANGE (1UL << 31) +// R1 response sets +#define ERROR_STATUS (STATUS_ADDR_OUT_OR_RANGE | STATUS_ADDRESS_MISALIGN | STATUS_BLOCK_LEN_ERROR | STATUS_ERASE_SEQ_ERROR | \ + STATUS_ERASE_PARAM | STATUS_WP_VIOLATION | STATUS_CARD_IS_LOCKED | STATUS_UN_LOCK_FAILED | \ + STATUS_COM_CRC_ERROR | STATUS_ILLEGAL_COMMAND | STATUS_CARD_ECC_FAILED | STATUS_CC_ERROR | STATUS_ERROR | \ + STATUS_UNERRUN | STATUS_OVERRUN | STATUS_CIDCSD_OVERWRITE | STATUS_SWITCH_ERROR) +// command arguments +#define CMD0_IDLE_STATE_ARGUMENT 0 +#define CMD1_ACCESS_MODE_SECTOR (1UL << 30) +#define CMD1_HOST_VOLTAGE_RANGE (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | \ + OCR_VDD_31_32 | OCR_VDD_32_33 | OCR_VDD_33_34 | OCR_VDD_34_35 | \ + OCR_VDD_35_36) +#define CMD2_ARGUMENT 0 +#define CMD6_SET_4_LINE_BUS 0x03B70100 +#define CMD6_SET_HS_MODE 0x03B90100 +// relative card address +#define REVALITE_CARD_ADDRESS (1 << 16) +// command responses length +#define NO_RESPONSE_LENGTH 0 +#define R1_RESPONSE_LENGTH 1 +#define R2_RESPONSE_LENGTH 4 +#define R3_RESPONSE_LENGTH 1 +// retry amount of card initialization +#define RETRY_AMOUNT 10000 +// memory frequency masks for CDS memory register +#define FREQ_UNITS_MASK 0x07 +#define FREQ_MULTIPLIER_MASK 0x78 +#define FREQ_MULTIPLIER_OFFSET 0x03 +// csd register definitions +#define CSD_SPEC_VERS_FOUR 4 + +/****************************************************************************** + External global variables section +******************************************************************************/ +/****************************************************************************** + Types section +******************************************************************************/ +typedef union +{ + uint32_t reg; + struct + { + uint32_t reserved1 : 5; + uint32_t appCmd : 1; + uint32_t urgentBkops : 1; + uint32_t switchError : 1; + uint32_t readyForData : 1; + uint32_t currentState : 4; + uint32_t eraseReset : 1; + uint32_t reserved2 : 1; + uint32_t wpEraseSkip : 1; + uint32_t cidCsdOverwrite : 1; + uint32_t overrun : 1; + uint32_t underrun : 1; + uint32_t error : 1; + uint32_t ccEror : 1; + uint32_t cardEccFailed : 1; + uint32_t illegalCommand : 1; + uint32_t comCrcError : 1; + uint32_t lockUnlockFailed : 1; + uint32_t cardIsLocked : 1; + uint32_t wpViolation : 1; + uint32_t eraseParam : 1; + uint32_t eraseSeqError : 1; + uint32_t blockLenError : 1; + uint32_t addressMisalign : 1; + uint32_t addressOutOfRange: 1; + }; +} MmcCardStatus_t; + +typedef union +{ + uint32_t reg; + struct + { + uint32_t reserverd1 : 7; + uint32_t voltage170_195: 1; + uint32_t voltage20_26 : 7; + uint32_t voltage27_36 : 9; + uint32_t reserved2 : 5; + uint32_t accessMode : 2; + uint32_t busy : 1; + }; +} MmcOcrRegister_t; + +typedef struct +{ + uint8_t tranSpeed; + uint8_t nsac; + uint8_t taac; + uint8_t reserved3 : 2; + uint8_t specVersion : 4; + uint8_t csdStructure : 2; + uint32_t cSizeDown : 10; + uint32_t reserved2 : 2; + uint32_t dsrImp : 1; + uint32_t readBlkMisalign : 1; + uint32_t writeBlkMisalign: 1; + uint32_t readBlPartial : 1; + uint32_t readBlLen : 4; + uint32_t ccc : 12; + uint32_t wpGroupSize : 5; + uint32_t eraseGroupMult : 5; + uint32_t eraseGroupSize : 5; + uint32_t cSizeMult : 3; + uint32_t vddWCurrMax : 3; + uint32_t vddWCurrMin : 3; + uint32_t vddRCurrMax : 3; + uint32_t vddRCurrMin : 3; + uint32_t cSizeUp : 2; + uint8_t notUsed : 1; + uint8_t crc : 7; + uint8_t ecc : 2; + uint8_t fileFormat : 2; + uint8_t tmpWriteProtect : 1; + uint8_t permWriteProtect : 1; + uint8_t copy : 1; + uint8_t fileFormatGroup : 1; + uint16_t contentPropApp : 1; + uint16_t reserved1 : 4; + uint16_t writeBlPartial : 1; + uint16_t writeBlLen : 4; + uint16_t r2wFactor : 3; + uint16_t defaultEcc : 2; + uint16_t wpGroupEnable : 1; +} MmcCSDRegister_t; + +/****************************************************************************** + Constants section +******************************************************************************/ +static const uint32_t mmcFrequencyUnits[8] = {100, 1000, 10000, 100000, 0, 0, 0, 0}; +static const uint32_t mmcFrequencyMulptiplier[16] = {0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80}; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength); +static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state); +static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode); +static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg); +static void (*absMemoryCallback)(MemStatus_t) = NULL; +static HAL_HsmciDescriptor_t *memDescriptor = NULL; + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief HSMCI write callback. +******************************************************************************/ +void memWriteCallback(void) +{ + MmcCardStatus_t *cardStatus; + + cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + absMemoryCallback(hsmciWriteError); + absMemoryCallback(memSuccess); +} + +/**************************************************************************//** +\brief HSMCI read callback. +******************************************************************************/ +void memReadCallback(void) +{ + MmcCardStatus_t *cardStatus; + + cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + absMemoryCallback(hsmciReadError); + absMemoryCallback(memSuccess); +} +/**************************************************************************//** +\brief Performs MMC memory initialization. +\param[in] + commandDescr - pointer to hsmci command descriptor. +\return + status of initialization procedure. +******************************************************************************/ +MemStatus_t memInit(HAL_HsmciDescriptor_t *descriptor) +{ + uint16_t i = RETRY_AMOUNT; + MmcCardStatus_t *cardStatus; + MmcOcrRegister_t *ocrRegister; + MmcCSDRegister_t *csdReg; + HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor; + uint32_t sendOpCondResponse; + MemStatus_t status; + + /* send first command - CMD0 with power init parameters */ + if (!memSendCommand(descriptor, POWER_ON_INIT, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + /* send CMD0 command to go to idle mode */ + if (!memSendCommand(descriptor, GO_IDLE_STATE, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + /* wait for internal initialization process */ + for (; i > 0; i--) + { + /* send CMD1 command to check host and device voltage correlation */ + if (!memSendCommand(descriptor, SEND_OP_COND, CMD1_HOST_VOLTAGE_RANGE | CMD1_ACCESS_MODE_SECTOR, R3_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + ocrRegister = (MmcOcrRegister_t *)(commandDescr->responseBuffer); + if (!(ocrRegister->reg & CMD1_HOST_VOLTAGE_RANGE)) + return voltageError; + if (0 == ocrRegister->busy) + continue; + break; + } + if (0 == i) + return initTimeoutError; + sendOpCondResponse = commandDescr->responseBuffer[0]; + i = RETRY_AMOUNT; + while (i--) + { + /* send CMD2 command to get card CID number */ + if (!memSendCommand(descriptor, ALL_SEND_CID, CMD2_ARGUMENT, R2_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + if (sendOpCondResponse != commandDescr->responseBuffer[0]) + break; + } + if (0 == i) + return stateError; + /* send CMD3 command to set card relative address */ + if (!memSendCommand(descriptor, SEND_RELATIVE_ADDR, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_STBY)) + return stateError; + /* send CMD9 command to read CSD register */ + if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + /* read allowed maximum communication frequency and set it */ + csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer); + status = setBusWidthAndHsMode(descriptor, csdReg); + if (status != memSuccess) + return setMaxFreqError; + + return memSuccess; +} + +/**************************************************************************//** +\brief Reads MMC memory capacity. +\param[in] + descriptor - pointer to hsmci descriptor. +\param[out] + capInfo - pointer to memory capacity structure. +\return + status of read capacity procedure. +******************************************************************************/ +MemStatus_t memGetCapacityInfo(HAL_HsmciDescriptor_t *descriptor, MemCapacityInfo_t *capInfo) +{ + MmcCardStatus_t *cardStatus; + MmcCSDRegister_t *csdReg; + HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor; + + /* send CMD13 command to discover current state */ + if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (STATUS_TRAN == (cardStatus->reg & STATUS_TRAN)) + { + /* send CMD7 command to switch to stand-by state*/ + if (!memSendCommand(descriptor, SELECT_CARD, ~REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_STBY)) + return stateError; + } + /* send CMD9 command to read CSD register */ + if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + + capInfo->logicalBlockLength = STANDARD_BLOCK_LENGTH; + csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer); + capInfo->lastLogicalBlock = (1 << (csdReg->cSizeMult + 2)) * (csdReg->cSizeUp + 1 + (csdReg->cSizeDown << 2)) * ((1 << csdReg->readBlLen) / STANDARD_BLOCK_LENGTH) - 1; + + if (!memCheckState(descriptor, STATUS_STBY)) + return stateError; + + /* send CMD7 command to switch to transfer state */ + if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + return memSuccess; +} + +/**************************************************************************//** +\brief Checks MMC memory state. +\param[in] + descriptor - pointer to hsmci descriptor; + state - state in which MMC memory meant to be. +\return + false - check failed; + true - check success. +******************************************************************************/ +static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength) +{ + descriptor->commandDescriptor->command = command; + descriptor->commandDescriptor->argument = argument; + descriptor->commandDescriptor->responseLength = respLength; + + if (-1 == HAL_WriteHsmciCommand(descriptor)) + return false; + + return true; +} + +/**************************************************************************//** +\brief Sends MMC command. +\param[in] + descriptor - pointer to hsmci descriptor; + command - command index and attributes; + argument - command argument; + respLength - command response length. +\return + false - command sent failed; + true - command sent success. +******************************************************************************/ +static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state) +{ + MmcCardStatus_t *cardStatus; + /* send CMD13 command to discover current state */ + if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(descriptor->commandDescriptor->responseBuffer); + + return (cardStatus->reg & STATUS_STATE) == state; +} + +/**************************************************************************//** +\brief Writes one data block to MMC memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of block to write. +\return + status of write procedure. +******************************************************************************/ +MemStatus_t memWriteBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t)) +{ + HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor; + HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor; + + memDescriptor = descriptor; + + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + commandDescr->command = WRITE_BLOCK; + commandDescr->argument = address << 9; + commandDescr->responseLength = R1_RESPONSE_LENGTH; + + dataDescr->direction = HSMCI_WRITE; + dataDescr->blockSize = STANDARD_BLOCK_LENGTH; + absMemoryCallback = callback; + descriptor->callback = memWriteCallback; + + if (-1 == HAL_WriteHsmci(descriptor)) + return hsmciWriteError; + + return memSuccess; +} + +/**************************************************************************//** +\brief Reads one data block from MMC memory at "address". +\param[in] + descriptor - pointer to hsmci descriptor; + address - address of block to read. +\return + status of read procedure. +******************************************************************************/ +MemStatus_t memReadBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t)) +{ + HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor; + HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor; + + memDescriptor = descriptor; + + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + commandDescr->command = READ_SINGLE_BLOCK; + commandDescr->argument = address << 9; + commandDescr->responseLength = R1_RESPONSE_LENGTH; + + dataDescr->direction = HSMCI_READ; + dataDescr->blockSize = STANDARD_BLOCK_LENGTH; + absMemoryCallback = callback; + descriptor->callback = memReadCallback; + + if (-1 == HAL_ReadHsmci(descriptor)) + return hsmciReadError; + + return memSuccess; +} + +/**************************************************************************//** +\brief Checks if MMC memory is ready for any data transfer. +\return + false - memory is busy; + true - memory is ready. +******************************************************************************/ +bool memIsBusy(void) +{ + return HAL_HsmciCheckReady(); +} + +/**************************************************************************//** +\brief Sets maximum bus frequency for MMC memory. +\param[in] + descriptor - pointer to hsmci descriptor; + freqCode - frequency code. +\return + false - setting failed; + true - setting success. +******************************************************************************/ +static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode) +{ + uint32_t freqUnit = mmcFrequencyUnits[freqCode & FREQ_UNITS_MASK]; + uint32_t freqMult = mmcFrequencyMulptiplier[(freqCode & FREQ_MULTIPLIER_MASK) >> FREQ_MULTIPLIER_OFFSET]; + + descriptor->clockRate = freqUnit * freqMult * 100; + if (hsMode) + descriptor->clockRate *= 2; + if (-1 == HAL_SetHsmciSpeed(descriptor)) + return false; + + return true; +} + +/**************************************************************************//** +\brief Sets maximum 4-line dat bus and high speed mode if card supports it. +\param[in] + descriptor - pointer to hsmci descriptor; + csdReg - pointer to csd register structure. +\return + status of operation. +******************************************************************************/ +static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg) +{ + MmcCardStatus_t *cardStatus; + uint8_t specVersion = csdReg->specVersion; + uint8_t tranSpeed = csdReg->tranSpeed; + HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor; + + /* send CMD7 command to switch to transfer state */ + if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + /* send CMD16 command to set card block length */ + if (!memSendCommand(descriptor, SET_BLOCKLEN, STANDARD_BLOCK_LENGTH, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + if (specVersion < CSD_SPEC_VERS_FOUR) + { + if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false)) + return hsmciError; + else + return memSuccess; + } + + /* send CMD6 command to switch to 4-line bus */ + if (!memSendCommand(descriptor, SWITCH, CMD6_SET_4_LINE_BUS, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + descriptor->busWidth = HSMCI_BUS_WIDTH_4; + if (-1 == HAL_SetHsmciBusWidth(descriptor)) + return hsmciError; + + /* send CMD6 command to switch to high speed mode */ + if (!memSendCommand(descriptor, SWITCH, CMD6_SET_HS_MODE, R1_RESPONSE_LENGTH)) + return hsmciError; + /* wait for hsmci bus becomes free */ + while (!HAL_HsmciCheckReady()); + cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer); + if (0 != (cardStatus->reg & ERROR_STATUS)) + return commandError; + if (!memCheckState(descriptor, STATUS_TRAN)) + return stateError; + + descriptor->highSpeedMode = true; + if (-1 == HAL_SetHsmciHighSpeedMode(descriptor)) + return hsmciError; + + if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false)) + return hsmciError; + + return memSuccess; +} + +//eof mmc.c diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c new file mode 100644 index 00000000..47e5c2d8 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c @@ -0,0 +1,53 @@ +/****************************************************************************//** + \file mscProtocol.c + + \brief Implementation of communication device protocol command. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief Mass storage device request handler. +\param[in] + data - pointer to host's request. +******************************************************************************/ +void msdRequestHandler(uint8_t *data) +{ + UsbMscRequest_t *pRequest = NULL; + + pRequest = (UsbMscRequest_t *)data; + if (NULL == pRequest) + return; + + // Check request code + switch (pRequest->request.bRequest) + { + case BULK_ONLY_MASS_STORAGE_RESET: + break; + case GET_MAX_LUN: + HAL_Stall(0); + break; + default: + HAL_Stall(0); + break; + } +} + +//eof mscProtocol.c diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c new file mode 100644 index 00000000..68c3cfb6 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c @@ -0,0 +1,398 @@ +/****************************************************************************//** + \files scsiProtocol.h + + \brief Implementation of communication device protocol command. + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 30/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include + +/****************************************************************************** + Define(s) section +******************************************************************************/ +// scsi commands +#define INQUIRY 0x12 +#define READ_CAPACITY_10 0x25 +#define READ_10 0x28 +#define REQUEST_SENSE 0x03 +#define TEST_UNIT_READY 0x00 +#define WRITE_10 0x2A +#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E +#define MODE_SENSE_6 0x1A +#define READ_FORMAT_CAPACITIES 0x23 +#define VERIFY_10 0x2F + +// capacity definitions +#define BLOCK_SIZE 512 + +//inquiry definitions +#define INQUIRY_PERIPHERAL 0x00 +#define INQUIRY_REMOVABLE 0x80 +#define INQUIRY_VERSION 0x04 +#define INQUIRY_RESPONSE_FORMAT 0x02 +#define INQUIRY_ADDITIONAL_LENGTH 0x20 +#define INQUIRY_FLAGS 0x00 +#define INQUIRY_VENDOR_ID "Atmel " +#define INQUIRY_PRODUCT_ID "Mass Storage " +#define INQUIRY_PRODUCT_REVISION "0001" + +// request sense definitions +#define REQUEST_SENSE_CODE 0xF0 +#define REQUEST_SENSE_OBSOLETE 0x00 +#define REQUEST_SENSE_NORMAL_FLAGS 0x00 +#define REQUEST_SENSE_ERROR_FLAGS 0x05 +#define REQUEST_SENSE_INFO 0x00 +#define REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH 0x0A +#define REQUEST_SENSE_CMD_SPECIFIC_INFO 0x00 +#define REQUEST_SENSE_NORMAL_ADDITIONAL_SENSE_CODE 0x00 +#define REQUEST_SENSE_ERROR_ADDITIONAL_SENSE_CODE 0x20 +#define REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER 0x00 +#define REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE 0x00 +#define REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID 0x80 +#define REQUEST_SENSE_SENSE_KEY_SPECIFIC 0x00 + +// mode sense definitions +#define MODE_SENSE_LENGTH 0x03 +#define MODE_SENSE_MEDIA_TYPE 0x00 +#define MODE_SENSE_DEVICE_SPECIFIC 0x00 +#define MODE_SENSE_BLOCK_DESC_LENGTH 0x00 + +// format capacities definitions +#define FORMAT_CAPACITIES_RESERVED 0x00 +#define FORMAT_CAPACITIES_LENGTH 0x08 +#define FORMAT_CAPACITIES_DESC_TYPE 0x01 + +/****************************************************************************** + Types section +******************************************************************************/ +BEGIN_PACK +typedef struct PACK +{ + uint32_t lastLogicalBlock; + uint32_t logicalBlockLength; +} ScsiReadCapacityResponse_t; + +typedef struct PACK +{ + uint8_t peripheral; + uint8_t removable; + uint8_t version; + uint8_t responseDataFormat; + uint8_t additionalLength; + uint8_t flags[3]; + uint8_t vendorId[8]; + uint8_t productId[16]; + uint8_t productRevision[4]; +} ScsiInquiryResponse_t; + +typedef struct PACK +{ + uint8_t responseCodeAndValid; + uint8_t obsolete; + uint8_t flags; + uint32_t information; + uint8_t addSenseLen; + uint32_t cmdSpecificInfo; + uint8_t additionalSenseCode; + uint8_t additionalSenseCodeQualifier; + uint8_t fieldReplacableUnitCode; + uint8_t senseKeySpecific[3]; +} ScsiRequestSenseResponse_t; + +typedef struct PACK +{ + uint8_t modeDataLength; + uint8_t mediumType; + uint8_t deviceSpecific; + uint8_t blockDescriptorLength; +} ScsiModeSense6Response_t; + +typedef struct PACK +{ + uint8_t reserved[3]; + uint8_t length; + uint32_t blocksNumber; + uint8_t descType; + uint8_t blockLengthUp; + uint16_t blockLengthDown; +} ScsiReadFormatCapacities_t; + +typedef struct PACK +{ + uint8_t flags; + uint32_t logicalBlockAddress; + uint8_t groupNumber; + uint16_t transferLength; + uint8_t control; +} ScsiReadWriteCommand_t; + +typedef struct PACK +{ + uint8_t index; + union + { + ScsiReadWriteCommand_t rwCommand; + }; +} ScsiCommand_t; +END_PACK + +/****************************************************************************** + Global variables section +******************************************************************************/ +static bool defaultRequestSenseResponse; +static uint32_t lastLogicalBlockNum; + +/****************************************************************************** + Constants section +******************************************************************************/ +const ScsiInquiryResponse_t inquiryResponse = { + INQUIRY_PERIPHERAL, + INQUIRY_REMOVABLE, + INQUIRY_VERSION, + INQUIRY_RESPONSE_FORMAT, + INQUIRY_ADDITIONAL_LENGTH, + {INQUIRY_FLAGS, INQUIRY_FLAGS, INQUIRY_FLAGS}, + INQUIRY_VENDOR_ID, + INQUIRY_PRODUCT_ID, + INQUIRY_PRODUCT_REVISION +}; + +const ScsiRequestSenseResponse_t normalRequestSenseResponse = { + REQUEST_SENSE_CODE, + REQUEST_SENSE_OBSOLETE, + REQUEST_SENSE_NORMAL_FLAGS, + SWAP32(REQUEST_SENSE_INFO), + REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH, + SWAP32(REQUEST_SENSE_CMD_SPECIFIC_INFO), + REQUEST_SENSE_NORMAL_ADDITIONAL_SENSE_CODE, + REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER, + REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE, + {REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID, REQUEST_SENSE_SENSE_KEY_SPECIFIC, REQUEST_SENSE_SENSE_KEY_SPECIFIC} +}; + +const ScsiRequestSenseResponse_t errorRequestSenseResponse = { + REQUEST_SENSE_CODE, + REQUEST_SENSE_OBSOLETE, + REQUEST_SENSE_ERROR_FLAGS, + SWAP32(REQUEST_SENSE_INFO), + REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH, + SWAP32(REQUEST_SENSE_CMD_SPECIFIC_INFO), + REQUEST_SENSE_ERROR_ADDITIONAL_SENSE_CODE, + REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER, + REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE, + {REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID, REQUEST_SENSE_SENSE_KEY_SPECIFIC, REQUEST_SENSE_SENSE_KEY_SPECIFIC} +}; + +const ScsiModeSense6Response_t modeSense6Response = { + MODE_SENSE_LENGTH, + MODE_SENSE_MEDIA_TYPE, + MODE_SENSE_DEVICE_SPECIFIC, + MODE_SENSE_BLOCK_DESC_LENGTH +}; + +/****************************************************************************** + Implementations section +******************************************************************************/ + +/**************************************************************************//** +\brief Checks if received scsi command is supported. +\param[in] + data - pointer to received command with parameters. +\return + false - command is not supported; + true - command is supported. +******************************************************************************/ +bool scsiIsValidCommand(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + command->rwCommand.transferLength = SWAP16(command->rwCommand.transferLength); + command->rwCommand.logicalBlockAddress = SWAP32(command->rwCommand.logicalBlockAddress); + + switch (command->index) + { + case INQUIRY: + case READ_CAPACITY_10: + case TEST_UNIT_READY: + case PREVENT_ALLOW_MEDIUM_REMOVAL: + case READ_10: + case WRITE_10: + case MODE_SENSE_6: + case READ_FORMAT_CAPACITIES: + case VERIFY_10: + defaultRequestSenseResponse = true; + break; + case REQUEST_SENSE: + return true; + default: + defaultRequestSenseResponse = false; + break; + } + + return defaultRequestSenseResponse; +} + +/**************************************************************************//** +\brief Checks if any response or data transfer needed for received + scsi command. +\param[in] + command - received command. +\return + false - response is not needed; + true - response is needed. +******************************************************************************/ +bool scsiIsDataInOutPhaseNeeded(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + if ((TEST_UNIT_READY == command->index) || (PREVENT_ALLOW_MEDIUM_REMOVAL == command->index) + || (VERIFY_10 == command->index)) + return false; + if ((READ_10 == command->index) || (WRITE_10 == command->index)) + if (0 == command->rwCommand.transferLength) + return false; + return true; +} + +/**************************************************************************//** +\brief Checks if command is read or write command. +\param[in] + command - received command. +\return + false - command is not read/write command; + true - command is read/write command. +******************************************************************************/ +bool scsiIsReadWriteCommand(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + return ((READ_10 == command->index) || (WRITE_10 == command->index)); +} + +/**************************************************************************//** +\brief Checks if command is read command. +\param[in] + command - received command. +\return + false - command is not read command; + true - command is read command. +******************************************************************************/ +bool scsiIsReadCommand(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + return (READ_10 == command->index); +} + +/**************************************************************************//** +\brief Blocks for read/write command. +\param[in] + data - pointer to received command with parameters. +\return + number of blocks to read or write from memory. +******************************************************************************/ +uint16_t scsiBlocksAmount(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + if ((READ_10 == command->index) || (WRITE_10 == command->index)) + return command->rwCommand.transferLength; + + return 0; +} + +/**************************************************************************//** +\brief Response for scsi command. +\param[in] + command - received command. +\param[out] + buffer - buffer with scsi command response. +\return + length of response +******************************************************************************/ +uint8_t scsiGetCommandResponse(uint8_t *data, uint8_t *buffer) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + ScsiReadCapacityResponse_t readCapacityResponse = { + .lastLogicalBlock = SWAP32(lastLogicalBlockNum), + .logicalBlockLength = SWAP32(BLOCK_SIZE) + }; + ScsiReadFormatCapacities_t readFormatCapacitiesResponse = { + .reserved = {FORMAT_CAPACITIES_RESERVED, FORMAT_CAPACITIES_RESERVED, FORMAT_CAPACITIES_RESERVED}, + .length = FORMAT_CAPACITIES_LENGTH, + .blocksNumber = SWAP32(lastLogicalBlockNum + 1), + .descType = FORMAT_CAPACITIES_DESC_TYPE, + .blockLengthUp = 0, + .blockLengthDown = SWAP16(BLOCK_SIZE) + }; + + if (INQUIRY == command->index) + { + memcpy(buffer, (uint8_t *)&inquiryResponse, sizeof(ScsiInquiryResponse_t)); + return sizeof(ScsiInquiryResponse_t); + } + if (READ_CAPACITY_10 == command->index) + { + memcpy(buffer, (uint8_t *)&readCapacityResponse, sizeof(ScsiReadCapacityResponse_t)); + return sizeof(ScsiReadCapacityResponse_t); + } + if (REQUEST_SENSE == command->index) + { + if (defaultRequestSenseResponse) + memcpy(buffer, (uint8_t *)&normalRequestSenseResponse, sizeof(ScsiRequestSenseResponse_t)); + else + memcpy(buffer, (uint8_t *)&errorRequestSenseResponse, sizeof(ScsiRequestSenseResponse_t)); + return sizeof(ScsiRequestSenseResponse_t); + } + if (MODE_SENSE_6 == command->index) + { + memcpy(buffer, (uint8_t *)&modeSense6Response, sizeof(ScsiModeSense6Response_t)); + return sizeof(ScsiModeSense6Response_t); + } + if (READ_FORMAT_CAPACITIES == command->index) + { + memcpy(buffer, (uint8_t *)&readFormatCapacitiesResponse, sizeof(ScsiReadFormatCapacities_t)); + return sizeof(ScsiReadFormatCapacities_t); + } + return 0; +} + +/**************************************************************************//** +\brief Sets number of last available memory block for scsi response. +\param[in] + lastBlock - received command. +\param[out] + buffer - number of last available memory block +******************************************************************************/ +void scsiSetCapacity(uint32_t lastBlock) +{ + lastLogicalBlockNum = lastBlock; +} + +/**************************************************************************//** +\brief Block address for read/write command. +\param[in] + data - pointer to received command with parameters. +\return + block address for read or write from memory. +******************************************************************************/ +uint32_t scsiGetBlockAddress(uint8_t *data) +{ + ScsiCommand_t *command = (ScsiCommand_t *)data; + + return command->rwCommand.logicalBlockAddress; +} + +//eof scsiProtocol.c -- cgit v1.2.3