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

📄 sbcmethods.c

📁 Include startup files and peripherial devices Code for Atmel ARM7 development
💻 C
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
static unsigned char SBC_ModeSense6(MSDCommandState *commandState)
{
    unsigned char      result = MSDD_STATUS_INCOMPLETE;
    unsigned char      status;
    MSDTransfer     *transfer = &(commandState->transfer);

    // Check if mode page is supported
    if (((SBCCommand *) commandState->cbw.pCommand)->modeSense6.bPageCode
        != SBC_PAGE_RETURN_ALL) {

        return MSDD_STATUS_PARAMETER;
    }

    // Initialize command state if needed
    if (commandState->state == 0) {

        commandState->state = SBC_STATE_WRITE;
    }

    // Check current command state
    switch (commandState->state) {
    //-------------------
    case SBC_STATE_WRITE:
    //-------------------
        // Start transfer
        status = MSDD_Write((void *) &modeParameterHeader6,
                            commandState->length,
                            (TransferCallback) MSDDriver_Callback,
                            (void *) transfer);

        // Check operation result code
        if (status != USBD_STATUS_SUCCESS) {

            TRACE_WARNING(
                "SPC_ModeSense6: Cannot start data transfer\n\r");
            result = MSDD_STATUS_ERROR;
        }
        else {

            // Proceed to next state
            commandState->state = SBC_STATE_WAIT_WRITE;
        }
        break;

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

        // Check semaphore value
        if (transfer->semaphore > 0) {

            // Take semaphore and terminate command
            transfer->semaphore--;

            if (transfer->status != USBD_STATUS_SUCCESS) {

                TRACE_WARNING(
                    "SPC_ModeSense6: Data transfer failed\n\r");
                result = MSDD_STATUS_ERROR;
            }
            else {

                result = MSDD_STATUS_SUCCESS;
            }

            // Update length field
            commandState->length -= transfer->transferred;

        }
        break;
    }

    return result;
}

//------------------------------------------------------------------------------
//! \brief  Performs a TEST UNIT READY COMMAND command.
//! \param  lun          Pointer to the LUN affected by the command
//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
//! \see    MSDLun
//------------------------------------------------------------------------------
static unsigned char SBC_TestUnitReady(MSDLun *lun)
{
    unsigned char result = MSDD_STATUS_ERROR;

    // Check current media state
    switch(lun->media->state) {
    //-------------------
    case MED_STATE_READY:
    //-------------------
        // Nothing to do
        TRACE_INFO_WP("Rdy ");
        result = MSDD_STATUS_SUCCESS;
        break;

    //------------------
    case MED_STATE_BUSY:
    //------------------
        TRACE_INFO_WP("Bsy ");
        SBC_UpdateSenseData(&(lun->requestSenseData),
                            SBC_SENSE_KEY_NOT_READY,
                            0,
                            0);
        break;

    //------
    default:
    //------
        TRACE_INFO_WP("? ");
        SBC_UpdateSenseData(&(lun->requestSenseData),
                            SBC_SENSE_KEY_NOT_READY,
                            SBC_ASC_MEDIUM_NOT_PRESENT,
                            0);
        break;
    }

    return result;
}

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief  Updates the sense data of a LUN with the given key and codes
//! \param  requestSenseData             Pointer to the sense data to update
//! \param  senseKey                     Sense key
//! \param  additionalSenseCode          Additional sense code
//! \param  additionalSenseCodeQualifier Additional sense code qualifier
//------------------------------------------------------------------------------
void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
                         unsigned char senseKey,
                         unsigned char additionalSenseCode,
                         unsigned char additionalSenseCodeQualifier)
{
    requestSenseData->bSenseKey = senseKey;
    requestSenseData->bAdditionalSenseCode = additionalSenseCode;
    requestSenseData->bAdditionalSenseCodeQualifier
        = additionalSenseCodeQualifier;
}

//------------------------------------------------------------------------------
//! \brief  Return information about the transfer length and direction expected
//!         by the device for a particular command.
//! \param  command Pointer to a buffer holding the command to evaluate
//! \param  length  Expected length of the data transfer
//! \param  type    Expected direction of data transfer
//! \param  lun     Pointer to the LUN affected by the command
//------------------------------------------------------------------------------
unsigned char SBC_GetCommandInformation(void          *command,
                               unsigned int  *length,
                               unsigned char *type,
                               MSDLun         *lun)
{
    SBCCommand *sbcCommand = (SBCCommand *) command;
    unsigned char          isCommandSupported = 1;

    // Identify command
    switch (sbcCommand->bOperationCode) {
    //---------------
    case SBC_INQUIRY:
    //---------------
        (*type) = MSDD_DEVICE_TO_HOST;

        // Allocation length is stored in big-endian format
        (*length) = WORDB(sbcCommand->inquiry.pAllocationLength);
        break;

    //--------------------
    case SBC_MODE_SENSE_6:
    //--------------------
        (*type) = MSDD_DEVICE_TO_HOST;
        if (sbcCommand->modeSense6.bAllocationLength >
            sizeof(SBCModeParameterHeader6)) {

            *length = sizeof(SBCModeParameterHeader6);
        }
        else {

            *length = sbcCommand->modeSense6.bAllocationLength;
        }

        // Only "return all pages" command is supported
        if (sbcCommand->modeSense6.bPageCode != SBC_PAGE_RETURN_ALL) {

            // Unsupported page
            TRACE_WARNING(
            "SBC_GetCommandInformation: Page code not supported(0x%02X)\n\r",
                          sbcCommand->modeSense6.bPageCode);
            isCommandSupported = 0;
            (*length) = 0;
        }
        break;

    //------------------------------------
    case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
    //------------------------------------
        (*type) = MSDD_NO_TRANSFER;
        break;

    //---------------------
    case SBC_REQUEST_SENSE:
    //---------------------
        (*type) = MSDD_DEVICE_TO_HOST;
        (*length) = sbcCommand->requestSense.bAllocationLength;
        break;

    //-----------------------
    case SBC_TEST_UNIT_READY:
    //-----------------------
        (*type) = MSDD_NO_TRANSFER;
        break;

    //---------------------
    case SBC_READ_CAPACITY_10:
    //---------------------
        (*type) = MSDD_DEVICE_TO_HOST;
        (*length) = sizeof(SBCReadCapacity10Data);
        break;

    //---------------
    case SBC_READ_10:
    //---------------
        (*type) = MSDD_DEVICE_TO_HOST;
        (*length) = WORDB(sbcCommand->read10.pTransferLength)
                     * lun->blockSize;
        break;

    //----------------
    case SBC_WRITE_10:
    //----------------
        (*type) = MSDD_HOST_TO_DEVICE;
        (*length) = WORDB(sbcCommand->write10.pTransferLength)
                     * lun->blockSize;
        break;

    //-----------------
    case SBC_VERIFY_10:
    //-----------------
        (*type) = MSDD_NO_TRANSFER;
        break;

    //------
    default:
    //------
        isCommandSupported = 0;
    }

    // If length is 0, no transfer is expected
    if ((*length) == 0) {

        (*type) = MSDD_NO_TRANSFER;
    }

    return isCommandSupported;
}

//------------------------------------------------------------------------------
//! \brief  Processes a SBC command by dispatching it to a subfunction.
//! \param  lun          Pointer to the affected LUN
//! \param  commandState Pointer to the current command state
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char SBC_ProcessCommand(MSDLun               *lun,
                                 MSDCommandState *commandState)
{
    unsigned char result = MSDD_STATUS_INCOMPLETE;
    SBCCommand *command = (SBCCommand *) commandState->cbw.pCommand;

    // Identify command
    switch (command->bOperationCode) {
    //---------------
    case SBC_READ_10:
    //---------------
        TRACE_INFO_WP("Read(10) ");

        // Perform the Read10 command
        result = SBC_Read10(lun, commandState);
        break;

    //----------------
    case SBC_WRITE_10:
    //----------------
        TRACE_INFO_WP("Write(10) ");

        // Perform the Write10 command
        result = SBC_Write10(lun, commandState);
        break;

    //---------------------
    case SBC_READ_CAPACITY_10:
    //---------------------
        TRACE_INFO_WP("RdCapacity(10) ");

        // Perform the ReadCapacity command
        result = SBC_ReadCapacity10(lun, commandState);
        break;

    //---------------------
    case SBC_VERIFY_10:
    //---------------------
        TRACE_INFO_WP("Verify(10) ");

        // Flush media
        MED_Flush(lun->media);
        result = MSDD_STATUS_SUCCESS;
        break;

    //---------------
    case SBC_INQUIRY:
    //---------------
        TRACE_INFO_WP("Inquiry ");

        // Process Inquiry command
        result = SBC_Inquiry(lun, commandState);
        break;

    //--------------------
    case SBC_MODE_SENSE_6:
    //--------------------
        TRACE_INFO_WP("ModeSense(6) ");

        // Process ModeSense6 command
        result = SBC_ModeSense6(commandState);
        break;

    //-----------------------
    case SBC_TEST_UNIT_READY:
    //-----------------------
        TRACE_INFO_WP("TstUnitRdy ");

        // Process TestUnitReady command
        //MED_Flush(lun->media);
        result = SBC_TestUnitReady(lun);
        break;

    //---------------------
    case SBC_REQUEST_SENSE:
    //---------------------
        TRACE_INFO_WP("ReqSense ");

        // Perform the RequestSense command
        result = SBC_RequestSense(lun, commandState);
        break;

    //------------------------------------
    case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
    //------------------------------------
        TRACE_INFO_WP("PrevAllowRem ");

        // Nothing to do
        result = MSDD_STATUS_SUCCESS;
        break;

    //------
    default:
    //------
        result = MSDD_STATUS_PARAMETER;
    }

    return result;
}

⌨️ 快捷键说明

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