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

/* Cypress West Bridge API source file (cyasmisc.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.
##
## ===========================
*/

#include "cyashal.h"
#include "cyasmisc.h"
#include "cyasdma.h"
#include "cyasintr.h"
#include "cyaserr.h"
#include "cyasregs.h"
#include "cyaslowlevel.h"
#include "cyasprotocol.h"

/*
* The device list, the only global in the API
*/
static CyAsDevice *gDeviceList = 0 ;

/*
 * The current debug level
 */
#ifdef CY_AS_LOG_SUPPORT
static uint8_t DebugLevel = 0 ; //commented out as it's not

/*
 * This function sets the debug level for the API
 *
 */
void
CyAsMiscSetLogLevel(uint8_t level)
{
    DebugLevel = level ;
}

//#ifdef CY_AS_LOG_SUPPORT

/*
 * This function is a low level logger for the API.
 */
void
CyAsLogDebugMessage(int level, const char *str)
{
    if (level <= DebugLevel)
        CyAsHalPrintMessage("Log %d: %s\n", level, str) ;
}

#endif

#define CyAsCheckDeviceReady(dev_p)                                     \
{                                                                       \
    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 ;                                \
}

/* Find an West Bridge device based on a TAG */
CyAsDevice *
CyAsDeviceFindFromTag(CyAsHalDeviceTag tag)
{
    CyAsDevice *dev_p ;

    for(dev_p = gDeviceList; dev_p != 0; dev_p = dev_p->next_p)
    {
        if (dev_p->tag == tag)
            return dev_p ;
    }

    return 0 ;
}

/* Map a pre-V1.2 media type to the V1.2+ bus number */
static void
CyAsBusFromMediaType(CyAsMediaType type,
                        CyAsBusNumber_t* bus)
{
    if (type == CyAsMediaNand)
    {
        *bus = 0 ;
    }
    else
    {
        *bus = 1 ;
    }
}

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 ;
    else
        ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;

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

    return ret ;
}

/*
* Create a new West Bridge device
*/
CyAsReturnStatus_t
CyAsMiscCreateDevice(CyAsDeviceHandle *handle_p, CyAsHalDeviceTag tag)
{
    CyAsDevice *dev_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    CyAsLogDebugMessage(6, "CyAsMiscCreateDevice called") ;

    dev_p = (CyAsDevice *)CyAsHalAlloc(sizeof(CyAsDevice)) ;
    if (dev_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    CyAsHalMemSet(dev_p, 0, sizeof(CyAsDevice)) ;

    /*
     * Dynamically allocating this buffer to ensure that it is
     * word aligned.
     */
    dev_p->usb_ep_data = (uint8_t *)CyAsHalAlloc(64 * sizeof(uint8_t)) ;
    if (dev_p->usb_ep_data == 0)
    {
        CyAsHalFree(dev_p) ;
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }

    dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE ;
    dev_p->tag = tag ;
    dev_p->usb_max_tx_size = 0x40 ;

    dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT ;
    dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT ;

    dev_p->func_cbs_misc = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
    if(dev_p->func_cbs_misc == 0)
        goto destroy ;

    dev_p->func_cbs_res = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
    if(dev_p->func_cbs_res == 0)
        goto destroy ;

    dev_p->func_cbs_stor = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
    if(dev_p->func_cbs_stor == 0)
        goto destroy ;

    dev_p->func_cbs_usb = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
    if(dev_p->func_cbs_usb == 0)
        goto destroy ;

    dev_p->func_cbs_mtp = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
    if(dev_p->func_cbs_mtp == 0)
            goto destroy ;

    /*
     * Allocate memory for the DMA module here. It is then marked idle, and
     * will be activated when CyAsMiscConfigureDevice is called.
     */
    ret = CyAsDmaStart(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    CyAsDeviceSetDmaStopped(dev_p) ;

    /*
     * Allocate memory for the low level module here. This module is also
     * activated only when CyAsMiscConfigureDevice is called.
     */
    ret = CyAsLLStart(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        goto destroy ;

    CyAsDeviceSetLowLevelStopped(dev_p) ;

    dev_p->next_p = gDeviceList ;
    gDeviceList = dev_p ;

    *handle_p = dev_p ;
    CyAsHalInitDevRegisters(tag, CyFalse) ;
    return CY_AS_ERROR_SUCCESS ;

destroy:
    /* Free any queues that were successfully allocated. */
    if (dev_p->func_cbs_misc) CyAsDestroyCBQueue(dev_p->func_cbs_misc) ;
    if (dev_p->func_cbs_res)  CyAsDestroyCBQueue(dev_p->func_cbs_res) ;
    if (dev_p->func_cbs_stor) CyAsDestroyCBQueue(dev_p->func_cbs_stor) ;
    if (dev_p->func_cbs_usb)  CyAsDestroyCBQueue(dev_p->func_cbs_usb) ;
    if (dev_p->func_cbs_mtp)  CyAsDestroyCBQueue(dev_p->func_cbs_mtp) ;

    CyAsHalFree(dev_p->usb_ep_data) ;
    CyAsHalFree(dev_p) ;

    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;
    else
        return CY_AS_ERROR_OUT_OF_MEMORY ;
}

/*
* Destroy an existing West Bridge device
*/
CyAsReturnStatus_t
CyAsMiscDestroyDevice(CyAsDeviceHandle handle)
{
    CyAsReturnStatus_t ret ;
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscDestroyDevice called") ;

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

    /*
    * If the USB stack is still running, it must be stopped first
    */
    if (dev_p->usb_count > 0)
        return CY_AS_ERROR_STILL_RUNNING ;

    /*
    * If the STORAGE stack is still running, it must be stopped first
    */
    if (dev_p->storage_count > 0)
        return CY_AS_ERROR_STILL_RUNNING ;

    if(CyAsDeviceIsIntrRunning(dev_p))
        ret = CyAsIntrStop(dev_p) ;

    ret = CyAsLLStop(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsIntrStart(dev_p, dev_p->use_int_drq) ;
        return ret ;
    }

    ret = CyAsDmaStop(dev_p) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsIntrStart(dev_p, dev_p->use_int_drq) ;
        return ret ;
    }

    /* Reset the West Bridge device. */
    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;

    /*
    * Remove the device from the device list
    */
    if (gDeviceList == dev_p)
    {
        gDeviceList = dev_p->next_p ;
    }
    else
    {
        CyAsDevice *tmp_p = gDeviceList ;
        while (tmp_p && tmp_p->next_p != dev_p)
            tmp_p = tmp_p->next_p ;

        CyAsHalAssert(tmp_p != 0) ;
        tmp_p->next_p = dev_p->next_p ;
    }

    /*
    * Reset the signature so this will not be detected
    * as a valid handle
    */
    dev_p->sig = 0 ;

    CyAsDestroyCBQueue(dev_p->func_cbs_misc) ;
    CyAsDestroyCBQueue(dev_p->func_cbs_res) ;
    CyAsDestroyCBQueue(dev_p->func_cbs_stor) ;
    CyAsDestroyCBQueue(dev_p->func_cbs_usb) ;
    CyAsDestroyCBQueue(dev_p->func_cbs_mtp) ;

    /*
    * Free the memory associated with the device
    */
    CyAsHalFree(dev_p->usb_ep_data) ;
    CyAsHalFree(dev_p) ;

    return CY_AS_ERROR_SUCCESS ;
}

/*
* Determine the endian mode for the processor we are running on, then
* set the endian mode register
*/
static void
CyAsSetupEndianMode(CyAsDevice *dev_p)
{
    /*
    * BWG: In general, we always set West Bridge into the little endian mode.  This
    *      causes the data on bit 0 internally to come out on data line 0 externally
    *      and it is generally what we want regardless of the endian mode of the
    *      processor.  This capability in West Bridge should be labeled as a "SWAP" capability
    *      and can be used to swap the bytes of data in and out of West Bridge.  This is
    *      useful if there is DMA hardware that requires this for some reason I cannot
    *      imagine at this time.  Basically if the wires are connected correctly, we should
    *      never need to change the endian-ness of West Bridge.
    */
    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_ENDIAN, CY_AS_LITTLE_ENDIAN) ;
}

/*
* Query the West Bridge device and determine if we are an standby mode
*/
CyAsReturnStatus_t
CyAsMiscInStandby(CyAsDeviceHandle handle, CyBool *standby)
{
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscInStandby called") ;

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

    if (CyAsDeviceIsPinStandby(dev_p) || CyAsDeviceIsRegisterStandby(dev_p))
    {
        *standby = CyTrue ;
    }
    else
        *standby = CyFalse ;

    return CY_AS_ERROR_SUCCESS ;
}

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


static void
MyMiscCallback(CyAsDevice *dev_p, uint8_t context, CyAsLLRequestResponse *req_p, CyAsLLRequestResponse *resp_p,
               CyAsReturnStatus_t ret)
{
    (void)resp_p ;
    (void)context ;
    (void)ret ;

    switch (CyAsLLRequestResponse_GetCode(req_p))
    {
        case CY_RQT_INITIALIZATION_COMPLETE:
            {
                uint16_t v ;

                CyAsLLSendStatusResponse(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
                CyAsDeviceSetFirmwareLoaded(dev_p) ;

                if (CyAsDeviceIsWaking(dev_p))
                {
                    /*
                     * This is a callback from a CyAsMiscLeaveStandby() request.  In this case we call the
                     * standby callback and clear the waking state.
                     */
                    if (dev_p->misc_event_cb)
                        dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscAwake, 0) ;
                    CyAsDeviceClearWaking(dev_p) ;
                }
                else
                {
                    v = CyAsLLRequestResponse_GetWord(req_p, 3) ;

                    /*
                     * Store the media supported on each of the device buses.
                     */
                    dev_p->media_supported[0] = (uint8_t)(v & 0xFF) ;
                    dev_p->media_supported[1] = (uint8_t)((v >> 8) & 0xFF) ;

                    v = CyAsLLRequestResponse_GetWord(req_p, 4) ;
                    dev_p->is_mtp_firmware    = (CyBool)((v >> 8) & 0xFF) ;

                    if (dev_p->misc_event_cb)
                        dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscInitialized, 0) ;
                }

                v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET) ;
                if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
                    CyAsHalPrintMessage("Initialization Message Recieved, but config bit still set\n") ;

                v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG) ;
                if ((v & CY_AS_MEM_RST_RSTCMPT) ==0)
                    CyAsHalPrintMessage("Initialization Message Recieved, but reset complete bit still not set\n") ;
            }
            break ;

        case CY_RQT_OUT_OF_SUSPEND:
            CyAsLLSendStatusResponse(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
            CyAsDeviceClearSuspendMode(dev_p) ;

            /*
             * If the wakeup was caused by an async CyAsMiscLeaveSuspend call, we have to
             * call the corresponding callback.
             */
            if (dev_p->func_cbs_misc->count > 0)
            {
                CyAsFuncCBNode *node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;
                CyAsHalAssert(node) ;

                if (CyAsFunctCBTypeGetType(node->dataType) == CY_FUNCT_CB_MISC_LEAVESUSPEND)
                {
                    CyAsHalAssert(node->cb_p != 0) ;
                    node->cb_p((CyAsDeviceHandle)dev_p, CY_AS_ERROR_SUCCESS, node->client_data,
                            CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ;
                    CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
                }
            }

            if (dev_p->misc_event_cb)
                dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscWakeup, 0) ;
            break ;

        case CY_RQT_DEBUG_MESSAGE:
            if ((req_p->data[0] == 0) && (req_p->data[1] == 0) && (req_p->data[2] == 0))
            {
                if (dev_p->misc_event_cb)
                    dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscHeartBeat, 0) ;
            }
            else
            {
                CyAsHalPrintMessage("**** Debug Message: %02x %02x %02x %02x %02x %02x\n",
                        req_p->data[0] & 0xff, (req_p->data[0] >> 8) & 0xff,
                        req_p->data[1] & 0xff, (req_p->data[1] >> 8) & 0xff,
                        req_p->data[2] & 0xff, (req_p->data[2] >> 8) & 0xff) ;
            }
            break ;

        case CY_RQT_WB_DEVICE_MISMATCH:
            {
                if (dev_p->misc_event_cb)
                    dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscDeviceMismatch, 0) ;
            }
            break ;

        case CY_RQT_BOOTLOAD_NO_FIRMWARE:
            {
                /* TODO Handle case when firmware is not found during bootloading. */
                CyAsHalPrintMessage("No firmware image found during bootload. Device not started\n") ;
            }
            break ;

        default:
            CyAsHalAssert (0) ;
    }
}

static CyBool
IsValidSiliconId(uint16_t v)
{
    CyBool idok = CyFalse ;

    /*
    * Remove the revision number from the ID value
    */
    v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK ;

    /*
    * If this is West Bridge, then we are OK.
    */
    if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE ||
        v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE ||
        v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE)
        idok = CyTrue ;

    return idok ;
}

/*
* Configure the West Bridge device hardware
*/
CyAsReturnStatus_t
CyAsMiscConfigureDevice(CyAsDeviceHandle handle, CyAsDeviceConfig *config_p)
{
    CyAsReturnStatus_t ret ;
    CyBool standby ;
    CyAsDevice *dev_p ;
    uint16_t v ;
    uint16_t fw_present;
    CyAsLogDebugMessage(6, "CyAsMiscConfigureDevice called") ;

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

    /* Setup big endian vs little endian */
    CyAsSetupEndianMode(dev_p) ;

    /* Now, confirm that we can talk to the West Bridge device */
    dev_p->silicon_id = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
    fw_present = CyAsHalReadRegister(dev_p->tag,CY_AS_MEM_RST_CTRL_REG ) ;
    if (!(fw_present & CY_AS_MEM_RST_RSTCMPT))
    {
        if (!IsValidSiliconId(dev_p->silicon_id))
            return CY_AS_ERROR_NO_ANTIOCH ;
    }
    /* Check for standby mode */
    ret = CyAsMiscInStandby(handle, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;
    if (ret)
        return CY_AS_ERROR_IN_STANDBY ;

    /* Setup P-port interface mode (CRAM / SRAM). */
    if (CyAsDeviceIsAstoriaDev(dev_p))
    {
        if (config_p->srammode)
            v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM ;
        else
            v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ;
    }
    else
        v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ;

    /* Setup synchronous versus asynchronous mode */
    if (config_p->sync)
        v |= CY_AS_MEM_P0_VM_SET_IFMODE ;
    if (config_p->dackmode == CyAsDeviceDackAck)
        v |= CY_AS_MEM_P0_VM_SET_DACKEOB ;
    if (config_p->drqpol)
        v |= CY_AS_MEM_P0_VM_SET_DRQPOL ;
    if (config_p->dackpol)
        v |= CY_AS_MEM_P0_VM_SET_DACKPOL ;
    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET, v) ;

    if (config_p->crystal)
        CyAsDeviceSetCrystal(dev_p) ;
    else
        CyAsDeviceSetExternalClock(dev_p) ;

    /* Register a callback to handle MISC requests from the firmware */
    CyAsLLRegisterRequestCallback(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, MyMiscCallback) ;

    /* Now mark the DMA and low level modules as active. */
    CyAsDeviceSetDmaRunning(dev_p) ;
    CyAsDeviceSetLowLevelRunning(dev_p) ;

    /* Now, initialize the interrupt module */
    dev_p->use_int_drq = config_p->dmaintr ;

    ret = CyAsIntrStart(dev_p, config_p->dmaintr) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /* Mark the interface as initialized */
    CyAsDeviceSetConfigured(dev_p) ;

    return CY_AS_ERROR_SUCCESS ;
}

static void
MyDmaCallback(CyAsDevice *          dev_p,
              CyAsEndPointNumber_t  ep,
              void *                mem_p,
              uint32_t              size,
              CyAsReturnStatus_t    ret
              )
{
    CyAsDmaEndPoint *ep_p ;

    (void)size ;

    /* Get the endpoint pointer based on the endpoint number */
    ep_p = CY_AS_NUM_EP(dev_p, ep) ;

    /* Check the queue to see if is drained */
    if (ep_p->queue_p == 0)
    {
        CyAsFuncCBNode* node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;

        CyAsHalAssert(node) ;

        if (ret == CY_AS_ERROR_SUCCESS)
        {
            /*
             * Disable endpoint 2.  The storage module will enable this EP if necessary.
             */
            CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyFalse, CyAsDirectionIn) ;

            /*
             * Clear the reset register.  This releases the Antioch micro-controller from
             * reset and begins running the code at address zero.
             */
            CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
        }

        /* Call the user Callback */
        node->cb_p((CyAsDeviceHandle)dev_p, ret, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
        CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
    }
    else
    {
        /* This is the header data that was allocated in the download firmware function,
        * and can be safely freed here. */
        uint32_t state = CyAsHalDisableInterrupts() ;
        CyAsHalCBFree(mem_p) ;
        CyAsHalEnableInterrupts(state) ;
    }
}

CyAsReturnStatus_t
CyAsMiscDownloadFirmware(CyAsDeviceHandle handle,
                           const void *mem_p,
                           uint16_t size,
                           CyAsFunctionCallback cb,
                           uint32_t client)
{
    uint8_t *header ;
    CyAsReturnStatus_t ret ;
    CyBool standby ;
    CyAsDevice *dev_p ;
    CyAsDmaCallback dmacb = 0 ;
    uint32_t state ;

    CyAsLogDebugMessage(6, "CyAsMiscDownloadFirmware called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    /*
    * If the device has not been initialized, we cannot download firmware
    * to the device.
    */
    if (!CyAsDeviceIsConfigured(dev_p))
        return CY_AS_ERROR_NOT_CONFIGURED ;

    /*
    * Make sure West Bridge is not in standby
    */
    ret = CyAsMiscInStandby(dev_p, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (standby)
        return CY_AS_ERROR_IN_STANDBY ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /*
    * Make sure we are in configuration mode
    */
    if ((CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET) & CY_AS_MEM_P0_VM_SET_CFGMODE) == 0)
        return CY_AS_ERROR_NOT_IN_CONFIG_MODE ;

    /* Maximum firmware size is 24k */
    if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE)
        return CY_AS_ERROR_INVALID_SIZE ;

    /* Make sure the size is an even number of bytes as well */
    if (size & 0x01)
        return CY_AS_ERROR_ALIGNMENT_ERROR ;

    /*
     * Write the two word header that gives the base address and
     * size of the firmware image to download
     */
    state = CyAsHalDisableInterrupts() ;
    header = (uint8_t *)CyAsHalCBAlloc(4) ;
    CyAsHalEnableInterrupts(state) ;
    if (header == NULL)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    header[0] = 0x00 ;
    header[1] = 0x00 ;
    header[2] = (uint8_t)(size & 0xff) ;
    header[3] = (uint8_t)((size >> 8) & 0xff) ;

    /* Enable the firmware endpoint */
    ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyTrue, CyAsDirectionIn) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /*
    * Setup DMA for 64 byte packets.  This is the requirement for downloading
    * firmware to West Bridge.
    */
    CyAsDmaSetMaxDmaSize(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64) ;

    if(cb)
    {
        dmacb = MyDmaCallback ;
    }

    ret = CyAsDmaQueueRequest(dev_p, CY_AS_FIRMWARE_ENDPOINT, header, 4, CyFalse, CyFalse, dmacb) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /*
    * Write the firmware image to the West Bridge device
    */
    ret = CyAsDmaQueueRequest(dev_p, CY_AS_FIRMWARE_ENDPOINT, (void *)mem_p, size, CyFalse, CyFalse, dmacb) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if(cb)
    {
        CyAsFuncCBNode* cbnode = CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0) ;

        if(cbnode == 0)
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        else
            CyAsInsertCBNode(dev_p->func_cbs_misc, cbnode) ;

        ret = CyAsDmaKickStart(dev_p, CY_AS_FIRMWARE_ENDPOINT) ;
        if (ret != CY_AS_ERROR_SUCCESS)
            return ret ;
    }
    else
    {

        ret = CyAsDmaDrainQueue(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyTrue) ;

        /* Free the header memory that was allocated earlier. */
        CyAsHalCBFree(header) ;

        if (ret != CY_AS_ERROR_SUCCESS)
        {
			return ret ;
		}
        /*
        * Disable endpoint 2.  The storage module will enable this EP if necessary.
        */
        CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyFalse, CyAsDirectionIn) ;

        /*
        * Clear the reset register.  This releases the West Bridge micro-controller from
        * reset and begins running the code at address zero.
        */
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
    }

    /*
    * The firmware is not marked as loaded until the firmware initializes West Bridge and a request
    * is sent from West Bridge to the P port processor indicating that West Bridge is ready.
    */
    return CY_AS_ERROR_SUCCESS ;
}


static CyAsReturnStatus_t
MyHandleResponseGetFirmwareVersion(CyAsDevice* dev_p,
                                   CyAsLLRequestResponse *req_p,
                                   CyAsLLRequestResponse *reply_p,
                                   CyAsGetFirmwareVersionData *data_p)
{

    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint16_t val ;

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

    data_p->major = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    data_p->minor = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
    data_p->build = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
    val    = CyAsLLRequestResponse_GetWord(reply_p, 3) ;
    data_p->mediaType   = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF)) ;
    val    = CyAsLLRequestResponse_GetWord(reply_p, 4) ;
    data_p->isDebugMode = (CyBool)(val & 0xFF) ;

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

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscGetFirmwareVersion(CyAsDeviceHandle handle,
                             CyAsGetFirmwareVersionData* data,
                             CyAsFunctionCallback cb,
                             uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyBool standby ;
    CyAsLLRequestResponse *req_p, *reply_p ;

    CyAsDevice *dev_p ;

    (void)client ;

    CyAsLogDebugMessage(6, "CyAsMiscGetFirmwareVersion called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /*
    * Make sure Antioch is not in standby
    */
    ret = CyAsMiscInStandby(dev_p, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;
    if (standby)
        return CY_AS_ERROR_IN_STANDBY ;

    /* Make sure the Antioch is not in suspend mode. */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

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

    /* Reserve space for the reply, the reply data will not exceed three 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 ;

        /* Request and response are freed in MyHandleResponseGetFirmwareVersion. */
        ret = MyHandleResponseGetFirmwareVersion(dev_p, req_p, reply_p, data) ;
        return ret ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_GETFIRMWAREVERSION,
            data, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
            reply_p, CyAsMiscFuncCallback) ;

        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 ;
}
static CyAsReturnStatus_t
MyHandleResponseReadMCURegister(CyAsDevice* dev_p,
                                   CyAsLLRequestResponse *req_p,
                                   CyAsLLRequestResponse *reply_p,
                                   uint8_t *data_p)
{

    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

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

    *data_p = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;

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

    return ret ;
}

static CyAsReturnStatus_t
MyHandleResponseGetGpioValue(CyAsDevice* dev_p,
        CyAsLLRequestResponse *req_p,
        CyAsLLRequestResponse *reply_p,
        uint8_t *data_p)
{

    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_GPIO_STATE)
    {
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
    }
    else
        *data_p = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;

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

    return ret ;
}


CyAsReturnStatus_t CyAsMiscSetSDPowerPolarity(
    CyAsDeviceHandle handle,
    CyAsMiscSignalPolarity polarity,
    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 ;


    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDPOLARITY , CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
    if (req_p == 0)
    {

        return CY_AS_ERROR_OUT_OF_MEMORY ;
    }
    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)polarity) ;

    /* 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 ;
    }

    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_MISC_SETSDPOLARITY,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
               req_p, reply_p, CyAsMiscFuncCallback) ;

        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
CyAsMiscReadMCURegister(CyAsDeviceHandle handle,
                          uint16_t address,
                          uint8_t *value,
                          CyAsFunctionCallback cb,
                          uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsLLRequestResponse *req_p, *reply_p ;

    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscReadMCURegister called") ;

    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /* Check whether the firmware supports this command. */
    if (CyAsDeviceIsNandStorageSupported(dev_p))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    /* Make sure the Antioch is not in suspend mode. */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)address) ;

    /* 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 ;
    }

    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_MCU_REGISTER_DATA)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        *value = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_READMCUREGISTER,
            value, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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
CyAsMiscWriteMCURegister(CyAsDeviceHandle handle,
                           uint16_t address,
                           uint8_t mask,
                           uint8_t value,
                           CyAsFunctionCallback cb,
                           uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscWriteMCURegister called") ;

    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /* Check whether the firmware supports this command. */
    if (CyAsDeviceIsNandStorageSupported(dev_p))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    /* Make sure the Antioch is not in suspend mode. */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)address) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((mask << 8) | value)) ;

    /* 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 ;
    }

    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_MISC_WRITEMCUREGISTER,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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
MyHandleResponseReset(CyAsDevice* dev_p,
                      CyAsLLRequestResponse *req_p,
                      CyAsLLRequestResponse *reply_p,
                      CyAsResetType type)
{
    (void)req_p ;
    (void)reply_p ;

    /*
    * If the device is in suspend mode, it needs to be woken up so that the write
    * to the reset control register succeeds. We need not however wait for the
     * wake up procedure to be complete.
     */
    if (CyAsDeviceIsInSuspendMode(dev_p))
    {
        CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
        CyAsHalSleep (1) ;
    }

    if (type == CyAsResetHard)
    {
        CyAsMiscCancelExRequests(dev_p) ;
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;
        CyAsDeviceSetUnconfigured(dev_p) ;
        CyAsDeviceSetFirmwareNotLoaded(dev_p) ;
        CyAsDeviceSetDmaStopped(dev_p) ;
        CyAsDeviceSetLowLevelStopped(dev_p) ;
        CyAsDeviceSetIntrStopped(dev_p) ;
        CyAsDeviceClearSuspendMode(dev_p) ;
        CyAsUsbCleanup(dev_p) ;
        CyAsStorageCleanup(dev_p) ;

        /*
         * Wait for a small amount of time to allow reset to be complete.
         */
        CyAsHalSleep(100) ;
    }

    CyAsDeviceClearResetPending(dev_p) ;

    return CY_AS_ERROR_SUCCESS ;
}

CyAsReturnStatus_t
CyAsMiscReset(CyAsDeviceHandle handle,
                CyAsResetType type,
                CyBool flush,
                CyAsFunctionCallback cb,
                uint32_t client)
{
    CyAsDevice *dev_p ;
    CyAsEndPointNumber_t i ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    (void)client ;
    (void)cb ;

    CyAsLogDebugMessage(6, "CyAsMiscResetEX called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /*
     * Soft reset is not supported until we close on the issues in the
     * firmware with what needs to happen.
     */
    if (type == CyAsResetSoft)
        return CY_AS_ERROR_NOT_YET_SUPPORTED ;

    CyAsDeviceSetResetPending(dev_p) ;

    if (flush)
    {

        /* Unable to DrainQueues in polling mode */
        if((dev_p->storage_cb || dev_p->storage_cb_ms) && CyAsHalIsPolling())
            return CY_AS_ERROR_ASYNC_PENDING ;

        /*
        * Shutdown the endpoints so no more traffic can be queued
        */
        for(i = 0; i < 15; i++)
            CyAsDmaEnableEndPoint(dev_p, i, CyFalse, CyAsDirectionDontChange) ;

        /*
         * If we are in normal mode, drain all traffic across all endpoints to be sure all traffic
         * is flushed. If the device is suspended, data will not be coming in on any endpoint and
         * all outstanding DMA operations can be canceled.
         */
        if (CyAsDeviceIsInSuspendMode(dev_p))
        {
            for(i = 0; i < 15; i++)
            {
                CyAsDmaCancel(dev_p, i, CY_AS_ERROR_CANCELED) ;
            }
        }
        else
        {
            for(i = 0; i < 15; i++)
            {
                if ((i == CY_AS_P2S_WRITE_ENDPOINT) || (i == CY_AS_P2S_READ_ENDPOINT))
                    CyAsDmaDrainQueue(dev_p, i, CyFalse) ;
                else
                    CyAsDmaDrainQueue(dev_p, i, CyTrue) ;
            }
        }
    }
    else
    {
        /* No flush was requested, so cancel any outstanding DMAs
         * so the user callbacks are called as needed
         */
        if(CyAsDeviceIsStorageAsyncPending(dev_p))
        {
            for(i = 0; i < 15; i++)
                CyAsDmaCancel(dev_p, i, CY_AS_ERROR_CANCELED) ;
        }
    }

    ret = MyHandleResponseReset(dev_p, 0, 0, type) ;

    if(cb)
        /* Even though no mailbox communication was needed, issue the callback so the
        * user does not need to special case their code. */
        cb((CyAsDeviceHandle)dev_p, ret, client, CY_FUNCT_CB_MISC_RESET, 0) ;

    /*
     * Initialize any registers that may have been changed when the device was reset.
     */
    CyAsHalInitDevRegisters(dev_p->tag, CyFalse) ;

    return ret ;
}

static CyAsReturnStatus_t
GetUnallocatedResource(CyAsDevice *dev_p, CyAsResourceType resource)
{
    uint8_t shift = 0 ;
    uint16_t v ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_NOT_ACQUIRED ;

    switch(resource)
    {
    case CyAsBusUSB:
        shift = 4 ;
        break ;
    case CyAsBus_1:
        shift = 0 ;
        break ;
    case CyAsBus_0:
        shift = 2 ;
        break ;
    default:
        CyAsHalAssert(CyFalse) ;
        break ;
    }

    /* Get the semaphore value for this resource */
    v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) ;
    v = (v >> shift) & 0x03 ;

    if (v == 0x03)
    {
        ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED ;
    }
    else if ((v & 0x01) == 0)
    {
        /* The resource is not owned by anyone, we can try to get it */
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ;
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ;
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift)) ;
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ;

        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) ;
        v = (v >> shift) & 0x03 ;
        if (v == 0x03)
            ret = CY_AS_ERROR_SUCCESS ;
    }

    return ret ;
}

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

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

    if (ret == CY_AS_ERROR_SUCCESS)
    {
            ret = GetUnallocatedResource(dev_p, *resource) ;
            if (ret != CY_AS_ERROR_NOT_ACQUIRED)
                ret = CY_AS_ERROR_SUCCESS ;
    }

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

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscAcquireResource(CyAsDeviceHandle handle,
                          CyAsResourceType *resource,
                          CyBool force,
                          CyAsFunctionCallback cb,
                          uint32_t client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret ;

    CyAsDevice *dev_p ;

    (void)client ;

    CyAsLogDebugMessage(6, "CyAsMiscAcquireResource called") ;

    if (*resource != CyAsBusUSB && *resource != CyAsBus_0 && *resource != CyAsBus_1)
            return CY_AS_ERROR_INVALID_RESOURCE ;


    /* Make sure the device is ready to accept the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;


    ret = GetUnallocatedResource(dev_p, *resource) ;

    /*
     * Make sure that the callback is called if the resource is successfully
     * acquired at this point.
     */
    if ((ret == CY_AS_ERROR_SUCCESS) && (cb != 0))
        cb(handle, ret, client, CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource) ;

    if (ret != CY_AS_ERROR_NOT_ACQUIRED)
        return ret ;

    if (!force)
        return CY_AS_ERROR_NOT_ACQUIRED ;

    /* Create the request to acquire the resource */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ACQUIRE_RESOURCE, CY_RQT_RESOURCE_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)(*resource)) ;

    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_MISC_ACQUIRERESOURCE,
                resource, dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX, req_p,
                reply_p, CyAsMiscFuncCallback) ;

            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) ;

    if (ret == CY_AS_ERROR_SUCCESS)
    {
            ret = GetUnallocatedResource(dev_p, *resource) ;
            if (ret != CY_AS_ERROR_NOT_ACQUIRED)
                ret = CY_AS_ERROR_SUCCESS ;
    }

    return ret ;
}
CyAsReturnStatus_t
CyAsMiscReleaseResource(CyAsDeviceHandle handle, CyAsResourceType resource)
{
    uint8_t shift = 0 ;
    uint16_t v ;

    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscReleaseResource called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if (resource != CyAsBusUSB && resource != CyAsBus_0 && resource != CyAsBus_1)
        return CY_AS_ERROR_INVALID_RESOURCE ;

    switch(resource)
    {
        case CyAsBusUSB:
            shift = 4 ;
            break ;
        case CyAsBus_1:
            shift = 0 ;
            break ;
        case CyAsBus_0:
            shift = 2 ;
            break ;
        default:
            CyAsHalAssert(CyFalse) ;
            break ;
    }

    /* Get the semaphore value for this resource */
    v = (CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03 ;
    if (v == 0 || v == 1 || v == 2)
        return CY_AS_ERROR_RESOURCE_NOT_OWNED ;

    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ;
    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift)) ;
    CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, 0) ;

    return CY_AS_ERROR_SUCCESS ;
}

CyAsReturnStatus_t
CyAsMiscSetTraceLevel(CyAsDeviceHandle handle,
                        uint8_t level,
                        CyAsBusNumber_t bus,
                        uint32_t device,
                        uint32_t unit,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret ;
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscSetTraceLevel called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if (bus >= CY_AS_MAX_BUSES)
        return CY_AS_ERROR_NO_SUCH_BUS ;

    if (device >= CY_AS_MAX_STORAGE_DEVICES)
        return CY_AS_ERROR_NO_SUCH_DEVICE ;

    if (unit > 255)
        return CY_AS_ERROR_NO_SUCH_UNIT ;

    if (level >= CYAS_FW_TRACE_MAX_LEVEL)
        return CY_AS_ERROR_INVALID_TRACE_LEVEL ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)level) ;
    CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((bus << 12) | (device << 8) | (unit))) ;

    /* Reserve space for the reply, the reply data will not exceed three 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 ;

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

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

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_SETTRACELEVEL,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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
CyAsMiscHeartBeatControl(CyAsDeviceHandle handle,
                           CyBool enable,
                           CyAsFunctionCallback cb,
                           uint32_t client)
{
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsReturnStatus_t ret ;
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscHeartBeatControl called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)enable) ;

    /* 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 ;
    }

    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_MISC_HEARTBEATCONTROL,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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 ;
}

static CyAsReturnStatus_t
MySetSDClockFreq (
        CyAsDevice          *dev_p,
        uint8_t              cardType,
        uint8_t              setting,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsLLRequestResponse *req_p, *reply_p ;

    if (CyAsDeviceIsInCallback(dev_p) && (cb == 0))
        return CY_AS_ERROR_INVALID_IN_CALLBACK ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((cardType << 8) | setting)) ;

    /* Reserve space for the reply, which 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 ;
    }

    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_MISC_SETSDFREQ, 0,
            dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, CyAsMiscFuncCallback) ;

        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
CyAsMiscSetLowSpeedSDFreq(
        CyAsDeviceHandle     handle,
        CyAsLowSpeedSDFreq   setting,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscSetLowSpeedSDFreq called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if ((setting != CY_AS_SD_DEFAULT_FREQ) && (setting != CY_AS_SD_RATED_FREQ))
        return CY_AS_ERROR_INVALID_PARAMETER ;

    return MySetSDClockFreq(dev_p, 0, (uint8_t)setting, cb, client) ;
}

CyAsReturnStatus_t
CyAsMiscSetHighSpeedSDFreq(
        CyAsDeviceHandle     handle,
        CyAsHighSpeedSDFreq  setting,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscSetHighSpeedSDFreq called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    if ((setting != CY_AS_HS_SD_FREQ_24) && (setting != CY_AS_HS_SD_FREQ_48))
        return CY_AS_ERROR_INVALID_PARAMETER ;

    return MySetSDClockFreq(dev_p, 1, (uint8_t)setting, cb, client) ;
}

CyAsReturnStatus_t
CyAsMiscGetGpioValue(CyAsDeviceHandle handle,
        CyAsMiscGpio pin,
        uint8_t *value,
        CyAsFunctionCallback cb,
        uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsDevice *dev_p ;
    uint16_t v ;

    CyAsLogDebugMessage(6, "CyAsMiscGetGpioValue called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /* If the pin specified is UVALID, there is no need for firmware to be loaded. */
    if (pin == CyAsMiscGpio_UValid)
    {
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ;
        *value = (uint8_t)(v & CY_AS_MEM_PMU_UPDATE_UVALID) ;

        if (cb != 0)
            cb(dev_p, ret, client, CY_FUNCT_CB_MISC_GETGPIOVALUE, value) ;

        return ret ;
    }

    /* Check whether the firmware supports this command. */
    if (CyAsDeviceIsNandStorageSupported(dev_p))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /* Make sure the pin selected is valid */
    if ((pin != CyAsMiscGpio_1) && (pin != CyAsMiscGpio_0))
        return CY_AS_ERROR_INVALID_PARAMETER ;

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

    CyAsLLRequestResponse_SetWord(req_p, 0, ((uint8_t)pin << 8)) ;

    /* Reserve space for the reply, which 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 ;
    }

    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_GPIO_STATE)
        {
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            goto destroy ;
        }

        *value = (uint8_t)CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    }
    else
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_GETGPIOVALUE,
            value, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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
CyAsMiscSetGpioValue(CyAsDeviceHandle handle,
        CyAsMiscGpio pin,
        uint8_t value,
        CyAsFunctionCallback cb,
        uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyAsLLRequestResponse *req_p, *reply_p ;
    CyAsDevice *dev_p ;
    uint16_t v ;

    CyAsLogDebugMessage(6, "CyAsMiscSetGpioValue called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /* If the pin specified is UVALID, there is no need for firmware to be loaded. */
    if (pin == CyAsMiscGpio_UValid)
    {
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ;
        if (value)
            CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE, (v | CY_AS_MEM_PMU_UPDATE_UVALID)) ;
        else
            CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE, (v & ~CY_AS_MEM_PMU_UPDATE_UVALID)) ;

        if (cb != 0)
            cb(dev_p, ret, client, CY_FUNCT_CB_MISC_SETGPIOVALUE, 0) ;
        return ret ;
    }

    /* Check whether the firmware supports this command. */
    if (CyAsDeviceIsNandStorageSupported(dev_p))
        return CY_AS_ERROR_NOT_SUPPORTED ;

    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /* Make sure the pin selected is valid */
    if ((pin < CyAsMiscGpio_0) || (pin > CyAsMiscGpio_UValid))
        return CY_AS_ERROR_INVALID_PARAMETER ;

    /* Create and initialize the low level request to the firmware. */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_GPIO_STATE, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
    if (req_p == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;

    v = (uint16_t)(((uint8_t)pin << 8) | (value > 0)) ;
    CyAsLLRequestResponse_SetWord(req_p, 0, v) ;

    /* Reserve space for the reply, which 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 ;
    }

    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_MISC_SETGPIOVALUE,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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 ;
}

static CyAsReturnStatus_t
MyEnterStandby(CyAsDevice *dev_p, CyBool pin)
{
    CyAsMiscCancelExRequests(dev_p) ;

    /* Save the current values in the critical P-port registers, where necessary. */
    CyAsHalReadRegsBeforeStandby(dev_p->tag) ;

    if (pin)
    {
        if (CyAsHalSetWakeupPin(dev_p->tag, CyFalse))
            CyAsDeviceSetPinStandby(dev_p) ;
        else
            return CY_AS_ERROR_SETTING_WAKEUP_PIN ;
    }
    else
    {
        /*
         * Put antioch in the standby mode
         */
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT, 0x02) ;
        CyAsDeviceSetRegisterStandby(dev_p) ;
    }

    /*
     * When the Antioch comes out of standby, we have to wait until
     * the firmware initialization completes before sending other
     * requests down.
     */
    CyAsDeviceSetFirmwareNotLoaded(dev_p) ;

    /*
     * Keep West Bridge interrupt disabled until the device is being woken
     * up from standby.
     */
    dev_p->stby_int_mask = CyAsHalDisableInterrupts ();

    return CY_AS_ERROR_SUCCESS ;
}

static CyAsReturnStatus_t
MyHandleResponseEnterStandby(CyAsDevice* dev_p,
                         CyAsLLRequestResponse *req_p,
                         CyAsLLRequestResponse *reply_p,
                         CyBool pin)
{
    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) ;

    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    ret = MyEnterStandby(dev_p, pin) ;

    return ret ;
}

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

    CyAsLogDebugMessage(6, "CyAsMiscEnterStandby called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    /*
     * If we already are in standby, do not do it again and let the
     * user know via the error return.
     */
    ret = CyAsMiscInStandby(handle, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (standby == CyTrue)
        return CY_AS_ERROR_ALREADY_STANDBY ;

    /*
     * If the user wants to transition from suspend mode to standby mode,
     * the device needs to be woken up so that it can complete all pending
     * operations.
     */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        CyAsMiscLeaveSuspend(dev_p, 0, 0) ;

    if (dev_p->usb_count)
    {
        /*
         * We do not allow West Bridge to go into standby mode when the
         * USB stack is initialized.  You must stop the USB stack in
         * order to enter standby mode.
         */
        return CY_AS_ERROR_USB_RUNNING ;
    }

    /*
     * If the storage stack is not running, the device can directly be put into
     * sleep mode. Otherwise, the firmware needs to be signaled to prepare for
     * going into sleep mode.
     */
    if (dev_p->storage_count)
    {
        /*
         * If there are async storage operations pending, make one attempt to
         * complete them.
         */
        if (CyAsDeviceIsStorageAsyncPending(dev_p))
        {
            /* DrainQueue will not work in polling mode */
            if(CyAsHalIsPolling())
                return CY_AS_ERROR_ASYNC_PENDING ;

            CyAsDmaDrainQueue(dev_p, CY_AS_P2S_READ_ENDPOINT, CyFalse) ;
            CyAsDmaDrainQueue(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CyFalse) ;

            /*
             * If more storage operations were queued at this stage, return
             * an error.
             */
            if (CyAsDeviceIsStorageAsyncPending(dev_p))
                return CY_AS_ERROR_ASYNC_PENDING ;
        }

        req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PREPARE_FOR_STANDBY, 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 ;
        }

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

            /* The request and response are freed in the HandleResponse */
            return MyHandleResponseEnterStandby(dev_p, req_p, reply_p, pin) ;

        }
        else
        {
            ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_ENTERSTANDBY,
                (void*)pin, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
                reply_p, CyAsMiscFuncCallback) ;

            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
    {
        ret = MyEnterStandby(dev_p, pin) ;
        if(cb)
            /* Even though no mailbox communication was needed, issue the callback so the
            * user does not need to special case their code. */
            cb((CyAsDeviceHandle)dev_p, ret, client, CY_FUNCT_CB_MISC_ENTERSTANDBY, 0) ;
    }

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscEnterStandbyEXU(CyAsDeviceHandle handle,
                        CyBool pin,
                        CyBool uvalid_special,
                        CyAsFunctionCallback cb,
                        uint32_t client)
{
    CyAsDevice *dev_p ;

    dev_p = (CyAsDevice *)handle ;
    if(uvalid_special)
    {
        CyAsHalWriteRegister(dev_p->tag, 0xc5, 0x4) ;
    }

    return CyAsMiscEnterStandby(handle, pin, cb, client) ;
}

CyAsReturnStatus_t
CyAsMiscLeaveStandby(CyAsDeviceHandle handle, CyAsResourceType resource)
{
    CyAsDevice *dev_p ;
    uint16_t v ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint32_t count = 8 ;
    uint8_t  retry = 1 ;

    CyAsLogDebugMessage(6, "CyAsMiscLeaveStandby called") ;
    (void)resource ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    if (CyAsDeviceIsRegisterStandby(dev_p))
    {
        /*
         * Set a flag to indicate that the West Bridge is waking up from standby.
         */
        CyAsDeviceSetWaking(dev_p) ;

        /*
         * The initial read will not succeed, but will just wake the West Bridge
         * device from standby.  Successive reads should succeed and in that way
         * we know West Bridge is awake.
         */
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;

        do
        {
            /*
             * We have initiated the operation to leave standby, now we need to wait at least
             * N ms before trying to access the West Bridge device to insure the PLLs have locked and we
             * can talk to the device.
             */
            if (CyAsDeviceIsCrystal(dev_p))
                CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ;
            else
                CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
            v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;

            /*
            * If the P-SPI interface mode is in use, there may be a need to re-synchronise the
            * serial clock used for Astoria access.
            */
            if (!IsValidSiliconId(v))
            {
                if (CyAsHalSyncDeviceClocks(dev_p->tag) != CyTrue)
                {
                    CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
                    return CY_AS_ERROR_TIMEOUT ;
                }
            }
        } while (!IsValidSiliconId(v) && count-- > 0) ;

        /*
         * If we tried to read the register and could not, return a timeout
         */
        if (count == 0)
        {
            CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
            return CY_AS_ERROR_TIMEOUT ;
        }

        /*
         * The standby flag is cleared here, after the action to exit standby has
         * been taken. The wait for firmware initialization, is ensured by marking
         * the firmware as not loaded until the init event is received.
         */
        CyAsDeviceClearRegisterStandby(dev_p) ;

        /*
         * Initialize any registers that may have been changed while the device was in standby mode.
         */
        CyAsHalInitDevRegisters(dev_p->tag, CyTrue) ;
    }
    else if (CyAsDeviceIsPinStandby(dev_p))
    {
        /*
         * Set a flag to indicate that the West Bridge is waking up from standby.
         */
        CyAsDeviceSetWaking(dev_p) ;

TryWakeupAgain:
        /*
        * Try to set the wakeup pin, if this fails in the HAL layer, return this
        * failure to the user.
        */
        if (!CyAsHalSetWakeupPin(dev_p->tag, CyTrue))
        {
            CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
            return CY_AS_ERROR_SETTING_WAKEUP_PIN ;
        }

        /*
        * We have initiated the operation to leave standby, now we need to wait at least
        * N ms before trying to access the West Bridge device to insure the PLLs have locked and we
        * can talk to the device.
        */
        if (CyAsDeviceIsCrystal(dev_p))
            CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ;
        else
            CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;

        /*
         * Initialize any registers that may have been changed while the device was in standby mode.
         */
        CyAsHalInitDevRegisters(dev_p->tag, CyTrue) ;

        /*
         * The standby flag is cleared here, after the action to exit standby has
         * been taken. The wait for firmware initialization, is ensured by marking
         * the firmware as not loaded until the init event is received.
         */
        CyAsDeviceClearPinStandby(dev_p) ;
    }
    else
    {
        return CY_AS_ERROR_NOT_IN_STANDBY ;
    }

    /*
     * The West Bridge interrupt can be enabled now.
     */
    CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;

    /*
     * Release the West Bridge Micro-Controller from reset, so that firmware initialization
     * can complete.
     * The attempt to release Antioch reset is made upto 8 times.
     */
    v     = 0x03 ;
    count = 0x08 ;
    while ((v & 0x03) && (count))
    {
        CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG) ;
        count-- ;
    }

    if (v & 0x03)
    {
        CyAsHalPrintMessage("Failed to clear Antioch reset\n") ;
        return CY_AS_ERROR_TIMEOUT ;
    }

    /*
     * If the wake-up pin is being used, wait here to make sure that the wake-up event
     * is received within a reasonable delay. Otherwise, toggle the wake-up pin again
     * in an attempt to start the firmware properly.
     */
    if (retry)
    {
        count = 10 ;
        while (count)
        {
            /* If the wake-up event has been received, we can return. */
            if (CyAsDeviceIsFirmwareLoaded (dev_p))
                break ;
            /* If we are in polling mode, the interrupt may not have been serviced as yet.
             * Read the interrupt status register. If a pending mailbox interrupt is seen,
             * we can assume that the wake-up event will be received soon. */
            v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_INTR_REG) ;
            if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
                break ;

            CyAsHalSleep (10) ;
            count-- ;
        }

        if (!count)
        {
            retry = 0 ;
            dev_p->stby_int_mask = CyAsHalDisableInterrupts() ;
            CyAsHalSetWakeupPin(dev_p->tag, CyFalse) ;
            CyAsHalSleep (10) ;
            goto TryWakeupAgain ;
        }
    }

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscRegisterCallback(
                         CyAsDeviceHandle               handle,         /* Handle to the West Bridge device */
                         CyAsMiscEventCallback  callback        /* The function to call */
                         )
{
    CyAsDevice *dev_p ;

    CyAsLogDebugMessage(6, "CyAsMiscRegisterCallback called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
        return CY_AS_ERROR_INVALID_HANDLE ;

    dev_p->misc_event_cb = callback ;
    return CY_AS_ERROR_SUCCESS ;
}

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

    CyAsLogDebugMessage(6, "CyAsMiscStorageChanged called") ;

    /* Make sure the device is ready for the command. */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /*
    * Make sure Antioch is not in standby
    */
    ret = CyAsMiscInStandby(dev_p, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    if (standby)
        return CY_AS_ERROR_IN_STANDBY ;

    /*
     * Make sure Westbridge is not in suspend mode.
     */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STORAGE_MEDIA_CHANGED, CY_RQT_GENERAL_RQT_CONTEXT, 0) ;
    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 ;
    }

    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_MISC_STORAGECHANGED,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        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
CyAsMiscEnterSuspend(
        CyAsDeviceHandle     handle,
        CyBool               usb_wakeup_en,
        CyBool               gpio_wakeup_en,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsDevice *dev_p ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyBool standby ;
    CyAsLLRequestResponse *req_p, *reply_p ;
    uint16_t value ;
    uint32_t int_state ;

    CyAsLogDebugMessage(6, "CyAsMiscEnterSuspend called") ;

    /*
     * Basic sanity checks to ensure that the device is initialised.
     */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /*
     * Make sure West Bridge is not already in standby
     */
    CyAsMiscInStandby(dev_p, &standby) ;
    if (standby)
        return CY_AS_ERROR_IN_STANDBY ;

    /*
     * Make sure that the device is not already in suspend mode.
     */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /*
     * Make sure there is no active USB connection.
     */
    if ((CyAsDeviceIsUsbConnected(dev_p)) && (dev_p->usb_last_event != CyAsEventUsbSuspend))
        return CY_AS_ERROR_USB_CONNECTED ;

    /*
     * Make sure that there are no async requests at this point in time.
     */
    int_state = CyAsHalDisableInterrupts() ;
    if ((dev_p->func_cbs_misc->count) || (dev_p->func_cbs_res->count) ||
            (dev_p->func_cbs_stor->count) || (dev_p->func_cbs_usb->count))
    {
        CyAsHalEnableInterrupts(int_state) ;
        return CY_AS_ERROR_ASYNC_PENDING ;
    }
    CyAsHalEnableInterrupts(int_state) ;

    /* Create the request to send to the Antioch device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ENTER_SUSPEND_MODE, CY_RQT_GENERAL_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 ;
    }

    /* Wakeup control flags. */
    value = 0x0001 ;
    if (usb_wakeup_en)
        value |= 0x04 ;
    if (gpio_wakeup_en)
        value |= 0x02 ;
    CyAsLLRequestResponse_SetWord(req_p, 0, value) ;

    if (cb != 0)
    {

        ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_ENTERSUSPEND,
            0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
            CyAsMiscFuncCallback) ;

        if (ret != CY_AS_ERROR_SUCCESS)
                goto destroy ;

        return CY_AS_ERROR_SUCCESS ;
    }
    else
    {
        ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
        if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
        else
            ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
    }

destroy:
    if (ret == CY_AS_ERROR_SUCCESS)
        CyAsDeviceSetSuspendMode(dev_p) ;

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

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscLeaveSuspend(
        CyAsDeviceHandle     handle,
        CyAsFunctionCallback cb,
        uint32_t             client)
{
    CyAsDevice *dev_p ;
    uint16_t v, count ;
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;

    CyAsLogDebugMessage(6, "CyAsMiscLeaveSuspend called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /* Make sure we are in suspend mode. */
    if (CyAsDeviceIsInSuspendMode(dev_p))
    {
        if (cb)
        {
            CyAsFuncCBNode *cbnode = CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ;
            if (cbnode == 0)
                return CY_AS_ERROR_OUT_OF_MEMORY ;

            CyAsInsertCBNode(dev_p->func_cbs_misc, cbnode) ;
        }

        /*
         * Do a read from the ID register so that the CE assertion will wake West Bridge.
         * The read is repeated until the read comes back with valid data.
         */
        count = 8 ;

        v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;

        while (!IsValidSiliconId(v) && count-- > 0)
        {
            CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
            v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
        }

        /*
         * If we tried to read the register and could not, return a timeout
         */
        if (count == 0)
            return CY_AS_ERROR_TIMEOUT ;
    }
    else
        return CY_AS_ERROR_NOT_IN_SUSPEND ;

    if (cb == 0)
    {
        /*
         * Wait until the in suspend mode flag is cleared.
         */
        count = 20 ;
        while ((CyAsDeviceIsInSuspendMode(dev_p)) && (count--))
        {
            CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
        }

        if (CyAsDeviceIsInSuspendMode(dev_p))
            ret = CY_AS_ERROR_TIMEOUT ;
    }

    return ret ;
}

CyAsReturnStatus_t
CyAsMiscReserveLNABootArea(CyAsDeviceHandle handle,
                           uint8_t numzones,
                           CyAsFunctionCallback cb,
                           uint32_t client)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    CyBool standby ;
    CyAsLLRequestResponse *req_p, *reply_p ;

    CyAsDevice *dev_p ;

    (void)client ;

    CyAsLogDebugMessage(6, "CyAsMiscSwitchPnandMode called") ;

    /* Make sure we have a valid device */
    dev_p = (CyAsDevice *)handle ;
    CyAsCheckDeviceReady(dev_p) ;

    /*
    * Make sure Antioch is not in standby
    */
    ret = CyAsMiscInStandby(dev_p, &standby) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;
    if (standby)
        return CY_AS_ERROR_IN_STANDBY ;

    /* Make sure the Antioch is not in suspend mode. */
    if (CyAsDeviceIsInSuspendMode(dev_p))
        return CY_AS_ERROR_IN_SUSPEND ;

    /* Create the request to send to the West Bridge device */
    req_p = CyAsLLCreateRequest(dev_p, CY_RQT_RESERVE_LNA_BOOT_AREA, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
    if (req_p == 0)
            return CY_AS_ERROR_OUT_OF_MEMORY ;
        CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)numzones) ;

    /* 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 ;
    }

    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_MISC_RESERVELNABOOTAREA,
                0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
                reply_p, CyAsMiscFuncCallback) ;

            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 ;
}

CyAsFuncCBNode*
CyAsCreateFuncCBNodeData(CyAsFunctionCallback cb,
                     uint32_t client,
                     CyAsFunctCBType type,
                     void* data)
{
    uint32_t state = CyAsHalDisableInterrupts() ;
    CyAsFuncCBNode* node = (CyAsFuncCBNode*)CyAsHalCBAlloc(sizeof(CyAsFuncCBNode)) ;
    CyAsHalEnableInterrupts(state) ;
    if(node != 0)
    {
        node->nodeType = CYAS_FUNC_CB ;
        node->cb_p = cb ;
        node->client_data = client ;
        node->dataType = type ;
        if(data != 0)
            node->dataType |= CY_FUNCT_CB_DATA ;
        else
            node->dataType |= CY_FUNCT_CB_NODATA ;
        node->data = data ;
        node->next_p = 0 ;
    }
    return node ;
}

CyAsFuncCBNode*
CyAsCreateFuncCBNode(CyAsFunctionCallback cb,
                     uint32_t client)
{
    return CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_NODATA, 0) ;
}

void
CyAsDestroyFuncCBNode(CyAsFuncCBNode* node)
{
    uint32_t state ;

    node->nodeType = CYAS_INVALID ;
    state = CyAsHalDisableInterrupts() ;
    CyAsHalCBFree(node) ;
    CyAsHalEnableInterrupts(state) ;
}

CyAsUsbFuncCBNode*
CyAsCreateUsbFuncCBNode(CyAsUsbFunctionCallback cb, uint32_t client)
{
    uint32_t state = CyAsHalDisableInterrupts() ;
    CyAsUsbFuncCBNode * node = (CyAsUsbFuncCBNode *)CyAsHalCBAlloc(sizeof(CyAsUsbFuncCBNode)) ;
    CyAsHalEnableInterrupts(state) ;
    if(node != 0)
    {
        node->type = CYAS_USB_FUNC_CB ;
        node->cb_p = cb ;
        node->client_data = client ;
        node->next_p = 0 ;
    }
    return node ;
}

void
CyAsDestroyUsbFuncCBNode(CyAsUsbFuncCBNode* node)
{
    uint32_t state ;

    node->type = CYAS_INVALID ;
    state = CyAsHalDisableInterrupts() ;
    CyAsHalCBFree(node) ;
    CyAsHalEnableInterrupts(state) ;
}

CyAsUsbIoCBNode*
CyAsCreateUsbIoCBNode(CyAsUsbIoCallback cb)
{
    uint32_t state = CyAsHalDisableInterrupts() ;
    CyAsUsbIoCBNode * node = (CyAsUsbIoCBNode *)CyAsHalCBAlloc(sizeof(CyAsUsbIoCBNode)) ;
    CyAsHalEnableInterrupts(state) ;
    if(node != 0)
    {
        node->type = CYAS_USB_IO_CB ;
        node->cb_p = cb ;
        node->next_p = 0 ;
    }
    return node ;
}

void
CyAsDestroyUsbIoCBNode(CyAsUsbIoCBNode* node)
{
    uint32_t state ;

    node->type = CYAS_INVALID ;

    state = CyAsHalDisableInterrupts() ;
    CyAsHalCBFree(node) ;
    CyAsHalEnableInterrupts(state) ;
}

CyAsStorageIoCBNode*
CyAsCreateStorageIoCBNode(CyAsStorageCallback cb, CyAsMediaType media, uint32_t device_index,
                          uint32_t unit, uint32_t block_addr, CyAsOperType oper,
                          CyAsLLRequestResponse* req_p, CyAsLLRequestResponse* reply_p)
{
    uint32_t state = CyAsHalDisableInterrupts() ;
    CyAsStorageIoCBNode * node = (CyAsStorageIoCBNode *)CyAsHalCBAlloc(sizeof(CyAsStorageIoCBNode)) ;
    CyAsHalEnableInterrupts(state) ;
    if(node != 0)
    {
        node->type = CYAS_STORAGE_IO_CB ;
        node->cb_p = cb ;
        node->media = media ;
        node->device_index = device_index ;
        node->unit = unit ;
        node->block_addr = block_addr ;
        node->oper = oper ;
        node->req_p = req_p ;
        node->reply_p = reply_p ;
        node->next_p = 0 ;
    }
    return node ;
}

void
CyAsDestroyStorageIoCBNode(CyAsStorageIoCBNode* node)
{
    uint32_t state ;
    node->type = CYAS_INVALID ;
    state = CyAsHalDisableInterrupts() ;
    CyAsHalCBFree(node) ;
    CyAsHalEnableInterrupts(state) ;
}

CyAsCBQueue *
CyAsCreateCBQueue(CyAsCBNodeType type)
{
    uint32_t state = CyAsHalDisableInterrupts() ;
    CyAsCBQueue * queue = (CyAsCBQueue *)CyAsHalCBAlloc(sizeof(CyAsCBQueue)) ;
    CyAsHalEnableInterrupts(state) ;
    if(queue)
    {
        queue->type = type ;
        queue->head_p = 0 ;
        queue->tail_p = 0 ;
        queue->count = 0 ;
    }

    return queue ;
}

void
CyAsDestroyCBQueue(CyAsCBQueue* queue)
{
    uint32_t state ;
    queue->type = CYAS_INVALID ;
    queue->head_p = 0 ;
    queue->tail_p = 0 ;
    queue->count = 0 ;
    state = CyAsHalDisableInterrupts() ;
    CyAsHalCBFree(queue) ;
    CyAsHalEnableInterrupts(state) ;
}

/* Inserts a CyAsCBNode into the queue, the node type must match the queue type*/
void
CyAsInsertCBNode(CyAsCBQueue * queue_p, void* cbnode)
{
    uint32_t int_state ;

    int_state = CyAsHalDisableInterrupts() ;

    CyAsHalAssert(queue_p != 0) ;

    switch (queue_p->type)
    {
        case CYAS_USB_FUNC_CB:
            {
                CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)cbnode ;
                CyAsUsbFuncCBNode* tail = (CyAsUsbFuncCBNode*)queue_p->tail_p ;

                CyAsHalAssert(node->type == CYAS_USB_FUNC_CB) ;
                CyAsHalAssert(tail == 0 || tail->type == CYAS_USB_FUNC_CB) ;
                if(queue_p->head_p == 0)
                    queue_p->head_p = node ;
                else
                    tail->next_p = node ;

                queue_p->tail_p = node ;
            }
            break ;

        case CYAS_USB_IO_CB:
            {
                CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)cbnode ;
                CyAsUsbIoCBNode* tail = (CyAsUsbIoCBNode*)queue_p->tail_p ;

                CyAsHalAssert(node->type == CYAS_USB_IO_CB) ;
                CyAsHalAssert(tail == 0 || tail->type == CYAS_USB_IO_CB) ;
                if(queue_p->head_p == 0)
                    queue_p->head_p = node ;
                else
                    tail->next_p = node ;

                queue_p->tail_p = node ;
            }
            break ;

        case CYAS_STORAGE_IO_CB:
            {
                CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)cbnode ;
                CyAsStorageIoCBNode* tail = (CyAsStorageIoCBNode*)queue_p->tail_p ;

                CyAsHalAssert(node->type == CYAS_STORAGE_IO_CB) ;
                CyAsHalAssert(tail == 0 || tail->type == CYAS_STORAGE_IO_CB) ;
                if(queue_p->head_p == 0)
                    queue_p->head_p = node ;
                else
                    tail->next_p = node ;

                queue_p->tail_p = node ;
            }
            break ;

        case CYAS_FUNC_CB:
            {
                CyAsFuncCBNode* node = (CyAsFuncCBNode*)cbnode ;
                CyAsFuncCBNode* tail = (CyAsFuncCBNode*)queue_p->tail_p ;

                CyAsHalAssert(node->nodeType == CYAS_FUNC_CB) ;
                CyAsHalAssert(tail == 0 || tail->nodeType == CYAS_FUNC_CB) ;
                if(queue_p->head_p == 0)
                    queue_p->head_p = node ;
                else
                    tail->next_p = node ;

                queue_p->tail_p = node ;
            }
            break ;

        default:
            CyAsHalAssert(CyFalse) ;
            break ;
    }

    queue_p->count++ ;

    CyAsHalEnableInterrupts(int_state) ;
}

/* Removes the tail node from the queue and frees it */
void
CyAsRemoveCBTailNode(CyAsCBQueue *queue_p)
{
    uint32_t int_state ;

    int_state = CyAsHalDisableInterrupts () ;

    if (queue_p->count > 0)
    {
        /*
         * The worst case length of the queue should be under 10 elements, and the average
         * case should be just 1 element. So, we just employ a linear search to find the node
         * to be freed.
         */
        switch (queue_p->type)
        {
            case CYAS_FUNC_CB:
                {
                    CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
                    CyAsFuncCBNode* tail = (CyAsFuncCBNode*)queue_p->tail_p ;
                    if (node != tail)
                    {
                        while (node->next_p != tail)
                            node = node->next_p ;
                        node->next_p = 0 ;
                        queue_p->tail_p = node ;
                    }
                    CyAsDestroyFuncCBNode (tail) ;
                }
                break ;

            case CYAS_USB_FUNC_CB:
                {
                    CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)queue_p->head_p ;
                    CyAsUsbFuncCBNode* tail = (CyAsUsbFuncCBNode*)queue_p->tail_p ;
                    if (node != tail)
                    {
                        while (node->next_p != tail)
                            node = node->next_p ;
                        node->next_p = 0 ;
                        queue_p->tail_p = node ;
                    }

                    CyAsDestroyUsbFuncCBNode (tail) ;
                }
                break ;

            case CYAS_USB_IO_CB:
                {
                    CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)queue_p->head_p ;
                    CyAsUsbIoCBNode* tail = (CyAsUsbIoCBNode*)queue_p->tail_p ;
                    if (node != tail)
                    {
                        while (node->next_p != tail)
                            node = node->next_p ;
                        node->next_p = 0 ;
                        queue_p->tail_p = node ;
                    }
                    CyAsDestroyUsbIoCBNode (tail) ;
                }
                break ;

            case CYAS_STORAGE_IO_CB:
                {
                    CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)queue_p->head_p ;
                    CyAsStorageIoCBNode* tail = (CyAsStorageIoCBNode*)queue_p->tail_p ;
                    if (node != tail)
                    {
                        while (node->next_p != tail)
                            node = node->next_p ;
                        node->next_p = 0 ;
                        queue_p->tail_p = node ;
                    }
                    CyAsDestroyStorageIoCBNode (tail) ;
                }
                break ;

            default:
                CyAsHalAssert (CyFalse) ;
        }

        queue_p->count-- ;
        if (queue_p->count == 0)
        {
            queue_p->head_p = 0 ;
            queue_p->tail_p = 0 ;
        }
    }

    CyAsHalEnableInterrupts (int_state) ;
}

/* Removes the first CyAsCBNode from the queue and frees it */
void
CyAsRemoveCBNode(CyAsCBQueue * queue_p)
{
    uint32_t int_state ;

    int_state = CyAsHalDisableInterrupts() ;

    CyAsHalAssert(queue_p->count >= 0) ;
    if(queue_p->count > 0)
    {
        if(queue_p->type == CYAS_USB_FUNC_CB)
        {
            CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)queue_p->head_p ;
            queue_p->head_p = node->next_p ;
            CyAsDestroyUsbFuncCBNode(node) ;
        }
        else if(queue_p->type == CYAS_USB_IO_CB)
        {
            CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)queue_p->head_p ;
            queue_p->head_p = node->next_p ;
            CyAsDestroyUsbIoCBNode(node) ;
        }
        else if(queue_p->type == CYAS_STORAGE_IO_CB)
        {
            CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)queue_p->head_p ;
            queue_p->head_p = node->next_p ;
            CyAsDestroyStorageIoCBNode(node) ;
        }
        else if(queue_p->type == CYAS_FUNC_CB)
        {
            CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
            queue_p->head_p = node->next_p ;
            CyAsDestroyFuncCBNode(node) ;
        }
        else
        {
            CyAsHalAssert(CyFalse) ;
        }

        queue_p->count-- ;
        if(queue_p->count == 0)
        {
            queue_p->head_p = 0 ;
            queue_p->tail_p = 0 ;
        }
    }

    CyAsHalEnableInterrupts(int_state) ;
}

void MyPrintFuncCBNode(CyAsFuncCBNode* node)
{
    CyAsHalPrintMessage("[cd:%2u dt:%2u cb:0x%08x d:0x%08x nt:%1i]",
        node->client_data, CyAsFunctCBTypeGetType(node->dataType), (uint32_t)node->cb_p, (uint32_t)node->data, node->nodeType) ;
}

void MyPrintCBQueue(CyAsCBQueue* queue_p)
{
    uint32_t i = 0 ;

    CyAsHalPrintMessage("| Count: %u Type: ", queue_p->count) ;

    if(queue_p->type == CYAS_USB_FUNC_CB)
    {
        CyAsHalPrintMessage("USB_FUNC_CB\n") ;
    }
    else if(queue_p->type == CYAS_USB_IO_CB)
    {
        CyAsHalPrintMessage("USB_IO_CB\n") ;
    }
    else if(queue_p->type == CYAS_STORAGE_IO_CB)
    {
        CyAsHalPrintMessage("STORAGE_IO_CB\n") ;
    }
    else if(queue_p->type == CYAS_FUNC_CB)
    {
        CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
        CyAsHalPrintMessage("FUNC_CB\n") ;
        if(queue_p->count > 0)
        {
            CyAsHalPrintMessage("| Head->") ;

            for(i = 0; i < queue_p->count; i++)
            {
                if(node)
                {
                    CyAsHalPrintMessage("->") ;
                    MyPrintFuncCBNode(node) ;
                    node = node->next_p ;
                }
                else
                    CyAsHalPrintMessage("->[NULL]\n") ;
            }

            CyAsHalPrintMessage("\n| Tail->") ;
            MyPrintFuncCBNode((CyAsFuncCBNode*)queue_p->tail_p) ;
            CyAsHalPrintMessage("\n") ;
        }
    }
    else
    {
        CyAsHalPrintMessage("INVALID\n") ;
    }

    CyAsHalPrintMessage("|----------\n") ;
}


/* Removes and frees all pending callbacks */
void
CyAsClearCBQueue(CyAsCBQueue * queue_p)
{
    uint32_t int_state = CyAsHalDisableInterrupts() ;

    while(queue_p->count != 0)
        CyAsRemoveCBNode(queue_p) ;

    CyAsHalEnableInterrupts(int_state) ;
}

CyAsReturnStatus_t
CyAsMiscSendRequest(CyAsDevice* dev_p,
                      CyAsFunctionCallback cb,
                      uint32_t client,
                      CyAsFunctCBType type,
                      void* data,
                      CyAsCBQueue* queue,
                      uint16_t req_type,
                      CyAsLLRequestResponse *req_p,
                      CyAsLLRequestResponse *reply_p,
                      CyAsResponseCallback rcb)
{

    CyAsFuncCBNode* cbnode = CyAsCreateFuncCBNodeData(cb, client, type, data) ;
    CyAsReturnStatus_t ret ;

    if(cbnode == 0)
        return CY_AS_ERROR_OUT_OF_MEMORY ;
    else
        CyAsInsertCBNode(queue, cbnode) ;

    req_p->flags |= req_type ;

    ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, rcb) ;
    if (ret != CY_AS_ERROR_SUCCESS)
    {
        CyAsRemoveCBTailNode(queue) ;
    }

    return ret ;
}

void
CyAsMiscCancelExRequests(CyAsDevice *dev_p)
{
    int i ;
    for(i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
        CyAsLLRemoveAllRequests(dev_p, dev_p->context[i]) ;
}


static void
CyAsMiscFuncCallback(CyAsDevice *dev_p,
                        uint8_t context,
                        CyAsLLRequestResponse *rqt,
                        CyAsLLRequestResponse *resp,
                        CyAsReturnStatus_t stat)
{
    CyAsFuncCBNode* node = NULL ;
    CyAsReturnStatus_t ret ;

    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 ;
    uint32_t            type ;
    uint8_t             cntxt ;

    CyAsHalAssert(exRequest || msRequest) ;
    (void) exRequest;
    (void) msRequest;
    (void)context ;

    cntxt = CyAsLLRequestResponse_GetContext(rqt) ;
    code = CyAsLLRequestResponse_GetCode(rqt) ;

    switch(cntxt)
    {
    case CY_RQT_GENERAL_RQT_CONTEXT:
        CyAsHalAssert(dev_p->func_cbs_misc->count != 0) ;
        CyAsHalAssert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB) ;
        node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;
        type = CyAsFunctCBTypeGetType(node->dataType) ;

        switch(code)
        {
        case CY_RQT_GET_FIRMWARE_VERSION:
            CyAsHalAssert(node->data != 0) ;
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_GETFIRMWAREVERSION) ;
            ret = MyHandleResponseGetFirmwareVersion(dev_p, rqt, resp, (CyAsGetFirmwareVersionData*)node->data) ;
            break ;
        case CY_RQT_READ_MCU_REGISTER:
            CyAsHalAssert(node->data != 0) ;
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_READMCUREGISTER) ;
            ret = MyHandleResponseReadMCURegister(dev_p, rqt, resp, (uint8_t*)node->data) ;
            break ;
        case CY_RQT_GET_GPIO_STATE:
            CyAsHalAssert(node->data != 0) ;
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_GETGPIOVALUE) ;
            ret = MyHandleResponseGetGpioValue(dev_p, rqt, resp, (uint8_t*)node->data) ;
            break ;
        case CY_RQT_SET_SD_CLOCK_FREQ:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETSDFREQ) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
        case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_HEARTBEATCONTROL) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
        case CY_RQT_WRITE_MCU_REGISTER:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_WRITEMCUREGISTER) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
        case CY_RQT_STORAGE_MEDIA_CHANGED:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_STORAGECHANGED) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
        case CY_RQT_SET_GPIO_STATE:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETGPIOVALUE) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
        case CY_RQT_SET_TRACE_LEVEL:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETTRACELEVEL) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            if (ret == CY_AS_ERROR_INVALID_RESPONSE)
                ret = CY_AS_ERROR_NOT_SUPPORTED ;
            break ;
        case CY_RQT_PREPARE_FOR_STANDBY:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_ENTERSTANDBY) ;
            ret = MyHandleResponseEnterStandby(dev_p, rqt, resp, (CyBool)node->data) ;
            break ;
        case CY_RQT_ENTER_SUSPEND_MODE:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_ENTERSUSPEND) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            if (ret == CY_AS_ERROR_SUCCESS)
            {
                CyAsDeviceSetSuspendMode(dev_p) ;
            }
            break ;
    case CY_RQT_RESERVE_LNA_BOOT_AREA:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_RESERVELNABOOTAREA) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;
    case CY_RQT_SDPOLARITY:
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETSDPOLARITY) ;
            ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
            break ;


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

    case CY_RQT_RESOURCE_RQT_CONTEXT:
        CyAsHalAssert(dev_p->func_cbs_res->count != 0) ;
        CyAsHalAssert(dev_p->func_cbs_res->type == CYAS_FUNC_CB) ;
        node = (CyAsFuncCBNode*)dev_p->func_cbs_res->head_p ;
        type = CyAsFunctCBTypeGetType(node->dataType) ;

        switch(code)
        {
        case CY_RQT_ACQUIRE_RESOURCE:
            /* The node->data field is actually an enum value which could be
            0, thus no assert is done */
            CyAsHalAssert(type == CY_FUNCT_CB_MISC_ACQUIRERESOURCE) ;
            ret = MyHandleResponseAcquireResource(dev_p, rqt, resp, (CyAsResourceType*)node->data) ;
            break ;
        default:
            ret = CY_AS_ERROR_INVALID_RESPONSE ;
            CyAsHalAssert(CyFalse) ;
            break ;
        }
        break ;

    default:
        ret = CY_AS_ERROR_INVALID_RESPONSE ;
        CyAsHalAssert(CyFalse) ;
        break ;
    }
    (void) type;
    /*
     * 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 */
    node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
    if(cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
        CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
    else
        CyAsRemoveCBNode(dev_p->func_cbs_res) ;
}


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

/*[]*/