omap3530/beagle_drivers/wb/api/src/cyasstorage.c
author arunabha
Wed, 03 Mar 2010 13:10:32 +0000
changeset 27 117faf51deac
child 52 254b9435d75e
permissions -rw-r--r--
Bug 1996 - Contribution for West Bridge Astoria Symbian Storage Driver this storage driver is for the West Bridge Astoria chipset. This device has a USB, SD and processor port for communication with a baseband processor. In our port, we connected this device DVK to the Beagleboard through the SPI interface of the OMAP3. After driver installation, the Symbian OS can see an external device or D: drive represented by the SD card. In this driver, the USB interface is not used directly, though this may be the subject of future contributions. The appropriate way to test the driver is to access the external volume and do file read and write to it, pretty much the same way you would test a thumb drive on your PC

/* 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 < 0 || 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 < 0 || 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 < 0 || 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 < 0 || 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 < 0 || 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) ;

    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 < 0 || 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)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 < 0 || 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"

/*[]*/