omap3530/beagle_drivers/wb/api/src/cyasstorage.c
author Lukasz Forynski <lukasz.forynski@gmail.com>
Mon, 23 Aug 2010 02:29:41 +0100
changeset 51 254b9435d75e
parent 23 117faf51deac
permissions -rw-r--r--
Fixed build warnings

/* Cypress West Bridge API source file (cyasstorage.c)
## ===========================
##
##  Copyright Cypress Semiconductor Corporation, 2006-2009,
##  All Rights Reserved
##  UNPUBLISHED, LICENSED SOFTWARE.
##
##  CONFIDENTIAL AND PROPRIETARY INFORMATION
##  WHICH IS THE PROPERTY OF CYPRESS.
##
##  Use of this file is governed
##  by the license agreement included in the file
##
##     <install>/license/license.txt
##
##  where <install> is the Cypress software
##  installation root directory path.
##
## ===========================
*/

/*
* Storage Design
*
* The storage module is fairly straight forward once the DMA and LOWLEVEL modules
* have been designed.  The storage module simple takes requests from the user, queues the
* associated DMA requests for action, and then sends the low level requests to the
* West Bridge firmware.
*
*/

#include "cyashal.h"
#include "cyasstorage.h"
#include "cyaserr.h"
#include "cyasdevice.h"
#include "cyaslowlevel.h"
#include "cyasdma.h"
#include "cyasregs.h"

/* Map a pre-V1.2 media type to the V1.2+ bus number */
CyAsReturnStatus_t
CyAnMapBusFromMediaType(CyAsDevice *dev_p, CyAsMediaType type, CyAsBusNumber_t *bus)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t code = (uint8_t)(1 << type) ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
        return CY_AS_ERROR_NO_FIRMWARE ;


    if (dev_p->media_supported[0] & code)
    {
        if (dev_p->media_supported[1] & code)
        {
            /*
             * This media type could be supported on multiple buses. So, report
             * an address resolution error.
             */
            ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR ;
        }
        else
            *bus = 0 ;
    }
    else
    {
        if (dev_p->media_supported[1] & code)
            *bus = 1 ;
        else
            ret = CY_AS_ERROR_NO_SUCH_MEDIA ;
    }

    return ret ;
}

static uint16_t
CreateAddress(CyAsBusNumber_t bus, uint32_t device, uint8_t unit)
{
    CyAsHalAssert(bus >= 0  && bus < CY_AS_MAX_BUSES) ;
    CyAsHalAssert(device < 16) ;

    return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit) ;
}

CyAsMediaType
CyAsStorageGetMediaFromAddress(uint16_t v)
{
    CyAsMediaType media = CyAsMediaMaxMediaValue ;

    switch(v & 0xFF)
    {
        case 0x00:
            break;
        case 0x01:
            media = CyAsMediaNand ;
            break ;
        case 0x02:
            media = CyAsMediaSDFlash ;
            break ;
        case 0x04:
            media = CyAsMediaMMCFlash ;
            break ;
        case 0x08:
            media = CyAsMediaCEATA ;
            break ;
        case 0x10:
            media = CyAsMediaSDIO ;
            break ;
        default:
            CyAsHalAssert(0) ;
            break ;
    }

    return media ;
}

CyAsBusNumber_t
CyAsStorageGetBusFromAddress(uint16_t v)
{
    CyAsBusNumber_t bus = (CyAsBusNumber_t)((v >> 12) & 0x0f) ;
    CyAsHalAssert(bus >= 0 && bus < CY_AS_MAX_BUSES) ;
    return bus ;
}

uint32_t
CyAsStorageGetDeviceFromAddress(uint16_t v)
{
    return (uint32_t)((v >> 8) & 0x0f) ;
}

static uint8_t
GetUnitFromAddress(uint16_t v)
{
    return (uint8_t)(v & 0xff) ;
}

static CyAsReturnStatus_t
CyAsMapBadAddr(uint16_t val)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_INVALID_RESPONSE ;

    switch(val)
    {
    case 0:
        ret = CY_AS_ERROR_NO_SUCH_BUS ;
        break ;
    case 1:
        ret = CY_AS_ERROR_NO_SUCH_DEVICE ;
        break ;
    case 2:
        ret = CY_AS_ERROR_NO_SUCH_UNIT ;
        break ;
    case 3:
        ret = CY_AS_ERROR_INVALID_BLOCK ;
        break ;
    }

    return ret ;
}

static void
MyStorageRequestCallback(CyAsDevice *dev_p, uint8_t context, CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *resp_p, CyAsReturnStatus_t ret)
{
    uint16_t val ;
    uint16_t addr ;
    CyAsBusNumber_t bus;
    uint32_t device;
    CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
    CyAsDmaEndPoint *ep_p = NULL ;

    (void)resp_p ;
    (void)context ;
    (void)ret ;

    switch(CyAsLLRequestResponse_GetCode(req_p))
    {
    case CY_RQT_MEDIA_CHANGED:
        CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;

        /* Media has either been inserted or removed */
        addr = CyAsLLRequestResponse_GetWord(req_p, 0) ;

        bus = CyAsStorageGetBusFromAddress(addr);
        device = CyAsStorageGetDeviceFromAddress(addr);

        /* Clear the entry for this device to force re-query later */
        CyAsHalMemSet(&(dev_p->storage_device_info[bus][device]), 0,
            sizeof(dev_p->storage_device_info[bus][device])) ;

        val = CyAsLLRequestResponse_GetWord(req_p, 1) ;
        if (dev_p->storage_event_cb_ms)
        {
            if (val == 1)
                dev_p->storage_event_cb_ms(h, bus, device, CyAsStorageRemoved, 0) ;
            else
                dev_p->storage_event_cb_ms(h, bus, device, CyAsStorageInserted, 0) ;
        }
        else if (dev_p->storage_event_cb)
        {
            if (val == 1)
                dev_p->storage_event_cb(h, (CyAsMediaType)bus, CyAsStorageRemoved, 0) ; /*nxz*/
            else
                dev_p->storage_event_cb(h, (CyAsMediaType)bus, CyAsStorageInserted, 0) ; /*nxz*/
        }

        break ;

    case CY_RQT_ANTIOCH_CLAIM:
        CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
        if (dev_p->storage_event_cb || dev_p->storage_event_cb_ms)
        {
            val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
            if (dev_p->storage_event_cb_ms)
            {
                if (val & 0x0100)
                    dev_p->storage_event_cb_ms(h, 0, 0, CyAsStorageAntioch, 0) ;
                if (val & 0x0200)
                    dev_p->storage_event_cb_ms(h, 1, 0, CyAsStorageAntioch, 0) ;
            }
            else
            {
                if (val & 0x01)
                    dev_p->storage_event_cb(h, CyAsMediaNand, CyAsStorageAntioch, 0) ;
                if (val & 0x02)
                    dev_p->storage_event_cb(h, CyAsMediaSDFlash, CyAsStorageAntioch, 0) ;
                if (val & 0x04)
                    dev_p->storage_event_cb(h, CyAsMediaMMCFlash, CyAsStorageAntioch, 0) ;
                if (val & 0x08)
                    dev_p->storage_event_cb(h, CyAsMediaCEATA, CyAsStorageAntioch, 0) ;
            }
        }
        break ;

    case CY_RQT_ANTIOCH_RELEASE:
        CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
        val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
        if (dev_p->storage_event_cb_ms)
        {
            if (val & 0x0100)
                dev_p->storage_event_cb_ms(h, 0, 0, CyAsStorageProcessor, 0) ;
            if (val & 0x0200)
                dev_p->storage_event_cb_ms(h, 1, 0, CyAsStorageProcessor, 0) ;
        }
        else if (dev_p->storage_event_cb)
        {
            if (val & 0x01)
                dev_p->storage_event_cb(h, CyAsMediaNand, CyAsStorageProcessor, 0) ;
            if (val & 0x02)
                dev_p->storage_event_cb(h, CyAsMediaSDFlash, CyAsStorageProcessor, 0) ;
            if (val & 0x04)
                dev_p->storage_event_cb(h, CyAsMediaMMCFlash, CyAsStorageProcessor, 0) ;
            if (val & 0x08)
                dev_p->storage_event_cb(h, CyAsMediaCEATA, CyAsStorageProcessor, 0) ;
        }
        break ;


    case CY_RQT_SDIO_INTR:
        CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
        val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
        if (dev_p->storage_event_cb_ms)
        {
            if (val & 0x0100)
                dev_p->storage_event_cb_ms(h, 1, 0, CyAsSdioInterrupt, 0) ;
            else
                dev_p->storage_event_cb_ms(h, 0, 0, CyAsSdioInterrupt, 0) ;

        }
        else if (dev_p->storage_event_cb)
        {
            dev_p->storage_event_cb(h, CyAsMediaSDIO, CyAsSdioInterrupt, 0) ;
        }
        break;

    case CY_RQT_P2S_DMA_START:
        /* Do the DMA setup for the waiting operation. This event is used only in
         * the MTP mode firmware. */
        CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
        if (dev_p->storage_oper == CyAsOpRead)
        {
            ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_READ_ENDPOINT) ;
            CyAsDmaEndPointSetStopped(ep_p) ;
            CyAsDmaKickStart(dev_p, CY_AS_P2S_READ_ENDPOINT) ;
        }
        else
        {
            ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ;
            CyAsDmaEndPointSetStopped(ep_p) ;
            CyAsDmaKickStart(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ;
        }
        break ;

    default:
        CyAsHalPrintMessage("Invalid request received on storage context\n") ;
        val = req_p->box0 ;
        CyAsLLSendDataResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_RESP_INVALID_REQUEST, sizeof(val), &val) ;
        break ;
    }
}

static CyAsReturnStatus_t
IsStorageActive(CyAsDevice *dev_p)
{
    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
        return CY_AS_ERROR_NO_FIRMWARE ;

    if (dev_p->storage_count == 0)
        return CY_AS_ERROR_NOT_RUNNING ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    return CY_AS_ERROR_SUCCESS ;
}

static void
CyAsStorageFuncCallback(CyAsDevice *dev_p,
                        uint8_t context,
                        CyAsLLRequestResponse *rqt,
                        CyAsLLRequestResponse *resp,
                        CyAsReturnStatus_t ret) ;

static CyAsReturnStatus_t
MyHandleResponseNoData(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyHandleResponseStorageStart(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         CyAsReturnStatus_t ret)
{
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    if (dev_p->storage_count > 0 && ret == CY_AS_ERROR_ALREADY_RUNNING)
        ret = CY_AS_ERROR_SUCCESS ;

    ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CyTrue, CyAsDirectionIn) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    ret = CyAsDmaSetMaxDmaSize(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_P2S_READ_ENDPOINT, CyTrue, CyAsDirectionOut) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    ret = CyAsDmaSetMaxDmaSize(dev_p, CY_AS_P2S_READ_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    CyAsLLRegisterRequestCallback(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, MyStorageRequestCallback) ;

    /* Create the request/response used for storage reads and writes. */
    dev_p->storage_rw_req_p  = CyAsLLCreateRequest(dev_p, 0, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
    if (dev_p->storage_rw_req_p == 0)
    {
        ret = CY_AS_ERROR_OUT_OF_MEMORY;
        goto destroy;
    }

    dev_p->storage_rw_resp_p = CyAsLLCreateResponse(dev_p, 5) ;
    if (dev_p->storage_rw_resp_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
        ret = CY_AS_ERROR_OUT_OF_MEMORY ;
    }

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    /* Increment the storage count only if the above functionality succeeds.*/
    if (ret == CY_AS_ERROR_SUCCESS)
    {
        if (dev_p->storage_count == 0)
        {
            CyAsHalMemSet(dev_p->storage_device_info, 0, sizeof(dev_p->storage_device_info)) ;
            dev_p->is_storage_only_mode = CyFalse ;
        }

        dev_p->storage_count++ ;
    }

    CyAsDeviceClearSSSPending(dev_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageStart(CyAsDeviceHandle handle,
                   CyAsFunctionCallback cb,
                   uint32_t client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
        return CY_AS_ERROR_NO_FIRMWARE ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if(CyAsDeviceIsSSSPending(dev_p))
        return CY_AS_ERROR_STARTSTOP_PENDING ;

    CyAsDeviceSetSSSPending(dev_p) ;

    if (dev_p->storage_count == 0)
    {
        /* Create the request to send to the West Bridge device */
        req_p = CyAsLLCreateRequest(dev_p, CY_RQT_START_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
        if (req_p == 0)
        {
            CyAsDeviceClearSSSPending(dev_p) ;
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        }

        /* Reserve space for the reply, the reply data will not exceed one word */
        reply_p = CyAsLLCreateResponse(dev_p, 1) ;
        if (reply_p == 0)
        {
            CyAsDeviceClearSSSPending(dev_p) ;
            CyAsLLDestroyRequest(dev_p, req_p) ;
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        }

        if(cb == 0)
        {
            ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
            if (ret != CY_AS_ERROR_SUCCESS)
                goto destroy ;

            return MyHandleResponseStorageStart(dev_p, req_p, reply_p, ret) ;
        }
        else
        {
            ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_START,
                0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

            if (ret != CY_AS_ERROR_SUCCESS)
                goto destroy ;

            /* The request and response are freed as part of the FuncCallback */
            return ret ;
        }

destroy:
        CyAsLLDestroyRequest(dev_p, req_p) ;
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    }
    else
    {
        dev_p->storage_count++ ;
        if (cb)
            cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0) ;
    }

    CyAsDeviceClearSSSPending(dev_p) ;

    return ret ;
}


static CyAsReturnStatus_t
MyHandleResponseStorageStop(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         CyAsReturnStatus_t ret)
{
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    if (ret == CY_AS_ERROR_SUCCESS)
    {
        CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
        CyAsLLDestroyResponse(dev_p, dev_p->storage_rw_resp_p) ;
        dev_p->storage_count-- ;
    }

    CyAsDeviceClearSSSPending(dev_p) ;

    return ret ;
}
CyAsReturnStatus_t
CyAsStorageStop(CyAsDeviceHandle handle,
                  CyAsFunctionCallback cb,
                  uint32_t client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (CyAsDeviceIsStorageAsyncPending(dev_p))
        return CY_AS_ERROR_ASYNC_PENDING ;

    if(CyAsDeviceIsSSSPending(dev_p))
        return CY_AS_ERROR_STARTSTOP_PENDING ;

    CyAsDeviceSetSSSPending(dev_p) ;

    if (dev_p->storage_count == 1)
    {

        /* Create the request to send to the West Bridge device */
        req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STOP_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 0) ;
        if (req_p == 0)
        {
            CyAsDeviceClearSSSPending(dev_p) ;
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        }

        /* Reserve space for the reply, the reply data will not exceed one word */
        reply_p = CyAsLLCreateResponse(dev_p, 1) ;
        if (reply_p == 0)
        {
            CyAsDeviceClearSSSPending(dev_p) ;
            CyAsLLDestroyRequest(dev_p, req_p) ;
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        }

        if(cb == 0)
        {
            ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
            if (ret != CY_AS_ERROR_SUCCESS)
                goto destroy ;

            return MyHandleResponseStorageStop(dev_p, req_p, reply_p, ret) ;
        }
        else
        {
            ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_STOP,
                0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

            if (ret != CY_AS_ERROR_SUCCESS)
                goto destroy ;

            /* The request and response are freed as part of the MiscFuncCallback */
            return ret ;
        }

destroy:
        CyAsLLDestroyRequest(dev_p, req_p) ;
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    }
    else if(dev_p->storage_count > 1)
    {
        dev_p->storage_count-- ;
        if (cb)
            cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0) ;
    }

    CyAsDeviceClearSSSPending(dev_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageRegisterCallback(CyAsDeviceHandle handle, CyAsStorageEventCallback callback)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
        return CY_AS_ERROR_NO_FIRMWARE ;

    if (dev_p->storage_count == 0)
        return CY_AS_ERROR_NOT_RUNNING ;

    dev_p->storage_event_cb = NULL ;
    dev_p->storage_event_cb_ms = callback ;

    return CY_AS_ERROR_SUCCESS ;
}



static CyAsReturnStatus_t
MyHandleResponseStorageClaim(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
    {
        ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
        goto destroy ;
    }

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MEDIA_CLAIMED_RELEASED)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    /* The response must be about the address I am trying to claim or the firmware is broken */
    if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
        CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))) ||
        (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
        CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))))
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    if (CyAsLLRequestResponse_GetWord(reply_p, 1) != 1)
        ret = CY_AS_ERROR_NOT_ACQUIRED ;

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyStorageClaim(CyAsDevice *dev_p,
                void* data,
                CyAsBusNumber_t bus,
                uint32_t device,
                uint16_t req_flags,
                CyAsFunctionCallback cb,
                uint32_t client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if(dev_p->mtp_count > 0)
        return CY_AS_ERROR_NOT_VALID_IN_MTP ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CLAIM_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;

    /* Reserve space for the reply, the reply data will not exceed one word */
    reply_p = CyAsLLCreateResponse(dev_p, 4) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseStorageClaim(dev_p, req_p, reply_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_CLAIM,
            data, dev_p->func_cbs_stor, req_flags,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageClaim(CyAsDeviceHandle handle,
                   CyAsBusNumber_t bus,
                   uint32_t device,
                   CyAsFunctionCallback cb,
                   uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    return MyStorageClaim(dev_p, NULL, bus, device, CY_AS_REQUEST_RESPONSE_MS, cb, client) ;
}

static CyAsReturnStatus_t
MyHandleResponseStorageRelease(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
    {
        ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
        goto destroy ;
    }

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MEDIA_CLAIMED_RELEASED)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    /* The response must be about the address I am trying to release or the firmware is broken */
    if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
        CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))) ||
        (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
        CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))))
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }


    if (CyAsLLRequestResponse_GetWord(reply_p, 1) != 0)
        ret = CY_AS_ERROR_NOT_RELEASED ;

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyStorageRelease(CyAsDevice* dev_p,
                    void* data,
                    CyAsBusNumber_t bus,
                    uint32_t device,
                    uint16_t req_flags,
                    CyAsFunctionCallback cb,
                    uint32_t client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if(dev_p->mtp_count > 0)
        return CY_AS_ERROR_NOT_VALID_IN_MTP ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_RELEASE_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;

    /* Reserve space for the reply, the reply data will not exceed one word */
    reply_p = CyAsLLCreateResponse(dev_p, 4) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseStorageRelease(dev_p, req_p, reply_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_RELEASE,
            data, dev_p->func_cbs_stor, req_flags,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageRelease(CyAsDeviceHandle handle,
                   CyAsBusNumber_t bus,
                   uint32_t device,
                   CyAsFunctionCallback cb,
                   uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    return MyStorageRelease(dev_p, NULL, bus, device, CY_AS_REQUEST_RESPONSE_MS, cb, client) ;
}

static CyAsReturnStatus_t
MyHandleResponseStorageQueryBus(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         uint32_t* count)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
    uint16_t v ;

    if (code == CY_RESP_NO_SUCH_ADDRESS)
    {
        ret = CY_AS_ERROR_NO_SUCH_BUS ;
        goto destroy ;
    }

    if (code != CY_RESP_BUS_DESCRIPTOR)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    /*
     * Verify that the response corresponds to the bus that was queried.
     */
    if (CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
                CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)))
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    v = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
    if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
    {
        /*
         * This request is only for the count of devices on the bus. There
         * is no need to check the media type.
         */
        if (v)
            *count = 1 ;
        else
            *count = 0 ;
    }
    else
    {
        /*
         * This request is for the count of devices of a particular type. We need
         * to check whether the media type found matches the queried type.
         */
        CyAsMediaType queried = (CyAsMediaType)CyAsLLRequestResponse_GetWord(req_p, 1) ;
        CyAsMediaType found   = CyAsStorageGetMediaFromAddress(v) ;

        if (queried == found)
            *count = 1 ;
        else
            *count = 0 ;
    }

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
MyStorageQueryBus(CyAsDevice *dev_p,
                        CyAsBusNumber_t bus,
                        CyAsMediaType   type,
                        uint16_t req_flags,
                        uint32_t *count,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsReturnStatus_t ret ;
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsFunctCBType cbType = CY_FUNCT_CB_STOR_QUERYBUS ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Create the request to send to the Antioch device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_BUS, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, 0, 0)) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)type) ;

    /* Reserve space for the reply, the reply data will not exceed two words. */
    reply_p = CyAsLLCreateResponse(dev_p, 2) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        req_p->flags |= req_flags;
        return MyHandleResponseStorageQueryBus(dev_p, req_p, reply_p, count) ;
    }
    else
    {
        if (req_flags == CY_AS_REQUEST_RESPONSE_EX)
            cbType = CY_FUNCT_CB_STOR_QUERYMEDIA ;

        ret = CyAsMiscSendRequest(dev_p, cb, client, cbType,
            count, dev_p->func_cbs_stor, req_flags,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageQueryBus(CyAsDeviceHandle handle,
                        CyAsBusNumber_t bus,
                        uint32_t *count,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    return MyStorageQueryBus(dev_p, bus, CyAsMediaMaxMediaValue, CY_AS_REQUEST_RESPONSE_MS,
            count, cb, client) ;
}

CyAsReturnStatus_t
CyAsStorageQueryMedia(CyAsDeviceHandle handle,
                        CyAsMediaType type,
                        uint32_t *count,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsBusNumber_t bus ;

    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    ret = CyAnMapBusFromMediaType(dev_p, type, &bus) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    return MyStorageQueryBus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
            count, cb, client) ;
}

static CyAsReturnStatus_t
MyHandleResponseStorageQueryDevice(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         void* data_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint16_t v ;
    CyAsBusNumber_t bus ;
    CyAsMediaType type ;
    uint32_t device ;
    CyBool removable ;
    CyBool writeable ;
    CyBool locked ;
    uint16_t block_size ;
    uint32_t number_units ;
    uint32_t number_eus ;

    if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
    {
        ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
        goto destroy ;
    }

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_DEVICE_DESCRIPTOR)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    /* Unpack the response */
    v = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    type = CyAsStorageGetMediaFromAddress(v) ;
    bus  = CyAsStorageGetBusFromAddress(v) ;
    device = CyAsStorageGetDeviceFromAddress(v) ;

    block_size = CyAsLLRequestResponse_GetWord(reply_p, 1) ;

    v = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
    removable = (v & 0x8000) ? CyTrue : CyFalse ;
    writeable = (v & 0x0100) ? CyTrue : CyFalse ;
    locked = (v & 0x0200) ? CyTrue : CyFalse ;
    number_units = (v & 0xff) ;

    number_eus  = (CyAsLLRequestResponse_GetWord(reply_p, 3) << 16) | CyAsLLRequestResponse_GetWord(reply_p, 4) ;

    /* Store the results based on the version of originating function */
    if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
    {
        CyAsStorageQueryDeviceData  *store_p = (CyAsStorageQueryDeviceData*)data_p ;

        /* Make sure the response is about the address we asked about - if not, firmware error */
        if ((bus != store_p->bus) || (device != store_p->device))
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        store_p->desc_p.type = type ;
        store_p->desc_p.removable = removable ;
        store_p->desc_p.writeable = writeable ;
        store_p->desc_p.block_size = block_size ;
        store_p->desc_p.number_units = number_units ;
        store_p->desc_p.locked = locked ;
        store_p->desc_p.erase_unit_size = number_eus ;
        dev_p->storage_device_info[bus][device] = store_p->desc_p ;
    }
    else
    {
        CyAsStorageQueryDeviceData_dep    *store_p = (CyAsStorageQueryDeviceData_dep*)data_p ;

        /* Make sure the response is about the address we asked about - if not, firmware error */
        if ((type != store_p->type) || (device != store_p->device))
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        store_p->desc_p.type = type ;
        store_p->desc_p.removable = removable ;
        store_p->desc_p.writeable = writeable ;
        store_p->desc_p.block_size = block_size ;
        store_p->desc_p.number_units = number_units ;
        store_p->desc_p.locked = locked ;
        store_p->desc_p.erase_unit_size = number_eus ;
        dev_p->storage_device_info[bus][device] = store_p->desc_p ;
    }

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyStorageQueryDevice(CyAsDevice *dev_p,
                        void* data_p,
                        uint16_t req_flags,
                        CyAsBusNumber_t bus,
                        uint32_t device,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Create the request to send to the Antioch device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;

    /* Reserve space for the reply, the reply data will not exceed five words. */
    reply_p = CyAsLLCreateResponse(dev_p, 5) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        req_p->flags |= req_flags;
        return MyHandleResponseStorageQueryDevice(dev_p, req_p, reply_p, data_p) ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_QUERYDEVICE,
            data_p, dev_p->func_cbs_stor, req_flags,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageQueryDevice(CyAsDeviceHandle handle,
                         CyAsStorageQueryDeviceData* data_p,
                         CyAsFunctionCallback cb,
                         uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    return MyStorageQueryDevice(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
            data_p->device, cb, client) ;
}

static CyAsReturnStatus_t
MyHandleResponseStorageQueryUnit(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         void* data_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsBusNumber_t bus ;
    uint32_t device ;
    uint32_t unit ;
    CyAsMediaType type ;
    uint16_t block_size ;
    uint32_t start_block ;
    uint32_t unit_size ;
    uint16_t v ;

    if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
    {
        ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
        goto destroy ;
    }

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_UNIT_DESCRIPTOR)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    /* Unpack the response */
    v      = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    bus    = CyAsStorageGetBusFromAddress(v) ;
    device = CyAsStorageGetDeviceFromAddress(v) ;
    unit   = GetUnitFromAddress(v) ;

    type   = CyAsStorageGetMediaFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 1));

    block_size = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
    start_block = CyAsLLRequestResponse_GetWord(reply_p, 3) | (CyAsLLRequestResponse_GetWord(reply_p, 4) << 16) ;
    unit_size = CyAsLLRequestResponse_GetWord(reply_p, 5) | (CyAsLLRequestResponse_GetWord(reply_p, 6) << 16) ;

    /* Store the results based on the version of originating function */
    if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
    {
        CyAsStorageQueryUnitData  *store_p = (CyAsStorageQueryUnitData*)data_p ;

        /* Make sure the response is about the address we asked about - if not, firmware error */
        if (bus != store_p->bus || device != store_p->device || unit != store_p->unit)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        store_p->desc_p.type = type ;
        store_p->desc_p.block_size = block_size ;
        store_p->desc_p.start_block = start_block ;
        store_p->desc_p.unit_size = unit_size ;
    }
    else
    {
        CyAsStorageQueryUnitData_dep    *store_p = (CyAsStorageQueryUnitData_dep*)data_p ;

        /* Make sure the response is about the media type we asked about - if not, firmware error */
        if ((type != store_p->type) || (device != store_p->device) || (unit != store_p->unit) ) {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        store_p->desc_p.type = type ;
        store_p->desc_p.block_size = block_size ;
        store_p->desc_p.start_block = start_block ;
        store_p->desc_p.unit_size = unit_size ;
    }

    dev_p->storage_device_info[bus][device].type = type ;
    dev_p->storage_device_info[bus][device].block_size = block_size ;

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyStorageQueryUnit(CyAsDevice *dev_p,
                    void* data_p,
                    uint16_t req_flags,
                    CyAsBusNumber_t bus,
                    uint32_t device,
                    uint32_t unit,
                    CyAsFunctionCallback cb,
                    uint32_t client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_UNIT, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    if (device > 255)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (unit > 255)
        return CY_AS_ERROR_NO_SUCH_UNIT ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, (uint8_t)unit)) ;

    /* Reserve space for the reply, the reply data will be of seven words. */
    reply_p = CyAsLLCreateResponse(dev_p, 7) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        req_p->flags |= req_flags ;
        return MyHandleResponseStorageQueryUnit(dev_p, req_p, reply_p, data_p) ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_QUERYUNIT,
            data_p, dev_p->func_cbs_stor, req_flags,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageQueryUnit(CyAsDeviceHandle handle,
                       CyAsStorageQueryUnitData* data_p,
                       CyAsFunctionCallback cb,
                       uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    return MyStorageQueryUnit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
            data_p->device, data_p->unit, cb, client) ;
}


static CyAsReturnStatus_t
CyAsGetBlockSize(CyAsDevice *dev_p,
                    CyAsBusNumber_t bus,
                    uint32_t device,
                    CyAsFunctionCallback cb)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;

    reply_p = CyAsLLCreateResponse(dev_p, 4) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
        {
            ret = CY_AS_ERROR_NO_SUCH_BUS ;
            goto destroy ;
        }

        if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_DEVICE_DESCRIPTOR)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        /* Make sure the response is about the media type we asked about - if not, firmware error */
        if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)) != bus) ||
            (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)) != device) )
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }


        dev_p->storage_device_info[bus][device].block_size = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
    }
    else
        ret = CY_AS_ERROR_INVALID_REQUEST ;

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
MyStorageDeviceControl(
        CyAsDevice          *dev_p,
        CyAsBusNumber_t      bus,
        uint32_t             device,
        CyBool               card_detect_en,
        CyBool               write_prot_en,
                CyAsStorageCardDetect config_detect,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret ;
    CyBool use_gpio = CyFalse ;

    (void)device ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    if (!CyAsDeviceIsFirmwareLoaded(dev_p))
        return CY_AS_ERROR_NO_FIRMWARE ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    /* If SD is not supported on the specified bus, then return ERROR */
    if((dev_p->media_supported[bus] ==0 ) || (dev_p->media_supported[bus] &(1<<CyAsMediaNand)))
        return CY_AS_ERROR_NOT_SUPPORTED;

    if(config_detect == CyAsStorageDetect_GPIO)
        use_gpio = CyTrue ;
    else if(config_detect == CyAsStorageDetect_SDAT_3)
        use_gpio = CyFalse ;
    else
        return CY_AS_ERROR_INVALID_PARAMETER ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SD_INTERFACE_CONTROL, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (((uint16_t)card_detect_en << 8) | ((uint16_t)use_gpio << 1) | (uint16_t)write_prot_en)) ;

    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_DEVICECONTROL,
            0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }
destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageDeviceControl(CyAsDeviceHandle handle,
                            CyAsBusNumber_t bus,
                            uint32_t device,
                            CyBool card_detect_en,
                            CyBool write_prot_en,
                            CyAsStorageCardDetect config_detect,
                            CyAsFunctionCallback cb,
                            uint32_t client)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    return MyStorageDeviceControl(dev_p, bus, device, card_detect_en, write_prot_en, config_detect, cb, client);
}

static void
CyAsAsyncStorageCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t ret)
{
    CyAsStorageCallback_dep cb ;
    CyAsStorageCallback cb_ms ;

    (void)size ;
    (void)buf_p ;
    (void)ep ;

    CyAsDeviceClearStorageAsyncPending(dev_p) ;

    /*
    * If the LL request callback has already been called, the user
    * callback has to be called from here.
    */
    if (!dev_p->storage_wait)
    {
            CyAsHalAssert(dev_p->storage_cb != NULL || dev_p->storage_cb_ms != NULL) ;
            cb = dev_p->storage_cb ;
            cb_ms = dev_p->storage_cb_ms ;

            dev_p->storage_cb = 0 ;
            dev_p->storage_cb_ms = 0 ;

            if (ret == CY_AS_ERROR_SUCCESS)
                ret = dev_p->storage_error ;

        if (cb_ms)
        {
            cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
                dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
        }
        else
        {
            cb((CyAsDeviceHandle)dev_p,
                dev_p->storage_device_info[dev_p->storage_bus_index][dev_p->storage_device_index].type,
                dev_p->storage_device_index, dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
        }
    }
    else
        dev_p->storage_error = ret ;
}

static void
CyAsAsyncStorageReplyCallback(
                              CyAsDevice *dev_p,
                              uint8_t context,
                              CyAsLLRequestResponse *rqt,
                              CyAsLLRequestResponse *resp,
                              CyAsReturnStatus_t ret)
{
    CyAsStorageCallback_dep cb ;
    CyAsStorageCallback cb_ms ;
    uint8_t reqtype ;
    (void)rqt ;
    (void)context ;

    reqtype = CyAsLLRequestResponse_GetCode(rqt) ;

    if (ret == CY_AS_ERROR_SUCCESS)
    {
        if (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_ANTIOCH_DEFERRED_ERROR)
        {
            ret = CyAsLLRequestResponse_GetWord(resp, 0) & 0x00FF ;
        }
        else if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        }
    }

    if (ret != CY_AS_ERROR_SUCCESS)
    {
        if(reqtype == CY_RQT_READ_BLOCK)
            CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
        else
            CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
    }

    dev_p->storage_wait = CyFalse ;

    /*
    * If the DMA callback has already been called, the user callback
    * has to be called from here.
    */
    if (!CyAsDeviceIsStorageAsyncPending(dev_p))
    {
            CyAsHalAssert(dev_p->storage_cb != NULL || dev_p->storage_cb_ms != NULL) ;
        cb = dev_p->storage_cb ;
        cb_ms = dev_p->storage_cb_ms ;

            dev_p->storage_cb = 0 ;
            dev_p->storage_cb_ms = 0 ;

            if (ret == CY_AS_ERROR_SUCCESS)
                ret = dev_p->storage_error ;

        if (cb_ms)
        {
            cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
                dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
        }
        else
        {
            cb((CyAsDeviceHandle)dev_p,
                dev_p->storage_device_info[dev_p->storage_bus_index][dev_p->storage_device_index].type,
                dev_p->storage_device_index, dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
        }
    }
    else
        dev_p->storage_error = ret ;
}

static CyAsReturnStatus_t
CyAsStorageAsyncOper(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, uint8_t reqtype, uint16_t req_flags,
                     CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
                     uint32_t block, void *data_p, uint16_t num_blocks,
                     CyAsStorageCallback_dep callback, CyAsStorageCallback callback_ms)
{
    uint32_t mask ;
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (unit > 255)
        return CY_AS_ERROR_NO_SUCH_UNIT ;

    /* We are supposed to return sucess if the number of
    * blocks is zero
    */
    if (num_blocks == 0)
    {
        if (callback_ms)
            callback_ms((CyAsDeviceHandle)dev_p, bus, device, unit, block,
                ((reqtype == CY_RQT_WRITE_BLOCK) ? CyAsOpWrite : CyAsOpRead),
                CY_AS_ERROR_SUCCESS) ;
        else
            callback((CyAsDeviceHandle)dev_p, dev_p->storage_device_info[bus][device].type,
                device, unit, block, ((reqtype == CY_RQT_WRITE_BLOCK) ? CyAsOpWrite : CyAsOpRead),
                CY_AS_ERROR_SUCCESS) ;

        return CY_AS_ERROR_SUCCESS ;
    }

    if (dev_p->storage_device_info[bus][device].block_size == 0)
            return CY_AS_ERROR_QUERY_DEVICE_NEEDED ;

    /*
    * Since async operations can be triggered by interrupt code, we must
    * insure that we do not get multiple async operations going at one time and
    * protect this test and set operation from interrupts.
    * Also need to check for pending Async MTP writes
    */
    mask = CyAsHalDisableInterrupts() ;
    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait) || (CyAsDeviceIsUsbAsyncPending(dev_p, 6)))
    {
        CyAsHalEnableInterrupts(mask) ;
        return CY_AS_ERROR_ASYNC_PENDING ;
    }

    CyAsDeviceSetStorageAsyncPending(dev_p) ;
    CyAsHalEnableInterrupts(mask) ;

    /*
    * Storage information about the currently outstanding request
    */
    dev_p->storage_cb = callback ;
    dev_p->storage_cb_ms = callback_ms ;
    dev_p->storage_bus_index = bus ;
    dev_p->storage_device_index = device ;
    dev_p->storage_unit = unit ;
    dev_p->storage_block_addr = block ;

    /* Initialise the request to send to the West Bridge. */
    req_p = dev_p->storage_rw_req_p ;
    CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;

    /* Initialise the space for reply from the West Bridge. */
    reply_p = dev_p->storage_rw_resp_p ;
    CyAsLLInitResponse(reply_p, 5) ;

    /* Remember which version of the API originated the request */
    req_p->flags |= req_flags ;

    /* Setup the DMA request and adjust the storage operation if we are reading */
    if (reqtype == CY_RQT_READ_BLOCK)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks,
            CyFalse, CyTrue, CyAsAsyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpRead ;
    }
    else if (reqtype == CY_RQT_WRITE_BLOCK)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks,
            CyFalse, CyFalse, CyAsAsyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpWrite ;
    }
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDeviceClearStorageAsyncPending(dev_p) ;
        return ret ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, (uint8_t)unit)) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((block >> 16) & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(block & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_blocks >> 8) & 0x00ff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_blocks << 8) & 0xff00)) ;

    /* Set the burst mode flag. */
    if (dev_p->is_storage_only_mode)
        req_p->data[4] |= 0x0001;

    /* Send the request and wait for completion of storage request */
    dev_p->storage_wait = CyTrue ;
    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsAsyncStorageReplyCallback) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
        CyAsDeviceClearStorageAsyncPending(dev_p) ;
    }

    return ret ;
}

static void
CyAsSyncStorageCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
{
    (void)ep ;
    (void)buf_p ;
    (void)size ;

    dev_p->storage_error = err ;
}

static void
CyAsSyncStorageReplyCallback(
                             CyAsDevice *dev_p,
                             uint8_t context,
                             CyAsLLRequestResponse *rqt,
                             CyAsLLRequestResponse *resp,
                             CyAsReturnStatus_t ret)
{
    uint8_t reqtype ;
    (void)rqt ;

    reqtype = CyAsLLRequestResponse_GetCode(rqt) ;

    if (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_ANTIOCH_DEFERRED_ERROR)
    {
        ret = CyAsLLRequestResponse_GetWord(resp, 0) & 0x00FF ;

        if (ret != CY_AS_ERROR_SUCCESS)
        {
            if(reqtype == CY_RQT_READ_BLOCK)
                CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
            else
                CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
        }
    }
    else if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }

    dev_p->storage_wait = CyFalse ;
    dev_p->storage_error = ret ;

    /* Wake any threads/processes that are waiting on the read/write completion. */
    CyAsHalWake (&dev_p->context[context]->channel) ;
}

static CyAsReturnStatus_t
CyAsStorageSyncOper(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, uint8_t reqtype, CyAsBusNumber_t bus, uint32_t device,
                    uint32_t unit, uint32_t block, void *data_p, uint16_t num_blocks)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsContext *ctxt_p ;
    uint32_t loopcount = 200 ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (unit > 255)
        return CY_AS_ERROR_NO_SUCH_UNIT ;

    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
        return CY_AS_ERROR_ASYNC_PENDING ;

    /* Also need to check for pending Async MTP writes */
    if(CyAsDeviceIsUsbAsyncPending(dev_p, 6))
        return CY_AS_ERROR_ASYNC_PENDING ;

    /* We are supposed to return sucess if the number of
    * blocks is zero
    */
    if (num_blocks == 0)
        return CY_AS_ERROR_SUCCESS ;

    if (dev_p->storage_device_info[bus][device].block_size == 0)
    {
        /*
        * Normally, a given device has been queried via the query device call before a
        * read request is issued.  Therefore, this normally will not be run.
        */
        ret = CyAsGetBlockSize(dev_p, bus, device, 0) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            return ret ;
    }

    /* Initialise the request to send to the West Bridge. */
    req_p = dev_p->storage_rw_req_p ;
    CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;

    /* Initialise the space for reply from the West Bridge. */
    reply_p = dev_p->storage_rw_resp_p ;
    CyAsLLInitResponse(reply_p, 5) ;

    /* Setup the DMA request */
    if (reqtype == CY_RQT_READ_BLOCK)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks, CyFalse,
            CyTrue, CyAsSyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpRead ;
    }
    else if (reqtype == CY_RQT_WRITE_BLOCK)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks, CyFalse,
            CyFalse, CyAsSyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpWrite ;
    }
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        return ret ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, (uint8_t)unit)) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((block >> 16) & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(block & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_blocks >> 8) & 0x00ff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_blocks << 8) & 0xff00)) ;

    /* Set the burst mode flag. */
    if (dev_p->is_storage_only_mode)
        req_p->data[4] |= 0x0001;

    /* Send the request and wait for completion of storage request */
    dev_p->storage_wait = CyTrue ;
    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSyncStorageReplyCallback) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
    }
    else
    {
        /* Setup the DMA request */
        ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
        ret = CyAsDmaDrainQueue(dev_p, ep, CyFalse) ;

        while (loopcount-- > 0)
        {
            if (dev_p->storage_wait == CyFalse)
                break ;
            CyAsHalSleepOn(&ctxt_p->channel, 10) ;
        }

        if (dev_p->storage_wait == CyTrue)
        {
            dev_p->storage_wait = CyFalse ;
            CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
            ret = CY_AS_ERROR_TIMEOUT ;
        }

        if (ret == CY_AS_ERROR_SUCCESS)
            ret = dev_p->storage_error ;
    }

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageRead(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit, uint32_t block,
                void *data_p, uint16_t num_blocks)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    return CyAsStorageSyncOper(dev_p, dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK, bus, device,
        unit, block, data_p, num_blocks) ;
}

CyAsReturnStatus_t
CyAsStorageWrite(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit, uint32_t block,
                 void *data_p, uint16_t num_blocks)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if(dev_p->mtp_turbo_active)
        return CY_AS_ERROR_NOT_VALID_DURING_MTP ;

    return CyAsStorageSyncOper(dev_p, dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK, bus, device,
        unit, block, data_p, num_blocks) ;
}


CyAsReturnStatus_t
CyAsStorageReadAsync(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
                     uint32_t block, void *data_p, uint16_t num_blocks, CyAsStorageCallback callback)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (callback == 0)
        return CY_AS_ERROR_NULL_CALLBACK ;

    return CyAsStorageAsyncOper(dev_p, dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK,
        CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block, data_p, num_blocks, NULL, callback);
}

CyAsReturnStatus_t
CyAsStorageWriteAsync(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
                      uint32_t block, void *data_p, uint16_t num_blocks, CyAsStorageCallback callback)
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (callback == 0)
        return CY_AS_ERROR_NULL_CALLBACK ;

    if(dev_p->mtp_turbo_active)
        return CY_AS_ERROR_NOT_VALID_DURING_MTP ;

    return CyAsStorageAsyncOper(dev_p, dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK,
        CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block, data_p, num_blocks, NULL, callback);
}


static void
MyStorageCancelCallback (
        CyAsDevice *dev_p,
        uint8_t context,
        CyAsLLRequestResponse *rqt,
        CyAsLLRequestResponse *resp,
        CyAsReturnStatus_t stat)
{
    (void)context ;
    (void)stat ;

    /* Nothing to do here, except free up the request and response structures. */
    CyAsLLDestroyResponse(dev_p, resp) ;
    CyAsLLDestroyRequest(dev_p, rqt) ;
}


CyAsReturnStatus_t
CyAsStorageCancelAsync(CyAsDeviceHandle handle)
{
    CyAsReturnStatus_t ret ;
    CyAsLLRequestResponse *req_p , *reply_p ;

    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (!CyAsDeviceIsStorageAsyncPending(dev_p))
        return CY_AS_ERROR_ASYNC_NOT_PENDING ;

    /*
     * Create and send a mailbox request to firmware asking it to abort processing
     * of the current P2S operation. The rest of the cancel processing will be
     * driven through the callbacks for the read/write call.
     */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ABORT_P2S_XFER, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MyStorageCancelCallback) ;
    if (ret)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    }

    return CY_AS_ERROR_SUCCESS ;
}

/*
 * This function does all the API side clean-up associated with
 * CyAsStorageStop, without any communication with the firmware.
 */
void CyAsStorageCleanup(CyAsDevice *dev_p)
{
    if (dev_p->storage_count)
    {
        CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
        CyAsLLDestroyResponse(dev_p, dev_p->storage_rw_resp_p) ;
        dev_p->storage_count = 0 ;
        CyAsDeviceClearScsiMessages(dev_p) ;
        CyAsHalMemSet(dev_p->storage_device_info, 0, sizeof(dev_p->storage_device_info)) ;

        CyAsDeviceClearStorageAsyncPending(dev_p) ;
        dev_p->storage_cb = 0 ;
        dev_p->storage_cb_ms = 0 ;
        dev_p->storage_wait = CyFalse ;
    }
}

static CyAsReturnStatus_t
MyHandleResponseSDRegRead(
        CyAsDevice               *dev_p,
        CyAsLLRequestResponse    *req_p,
        CyAsLLRequestResponse    *reply_p,
        CyAsStorageSDRegReadData *info)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t  resp_type, i ;
    uint16_t resp_len ;
    uint8_t  length = info->length ;
    uint8_t *data_p = info->buf_p ;

    resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;
    if (resp_type == CY_RESP_SD_REGISTER_DATA)
    {
        uint16_t *resp_p = reply_p->data + 1 ;
        uint16_t temp ;

        resp_len = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        CyAsHalAssert(resp_len >= length) ;

        /*
         * Copy the values into the output buffer after doing the
         * necessary bit shifting. The bit shifting is required because
         * the data comes out of the West Bridge with a 6 bit offset.
         */
        i = 0 ;
        while (length)
        {
            temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10)) ;
            i++ ;

            *data_p++ = (uint8_t)(temp >> 8) ;
            length-- ;

            if (length)
            {
                *data_p++ = (uint8_t)(temp & 0xFF) ;
                length-- ;
            }
        }
    }
    else
    {
        if (resp_type == CY_RESP_SUCCESS_FAILURE)
            ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        else
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }

    CyAsLLDestroyResponse(dev_p, reply_p) ;
    CyAsLLDestroyRequest(dev_p, req_p) ;
    (void)resp_len;
    return ret ;
}

CyAsReturnStatus_t
CyAsStorageSDRegisterRead(
        CyAsDeviceHandle          handle,
        CyAsBusNumber_t           bus,
        uint8_t                   device,
        CyAsSDCardRegType         regType,
        CyAsStorageSDRegReadData *data_p,
        CyAsFunctionCallback      cb,
        uint32_t                  client)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t  length ;

    /*
     * Sanity checks required before sending the request to the
     * firmware.
     */
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (regType > CyAsSDReg_CSD)
        return CY_AS_ERROR_INVALID_PARAMETER ;

    /* If SD/MMC media is not supported on the addressed bus, return error. */
    if ((dev_p->media_supported[bus] & (1 << CyAsMediaSDFlash)) == 0)
        return CY_AS_ERROR_INVALID_PARAMETER ;

    /*
     * Find the amount of data to be returned. This will be the minimum of
     * the actual data length, and the length requested.
     */
    switch (regType)
    {
        case CyAsSDReg_OCR:
            length = CY_AS_SD_REG_OCR_LENGTH ;
            break ;

        case CyAsSDReg_CID:
            length = CY_AS_SD_REG_CID_LENGTH ;
            break ;

        case CyAsSDReg_CSD:
            length = CY_AS_SD_REG_CSD_LENGTH ;
            break ;

        default:
            length = 0 ;
            CyAsHalAssert(0) ;
    }

    if (length < data_p->length)
        data_p->length = length ;
    length = data_p->length ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SD_REGISTER_READ, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, (CreateAddress(bus, device, 0) | (uint16_t)regType)) ;

    reply_p = CyAsLLCreateResponse(dev_p, CY_AS_SD_REG_MAX_RESP_LENGTH) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    if (cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseSDRegRead(dev_p, req_p, reply_p, data_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_SDREGISTERREAD,
            data_p, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
            req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the MiscFuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageCreatePPartition(
        CyAsDeviceHandle        handle,                 /* Handle to the device of interest */
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint32_t                size, /* of P-port only partition in blocks */
        CyAsFunctionCallback    cb,
        uint32_t                client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Partitions cannot be created or deleted while the USB stack is active. */
    if (dev_p->usb_count)
        return CY_AS_ERROR_USB_RUNNING ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PARTITION_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
    if (req_p == 0)
    {
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    /* Reserve space for the reply, the reply data will not exceed one word */
    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }
    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00) );
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((size >> 16) & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(size & 0xffff)) ;

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_PARTITION,
            0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the FuncCallback */
        return ret ;

    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageRemovePPartition(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        CyAsFunctionCallback    cb,
        uint32_t                client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Partitions cannot be created or deleted while the USB stack is active. */
    if (dev_p->usb_count)
        return CY_AS_ERROR_USB_RUNNING ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PARTITION_ERASE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
    {
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    /* Reserve space for the reply, the reply data will not exceed one word */
    reply_p = CyAsLLCreateResponse(dev_p, 1) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00) );

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_NODATA,
            0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the FuncCallback */
        return ret ;

    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static CyAsReturnStatus_t
MyHandleResponseGetTransferAmount(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         CyAsMSCProgressData *data)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
    uint16_t v1, v2 ;

    if (code != CY_RESP_TRANSFER_COUNT)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        goto destroy ;
    }

    v1 = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    v2 = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
    data->wr_count = (uint32_t)((v1 << 16) | v2) ;

    v1 = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
    v2 = CyAsLLRequestResponse_GetWord(reply_p, 3) ;
    data->rd_count = (uint32_t)((v1 << 16) | v2) ;

destroy :
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

CyAsReturnStatus_t
CyAsStorageGetTransferAmount(
        CyAsDeviceHandle handle,
        CyAsBusNumber_t  bus,
        uint32_t device,
        CyAsMSCProgressData *data_p,
        CyAsFunctionCallback cb,
        uint32_t client
    )
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Check if the firmware image supports this feature. */
    if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] == (1 << CyAsMediaNand)))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_TRANSFER_AMOUNT, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
    {
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    /* Reserve space for the reply, the reply data will not exceed four words. */
    reply_p = CyAsLLCreateResponse(dev_p, 4) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00));

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        return MyHandleResponseGetTransferAmount(dev_p, req_p, reply_p, data_p) ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT,
            (void *)data_p, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the FuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;

}

CyAsReturnStatus_t
CyAsStorageErase(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint32_t                erase_unit,
        uint16_t                num_erase_units,
        CyAsFunctionCallback    cb,
        uint32_t                client
        )
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    ret = IsStorageActive(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (dev_p->storage_device_info[bus][device].block_size == 0)
        return CY_AS_ERROR_QUERY_DEVICE_NEEDED ;

    /* If SD is not supported on the specified bus, then return ERROR */
    if(dev_p->storage_device_info[bus][device].type != CyAsMediaSDFlash)
        return CY_AS_ERROR_NOT_SUPPORTED;

    if (num_erase_units == 0)
        return CY_AS_ERROR_SUCCESS ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ERASE, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
    if (req_p == 0)
    {
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    /* Reserve space for the reply, the reply data will not exceed four words. */
    reply_p = CyAsLLCreateResponse(dev_p, 4) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00));
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((erase_unit >> 16) & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(erase_unit & 0xffff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_erase_units >> 8) & 0x00ff)) ;
    CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_erase_units << 8) & 0xff00)) ;

    if(cb == 0)
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        ret = MyHandleResponseNoData(dev_p, req_p, reply_p) ;

        /* If error = "invalid response", this (very likely) means that we are not using the SD-only firmware module
        which is the only one supporting StorageErase. In this case force a "non supported" error code */
        if (ret == CY_AS_ERROR_INVALID_RESPONSE)
            ret = CY_AS_ERROR_NOT_SUPPORTED;

        return ret ;
    }
    else
    {
        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_ERASE,
            0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
                req_p, reply_p, CyAsStorageFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
            goto destroy ;

        /* The request and response are freed as part of the FuncCallback */
        return ret ;
    }

destroy:
    CyAsLLDestroyRequest(dev_p, req_p) ;
    CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

static void
CyAsStorageFuncCallback(CyAsDevice *dev_p,
                        uint8_t context,
                        CyAsLLRequestResponse *rqt,
                        CyAsLLRequestResponse *resp,
                        CyAsReturnStatus_t stat)
{
    CyAsFuncCBNode* node = (CyAsFuncCBNode*)dev_p->func_cbs_stor->head_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    CyBool              exRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) == CY_AS_REQUEST_RESPONSE_EX ;
    CyBool              msRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) == CY_AS_REQUEST_RESPONSE_MS ;
    uint8_t             code ;
    uint8_t             cntxt ;

    CyAsHalAssert(exRequest || msRequest) ;
    CyAsHalAssert(dev_p->func_cbs_stor->count != 0) ;
    CyAsHalAssert(dev_p->func_cbs_stor->type == CYAS_FUNC_CB) ;
    (void) exRequest;
    (void) msRequest;
    (void)cntxt;
    (void)context ;

    cntxt = CyAsLLRequestResponse_GetContext(rqt) ;
    CyAsHalAssert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT) ;

    code = CyAsLLRequestResponse_GetCode(rqt) ;
    switch(code)
    {
    case CY_RQT_START_STORAGE:
        ret = MyHandleResponseStorageStart(dev_p, rqt, resp, stat) ;
        break ;
    case CY_RQT_STOP_STORAGE:
        ret = MyHandleResponseStorageStop(dev_p, rqt, resp, stat) ;
        break ;
    case CY_RQT_CLAIM_STORAGE:
        ret = MyHandleResponseStorageClaim(dev_p, rqt, resp) ;
        break ;
    case CY_RQT_RELEASE_STORAGE:
        ret = MyHandleResponseStorageRelease(dev_p, rqt, resp) ;
        break ;
    case CY_RQT_QUERY_MEDIA:
        CyAsHalAssert(CyFalse) ;        /* Not used any more. */
        break ;
    case CY_RQT_QUERY_BUS:
        CyAsHalAssert(node->data != 0) ;
        ret = MyHandleResponseStorageQueryBus(dev_p, rqt, resp, (uint32_t*)node->data) ;
        break ;
    case CY_RQT_QUERY_DEVICE:
        CyAsHalAssert(node->data != 0) ;
        ret = MyHandleResponseStorageQueryDevice(dev_p, rqt, resp, node->data) ;
        break ;
    case CY_RQT_QUERY_UNIT:
        CyAsHalAssert(node->data != 0) ;
        ret = MyHandleResponseStorageQueryUnit(dev_p, rqt, resp, node->data) ;
        break ;
    case CY_RQT_SD_INTERFACE_CONTROL:
        ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
        break ;
    case CY_RQT_SD_REGISTER_READ:
        CyAsHalAssert(node->data != 0) ;
        ret = MyHandleResponseSDRegRead(dev_p, rqt, resp, (CyAsStorageSDRegReadData *)node->data) ;
        break ;
    case CY_RQT_PARTITION_STORAGE:
        ret = MyHandleResponseNoData(dev_p, rqt, resp);
        break ;
    case CY_RQT_PARTITION_ERASE:
        ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
        break ;
    case CY_RQT_GET_TRANSFER_AMOUNT:
        CyAsHalAssert(node->data != 0) ;
        ret = MyHandleResponseGetTransferAmount(dev_p, rqt, resp, (CyAsMSCProgressData *)node->data) ;
        break ;
    case CY_RQT_ERASE:
        ret = MyHandleResponseNoData(dev_p, rqt, resp) ;

        /* If error = "invalid response", this (very likely) means that we are not using the SD-only firmware module
        which is the only one supporting StorageErase. In this case force a "non supported" error code */
        if (ret == CY_AS_ERROR_INVALID_RESPONSE)
            ret = CY_AS_ERROR_NOT_SUPPORTED;

        break ;

    default:
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        CyAsHalAssert(CyFalse) ;
        break ;
    }

    /*
     * If the low level layer returns a direct error, use the corresponding error code.
     * If not, use the error code based on the response from firmware.
     */
    if (stat == CY_AS_ERROR_SUCCESS)
        stat = ret ;

    /* Call the user callback, if there is one */
    if (node->cb_p)
        node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
    CyAsRemoveCBNode(dev_p->func_cbs_stor) ;
}


static void
CyAsSdioSyncReplyCallback(
        CyAsDevice *dev_p,
        uint8_t context,
        CyAsLLRequestResponse *rqt,
        CyAsLLRequestResponse *resp,
        CyAsReturnStatus_t ret)
{
    (void)rqt ;

    if ((CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_GET_TUPLE )||
            (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_EXT))
    {
        ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
        if ((ret & 0x00FF) != CY_AS_ERROR_SUCCESS)
        {
            if(CyAsLLRequestResponse_GetCode(rqt) == CY_RQT_SDIO_READ_EXTENDED)
                CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
            else
                CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
        }
    }
    else
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }

    dev_p->storage_rw_resp_p=resp;
    dev_p->storage_wait = CyFalse ;
    if(((ret & 0x00FF) == CY_AS_ERROR_IO_ABORTED) || ((ret & 0x00FF) == CY_AS_ERROR_IO_SUSPENDED))
        dev_p->storage_error =  (ret & 0x00FF);
    else
        dev_p->storage_error = (ret & 0x00FF)? CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS ;

    /* Wake any threads/processes that are waiting on the read/write completion. */
    CyAsHalWake (&dev_p->context[context]->channel);
}

CyAsReturnStatus_t
CyAsSdioDeviceCheck(
        CyAsDevice*         dev_p,
        CyAsBusNumber_t     bus,
        uint32_t            device)
{
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (!CyAsDeviceIsAstoriaDev(dev_p))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    return  (IsStorageActive(dev_p)) ;
}

CyAsReturnStatus_t
CyAsSdioDirectIo(
        CyAsDeviceHandle    handle,
        CyAsBusNumber_t     bus,
        uint32_t            device,
        uint8_t             nFunctionNo,
        uint32_t            address,
        uint8_t             miscBuf,
        uint16_t            argument,
        uint8_t             isWrite,
        uint8_t *           data_p )
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint16_t resp_data;

    /*
     * Sanity checks required before sending the request to the
     * firmware.
     */
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;


    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
        return CY_AS_ERROR_FUNCTION_SUSPENDED;

    req_p = CyAsLLCreateRequest(dev_p, (isWrite==CyTrue)?CY_RQT_SDIO_WRITE_DIRECT:CY_RQT_SDIO_READ_DIRECT,
            CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    /*Setting up request*/

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;
    /* D1 */
    if(isWrite==CyTrue)
    {
        CyAsLLRequestResponse_SetWord(req_p, 1,  ((argument<<8)|0x0080|(nFunctionNo<<4)|
                    ((miscBuf&CY_SDIO_RAW)<<3)|((miscBuf&CY_SDIO_REARM_INT)>>5)|(uint16_t)(address>>15)));
    }
    else
    {
        CyAsLLRequestResponse_SetWord(req_p, 1,  (nFunctionNo<<4)|((miscBuf&CY_SDIO_REARM_INT)>>5)|
                (uint16_t)(address>>15));
    }
    /* D2 */
    CyAsLLRequestResponse_SetWord(req_p, 2,  ((uint16_t)((address&0x00007fff)<<1))) ;

    /*Create response*/
    reply_p = CyAsLLCreateResponse(dev_p, 2) ;

    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    /*Sending the request*/
    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    /*Check reply type*/
    if ( CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SDIO_DIRECT)
    {
        resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        if(resp_data>>8)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        }
        else if (data_p!=0)
            *(uint8_t*)(data_p)=(uint8_t)(resp_data&0x00ff);
    }
    else
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }

destroy:
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;
}


CyAsReturnStatus_t
CyAsSdioDirectRead(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint8_t                 nFunctionNo,
        uint32_t                address,
        uint8_t                 miscBuf,
        uint8_t *               data_p)
{
    return (CyAsSdioDirectIo(handle,bus,device, nFunctionNo, address, miscBuf, 0x00, CyFalse, data_p));
}

CyAsReturnStatus_t
CyAsSdioDirectWrite(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint8_t                 nFunctionNo,
        uint32_t                address,
        uint8_t                 miscBuf,
        uint16_t                argument,
        uint8_t *               data_p)
{
    return (CyAsSdioDirectIo(handle,bus,device, nFunctionNo, address, miscBuf, argument, CyTrue, data_p));
}

/*Cmd53 IO*/
CyAsReturnStatus_t
CyAsSdioExtendedIO(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint8_t                 nFunctionNo,
        uint32_t                address,
        uint8_t                 miscBuf,
        uint16_t                argument,
        uint8_t                 isWrite,
        uint8_t *               data_p ,
        uint8_t                 isResume)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t resp_type;
    uint8_t reqtype;
    uint16_t resp_data;
    CyAsContext *ctxt_p ;
    uint32_t  dmasize,loopcount = 200;
    CyAsEndPointNumber_t ep;

    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;


    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
        return CY_AS_ERROR_FUNCTION_SUSPENDED;


    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
        return CY_AS_ERROR_ASYNC_PENDING ;

    /* Request for 0 bytes of blocks is returned as a success*/
    if(argument == 0)
        return CY_AS_ERROR_SUCCESS;

    /* Initialise the request to send to the West Bridge device. */
    if(isWrite == CyTrue)
    {
        reqtype =CY_RQT_SDIO_WRITE_EXTENDED;
        ep=dev_p->storage_write_endpoint;
    }
    else
    {
        reqtype=CY_RQT_SDIO_READ_EXTENDED;
        ep=dev_p->storage_read_endpoint;
    }

    req_p = dev_p->storage_rw_req_p ;
    CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;

    /* Initialise the space for reply from the Antioch. */
    reply_p = dev_p->storage_rw_resp_p ;
    CyAsLLInitResponse(reply_p, 2) ;

    /* Setup the DMA request */
    if(!(miscBuf&CY_SDIO_BLOCKMODE))
    {
        if(argument > dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize)
            return CY_AS_ERROR_INVALID_BLOCKSIZE;

    }
    else
    {
        if( argument > 511)
        {
            return CY_AS_ERROR_INVALID_BLOCKSIZE;
        }
    }

    if(argument == 512)
        argument =0;

    dmasize=((miscBuf&CY_SDIO_BLOCKMODE) !=0)? dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize*argument:argument;

    ret = CyAsDmaQueueRequest(dev_p, ep, (void*)(data_p), dmasize, CyFalse,
            (isWrite & CyTrue)?CyFalse:CyTrue, CyAsSyncStorageCallback) ;

    if (ret != CY_AS_ERROR_SUCCESS)
    {
        return ret ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo|((isResume)?0x80:0x00) )) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, ((uint16_t)nFunctionNo)<<12|
            ((uint16_t)(miscBuf&(CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))<<9|
            (uint16_t)(address>>7)|((isWrite==CyTrue)?0x8000:0x0000 )) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, ((uint16_t)(address&0x0000ffff)<<9) |  argument) ;


    /* Send the request and wait for completion of storage request */
    dev_p->storage_wait = CyTrue ;
    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioSyncReplyCallback) ;

    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
    }
    else
    {
        /* Setup the DMA request */
        ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
        ret = CyAsDmaDrainQueue(dev_p, ep, CyTrue) ;

        while (loopcount-- > 0)
        {
            if (dev_p->storage_wait == CyFalse)
                break;
            CyAsHalSleepOn(&ctxt_p->channel, 10) ;
        }
        if (dev_p->storage_wait == CyTrue)
        {
            dev_p->storage_wait = CyFalse ;
            CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
            dev_p->storage_error = CY_AS_ERROR_TIMEOUT ;
        }

        ret=dev_p->storage_error;

        if (ret != CY_AS_ERROR_SUCCESS)
        {
            return ret ;
        }


        resp_type = CyAsLLRequestResponse_GetCode(dev_p->storage_rw_resp_p) ;
        if (resp_type == CY_RESP_SDIO_EXT)
        {
            resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0)&0x00ff ;
            if(resp_data)
            {
                ret = CY_AS_ERROR_INVALID_REQUEST ;
            }

        }
        else
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        }
    }
    return ret;

}

static void
CyAsSdioAsyncReplyCallback(
        CyAsDevice*             dev_p,
        uint8_t                 context,
        CyAsLLRequestResponse*  rqt,
        CyAsLLRequestResponse*  resp,
        CyAsReturnStatus_t      ret )
{
    CyAsStorageCallback cb_ms ;
    uint8_t reqtype ;
    uint32_t pendingblocks;
    (void)rqt ;
    (void)context ;

    pendingblocks = 0;
    reqtype = CyAsLLRequestResponse_GetCode(rqt) ;
    if (ret == CY_AS_ERROR_SUCCESS)
    {
        if ((CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SUCCESS_FAILURE) ||
                (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_EXT))
        {
            ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
            ret &= 0x00FF ;
        }
        else
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        }
    }

    if (ret != CY_AS_ERROR_SUCCESS)
    {
        if(reqtype == CY_RQT_SDIO_READ_EXTENDED)
            CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
        else
            CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;

        dev_p->storage_error = ret;
    }



    dev_p->storage_wait = CyFalse ;

    /*
     * If the DMA callback has already been called, the user callback
     * has to be called from here.
     */
    if (!CyAsDeviceIsStorageAsyncPending(dev_p))
    {
        CyAsHalAssert(dev_p->storage_cb_ms != NULL) ;
        cb_ms = dev_p->storage_cb_ms ;

        dev_p->storage_cb = 0 ;
        dev_p->storage_cb_ms = 0 ;

        if ((ret == CY_AS_ERROR_SUCCESS) || (ret == CY_AS_ERROR_IO_ABORTED) || (ret == CY_AS_ERROR_IO_SUSPENDED))
        {
            ret = dev_p->storage_error ;
            pendingblocks = ((uint32_t)CyAsLLRequestResponse_GetWord(resp, 1))<<16;
        }
        else
            ret = CY_AS_ERROR_INVALID_RESPONSE;

        cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
                (dev_p->storage_unit | pendingblocks), dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
    }
    else
        dev_p->storage_error = ret ;
}


CyAsReturnStatus_t
CyAsSdioExtendedIOAsync(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint32_t                    address,
        uint8_t                     miscBuf,
        uint16_t                    argument,
        uint8_t                     isWrite,
        uint8_t *                   data_p,
        CyAsStorageCallback       callback )
{

    uint32_t mask ;
    uint32_t dmasize;
    CyAsLLRequestResponse *req_p , *reply_p ;
    uint8_t reqtype;
    CyAsEndPointNumber_t ep;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
        return CY_AS_ERROR_FUNCTION_SUSPENDED;

    if (callback == 0)
        return CY_AS_ERROR_NULL_CALLBACK ;

    /* We are supposed to return sucess if the number of
     * blocks is zero
     */
    if(((miscBuf&CY_SDIO_BLOCKMODE)!=0)&&(argument==0))
    {
        callback(handle, bus, device,nFunctionNo,address,((isWrite) ? CyAsOpWrite : CyAsOpRead), CY_AS_ERROR_SUCCESS) ;
        return CY_AS_ERROR_SUCCESS ;
    }


    /*
     * Since async operations can be triggered by interrupt code, we must
     * insure that we do not get multiple async operations going at one time and
     * protect this test and set operation from interrupts.
     */
    mask = CyAsHalDisableInterrupts() ;
    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
    {
        CyAsHalEnableInterrupts(mask) ;
        return CY_AS_ERROR_ASYNC_PENDING ;
    }
    CyAsDeviceSetStorageAsyncPending(dev_p) ;
    CyAsHalEnableInterrupts(mask) ;


    /*
     * Storage information about the currently outstanding request
     */
    dev_p->storage_cb_ms = callback ;
    dev_p->storage_bus_index = bus ;
    dev_p->storage_device_index = device ;
    dev_p->storage_unit = nFunctionNo ;
    dev_p->storage_block_addr = address ;

    if(isWrite == CyTrue)
    {
        reqtype =CY_RQT_SDIO_WRITE_EXTENDED;
        ep=dev_p->storage_write_endpoint;
    }
    else
    {
        reqtype=CY_RQT_SDIO_READ_EXTENDED;
        ep=dev_p->storage_read_endpoint;
    }

    /* Initialise the request to send to the West Bridge. */
    req_p = dev_p->storage_rw_req_p ;
    CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;

    /* Initialise the space for reply from the West Bridge. */
    reply_p = dev_p->storage_rw_resp_p ;
    CyAsLLInitResponse(reply_p, 2) ;

    if(!(miscBuf&CY_SDIO_BLOCKMODE))
    {
        if(argument > dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize)
            return CY_AS_ERROR_INVALID_BLOCKSIZE;

    }
    else
    {
        if( argument > 511)
        {
            return CY_AS_ERROR_INVALID_BLOCKSIZE;
        }
    }

    if(argument == 512)
        argument =0;
    dmasize=((miscBuf&CY_SDIO_BLOCKMODE) !=0)? dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize*argument:argument;

    /* Setup the DMA request and adjust the storage operation if we are reading */
    if (reqtype == CY_RQT_SDIO_READ_EXTENDED)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, (void*)data_p,dmasize , CyFalse, CyTrue,CyAsAsyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpRead ;
    }
    else if (reqtype == CY_RQT_SDIO_WRITE_EXTENDED)
    {
        ret = CyAsDmaQueueRequest(dev_p, ep, (void*)data_p, dmasize, CyFalse, CyFalse,CyAsAsyncStorageCallback) ;
        dev_p->storage_oper = CyAsOpWrite ;
    }
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDeviceClearStorageAsyncPending(dev_p) ;
        return ret ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, ((uint16_t)nFunctionNo)<<12|
            ((uint16_t)(miscBuf&(CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))<<9|
            (uint16_t)(address>>7)|((isWrite==CyTrue)?0x8000:0x0000 )) ;
    CyAsLLRequestResponse_SetWord(req_p, 2, ((uint16_t)(address&0x0000ffff)<<9) |  argument) ;


    /* Send the request and wait for completion of storage request */
    dev_p->storage_wait = CyTrue ;
    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioAsyncReplyCallback) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
        CyAsDeviceClearStorageAsyncPending(dev_p) ;
    }
    else
    {
        CyAsDmaKickStart(dev_p, ep) ;
    }

    return ret ;
}

/* CMD53 Extended Read*/
CyAsReturnStatus_t
CyAsSdioExtendedRead(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint32_t                    address,
        uint8_t                     miscBuf,
        uint16_t                    argument,
        uint8_t *                   data_p,
        CyAsSdioCallback            callback )
{
    if (callback==0)
        return CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyFalse,data_p,0);

    return CyAsSdioExtendedIOAsync(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyFalse,data_p,callback);
}

/* CMD53 Extended Write*/
CyAsReturnStatus_t
CyAsSdioExtendedWrite(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint32_t                    address,
        uint8_t                     miscBuf,
        uint16_t                    argument,
        uint8_t *                   data_p,
        CyAsSdioCallback            callback )
{
    if (callback==0)
        return CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyTrue,data_p,0);

    return CyAsSdioExtendedIOAsync(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyTrue,data_p,callback);
}


/* Read the CIS info tuples for the given function and Tuple ID*/
CyAsReturnStatus_t
CyAsSdioGetCISInfo(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint16_t                    tupleId,
        uint8_t *                   data_p )
{

    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint16_t resp_data;
    CyAsContext *ctxt_p ;
    uint32_t loopcount = 200;

    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!( CyAsSdioCheckFunctionInitialized(handle,bus,0) ))
        return CY_AS_ERROR_INVALID_FUNCTION;

    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
        return CY_AS_ERROR_ASYNC_PENDING ;


    /* Initialise the request to send to the Antioch. */
    req_p = dev_p->storage_rw_req_p ;
    CyAsLLInitRequest(req_p, CY_RQT_SDIO_GET_TUPLE, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;

    /* Initialise the space for reply from the Antioch. */
    reply_p = dev_p->storage_rw_resp_p ;
    CyAsLLInitResponse(reply_p, 3) ;

    /* Setup the DMA request */
    ret = CyAsDmaQueueRequest(dev_p, dev_p->storage_read_endpoint, data_p+1, 255, CyFalse, CyTrue,
            CyAsSyncStorageCallback) ;

    if (ret != CY_AS_ERROR_SUCCESS)
    {
        return ret ;
    }

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;

    /* Set tuple id to fetch. */
    CyAsLLRequestResponse_SetWord(req_p, 1, tupleId<<8) ;

    /* Send the request and wait for completion of storage request */
    dev_p->storage_wait = CyTrue ;
    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioSyncReplyCallback) ;


    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED) ;
    }
    else
    {
        /* Setup the DMA request */
        ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
        ret = CyAsDmaDrainQueue(dev_p, dev_p->storage_read_endpoint, CyTrue) ;

        while (loopcount-- > 0)
        {
            if (dev_p->storage_wait == CyFalse)
                break;
            CyAsHalSleepOn(&ctxt_p->channel, 10) ;
        }

        if (dev_p->storage_wait == CyTrue)
        {
            dev_p->storage_wait = CyFalse ;
            CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
            return CY_AS_ERROR_TIMEOUT ;
        }
        ret = dev_p->storage_error ;

        if (ret != CY_AS_ERROR_SUCCESS)
        {
            return ret ;
        }

        if ( CyAsLLRequestResponse_GetCode(dev_p->storage_rw_resp_p) == CY_RESP_SDIO_GET_TUPLE)
        {
            resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
            if(resp_data)
            {
                ret = CY_AS_ERROR_INVALID_REQUEST ;
            }
            else if (data_p!=0)
                *(uint8_t*)data_p=(uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)&0x00ff);
        }
        else
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        }
    }
    return ret;
}

/*Query Device*/
CyAsReturnStatus_t
CyAsSdioQueryCard(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        CyAsSDIOCard*               data_p )
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    uint8_t resp_type;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    /* Allocating memory to the SDIO device structure in dev_p */

    CyAsHalMemSet(& dev_p->sdiocard[bus],0,sizeof(CyAsSDIODevice));

    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_QUERY_CARD, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0 )) ;

    reply_p = CyAsLLCreateResponse(dev_p, 5) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;

    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    resp_type = CyAsLLRequestResponse_GetCode(reply_p);
    if ( resp_type == CY_RESP_SDIO_QUERY_CARD)
    {
        dev_p->sdiocard[bus].card.num_functions     = (uint8_t)((reply_p->data[0]&0xff00)>>8);
        dev_p->sdiocard[bus].card.memory_present    = (uint8_t)reply_p->data[0]&0x0001;
        dev_p->sdiocard[bus].card.manufacturer_Id   = reply_p->data[1];
        dev_p->sdiocard[bus].card.manufacturer_info = reply_p->data[2];
        dev_p->sdiocard[bus].card.blocksize         = reply_p->data[3];
        dev_p->sdiocard[bus].card.maxblocksize      = reply_p->data[3];
        dev_p->sdiocard[bus].card.card_capability   = (uint8_t)((reply_p->data[4]&0xff00)>>8);
        dev_p->sdiocard[bus].card.sdio_version      = (uint8_t)(reply_p->data[4]&0x00ff);
        dev_p->sdiocard[bus].function_init_map      = 0x01;
        data_p->num_functions       = dev_p->sdiocard[bus].card.num_functions;
        data_p->memory_present      = dev_p->sdiocard[bus].card.memory_present;
        data_p->manufacturer_Id     = dev_p->sdiocard[bus].card.manufacturer_Id;
        data_p->manufacturer_info   = dev_p->sdiocard[bus].card.manufacturer_info;
        data_p->blocksize           = dev_p->sdiocard[bus].card.blocksize;
        data_p->maxblocksize        = dev_p->sdiocard[bus].card.maxblocksize;
        data_p->card_capability     = dev_p->sdiocard[bus].card.card_capability;
        data_p->sdio_version        = dev_p->sdiocard[bus].card.sdio_version;
    }
    else
    {
        if (resp_type == CY_RESP_SUCCESS_FAILURE)
            ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        else
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }
destroy:
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;
}

/*Reset SDIO card. */
CyAsReturnStatus_t
CyAsSdioResetCard(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t         bus,
        uint32_t                device )
{

    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t resp_type;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);

    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(dev_p->sdiocard != 0)
    {
        dev_p->sdiocard[bus].function_init_map=0;
        dev_p->sdiocard[bus].function_suspended_map = 0;
    }


    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_RESET_DEV, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;

    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    /*Setup mailbox */
    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0) ) ;

    reply_p = CyAsLLCreateResponse(dev_p, 2) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;


    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;


    resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;


    if (resp_type == CY_RESP_SUCCESS_FAILURE)
    {
        ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        if(ret == CY_AS_ERROR_SUCCESS)
        {
            ret = CyAsSdioQueryCard(handle,bus,device,0);
        }
    }
    else
        ret = CY_AS_ERROR_INVALID_RESPONSE ;

destroy:
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;
}

/* Initialise an IO function*/
CyAsReturnStatus_t
CyAsSdioInitFunction(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint8_t                     miscBuf     )
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t resp_type;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);

    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,0)))
        return CY_AS_ERROR_NOT_RUNNING;

    if((CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
    {
        if(miscBuf&CY_SDIO_FORCE_INIT)
            dev_p->sdiocard[bus].function_init_map&=(~(1<<nFunctionNo));
        else
            return CY_AS_ERROR_ALREADY_RUNNING;
    }

    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;

    reply_p = CyAsLLCreateResponse(dev_p, 5) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;

    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;

    if (resp_type == CY_RESP_SDIO_INIT_FUNCTION)
    {

        dev_p->sdiocard[bus].function[nFunctionNo-1].function_code      = (uint8_t)((reply_p->data[0]&0xff00)>>8);
        dev_p->sdiocard[bus].function[nFunctionNo-1].extended_func_code = (uint8_t)reply_p->data[0]&0x00ff;
        dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize          =  reply_p->data[1];
        dev_p->sdiocard[bus].function[nFunctionNo-1].maxblocksize       =  reply_p->data[1];
        dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn           = (uint32_t)(reply_p->data[2])<<16;
        dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn           |=(uint32_t)(reply_p->data[3]);
        dev_p->sdiocard[bus].function[nFunctionNo-1].csa_bits           = (uint8_t)((reply_p->data[4]&0xff00)>>8);
        dev_p->sdiocard[bus].function[nFunctionNo-1].wakeup_support     = (uint8_t)(reply_p->data[4]&0x0001);
        dev_p->sdiocard[bus].function_init_map                          |= (1<<nFunctionNo);
        CyAsSdioClearFunctionSuspended(handle,bus,nFunctionNo);

    }
    else
    {
        if (resp_type == CY_RESP_SUCCESS_FAILURE)
            ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        else
            ret = CY_AS_ERROR_INVALID_FUNCTION ;
    }

destroy:
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;
}

/*Query individual functions. */
CyAsReturnStatus_t
CyAsSdioQueryFunction(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        CyAsSDIOFunc*               data_p )
{
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    CyAsReturnStatus_t ret;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;

    data_p->blocksize           =   dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize;
    data_p->card_psn            =   dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn;
    data_p->csa_bits            =   dev_p->sdiocard[bus].function[nFunctionNo-1].csa_bits;
    data_p->extended_func_code  =   dev_p->sdiocard[bus].function[nFunctionNo-1].extended_func_code;
    data_p->function_code       =   dev_p->sdiocard[bus].function[nFunctionNo-1].function_code;
    data_p->maxblocksize        =   dev_p->sdiocard[bus].function[nFunctionNo-1].maxblocksize;
    data_p->wakeup_support      =   dev_p->sdiocard[bus].function[nFunctionNo-1].wakeup_support;


    return CY_AS_ERROR_SUCCESS;
}

/* Abort the Current Extended IO Operation*/
CyAsReturnStatus_t
CyAsSdioAbortFunction(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint8_t resp_type;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;

    if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
    {
        if(!(CyAsSdioGetCardCapability(handle,bus) & CY_SDIO_SDC ))
        {
            return CY_AS_ERROR_INVALID_COMMAND;
        }
    }

    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_ABORT_IO, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;

    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    /*Setup mailbox */
    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;

    reply_p = CyAsLLCreateResponse(dev_p, 2) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;

    if (resp_type == CY_RESP_SUCCESS_FAILURE)
        ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    else
        ret = CY_AS_ERROR_INVALID_RESPONSE ;


destroy:
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;
}

/* Suspend IO to current function*/
CyAsReturnStatus_t
CyAsSdioSuspend(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint8_t                 nFunctionNo)
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(!(CyAsSdioCheckSupportBusSuspend(handle,bus)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(!(CyAsSdioGetCardCapability(handle,bus) & CY_SDIO_SDC))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
        return CY_AS_ERROR_FUNCTION_SUSPENDED;

    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    /*Setup mailbox */
    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;

    reply_p = CyAsLLCreateResponse(dev_p, 2) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }
    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;

    if (ret == CY_AS_ERROR_SUCCESS)
    {
        ret = CyAsLLRequestResponse_GetCode(reply_p) ;
        CyAsSdioSetFunctionSuspended(handle,bus,nFunctionNo);
    }

    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;

    return ret ;
}

/*Resume suspended function*/
CyAsReturnStatus_t
CyAsSdioResume(
        CyAsDeviceHandle        handle,
        CyAsBusNumber_t         bus,
        uint32_t                device,
        uint8_t                 nFunctionNo,
        CyAsOperType            op,
        uint8_t                 miscBuf,
        uint16_t                pendingblockcount,
        uint8_t                 *data_p
        )
{
    CyAsLLRequestResponse *req_p , *reply_p ;
    CyAsReturnStatus_t resp_data, ret = CY_AS_ERROR_SUCCESS ;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;

    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;

    /* If suspend resume is not supported return */
    if(!(CyAsSdioCheckSupportBusSuspend(handle,bus)))
        return CY_AS_ERROR_INVALID_FUNCTION;

    /* if the function is not suspended return. */
    if(!(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;

    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    /*Setup mailbox */
    CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;

    reply_p = CyAsLLCreateResponse(dev_p, 2) ;
    if (reply_p == 0)
    {
        CyAsLLDestroyRequest(dev_p, req_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }
    ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;

    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;


    if ( CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SDIO_RESUME)
    {
        resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
        if(resp_data & 0x00ff)
        {
            /* Send extended read request to resume the read. */
            if(op == CyAsOpRead)
            {
                ret = CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,0,miscBuf,pendingblockcount,CyFalse,data_p,1);
            }
            else
            {
                ret = CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,0,miscBuf,pendingblockcount,CyTrue,data_p,1);
            }
        }
        else
        {
            ret= CY_AS_ERROR_SUCCESS;
        }

    }
    else
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }

destroy:
    CyAsSdioClearFunctionSuspended(handle,bus,nFunctionNo);
    if(req_p!=0)
        CyAsLLDestroyRequest(dev_p, req_p) ;
    if(reply_p!=0)
        CyAsLLDestroyResponse(dev_p, reply_p) ;
    return ret ;

}

/*Set function blocksize. Size cannot exceed max block size for the function*/
CyAsReturnStatus_t
CyAsSdioSetBlocksize(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo,
        uint16_t                    blocksize)
{
    CyAsReturnStatus_t ret;
    CyAsDevice *dev_p = (CyAsDevice *)handle ;
    ret = CyAsSdioDeviceCheck(dev_p,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_INVALID_FUNCTION;
    if( nFunctionNo == 0)
    {
        if ( blocksize > CyAsSdioGetCardMaxBlocksize(handle,bus))
            return CY_AS_ERROR_INVALID_BLOCKSIZE;
        else if (blocksize == CyAsSdioGetCardBlocksize(handle,bus))
            return CY_AS_ERROR_SUCCESS;
    }
    else
    {
        if ( blocksize > CyAsSdioGetFunctionMaxBlocksize(handle,bus,nFunctionNo))
            return CY_AS_ERROR_INVALID_BLOCKSIZE;
        else if (blocksize == CyAsSdioGetFunctionBlocksize(handle,bus,nFunctionNo))
            return CY_AS_ERROR_SUCCESS;
    }

    ret = CyAsSdioDirectWrite(handle,bus,device,0,(uint16_t)(nFunctionNo<<8)|0x10,0,blocksize&0x00ff,0);
    if(ret != CY_AS_ERROR_SUCCESS )
        return ret;
    ret = CyAsSdioDirectWrite(handle,bus,device,0,(uint16_t)(nFunctionNo<<8)|0x11,0,(blocksize&0xff00)>>8,0);
    if (ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(nFunctionNo ==0)
        CyAsSdioSetCardBlockSize(handle,bus,blocksize);
    else
        CyAsSdioSetFunctionBlockSize(handle,bus,nFunctionNo,blocksize);
    return ret;
}

/* Deinitialize an SDIO function*/
CyAsReturnStatus_t
CyAsSdioDeInitFunction(
        CyAsDeviceHandle            handle,
        CyAsBusNumber_t             bus,
        uint32_t                    device,
        uint8_t                     nFunctionNo)
{
    CyAsReturnStatus_t ret;
    uint8_t temp;

    if(nFunctionNo == 0)
        return CY_AS_ERROR_INVALID_FUNCTION;

    ret = CyAsSdioDeviceCheck((CyAsDevice*)handle,bus,device);
    if( ret != CY_AS_ERROR_SUCCESS )
        return ret;

    if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
        return CY_AS_ERROR_SUCCESS;

    temp =(uint8_t)(((CyAsDevice*)handle)->sdiocard[bus].function_init_map & (~(1<<nFunctionNo)));
    CyAsSdioDirectWrite(handle,bus,device,0,0x02,0,temp,0);
    ((CyAsDevice*)handle)->sdiocard[bus].function_init_map &= (~(1<<nFunctionNo));

    return CY_AS_ERROR_SUCCESS;
}

/* This includes the implementation of the deprecated functions for backward
 * compatibility
 */
#include "cyasstorage_dep_impl.h"

/*[]*/